Commit 7d84938b authored by Peter Kasting's avatar Peter Kasting Committed by Chromium LUCI CQ

Convert toolbar icon highlight animation from CPU to GPU.

This avoids destroying and recreating a border every animation tick as
well.  Hopefully this will reduce CPU usage a tiny bit.

Bug: 1114976
Change-Id: I3b2b29a2c8bd04fd7d38aaf69bb9988070826a11
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2596438
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838247}
parent fc114d63
...@@ -59,10 +59,7 @@ class ToolbarAccountIconContainerViewBrowserTest : public InProcessBrowserTest { ...@@ -59,10 +59,7 @@ class ToolbarAccountIconContainerViewBrowserTest : public InProcessBrowserTest {
} }
bool IsHighlighted(ToolbarAccountIconContainerView* container) { bool IsHighlighted(ToolbarAccountIconContainerView* container) {
if (container->highlight_animation_.IsClosing()) return container->border_.layer()->GetTargetOpacity() == 1;
return false;
return container->highlight_animation_.IsShowing() ||
container->highlight_animation_.GetCurrentValue() == 1.0f;
} }
private: private:
......
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h" #include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/layout/animating_layout_manager.h" #include "ui/views/layout/animating_layout_manager.h"
...@@ -24,6 +27,38 @@ ...@@ -24,6 +27,38 @@
const char ToolbarIconContainerView::kToolbarIconContainerViewClassName[] = const char ToolbarIconContainerView::kToolbarIconContainerViewClassName[] =
"ToolbarIconContainerView"; "ToolbarIconContainerView";
ToolbarIconContainerView::RoundRectBorder::RoundRectBorder(views::View* parent)
: parent_(parent) {
layer_.set_delegate(this);
layer_.SetFillsBoundsOpaquely(false);
layer_.SetFillsBoundsCompletely(false);
layer_.SetOpacity(0);
layer_.SetAnimator(ui::LayerAnimator::CreateImplicitAnimator());
layer_.GetAnimator()->set_tween_type(gfx::Tween::EASE_OUT);
layer_.SetVisible(true);
}
void ToolbarIconContainerView::RoundRectBorder::OnPaintLayer(
const ui::PaintContext& context) {
ui::PaintRecorder paint_recorder(context, layer_.size());
gfx::Canvas* canvas = paint_recorder.canvas();
const int radius = ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
views::EMPHASIS_MAXIMUM, layer_.size());
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(1);
flags.setColor(ToolbarButton::GetDefaultBorderColor(parent_));
gfx::RectF rect(gfx::SizeF(layer_.size()));
rect.Inset(0.5f, 0.5f); // Pixel edges -> pixel centers.
canvas->DrawRoundRect(rect, radius, flags);
}
void ToolbarIconContainerView::RoundRectBorder::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
float new_device_scale_factor) {}
// Watches for widget restore (or first show) and resets the animation so icons // Watches for widget restore (or first show) and resets the animation so icons
// don't spuriously "animate in" when a window is shown or restored. See // don't spuriously "animate in" when a window is shown or restored. See
// crbug.com/1106506 for more details. // crbug.com/1106506 for more details.
...@@ -71,6 +106,11 @@ class ToolbarIconContainerView::WidgetRestoreObserver ...@@ -71,6 +106,11 @@ class ToolbarIconContainerView::WidgetRestoreObserver
ToolbarIconContainerView::ToolbarIconContainerView(bool uses_highlight) ToolbarIconContainerView::ToolbarIconContainerView(bool uses_highlight)
: uses_highlight_(uses_highlight) { : uses_highlight_(uses_highlight) {
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
layer()->SetFillsBoundsCompletely(false);
AddLayerBeneathView(border_.layer());
views::AnimatingLayoutManager* animating_layout = views::AnimatingLayoutManager* animating_layout =
SetLayoutManager(std::make_unique<views::AnimatingLayoutManager>()); SetLayoutManager(std::make_unique<views::AnimatingLayoutManager>());
animating_layout->SetBoundsAnimationMode( animating_layout->SetBoundsAnimationMode(
...@@ -143,6 +183,13 @@ void ToolbarIconContainerView::OnViewBlurred(views::View* observed_view) { ...@@ -143,6 +183,13 @@ void ToolbarIconContainerView::OnViewBlurred(views::View* observed_view) {
UpdateHighlight(); UpdateHighlight();
} }
void ToolbarIconContainerView::OnBoundsChanged(
const gfx::Rect& previous_bounds) {
const gfx::Rect bounds = ConvertRectToWidget(GetLocalBounds());
border_.layer()->SetBounds(bounds);
border_.layer()->SchedulePaint(gfx::Rect(bounds.size()));
}
void ToolbarIconContainerView::OnMouseEntered(const ui::MouseEvent& event) { void ToolbarIconContainerView::OnMouseEntered(const ui::MouseEvent& event) {
UpdateHighlight(); UpdateHighlight();
} }
...@@ -151,13 +198,6 @@ void ToolbarIconContainerView::OnMouseExited(const ui::MouseEvent& event) { ...@@ -151,13 +198,6 @@ void ToolbarIconContainerView::OnMouseExited(const ui::MouseEvent& event) {
UpdateHighlight(); UpdateHighlight();
} }
gfx::Insets ToolbarIconContainerView::GetInsets() const {
// Use empty insets to have the border paint into the view instead of around
// it. This prevents inadvertently increasing its size while the stroke is
// drawn.
return gfx::Insets();
}
const char* ToolbarIconContainerView::GetClassName() const { const char* ToolbarIconContainerView::GetClassName() const {
return kToolbarIconContainerViewClassName; return kToolbarIconContainerViewClassName;
} }
...@@ -168,15 +208,6 @@ void ToolbarIconContainerView::AddedToWidget() { ...@@ -168,15 +208,6 @@ void ToolbarIconContainerView::AddedToWidget() {
restore_observer_ = std::make_unique<WidgetRestoreObserver>(this); restore_observer_ = std::make_unique<WidgetRestoreObserver>(this);
} }
void ToolbarIconContainerView::AnimationProgressed(
const gfx::Animation* animation) {
SetHighlightBorder();
}
void ToolbarIconContainerView::AnimationEnded(const gfx::Animation* animation) {
SetHighlightBorder();
}
bool ToolbarIconContainerView::ShouldDisplayHighlight() { bool ToolbarIconContainerView::ShouldDisplayHighlight() {
if (!uses_highlight_) if (!uses_highlight_)
return false; return false;
...@@ -206,35 +237,19 @@ bool ToolbarIconContainerView::ShouldDisplayHighlight() { ...@@ -206,35 +237,19 @@ bool ToolbarIconContainerView::ShouldDisplayHighlight() {
} }
void ToolbarIconContainerView::UpdateHighlight() { void ToolbarIconContainerView::UpdateHighlight() {
bool showing_before = highlight_animation_.IsShowing(); bool showing_before = border_.layer()->GetTargetOpacity() == 1;
if (ShouldDisplayHighlight()) { {
highlight_animation_.Show(); ui::ScopedLayerAnimationSettings settings(border_.layer()->GetAnimator());
} else { border_.layer()->SetOpacity(ShouldDisplayHighlight() ? 1 : 0);
highlight_animation_.Hide();
} }
if (showing_before == highlight_animation_.IsShowing()) if (showing_before == (border_.layer()->GetTargetOpacity() == 1))
return; return;
for (Observer& observer : observers_) for (Observer& observer : observers_)
observer.OnHighlightChanged(); observer.OnHighlightChanged();
} }
void ToolbarIconContainerView::SetHighlightBorder() {
const float highlight_value = highlight_animation_.GetCurrentValue();
if (highlight_value > 0.0f) {
SkColor border_color = ToolbarButton::GetDefaultBorderColor(this);
SetBorder(views::CreateRoundedRectBorder(
1,
ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
views::EMPHASIS_MAXIMUM, size()),
SkColorSetA(border_color,
SkColorGetA(border_color) * highlight_value)));
} else {
SetBorder(nullptr);
}
}
void ToolbarIconContainerView::OnButtonHighlightedChanged( void ToolbarIconContainerView::OnButtonHighlightedChanged(
views::Button* button) { views::Button* button) {
if (button->GetHighlighted()) if (button->GetHighlighted())
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <list> #include <list>
#include "base/observer_list.h" #include "base/observer_list.h"
#include "ui/gfx/animation/animation_delegate.h" #include "ui/compositor/layer_delegate.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/layout/animating_layout_manager.h" #include "ui/views/layout/animating_layout_manager.h"
#include "ui/views/layout/flex_layout.h" #include "ui/views/layout/flex_layout.h"
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
// A general view container for any type of toolbar icons. // A general view container for any type of toolbar icons.
class ToolbarIconContainerView : public views::View, class ToolbarIconContainerView : public views::View,
public gfx::AnimationDelegate,
public views::ViewObserver { public views::ViewObserver {
public: public:
class Observer : public base::CheckedObserver { class Observer : public base::CheckedObserver {
...@@ -66,24 +65,41 @@ class ToolbarIconContainerView : public views::View, ...@@ -66,24 +65,41 @@ class ToolbarIconContainerView : public views::View,
static const char kToolbarIconContainerViewClassName[]; static const char kToolbarIconContainerViewClassName[];
protected:
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
private: private:
friend class ToolbarAccountIconContainerViewBrowserTest; friend class ToolbarAccountIconContainerViewBrowserTest;
// Responsible for painting a roundrect border for the owning view.
class RoundRectBorder : public ui::LayerDelegate {
public:
explicit RoundRectBorder(views::View* parent);
RoundRectBorder(const RoundRectBorder&) = delete;
RoundRectBorder& operator=(const RoundRectBorder&) = delete;
ui::Layer* layer() { return &layer_; }
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override;
private:
views::View* parent_;
ui::Layer layer_;
};
class WidgetRestoreObserver; class WidgetRestoreObserver;
// views::View: // views::View:
void OnMouseEntered(const ui::MouseEvent& event) override; void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override; void OnMouseExited(const ui::MouseEvent& event) override;
gfx::Insets GetInsets() const override;
const char* GetClassName() const override; const char* GetClassName() const override;
void AddedToWidget() override; void AddedToWidget() override;
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
bool ShouldDisplayHighlight(); bool ShouldDisplayHighlight();
void UpdateHighlight(); void UpdateHighlight();
void SetHighlightBorder();
// Called by |button| when its ink drop highlighted state changes. // Called by |button| when its ink drop highlighted state changes.
void OnButtonHighlightedChanged(views::Button* button); void OnButtonHighlightedChanged(views::Button* button);
...@@ -104,8 +120,7 @@ class ToolbarIconContainerView : public views::View, ...@@ -104,8 +120,7 @@ class ToolbarIconContainerView : public views::View,
// them from this set. // them from this set.
std::set<views::Button*> highlighted_buttons_; std::set<views::Button*> highlighted_buttons_;
// Fade-in/out animation for the highlight border. RoundRectBorder border_{this};
gfx::SlideAnimation highlight_animation_{this};
// Tracks when the widget is restored and resets the layout. // Tracks when the widget is restored and resets the layout.
std::unique_ptr<WidgetRestoreObserver> restore_observer_; std::unique_ptr<WidgetRestoreObserver> restore_observer_;
......
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