From a54da38a2d8b44643a70b1fbe8297f8fd2365f9c Mon Sep 17 00:00:00 2001 From: ccameron Date: Thu, 26 Nov 2015 16:52:33 -0800 Subject: Mac: Don't repaint scrollbars every frame The core issue here is that Blink, when it sees that it needs to change the scrollbar in any way (even just moving the thumb), uses the signal blink::Scrollbar::setNeedsPaintInvalidation(). This will trigger a call to cc::PaintedScrollbarLayer::Update(), which will re-paint all controls into textures and then emit quads the quads for the controls. We often only need to re-arrange the quads for the controls of the scrollbar, not re-paint them. The system that knows whether or not the controls need to be repainted is blink::ScrollbarTheme (because that's the code that knows the theme that will be used to do the painting). Add blink::ScrollbarTheme::shouldRepaintAllPartsOnInvalidation() to indicate if a call to blink::Scrollbar::setNeedsPaintInvalidation() should cause re-painting of all of the controls. If this returns false for a given theme, then methods blink::Scrollbar::setNeedsPaintTrack() and blink::Scrollbar::setNeedsPaintThumb() may be used to specify more granular control. Back in cc::PaintedScrollbarLayer::Update(), use the methods cc::Scrollbar::NeedsPaintPart() to check if re-paint is needed (it is hooked up to the bit that is set by the blink::Scrollbar methods). While we're in the neighborhood, it is worth noting that most of the repainting of scrollbars on Mac is due to the alpha of the thumb or the track changing. Add methods to blink::Scrollbar to query the opacity of the controls, so that we can do the blending at compositing time instead of requiring a repaint. And, while we're in that neighborhood, fix cc::CALayerOverlay's FromTextureQuad function to correctly take into account per-vertex opacity. BUG=549277 TEST= - Set the system to only show scrollbars while scrolling - Open a page with a vertical scrollbar - Scroll to make the scroll thumb appear - Hover the mouse somewhere below the thumb - The thumb should become thicker and the track should appear - After some time, the thumb and the track should fade away TEST= - Open a page with a scrollbar and search (command-F) for some text - Ensure that the ticks on the vertical scrollbar appear CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1458703010 Cr-Commit-Position: refs/heads/master@{#361938} --- cc/layers/painted_scrollbar_layer_unittest.cc | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 cc/layers/painted_scrollbar_layer_unittest.cc (limited to 'cc/layers/painted_scrollbar_layer_unittest.cc') diff --git a/cc/layers/painted_scrollbar_layer_unittest.cc b/cc/layers/painted_scrollbar_layer_unittest.cc new file mode 100644 index 0000000..ac814ee --- /dev/null +++ b/cc/layers/painted_scrollbar_layer_unittest.cc @@ -0,0 +1,87 @@ +// Copyright 2015 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. + +#include "cc/layers/painted_scrollbar_layer.h" + +#include "cc/layers/layer_settings.h" +#include "cc/test/fake_layer_tree_host.h" +#include "cc/test/fake_layer_tree_host_client.h" +#include "cc/test/fake_scrollbar.h" +#include "cc/test/test_task_graph_runner.h" +#include "testing/gmock/include/gmock/gmock.h" + +using ::testing::Mock; +using ::testing::_; + +namespace cc { + +namespace { + +class MockScrollbar : public FakeScrollbar { + public: + MockScrollbar() : FakeScrollbar(true, true, true) {} + MOCK_METHOD3(PaintPart, + void(SkCanvas* canvas, + ScrollbarPart part, + const gfx::Rect& content_rect)); +}; + +TEST(PaintedScrollbarLayerTest, NeedsPaint) { + FakeLayerTreeHostClient fake_client_(FakeLayerTreeHostClient::DIRECT_3D); + TestTaskGraphRunner task_graph_runner_; + scoped_ptr layer_tree_host_; + LayerSettings layer_settings_; + + layer_tree_host_ = + FakeLayerTreeHost::Create(&fake_client_, &task_graph_runner_); + RendererCapabilities renderer_capabilities; + renderer_capabilities.max_texture_size = 2048; + layer_tree_host_->set_renderer_capabilities(renderer_capabilities); + + MockScrollbar* scrollbar = new MockScrollbar(); + scoped_refptr scrollbar_layer = + PaintedScrollbarLayer::Create(layer_settings_, + scoped_ptr(scrollbar).Pass(), 1); + + scrollbar_layer->SetIsDrawable(true); + scrollbar_layer->SetBounds(gfx::Size(100, 100)); + + layer_tree_host_->SetRootLayer(scrollbar_layer); + EXPECT_EQ(scrollbar_layer->layer_tree_host(), layer_tree_host_.get()); + scrollbar_layer->SavePaintProperties(); + + // Request no paint, but expect them to be painted because they have not + // yet been initialized. + scrollbar->set_needs_paint_thumb(false); + scrollbar->set_needs_paint_track(false); + EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(1); + EXPECT_CALL(*scrollbar, PaintPart(_, TRACK, _)).Times(1); + scrollbar_layer->Update(); + Mock::VerifyAndClearExpectations(scrollbar); + + // The next update will paint nothing because the first update caused a paint. + EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(0); + EXPECT_CALL(*scrollbar, PaintPart(_, TRACK, _)).Times(0); + scrollbar_layer->Update(); + Mock::VerifyAndClearExpectations(scrollbar); + + // Enable the thumb. + EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(1); + EXPECT_CALL(*scrollbar, PaintPart(_, TRACK, _)).Times(0); + scrollbar->set_needs_paint_thumb(true); + scrollbar->set_needs_paint_track(false); + scrollbar_layer->Update(); + Mock::VerifyAndClearExpectations(scrollbar); + + // Enable the track. + EXPECT_CALL(*scrollbar, PaintPart(_, THUMB, _)).Times(0); + EXPECT_CALL(*scrollbar, PaintPart(_, TRACK, _)).Times(1); + scrollbar->set_needs_paint_thumb(false); + scrollbar->set_needs_paint_track(true); + scrollbar_layer->Update(); + Mock::VerifyAndClearExpectations(scrollbar); +} + +} // namespace +} // namespace cc -- cgit v1.1