Commit ee5a9c78 authored by Aldo Culquicondor's avatar Aldo Culquicondor Committed by Commit Bot

VR: Ability to clip elements

It affects drawing and hit testing. If the quad is completely outside the clip, nothing is sent to the CPU.
This is going to be used to implement scrolling.
Also, this CL removes the unused copy_rect.

Bug: 839488
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_vr
Change-Id: I07c087f3d7860456587de092797349851c26502a
Reviewed-on: https://chromium-review.googlesource.com/1054371
Commit-Queue: Aldo Culquicondor <acondor@chromium.org>
Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558021}
parent f812c075
...@@ -46,11 +46,10 @@ ContentElement::~ContentElement() = default; ...@@ -46,11 +46,10 @@ ContentElement::~ContentElement() = default;
void ContentElement::Render(UiElementRenderer* renderer, void ContentElement::Render(UiElementRenderer* renderer,
const CameraModel& model) const { const CameraModel& model) const {
gfx::RectF copy_rect(0, 0, 1, 1);
if (uses_quad_layer_) { if (uses_quad_layer_) {
renderer->DrawTexturedQuad(0, 0, texture_location(), renderer->DrawTexturedQuad(0, 0, texture_location(),
model.view_proj_matrix * world_space_transform(), model.view_proj_matrix * world_space_transform(),
copy_rect, computed_opacity(), size(), clip_rect(), computed_opacity(), size(),
corner_radius(), false); corner_radius(), false);
return; return;
} }
...@@ -60,7 +59,7 @@ void ContentElement::Render(UiElementRenderer* renderer, ...@@ -60,7 +59,7 @@ void ContentElement::Render(UiElementRenderer* renderer,
if (texture_id() || overlay_texture_id) { if (texture_id() || overlay_texture_id) {
renderer->DrawTexturedQuad( renderer->DrawTexturedQuad(
texture_id(), overlay_texture_id, texture_location(), texture_id(), overlay_texture_id, texture_location(),
model.view_proj_matrix * world_space_transform(), copy_rect, model.view_proj_matrix * world_space_transform(), clip_rect(),
computed_opacity(), size(), corner_radius(), true); computed_opacity(), size(), corner_radius(), true);
} }
} }
......
...@@ -16,7 +16,7 @@ void FullScreenRect::Render(UiElementRenderer* renderer, ...@@ -16,7 +16,7 @@ void FullScreenRect::Render(UiElementRenderer* renderer,
const CameraModel& model) const { const CameraModel& model) const {
gfx::Transform m; gfx::Transform m;
m.Scale3d(2.0f, 2.0f, 1.0f); m.Scale3d(2.0f, 2.0f, 1.0f);
renderer->DrawGradientQuad(m, edge_color(), center_color(), renderer->DrawGradientQuad(m, edge_color(), center_color(), clip_rect(),
computed_opacity(), gfx::SizeF(1.f, 1.f), computed_opacity(), gfx::SizeF(1.f, 1.f),
corner_radii()); corner_radii());
} }
......
...@@ -45,8 +45,8 @@ void Rect::Render(UiElementRenderer* renderer, const CameraModel& model) const { ...@@ -45,8 +45,8 @@ void Rect::Render(UiElementRenderer* renderer, const CameraModel& model) const {
if (opacity <= 0.f) if (opacity <= 0.f)
return; return;
renderer->DrawGradientQuad(model.view_proj_matrix * world_space_transform(), renderer->DrawGradientQuad(model.view_proj_matrix * world_space_transform(),
edge_color_, center_color_, opacity, size(), edge_color_, center_color_, clip_rect(), opacity,
corner_radii()); size(), corner_radii());
} }
void Rect::SetLocalOpacity(float opacity) { void Rect::SetLocalOpacity(float opacity) {
......
...@@ -83,10 +83,9 @@ void TexturedElement::Render(UiElementRenderer* renderer, ...@@ -83,10 +83,9 @@ void TexturedElement::Render(UiElementRenderer* renderer,
if (texture_handle_ <= 0) if (texture_handle_ <= 0)
return; return;
gfx::RectF copy_rect(0, 0, 1, 1);
renderer->DrawTexturedQuad( renderer->DrawTexturedQuad(
texture_handle_, 0, UiElementRenderer::kTextureLocationLocal, texture_handle_, 0, UiElementRenderer::kTextureLocationLocal,
model.view_proj_matrix * world_space_transform(), copy_rect, model.view_proj_matrix * world_space_transform(), clip_rect(),
computed_opacity(), size(), corner_radius(), true /* blend */); computed_opacity(), size(), corner_radius(), true /* blend */);
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/vr/model/camera_model.h" #include "chrome/browser/vr/model/camera_model.h"
#include "chrome/browser/vr/vr_gl_util.h"
#include "third_party/blink/public/platform/web_gesture_event.h" #include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/skia/include/core/SkRRect.h" #include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRect.h"
...@@ -466,9 +467,14 @@ bool UiElement::LocalHitTest(const gfx::PointF& point) const { ...@@ -466,9 +467,14 @@ bool UiElement::LocalHitTest(const gfx::PointF& point) const {
if (point.x() < 0.0f || point.x() > 1.0f || point.y() < 0.0f || if (point.x() < 0.0f || point.x() > 1.0f || point.y() < 0.0f ||
point.y() > 1.0f) { point.y() > 1.0f) {
return false; return false;
} else if (corner_radii_.IsZero()) { }
return point.x() >= 0.0f && point.x() <= 1.0f && point.y() >= 0.0f && if (!clip_rect_.IsEmpty() &&
point.y() <= 1.0f; !CalculateTexSpaceRect(size(), clip_rect_).Contains(point)) {
return false;
}
if (corner_radii_.IsZero()) {
return true;
} }
float width = size().width(); float width = size().width();
...@@ -806,6 +812,11 @@ bool UiElement::SizeAndLayOut() { ...@@ -806,6 +812,11 @@ bool UiElement::SizeAndLayOut() {
changed |= PrepareToDraw(); changed |= PrepareToDraw();
set_update_phase(kUpdatedSize); set_update_phase(kUpdatedSize);
DoLayOutChildren(); DoLayOutChildren();
if (clips_descendants_) {
clip_rect_ = {-0.5f * size().width(), 0.5f * size().height(),
size().width(), size().height()};
ClipChildren();
}
set_update_phase(kUpdatedLayout); set_update_phase(kUpdatedLayout);
return changed; return changed;
} }
...@@ -910,6 +921,21 @@ void UiElement::LayOutChildren() { ...@@ -910,6 +921,21 @@ void UiElement::LayOutChildren() {
} }
} }
void UiElement::ClipChildren() {
for (auto& child : children_) {
// Nested clipping is not supported yet.
DCHECK(!child->clips_descendants_);
if (!child->IsVisible())
continue;
DCHECK(child->LocalTransform().IsScaleOrTranslation());
child->clip_rect_ = clip_rect_;
child->LocalTransform().TransformRectReverse(&child->clip_rect_);
child->ClipChildren();
}
}
UiElement* UiElement::FirstLaidOutChild() const { UiElement* UiElement::FirstLaidOutChild() const {
auto i = std::find_if( auto i = std::find_if(
children_.begin(), children_.end(), children_.begin(), children_.end(),
......
...@@ -166,7 +166,7 @@ class UiElement : public cc::AnimationTarget { ...@@ -166,7 +166,7 @@ class UiElement : public cc::AnimationTarget {
// shapes. Points within the rectangular area are mapped from 0:1 as follows, // shapes. Points within the rectangular area are mapped from 0:1 as follows,
// though will extend outside this range when outside of the element: // though will extend outside this range when outside of the element:
// [(0.0, 0.0), (1.0, 0.0) // [(0.0, 0.0), (1.0, 0.0)
// (1.0, 0.0), (1.0, 1.0)] // (0.0, 1.0), (1.0, 1.0)]
virtual bool LocalHitTest(const gfx::PointF& point) const; virtual bool LocalHitTest(const gfx::PointF& point) const;
// Performs a hit test for the ray supplied in the request and populates the // Performs a hit test for the ray supplied in the request and populates the
...@@ -225,6 +225,9 @@ class UiElement : public cc::AnimationTarget { ...@@ -225,6 +225,9 @@ class UiElement : public cc::AnimationTarget {
void SetSize(float width, float hight); void SetSize(float width, float hight);
virtual void OnSetSize(const gfx::SizeF& size); virtual void OnSetSize(const gfx::SizeF& size);
gfx::RectF clip_rect() const { return clip_rect_; }
void set_clip_rect_for_test(const gfx::RectF& rect) { clip_rect_ = rect; }
gfx::PointF local_origin() const { return local_origin_; } gfx::PointF local_origin() const { return local_origin_; }
// These are convenience functions for setting the transform operations. They // These are convenience functions for setting the transform operations. They
...@@ -412,6 +415,10 @@ class UiElement : public cc::AnimationTarget { ...@@ -412,6 +415,10 @@ class UiElement : public cc::AnimationTarget {
// applies anchoring. // applies anchoring.
virtual void LayOutChildren(); virtual void LayOutChildren();
// Recursive method that clips element subtrees, given that a parent is
// clipped.
void ClipChildren();
UiElement* FirstLaidOutChild() const; UiElement* FirstLaidOutChild() const;
UiElement* LastLaidOutChild() const; UiElement* LastLaidOutChild() const;
...@@ -462,7 +469,10 @@ class UiElement : public cc::AnimationTarget { ...@@ -462,7 +469,10 @@ class UiElement : public cc::AnimationTarget {
// that override element hover and click methods must manage their own sounds. // that override element hover and click methods must manage their own sounds.
void SetSounds(Sounds sounds, AudioDelegate* delegate); void SetSounds(Sounds sounds, AudioDelegate* delegate);
bool resizable_by_layout() { return resizable_by_layout_; } bool clips_descendants() const { return clips_descendants_; }
void set_clip_descendants(bool clips) { clips_descendants_ = clips; }
bool resizable_by_layout() const { return resizable_by_layout_; }
void set_resizable_by_layout(bool resizable) { void set_resizable_by_layout(bool resizable) {
resizable_by_layout_ = resizable; resizable_by_layout_ = resizable;
} }
...@@ -518,6 +528,13 @@ class UiElement : public cc::AnimationTarget { ...@@ -518,6 +528,13 @@ class UiElement : public cc::AnimationTarget {
// The size of the object. This does not affect children. // The size of the object. This does not affect children.
gfx::SizeF size_; gfx::SizeF size_;
// The clip of the object. The rect is in relation to the element's size,
// with the origin at its center.
gfx::RectF clip_rect_;
// Indicates that this element clips its descendants with its size.
bool clips_descendants_ = false;
// The local orgin of the element. This can be updated, say, so that an // The local orgin of the element. This can be updated, say, so that an
// element can contain its children, even if they are not centered about its // element can contain its children, even if they are not centered about its
// true origin. // true origin.
......
...@@ -333,7 +333,7 @@ TEST(UiElement, HitTest) { ...@@ -333,7 +333,7 @@ TEST(UiElement, HitTest) {
{gfx::PointF(-0.1f, -0.1f), false, false, false}, {gfx::PointF(-0.1f, -0.1f), false, false, false},
}; };
for (size_t i = 0; i < arraysize(test_cases); ++i) { for (size_t i = 0; i < base::size(test_cases); ++i) {
SCOPED_TRACE(i); SCOPED_TRACE(i);
EXPECT_EQ(test_cases[i].expected_rect, EXPECT_EQ(test_cases[i].expected_rect,
rect.LocalHitTest(test_cases[i].location)); rect.LocalHitTest(test_cases[i].location));
...@@ -344,6 +344,37 @@ TEST(UiElement, HitTest) { ...@@ -344,6 +344,37 @@ TEST(UiElement, HitTest) {
} }
} }
TEST(UiElement, HitTestWithClip) {
UiElement rect;
rect.SetSize(1.0, 1.0);
// A horizontal band in the middle.
rect.set_clip_rect_for_test({-0.5f, 0.2f, 1.0f, 0.4f});
struct {
gfx::PointF location;
bool expected;
} test_cases[] = {
// Vertical walk.
{{0.5f, 0.0f}, false},
{{0.5f, 0.2f}, false},
{{0.5f, 0.4f}, true},
{{0.5f, 0.6f}, true},
{{0.5f, 0.8f}, false},
{{0.5f, 1.0f}, false},
// Horizontal walk.
{{0.0f, 0.5f}, true},
{{0.2f, 0.5f}, true},
{{0.4f, 0.5f}, true},
{{0.6f, 0.5f}, true},
{{0.8f, 0.5f}, true},
};
for (size_t i = 0; i < base::size(test_cases); ++i) {
SCOPED_TRACE(i);
EXPECT_EQ(test_cases[i].expected,
rect.LocalHitTest(test_cases[i].location));
}
}
class ElementEventHandlers { class ElementEventHandlers {
public: public:
explicit ElementEventHandlers(UiElement* element) { explicit ElementEventHandlers(UiElement* element) {
...@@ -429,4 +460,27 @@ TEST(UiElement, EventBubbling) { ...@@ -429,4 +460,27 @@ TEST(UiElement, EventBubbling) {
element_handlers.ExpectCalled(false); element_handlers.ExpectCalled(false);
} }
// The clip rect is properly transformed into the child's coordinates.
TEST(UiElement, ClipChildren) {
auto parent = std::make_unique<UiElement>();
parent->SetSize(16.0f, 8.0f);
parent->set_clip_descendants(true);
auto child = std::make_unique<UiElement>();
child->SetSize(4.0f, 4.0f);
child->set_y_anchoring(TOP);
auto* p_child = child.get();
parent->AddChild(std::move(child));
parent->SizeAndLayOut();
EXPECT_FLOAT_RECT_EQ(gfx::RectF(-8.0f, 0.0f, 16.0f, 8.0f),
p_child->clip_rect());
p_child->SetScale(0.5f, 0.5f, 1.0f);
parent->DoLayOutChildren();
parent->ClipChildren();
EXPECT_FLOAT_RECT_EQ(gfx::RectF(-16.0f, 0.0f, 32.0f, 16.0f),
p_child->clip_rect());
}
} // namespace vr } // namespace vr
...@@ -27,6 +27,7 @@ BaseRenderer::BaseRenderer(const char* vertex_src, const char* fragment_src) { ...@@ -27,6 +27,7 @@ BaseRenderer::BaseRenderer(const char* vertex_src, const char* fragment_src) {
glDeleteShader(fragment_shader_handle); glDeleteShader(fragment_shader_handle);
position_handle_ = glGetAttribLocation(program_handle_, "a_Position"); position_handle_ = glGetAttribLocation(program_handle_, "a_Position");
clip_rect_handle_ = glGetUniformLocation(program_handle_, "u_ClipRect");
} }
BaseRenderer::~BaseRenderer() = default; BaseRenderer::~BaseRenderer() = default;
......
...@@ -23,6 +23,8 @@ class BaseRenderer { ...@@ -23,6 +23,8 @@ class BaseRenderer {
GLuint program_handle_ = 0; GLuint program_handle_ = 0;
GLuint position_handle_ = 0; GLuint position_handle_ = 0;
GLuint clip_rect_handle_ = 0;
DISALLOW_COPY_AND_ASSIGN(BaseRenderer); DISALLOW_COPY_AND_ASSIGN(BaseRenderer);
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "chrome/browser/vr/elements/corner_radii.h" #include "chrome/browser/vr/elements/corner_radii.h"
#include "chrome/browser/vr/renderers/textured_quad_renderer.h" #include "chrome/browser/vr/renderers/textured_quad_renderer.h"
#include "chrome/browser/vr/vr_gl_util.h" #include "chrome/browser/vr/vr_gl_util.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size_f.h" #include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
...@@ -37,6 +38,7 @@ static constexpr char const* kVertexShader = SHADER( ...@@ -37,6 +38,7 @@ static constexpr char const* kVertexShader = SHADER(
attribute vec2 a_CornerPosition; attribute vec2 a_CornerPosition;
attribute vec2 a_OffsetScale; attribute vec2 a_OffsetScale;
varying vec2 v_CornerPosition; varying vec2 v_CornerPosition;
varying vec2 v_TexCoordinate;
varying vec2 v_Position; varying vec2 v_Position;
void main() { void main() {
...@@ -61,6 +63,7 @@ static constexpr char const* kVertexShader = SHADER( ...@@ -61,6 +63,7 @@ static constexpr char const* kVertexShader = SHADER(
} else { } else {
v_Position = vec2(position.x * u_AspectRatio, position.y); v_Position = vec2(position.x * u_AspectRatio, position.y);
} }
v_TexCoordinate = vec2(0.5 + position[0], 0.5 - position[1]);
gl_Position = u_ModelViewProjMatrix * position; gl_Position = u_ModelViewProjMatrix * position;
} }
); );
...@@ -69,10 +72,17 @@ static constexpr char const* kFragmentShader = SHADER( ...@@ -69,10 +72,17 @@ static constexpr char const* kFragmentShader = SHADER(
precision highp float; precision highp float;
varying vec2 v_CornerPosition; varying vec2 v_CornerPosition;
varying vec2 v_Position; varying vec2 v_Position;
varying vec2 v_TexCoordinate;
uniform mediump float u_Opacity; uniform mediump float u_Opacity;
uniform vec2 u_ClipRect[2];
uniform vec4 u_CenterColor; uniform vec4 u_CenterColor;
uniform vec4 u_EdgeColor; uniform vec4 u_EdgeColor;
void main() { void main() {
vec2 s = step(u_ClipRect[0], v_TexCoordinate)
- step(u_ClipRect[1], v_TexCoordinate);
float insideClip = s.x * s.y;
vec2 position = v_Position; vec2 position = v_Position;
float edge_color_weight = clamp(2.0 * length(position), 0.0, 1.0); float edge_color_weight = clamp(2.0 * length(position), 0.0, 1.0);
float center_color_weight = 1.0 - edge_color_weight; float center_color_weight = 1.0 - edge_color_weight;
...@@ -84,7 +94,7 @@ static constexpr char const* kFragmentShader = SHADER( ...@@ -84,7 +94,7 @@ static constexpr char const* kFragmentShader = SHADER(
color = color + n; color = color + n;
color = vec4(color.rgb * color.a, color.a); color = vec4(color.rgb * color.a, color.a);
gl_FragColor = color * u_Opacity * mask; gl_FragColor = insideClip * color * u_Opacity * mask;
} }
); );
// clang-format on // clang-format on
...@@ -124,6 +134,7 @@ GradientQuadRenderer::~GradientQuadRenderer() = default; ...@@ -124,6 +134,7 @@ GradientQuadRenderer::~GradientQuadRenderer() = default;
void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix, void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
SkColor edge_color, SkColor edge_color,
SkColor center_color, SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& radii) { const CornerRadii& radii) {
...@@ -132,6 +143,9 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix, ...@@ -132,6 +143,9 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
SkColorGetA(center_color) == SK_AlphaTRANSPARENT) { SkColorGetA(center_color) == SK_AlphaTRANSPARENT) {
return; return;
} }
auto tex_clip_rect = CalculateTexSpaceRect(element_size, clip_rect);
if (!tex_clip_rect.Intersects({0.0f, 0.0f, 1.0f, 1.0f}))
return;
glUseProgram(program_handle_); glUseProgram(program_handle_);
...@@ -171,6 +185,11 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix, ...@@ -171,6 +185,11 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false, glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
MatrixToGLArray(model_view_proj_matrix).data()); MatrixToGLArray(model_view_proj_matrix).data());
const GLfloat clip_rect_data[4] = {tex_clip_rect.x(), tex_clip_rect.y(),
tex_clip_rect.right(),
tex_clip_rect.bottom()};
glUniform2fv(clip_rect_handle_, 2, clip_rect_data);
if (radii.IsZero()) { if (radii.IsZero()) {
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
VOID_OFFSET(kInnerRectOffset)); VOID_OFFSET(kInnerRectOffset));
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
namespace gfx { namespace gfx {
class SizeF; class SizeF;
class Transform; class Transform;
class RectF;
} // namespace gfx } // namespace gfx
namespace vr { namespace vr {
...@@ -27,6 +28,7 @@ class GradientQuadRenderer : public BaseRenderer { ...@@ -27,6 +28,7 @@ class GradientQuadRenderer : public BaseRenderer {
void Draw(const gfx::Transform& model_view_proj_matrix, void Draw(const gfx::Transform& model_view_proj_matrix,
SkColor edge_color, SkColor edge_color,
SkColor center_color, SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& radii); const CornerRadii& radii);
......
...@@ -142,18 +142,20 @@ static constexpr char const* kFragmentShader = SHADER( ...@@ -142,18 +142,20 @@ static constexpr char const* kFragmentShader = SHADER(
precision highp float; precision highp float;
uniform sampler2D u_Texture; uniform sampler2D u_Texture;
uniform sampler2D u_OverlayTexture; uniform sampler2D u_OverlayTexture;
uniform vec4 u_CopyRect; uniform vec2 u_ClipRect[2];
varying vec2 v_TexCoordinate; varying vec2 v_TexCoordinate;
varying vec2 v_CornerPosition; varying vec2 v_CornerPosition;
uniform mediump float u_Opacity; uniform mediump float u_Opacity;
uniform mediump float u_OverlayOpacity; uniform mediump float u_OverlayOpacity;
void main() { void main() {
vec2 scaledTex = vec2 s = step(u_ClipRect[0], v_TexCoordinate)
vec2(u_CopyRect[0] + v_TexCoordinate.x * u_CopyRect[2], - step(u_ClipRect[1], v_TexCoordinate);
u_CopyRect[1] + v_TexCoordinate.y * u_CopyRect[3]); float insideClip = s.x * s.y;
lowp vec4 color = texture2D(u_Texture, scaledTex);
lowp vec4 color = texture2D(u_Texture, v_TexCoordinate);
float mask = 1.0 - step(1.0, length(v_CornerPosition)); float mask = 1.0 - step(1.0, length(v_CornerPosition));
gl_FragColor = color * u_Opacity * mask; gl_FragColor = insideClip * color * u_Opacity * mask;
} }
); );
// clang-format on // clang-format on
...@@ -174,8 +176,6 @@ TexturedQuadRenderer::TexturedQuadRenderer(const char* vertex_src, ...@@ -174,8 +176,6 @@ TexturedQuadRenderer::TexturedQuadRenderer(const char* vertex_src,
glGetAttribLocation(program_handle_, "a_CornerPosition"); glGetAttribLocation(program_handle_, "a_CornerPosition");
offset_scale_handle_ = glGetAttribLocation(program_handle_, "a_OffsetScale"); offset_scale_handle_ = glGetAttribLocation(program_handle_, "a_OffsetScale");
copy_rect_handler_ = glGetUniformLocation(program_handle_, "u_CopyRect");
opacity_handle_ = glGetUniformLocation(program_handle_, "u_Opacity"); opacity_handle_ = glGetUniformLocation(program_handle_, "u_Opacity");
overlay_opacity_handle_ = overlay_opacity_handle_ =
glGetUniformLocation(program_handle_, "u_OverlayOpacity"); glGetUniformLocation(program_handle_, "u_OverlayOpacity");
...@@ -190,7 +190,7 @@ TexturedQuadRenderer::~TexturedQuadRenderer() = default; ...@@ -190,7 +190,7 @@ TexturedQuadRenderer::~TexturedQuadRenderer() = default;
void TexturedQuadRenderer::AddQuad(int texture_data_handle, void TexturedQuadRenderer::AddQuad(int texture_data_handle,
int overlay_texture_data_handle, int overlay_texture_data_handle,
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -199,11 +199,12 @@ void TexturedQuadRenderer::AddQuad(int texture_data_handle, ...@@ -199,11 +199,12 @@ void TexturedQuadRenderer::AddQuad(int texture_data_handle,
quad.texture_data_handle = texture_data_handle; quad.texture_data_handle = texture_data_handle;
quad.overlay_texture_data_handle = overlay_texture_data_handle; quad.overlay_texture_data_handle = overlay_texture_data_handle;
quad.model_view_proj_matrix = model_view_proj_matrix; quad.model_view_proj_matrix = model_view_proj_matrix;
quad.copy_rect = copy_rect; quad.clip_rect = CalculateTexSpaceRect(element_size, clip_rect);
quad.opacity = opacity; quad.opacity = opacity;
quad.element_size = element_size; quad.element_size = element_size;
quad.corner_radius = corner_radius; quad.corner_radius = corner_radius;
quad.blend = blend; quad.blend = blend;
if (quad.clip_rect.Intersects({0.0f, 0.0f, 1.0f, 1.0f}))
quad_queue_.push(quad); quad_queue_.push(quad);
} }
...@@ -216,7 +217,7 @@ void TexturedQuadRenderer::Flush() { ...@@ -216,7 +217,7 @@ void TexturedQuadRenderer::Flush() {
float last_opacity = -1.0f; float last_opacity = -1.0f;
gfx::SizeF last_element_size; gfx::SizeF last_element_size;
float last_corner_radius = -1.0f; float last_corner_radius = -1.0f;
gfx::RectF last_copy_rect; gfx::RectF last_clip_rect;
bool last_blend = true; // All elements blend by default. bool last_blend = true; // All elements blend by default.
// Set up GL state that doesn't change between draw calls. // Set up GL state that doesn't change between draw calls.
...@@ -306,10 +307,12 @@ void TexturedQuadRenderer::Flush() { ...@@ -306,10 +307,12 @@ void TexturedQuadRenderer::Flush() {
glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false, glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
MatrixToGLArray(quad.model_view_proj_matrix).data()); MatrixToGLArray(quad.model_view_proj_matrix).data());
if (last_copy_rect != quad.copy_rect) { if (last_clip_rect != quad.clip_rect) {
last_copy_rect = quad.copy_rect; last_clip_rect = quad.clip_rect;
glUniform4f(copy_rect_handler_, quad.copy_rect.x(), quad.copy_rect.y(), const GLfloat clip_rect_data[4] = {quad.clip_rect.x(), quad.clip_rect.y(),
quad.copy_rect.width(), quad.copy_rect.height()); quad.clip_rect.right(),
quad.clip_rect.bottom()};
glUniform2fv(clip_rect_handle_, 2, clip_rect_data);
} }
if (quad.corner_radius == 0.0f) { if (quad.corner_radius == 0.0f) {
......
...@@ -26,7 +26,7 @@ class TexturedQuadRenderer : public BaseRenderer { ...@@ -26,7 +26,7 @@ class TexturedQuadRenderer : public BaseRenderer {
void AddQuad(int texture_data_handle, void AddQuad(int texture_data_handle,
int overlay_texture_data_handle, int overlay_texture_data_handle,
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -48,7 +48,7 @@ class TexturedQuadRenderer : public BaseRenderer { ...@@ -48,7 +48,7 @@ class TexturedQuadRenderer : public BaseRenderer {
int texture_data_handle; int texture_data_handle;
int overlay_texture_data_handle; int overlay_texture_data_handle;
gfx::Transform model_view_proj_matrix; gfx::Transform model_view_proj_matrix;
gfx::RectF copy_rect; gfx::RectF clip_rect;
float opacity; float opacity;
gfx::SizeF element_size; gfx::SizeF element_size;
float corner_radius; float corner_radius;
...@@ -65,7 +65,6 @@ class TexturedQuadRenderer : public BaseRenderer { ...@@ -65,7 +65,6 @@ class TexturedQuadRenderer : public BaseRenderer {
GLuint overlay_opacity_handle_; GLuint overlay_opacity_handle_;
GLuint texture_handle_; GLuint texture_handle_;
GLuint overlay_texture_handle_; GLuint overlay_texture_handle_;
GLuint copy_rect_handler_;
// Attributes // Attributes
GLuint corner_position_handle_; GLuint corner_position_handle_;
......
...@@ -16,7 +16,7 @@ void FakeUiElementRenderer::DrawTexturedQuad( ...@@ -16,7 +16,7 @@ void FakeUiElementRenderer::DrawTexturedQuad(
int overlay_texture_data_handle, int overlay_texture_data_handle,
TextureLocation texture_location, TextureLocation texture_location,
const gfx::Transform& view_proj_matrix, const gfx::Transform& view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -29,6 +29,7 @@ void FakeUiElementRenderer::DrawGradientQuad( ...@@ -29,6 +29,7 @@ void FakeUiElementRenderer::DrawGradientQuad(
const gfx::Transform& view_proj_matrix, const gfx::Transform& view_proj_matrix,
const SkColor edge_color, const SkColor edge_color,
const SkColor center_color, const SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& corner_radii) { const CornerRadii& corner_radii) {
......
...@@ -22,7 +22,7 @@ class FakeUiElementRenderer : public UiElementRenderer { ...@@ -22,7 +22,7 @@ class FakeUiElementRenderer : public UiElementRenderer {
int overlay_texture_data_handle, int overlay_texture_data_handle,
TextureLocation texture_location, TextureLocation texture_location,
const gfx::Transform& view_proj_matrix, const gfx::Transform& view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -31,6 +31,7 @@ class FakeUiElementRenderer : public UiElementRenderer { ...@@ -31,6 +31,7 @@ class FakeUiElementRenderer : public UiElementRenderer {
void DrawGradientQuad(const gfx::Transform& view_proj_matrix, void DrawGradientQuad(const gfx::Transform& view_proj_matrix,
const SkColor edge_color, const SkColor edge_color,
const SkColor center_color, const SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& corner_radii) override; const CornerRadii& corner_radii) override;
......
...@@ -58,7 +58,7 @@ void UiElementRenderer::DrawTexturedQuad( ...@@ -58,7 +58,7 @@ void UiElementRenderer::DrawTexturedQuad(
int overlay_texture_data_handle, int overlay_texture_data_handle,
TextureLocation texture_location, TextureLocation texture_location,
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -79,7 +79,7 @@ void UiElementRenderer::DrawTexturedQuad( ...@@ -79,7 +79,7 @@ void UiElementRenderer::DrawTexturedQuad(
} }
FlushIfNecessary(renderer); FlushIfNecessary(renderer);
renderer->AddQuad(texture_data_handle, overlay_texture_data_handle, renderer->AddQuad(texture_data_handle, overlay_texture_data_handle,
model_view_proj_matrix, copy_rect, opacity, element_size, model_view_proj_matrix, clip_rect, opacity, element_size,
corner_radius, blend); corner_radius, blend);
} }
...@@ -87,13 +87,15 @@ void UiElementRenderer::DrawGradientQuad( ...@@ -87,13 +87,15 @@ void UiElementRenderer::DrawGradientQuad(
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const SkColor edge_color, const SkColor edge_color,
const SkColor center_color, const SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& radii) { const CornerRadii& radii) {
TRACE_EVENT0("gpu", "UiElementRenderer::DrawGradientQuad"); TRACE_EVENT0("gpu", "UiElementRenderer::DrawGradientQuad");
FlushIfNecessary(gradient_quad_renderer_.get()); FlushIfNecessary(gradient_quad_renderer_.get());
gradient_quad_renderer_->Draw(model_view_proj_matrix, edge_color, gradient_quad_renderer_->Draw(model_view_proj_matrix, edge_color,
center_color, opacity, element_size, radii); center_color, clip_rect, opacity, element_size,
radii);
} }
void UiElementRenderer::DrawGradientGridQuad( void UiElementRenderer::DrawGradientGridQuad(
......
...@@ -64,7 +64,7 @@ class UiElementRenderer { ...@@ -64,7 +64,7 @@ class UiElementRenderer {
int overlay_texture_data_handle, int overlay_texture_data_handle,
TextureLocation texture_location, TextureLocation texture_location,
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect, const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
float corner_radius, float corner_radius,
...@@ -73,6 +73,7 @@ class UiElementRenderer { ...@@ -73,6 +73,7 @@ class UiElementRenderer {
const gfx::Transform& model_view_proj_matrix, const gfx::Transform& model_view_proj_matrix,
const SkColor edge_color, const SkColor edge_color,
const SkColor center_color, const SkColor center_color,
const gfx::RectF& clip_rect,
float opacity, float opacity,
const gfx::SizeF& element_size, const gfx::SizeF& element_size,
const CornerRadii& radii); const CornerRadii& radii);
......
...@@ -27,6 +27,19 @@ gfx::Rect CalculatePixelSpaceRect(const gfx::Size& texture_size, ...@@ -27,6 +27,19 @@ gfx::Rect CalculatePixelSpaceRect(const gfx::Size& texture_size,
return gfx::Rect(rect.x(), rect.y(), rect.width(), rect.height()); return gfx::Rect(rect.x(), rect.y(), rect.width(), rect.height());
} }
gfx::RectF CalculateTexSpaceRect(const gfx::SizeF& element_size,
const gfx::RectF& rect) {
if (rect.IsEmpty())
return {0.0f, 0.0f, 1.0f, 1.0f};
auto new_origin =
rect.origin() - gfx::Vector2dF(-element_size.width() * 0.5f,
element_size.height() * 0.5f);
new_origin.set_y(-new_origin.y());
gfx::RectF result(new_origin, rect.size());
result.Scale(1.0f / element_size.width(), 1.0f / element_size.height());
return result;
}
GLuint CompileShader(GLenum shader_type, GLuint CompileShader(GLenum shader_type,
const GLchar* shader_source, const GLchar* shader_source,
std::string& error) { std::string& error) {
......
...@@ -31,6 +31,9 @@ std::array<float, 16> MatrixToGLArray(const gfx::Transform& matrix); ...@@ -31,6 +31,9 @@ std::array<float, 16> MatrixToGLArray(const gfx::Transform& matrix);
gfx::Rect CalculatePixelSpaceRect(const gfx::Size& texture_size, gfx::Rect CalculatePixelSpaceRect(const gfx::Size& texture_size,
const gfx::RectF& texture_rect); const gfx::RectF& texture_rect);
gfx::RectF CalculateTexSpaceRect(const gfx::SizeF& element_size,
const gfx::RectF& rect);
// Compile a shader. // Compile a shader.
GLuint CompileShader(GLenum shader_type, GLuint CompileShader(GLenum shader_type,
const GLchar* shader_source, const GLchar* shader_source,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment