Commit f2ac1860 authored by Ian Vollick's avatar Ian Vollick Committed by Commit Bot

[vr] Add support for setting different corner radii for Rects

With this change, rects can now have individually configurable corner
radii. This does not apply to textured quads, and the utility for this
is not as clear.

(Also converts a few arguments to const refs and updates shadow to set
the corner radius automatically).

Bug: 782703
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Id49a1cce69dc59178c1b4a8ce15df8f8016bf709
Reviewed-on: https://chromium-review.googlesource.com/827026
Commit-Queue: Ian Vollick <vollick@chromium.org>
Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524094}
parent cea8306d
......@@ -41,6 +41,7 @@ static_library("vr_common") {
"elements/content_element.h",
"elements/controller.cc",
"elements/controller.h",
"elements/corner_radii.h",
"elements/draw_phase.cc",
"elements/draw_phase.h",
"elements/exclusive_screen_toast_texture.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_ELEMENTS_CORNER_RADII_H_
#define CHROME_BROWSER_VR_ELEMENTS_CORNER_RADII_H_
#include <algorithm>
namespace vr {
struct CornerRadii {
float upper_left;
float upper_right;
float lower_left;
float lower_right;
bool IsZero() const {
return upper_right == 0.0f && upper_left == 0.0f && lower_right == 0.0f &&
lower_left == 0.0f;
}
bool AllEqual() const {
return upper_left == upper_right && upper_left == lower_right &&
upper_left == lower_left;
}
float MaxRadius() const {
return std::max(upper_left,
std::max(upper_right, std::max(lower_left, lower_right)));
}
};
} // namespace vr
#endif // CHROME_BROWSER_VR_ELEMENTS_CORNER_RADII_H_
......@@ -17,7 +17,7 @@ void FullScreenRect::Render(UiElementRenderer* renderer,
gfx::Transform m;
m.Scale3d(2.0f, 2.0f, 1.0f);
renderer->DrawGradientQuad(m, edge_color(), center_color(),
computed_opacity(), size(), corner_radius());
computed_opacity(), size(), corner_radii());
}
bool FullScreenRect::IsWorldPositioned() const {
......
......@@ -43,7 +43,7 @@ void Rect::NotifyClientColorAnimated(SkColor color,
void Rect::Render(UiElementRenderer* renderer, const CameraModel& model) const {
renderer->DrawGradientQuad(model.view_proj_matrix * world_space_transform(),
edge_color_, center_color_, computed_opacity(),
size(), corner_radius());
size(), corner_radii());
}
} // namespace vr
......@@ -146,6 +146,8 @@ void Shadow::LayOutChildren() {
kXMaxShadowGradientFactor),
gfx::Tween::FloatValueBetween(depth_, kYMinShadowGradientFactor,
kYMaxShadowGradientFactor));
if (children().size() == 1u)
set_corner_radius(children().front()->corner_radii().MaxRadius());
}
Shadow::Renderer::Renderer()
......
......@@ -120,7 +120,7 @@ gfx::RectF Text::GetCursorBounds() const {
bounds.height() * scale * kCursorWidthRatio, bounds.height() * scale);
}
void Text::OnSetSize(gfx::SizeF size) {
void Text::OnSetSize(const gfx::SizeF& size) {
texture_->SetTextWidth(size.width());
}
......
......@@ -45,7 +45,7 @@ class Text : public TexturedElement {
// texture size, relative to the upper-left corner of the element.
gfx::RectF GetCursorBounds() const;
void OnSetSize(gfx::SizeF size) override;
void OnSetSize(const gfx::SizeF& size) override;
std::vector<std::unique_ptr<gfx::RenderText>> LayOutTextForTest(
const gfx::Size& texture_size);
......
......@@ -142,7 +142,7 @@ bool TextInput::OnBeginFrame(const base::TimeTicks& time,
return SetCursorBlinkState(time);
}
void TextInput::OnSetSize(gfx::SizeF size) {
void TextInput::OnSetSize(const gfx::SizeF& size) {
hint_element_->SetSize(size.width(), size.height());
text_element_->SetSize(size.width(), size.height());
}
......
......@@ -55,7 +55,7 @@ class TextInput : public UiElement {
bool OnBeginFrame(const base::TimeTicks& time,
const gfx::Vector3dF& look_at) final;
void OnSetSize(gfx::SizeF size) final;
void OnSetSize(const gfx::SizeF& size) final;
void OnSetName() final;
Text* get_hint_element() { return hint_element_; }
......
......@@ -203,7 +203,7 @@ void UiElement::SetSize(float width, float height) {
OnSetSize(gfx::SizeF(width, height));
}
void UiElement::OnSetSize(gfx::SizeF size) {}
void UiElement::OnSetSize(const gfx::SizeF& size) {}
void UiElement::SetVisible(bool visible) {
SetOpacity(visible ? opacity_when_visible_ : 0.0);
......@@ -314,18 +314,21 @@ bool UiElement::LocalHitTest(const gfx::PointF& point) const {
if (point.x() < 0.0f || point.x() > 1.0f || point.y() < 0.0f ||
point.y() > 1.0f) {
return false;
} else if (corner_radius() == 0.f) {
} else if (corner_radii_.IsZero()) {
return point.x() >= 0.0f && point.x() <= 1.0f && point.y() >= 0.0f &&
point.y() <= 1.0f;
} else if (size().width() == size().height() &&
corner_radius() == size().width() / 2) {
return (point - gfx::PointF(0.5, 0.5)).LengthSquared() < 0.25;
}
float width = size().width();
float height = size().height();
SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeWH(width, height),
corner_radius(), corner_radius());
SkRRect rrect;
SkVector radii[4] = {
{corner_radii_.upper_left, corner_radii_.upper_left},
{corner_radii_.upper_right, corner_radii_.upper_right},
{corner_radii_.lower_right, corner_radii_.lower_right},
{corner_radii_.lower_left, corner_radii_.lower_left},
};
rrect.setRectRadii(SkRect::MakeWH(width, height), radii);
float left = std::min(point.x() * width, width - kHitTestResolutionInMeter);
float top = std::min(point.y() * height, height - kHitTestResolutionInMeter);
......@@ -410,7 +413,7 @@ void UiElement::DumpHierarchy(std::vector<size_t> counts,
*os << DebugName() << kReset << " " << kCyan << DrawPhaseToString(draw_phase_)
<< " " << kReset;
if (draw_phase_ != kPhaseNone && !size().IsEmpty()) {
if (!size().IsEmpty()) {
*os << kRed << "[" << size().width() << ", " << size().height() << "] "
<< kReset;
}
......
......@@ -16,6 +16,7 @@
#include "cc/animation/transform_operations.h"
#include "chrome/browser/vr/animation_player.h"
#include "chrome/browser/vr/databinding/binding_base.h"
#include "chrome/browser/vr/elements/corner_radii.h"
#include "chrome/browser/vr/elements/draw_phase.h"
#include "chrome/browser/vr/elements/ui_element_iterator.h"
#include "chrome/browser/vr/elements/ui_element_name.h"
......@@ -218,7 +219,7 @@ class UiElement : public cc::AnimationTarget {
gfx::SizeF size() const;
void SetSize(float width, float hight);
virtual void OnSetSize(gfx::SizeF size);
virtual void OnSetSize(const gfx::SizeF& size);
gfx::PointF local_origin() const { return local_origin_; }
......@@ -239,9 +240,18 @@ class UiElement : public cc::AnimationTarget {
float opacity() const { return opacity_; }
virtual void SetOpacity(float opacity);
float corner_radius() const { return corner_radius_; }
CornerRadii corner_radii() const { return corner_radii_; }
void set_corner_radii(const CornerRadii& radii) { corner_radii_ = radii; }
float corner_radius() const {
DCHECK(corner_radii_.AllEqual());
return corner_radii_.upper_left;
}
// Syntax sugar for setting all corner radii to the same value.
void set_corner_radius(float corner_radius) {
corner_radius_ = corner_radius;
set_corner_radii(
{corner_radius, corner_radius, corner_radius, corner_radius});
}
float computed_opacity() const;
......@@ -459,7 +469,7 @@ class UiElement : public cc::AnimationTarget {
// The corner radius of the object. Analogous to the CSS property,
// border-radius. This is in meters (same units as |size|).
float corner_radius_ = 0.0f;
CornerRadii corner_radii_ = {0, 0, 0, 0};
// The computed opacity, incorporating opacity of parent objects.
float computed_opacity_ = 1.0f;
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/vr/renderers/gradient_quad_renderer.h"
#include "chrome/browser/vr/elements/corner_radii.h"
#include "chrome/browser/vr/renderers/textured_quad_renderer.h"
#include "chrome/browser/vr/vr_gl_util.h"
#include "ui/gfx/geometry/size_f.h"
......@@ -27,7 +28,10 @@ static constexpr size_t kInnerRectOffset = 6 * sizeof(GLushort);
static constexpr char const* kVertexShader = SHADER(
precision mediump float;
uniform mat4 u_ModelViewProjMatrix;
uniform vec2 u_CornerOffset;
uniform vec2 u_ULCornerOffset;
uniform vec2 u_URCornerOffset;
uniform vec2 u_LRCornerOffset;
uniform vec2 u_LLCornerOffset;
attribute vec4 a_Position;
attribute vec2 a_CornerPosition;
attribute vec2 a_OffsetScale;
......@@ -36,9 +40,19 @@ static constexpr char const* kVertexShader = SHADER(
void main() {
v_CornerPosition = a_CornerPosition;
vec2 corner_offset;
if (a_Position[0] < 0.0 && a_Position[1] > 0.0) {
corner_offset = u_ULCornerOffset;
} else if (a_Position[0] > 0.0 && a_Position[1] > 0.0) {
corner_offset = u_URCornerOffset;
} else if (a_Position[0] > 0.0 && a_Position[1] < 0.0) {
corner_offset = u_LRCornerOffset;
} else if (a_Position[0] < 0.0 && a_Position[1] < 0.0) {
corner_offset = u_LLCornerOffset;
}
vec4 position = vec4(
a_Position[0] + u_CornerOffset[0] * a_OffsetScale[0],
a_Position[1] + u_CornerOffset[1] * a_OffsetScale[1],
a_Position[0] + corner_offset[0] * a_OffsetScale[0],
a_Position[1] + corner_offset[1] * a_OffsetScale[1],
a_Position[2],
a_Position[3]);
v_Position = position.xy;
......@@ -73,14 +87,27 @@ static constexpr char const* kFragmentShader = SHADER(
);
// clang-format on
void SetCornerOffset(GLuint handle, float radius, const gfx::SizeF& size) {
if (radius == 0.0f)
glUniform2f(handle, 0.0, 0.0);
else
glUniform2f(handle, radius / size.width(), radius / size.height());
}
} // namespace
GradientQuadRenderer::GradientQuadRenderer()
: BaseRenderer(kVertexShader, kFragmentShader) {
model_view_proj_matrix_handle_ =
glGetUniformLocation(program_handle_, "u_ModelViewProjMatrix");
corner_offset_handle_ =
glGetUniformLocation(program_handle_, "u_CornerOffset");
ul_corner_offset_handle_ =
glGetUniformLocation(program_handle_, "u_ULCornerOffset");
ur_corner_offset_handle_ =
glGetUniformLocation(program_handle_, "u_URCornerOffset");
lr_corner_offset_handle_ =
glGetUniformLocation(program_handle_, "u_LRCornerOffset");
ll_corner_offset_handle_ =
glGetUniformLocation(program_handle_, "u_LLCornerOffset");
corner_position_handle_ =
glGetAttribLocation(program_handle_, "a_CornerPosition");
offset_scale_handle_ = glGetAttribLocation(program_handle_, "a_OffsetScale");
......@@ -96,7 +123,7 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
SkColor center_color,
float opacity,
const gfx::SizeF& element_size,
float corner_radius) {
const CornerRadii& radii) {
glUseProgram(program_handle_);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
......@@ -121,12 +148,10 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
VOID_OFFSET(kCornerPositionDataOffset));
glEnableVertexAttribArray(corner_position_handle_);
if (corner_radius == 0.0f) {
glUniform2f(corner_offset_handle_, 0.0, 0.0);
} else {
glUniform2f(corner_offset_handle_, corner_radius / element_size.width(),
corner_radius / element_size.height());
}
SetCornerOffset(ul_corner_offset_handle_, radii.upper_left, element_size);
SetCornerOffset(ur_corner_offset_handle_, radii.upper_right, element_size);
SetCornerOffset(lr_corner_offset_handle_, radii.lower_right, element_size);
SetCornerOffset(ll_corner_offset_handle_, radii.lower_left, element_size);
// Set the edge color to the fog color so that it seems to fade out.
SetColorUniform(edge_color_handle_, edge_color);
......@@ -137,7 +162,7 @@ void GradientQuadRenderer::Draw(const gfx::Transform& model_view_proj_matrix,
glUniformMatrix4fv(model_view_proj_matrix_handle_, 1, false,
MatrixToGLArray(model_view_proj_matrix).data());
if (corner_radius == 0.0f) {
if (radii.IsZero()) {
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT,
VOID_OFFSET(kInnerRectOffset));
} else {
......
......@@ -16,6 +16,8 @@ class Transform;
namespace vr {
struct CornerRadii;
class GradientQuadRenderer : public BaseRenderer {
public:
GradientQuadRenderer();
......@@ -26,11 +28,14 @@ class GradientQuadRenderer : public BaseRenderer {
SkColor center_color,
float opacity,
const gfx::SizeF& element_size,
float corner_radius);
const CornerRadii& radii);
private:
GLuint model_view_proj_matrix_handle_;
GLuint corner_offset_handle_;
GLuint ul_corner_offset_handle_;
GLuint ur_corner_offset_handle_;
GLuint lr_corner_offset_handle_;
GLuint ll_corner_offset_handle_;
GLuint corner_position_handle_;
GLuint offset_scale_handle_;
GLuint opacity_handle_;
......
......@@ -17,7 +17,7 @@ void FakeUiElementRenderer::DrawTexturedQuad(
const gfx::Transform& view_proj_matrix,
const gfx::RectF& copy_rect,
float opacity,
gfx::SizeF element_size,
const gfx::SizeF& element_size,
float corner_radius) {
opacity_ = opacity;
called_ = true;
......@@ -28,8 +28,8 @@ void FakeUiElementRenderer::DrawGradientQuad(
const SkColor edge_color,
const SkColor center_color,
float opacity,
gfx::SizeF element_size,
float corner_radius) {
const gfx::SizeF& element_size,
const CornerRadii& corner_radii) {
opacity_ = opacity;
called_ = true;
}
......
......@@ -23,15 +23,15 @@ class FakeUiElementRenderer : public UiElementRenderer {
const gfx::Transform& view_proj_matrix,
const gfx::RectF& copy_rect,
float opacity,
gfx::SizeF element_size,
const gfx::SizeF& element_size,
float corner_radius) override;
void DrawGradientQuad(const gfx::Transform& view_proj_matrix,
const SkColor edge_color,
const SkColor center_color,
float opacity,
gfx::SizeF element_size,
float corner_radius) override;
const gfx::SizeF& element_size,
const CornerRadii& corner_radii) override;
void DrawGradientGridQuad(const gfx::Transform& view_proj_matrix,
const SkColor edge_color,
......
......@@ -53,7 +53,7 @@ void UiElementRenderer::DrawTexturedQuad(
const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect,
float opacity,
gfx::SizeF element_size,
const gfx::SizeF& element_size,
float corner_radius) {
// TODO(vollick): handle drawing this degenerate situation crbug.com/768922
if (corner_radius * 2.0 > element_size.width() ||
......@@ -73,12 +73,11 @@ void UiElementRenderer::DrawGradientQuad(
const SkColor edge_color,
const SkColor center_color,
float opacity,
gfx::SizeF element_size,
float corner_radius) {
const gfx::SizeF& element_size,
const CornerRadii& radii) {
FlushIfNecessary(gradient_quad_renderer_.get());
gradient_quad_renderer_->Draw(model_view_proj_matrix, edge_color,
center_color, opacity, element_size,
corner_radius);
center_color, opacity, element_size, radii);
}
void UiElementRenderer::DrawGradientGridQuad(
......
......@@ -62,15 +62,15 @@ class UiElementRenderer {
const gfx::Transform& model_view_proj_matrix,
const gfx::RectF& copy_rect,
float opacity,
gfx::SizeF element_size,
const gfx::SizeF& element_size,
float corner_radius);
VIRTUAL_FOR_MOCKS void DrawGradientQuad(
const gfx::Transform& model_view_proj_matrix,
const SkColor edge_color,
const SkColor center_color,
float opacity,
gfx::SizeF element_size,
float corner_radius);
const gfx::SizeF& element_size,
const CornerRadii& radii);
VIRTUAL_FOR_MOCKS void DrawGradientGridQuad(
const gfx::Transform& model_view_proj_matrix,
const SkColor edge_color,
......
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