summaryrefslogtreecommitdiff
path: root/cc
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-11-12 17:59:43 +0000
committerTorne (Richard Coles) <torne@google.com>2014-11-12 17:59:43 +0000
commit1850ca92fc5c5faa2907b3befcf40067265148cc (patch)
tree7d10585f25356b3ee63b5ab4255161fe27725ee4 /cc
parente9e1f6521e4fef99aa1a1928c70ef3dfb55a8d9e (diff)
downloadchromium_org-1850ca92fc5c5faa2907b3befcf40067265148cc.tar.gz
Merge from Chromium at DEPS revision 03655fd3f6d7
This commit was generated by merge_to_master.py. Change-Id: Ifba5396691b9164ba027be04398f7bc8e938750d
Diffstat (limited to 'cc')
-rw-r--r--cc/BUILD.gn2
-rw-r--r--cc/cc.gyp1
-rw-r--r--cc/cc.target.darwin-arm.mk1
-rw-r--r--cc/cc.target.darwin-arm64.mk1
-rw-r--r--cc/cc.target.darwin-mips.mk1
-rw-r--r--cc/cc.target.darwin-mips64.mk1
-rw-r--r--cc/cc.target.darwin-x86.mk1
-rw-r--r--cc/cc.target.darwin-x86_64.mk1
-rw-r--r--cc/cc.target.linux-arm.mk1
-rw-r--r--cc/cc.target.linux-arm64.mk1
-rw-r--r--cc/cc.target.linux-mips.mk1
-rw-r--r--cc/cc.target.linux-mips64.mk1
-rw-r--r--cc/cc.target.linux-x86.mk1
-rw-r--r--cc/cc.target.linux-x86_64.mk1
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/input/input_handler.cc13
-rw-r--r--cc/input/input_handler.h36
-rw-r--r--cc/layers/picture_layer.cc24
-rw-r--r--cc/layers/picture_layer_impl.cc11
-rw-r--r--cc/layers/picture_layer_impl_unittest.cc31
-rw-r--r--cc/layers/picture_layer_unittest.cc4
-rw-r--r--cc/layers/surface_layer.cc92
-rw-r--r--cc/layers/surface_layer.h31
-rw-r--r--cc/layers/surface_layer_unittest.cc233
-rw-r--r--cc/output/gl_renderer.cc408
-rw-r--r--cc/output/gl_renderer.h23
-rw-r--r--cc/output/gl_renderer_draw_cache.cc11
-rw-r--r--cc/output/renderer_pixeltest.cc118
-rw-r--r--cc/output/shader.cc3
-rw-r--r--cc/resources/picture_pile.cc17
-rw-r--r--cc/resources/picture_pile.h5
-rw-r--r--cc/resources/picture_pile_base.cc54
-rw-r--r--cc/resources/picture_pile_base.h20
-rw-r--r--cc/resources/picture_pile_impl.cc81
-rw-r--r--cc/resources/picture_pile_impl.h38
-rw-r--r--cc/resources/picture_pile_unittest.cc21
-rw-r--r--cc/resources/raster_worker_pool.cc89
-rw-r--r--cc/resources/tile_manager.cc1
-rw-r--r--cc/surfaces/surface.cc17
-rw-r--r--cc/surfaces/surface.h14
-rw-r--r--cc/surfaces/surface_factory.cc16
-rw-r--r--cc/surfaces/surface_factory.h2
-rw-r--r--cc/surfaces/surface_factory_unittest.cc12
-rw-r--r--cc/surfaces/surface_manager.cc35
-rw-r--r--cc/surfaces/surface_manager.h15
-rw-r--r--cc/surfaces/surface_sequence.h12
-rw-r--r--cc/test/fake_picture_pile_impl.cc115
-rw-r--r--cc/test/fake_picture_pile_impl.h12
-rw-r--r--cc/trees/layer_tree_host.cc20
-rw-r--r--cc/trees/layer_tree_host.h7
-rw-r--r--cc/trees/layer_tree_host_impl.cc26
-rw-r--r--cc/trees/layer_tree_host_impl.h5
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc174
-rw-r--r--cc/trees/layer_tree_host_unittest_scroll.cc7
54 files changed, 1309 insertions, 560 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index a578b61c93..e9ef9e2728 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -112,6 +112,7 @@ component("cc") {
"debug/unittest_only_benchmark.h",
"debug/unittest_only_benchmark_impl.cc",
"debug/unittest_only_benchmark_impl.h",
+ "input/input_handler.cc",
"input/input_handler.h",
"input/page_scale_animation.cc",
"input/page_scale_animation.h",
@@ -705,6 +706,7 @@ test("cc_unittests") {
"layers/scrollbar_layer_unittest.cc",
"layers/solid_color_layer_impl_unittest.cc",
"layers/solid_color_scrollbar_layer_impl_unittest.cc",
+ "layers/surface_layer_unittest.cc",
"layers/surface_layer_impl_unittest.cc",
"layers/texture_layer_unittest.cc",
"layers/texture_layer_impl_unittest.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 308a61d245..7ac01225de 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -140,6 +140,7 @@
'debug/unittest_only_benchmark.h',
'debug/unittest_only_benchmark_impl.cc',
'debug/unittest_only_benchmark_impl.h',
+ 'input/input_handler.cc',
'input/input_handler.h',
'input/page_scale_animation.cc',
'input/page_scale_animation.h',
diff --git a/cc/cc.target.darwin-arm.mk b/cc/cc.target.darwin-arm.mk
index 250260e286..e8bdae628e 100644
--- a/cc/cc.target.darwin-arm.mk
+++ b/cc/cc.target.darwin-arm.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.darwin-arm64.mk b/cc/cc.target.darwin-arm64.mk
index bfb600b457..4561606db7 100644
--- a/cc/cc.target.darwin-arm64.mk
+++ b/cc/cc.target.darwin-arm64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.darwin-mips.mk b/cc/cc.target.darwin-mips.mk
index 4e8b2b331c..5239409cd0 100644
--- a/cc/cc.target.darwin-mips.mk
+++ b/cc/cc.target.darwin-mips.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.darwin-mips64.mk b/cc/cc.target.darwin-mips64.mk
index 4e8b2b331c..5239409cd0 100644
--- a/cc/cc.target.darwin-mips64.mk
+++ b/cc/cc.target.darwin-mips64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.darwin-x86.mk b/cc/cc.target.darwin-x86.mk
index ce5a3ee8dd..af5e231d79 100644
--- a/cc/cc.target.darwin-x86.mk
+++ b/cc/cc.target.darwin-x86.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.darwin-x86_64.mk b/cc/cc.target.darwin-x86_64.mk
index 2da1bf8654..124e9da220 100644
--- a/cc/cc.target.darwin-x86_64.mk
+++ b/cc/cc.target.darwin-x86_64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-arm.mk b/cc/cc.target.linux-arm.mk
index 250260e286..e8bdae628e 100644
--- a/cc/cc.target.linux-arm.mk
+++ b/cc/cc.target.linux-arm.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-arm64.mk b/cc/cc.target.linux-arm64.mk
index bfb600b457..4561606db7 100644
--- a/cc/cc.target.linux-arm64.mk
+++ b/cc/cc.target.linux-arm64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-mips.mk b/cc/cc.target.linux-mips.mk
index 4e8b2b331c..5239409cd0 100644
--- a/cc/cc.target.linux-mips.mk
+++ b/cc/cc.target.linux-mips.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-mips64.mk b/cc/cc.target.linux-mips64.mk
index 4e8b2b331c..5239409cd0 100644
--- a/cc/cc.target.linux-mips64.mk
+++ b/cc/cc.target.linux-mips64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-x86.mk b/cc/cc.target.linux-x86.mk
index ce5a3ee8dd..af5e231d79 100644
--- a/cc/cc.target.linux-x86.mk
+++ b/cc/cc.target.linux-x86.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc.target.linux-x86_64.mk b/cc/cc.target.linux-x86_64.mk
index 2da1bf8654..124e9da220 100644
--- a/cc/cc.target.linux-x86_64.mk
+++ b/cc/cc.target.linux-x86_64.mk
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES := \
cc/debug/traced_value.cc \
cc/debug/unittest_only_benchmark.cc \
cc/debug/unittest_only_benchmark_impl.cc \
+ cc/input/input_handler.cc \
cc/input/page_scale_animation.cc \
cc/input/layer_selection_bound.cc \
cc/input/top_controls_manager.cc \
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 1300d3203f..75267ef287 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -50,6 +50,7 @@
'layers/scrollbar_layer_unittest.cc',
'layers/solid_color_layer_impl_unittest.cc',
'layers/solid_color_scrollbar_layer_impl_unittest.cc',
+ 'layers/surface_layer_unittest.cc',
'layers/surface_layer_impl_unittest.cc',
'layers/texture_layer_unittest.cc',
'layers/texture_layer_impl_unittest.cc',
diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc
new file mode 100644
index 0000000000..336d0d4896
--- /dev/null
+++ b/cc/input/input_handler.cc
@@ -0,0 +1,13 @@
+// Copyright 2014 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/input/input_handler.h"
+
+namespace cc {
+
+InputHandlerScrollResult::InputHandlerScrollResult()
+ : did_scroll(false), did_overscroll_root(false) {
+}
+
+} // namespace cc
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index b3205a8a64..7a9c991968 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -6,6 +6,7 @@
#define CC_INPUT_INPUT_HANDLER_H_
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "cc/base/cc_export.h"
#include "cc/base/swap_promise_monitor.h"
@@ -24,6 +25,21 @@ namespace cc {
class LayerScrollOffsetDelegate;
+struct CC_EXPORT InputHandlerScrollResult {
+ InputHandlerScrollResult();
+ // Did any layer scroll as a result this ScrollBy call?
+ bool did_scroll;
+ // Was any of the scroll delta argument to this ScrollBy call not used?
+ bool did_overscroll_root;
+ // The total overscroll that has been accumulated by all ScrollBy calls that
+ // have had overscroll since the last ScrollBegin call. This resets upon a
+ // ScrollBy with no overscroll.
+ gfx::Vector2dF accumulated_root_overscroll;
+ // The amount of the scroll delta argument to this ScrollBy call that was not
+ // used for scrolling.
+ gfx::Vector2dF unused_scroll_delta;
+};
+
class CC_EXPORT InputHandlerClient {
public:
virtual ~InputHandlerClient() {}
@@ -32,13 +48,6 @@ class CC_EXPORT InputHandlerClient {
virtual void Animate(base::TimeTicks time) = 0;
virtual void MainThreadHasStoppedFlinging() = 0;
- // Called when scroll deltas reaching the root scrolling layer go unused.
- // The accumulated overscroll is scoped by the most recent call to
- // InputHandler::ScrollBegin.
- virtual void DidOverscroll(const gfx::PointF& causal_event_viewport_point,
- const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta) = 0;
-
protected:
InputHandlerClient() {}
@@ -85,15 +94,16 @@ class CC_EXPORT InputHandler {
// should be in viewport (logical pixel) coordinates. Otherwise they are in
// scrolling layer's (logical pixel) space. If there is no room to move the
// layer in the requested direction, its first ancestor layer that can be
- // scrolled will be moved instead. If no layer can be moved in the requested
- // direction at all, then false is returned. If any layer is moved, then
- // true is returned.
+ // scrolled will be moved instead. The return value's |did_scroll| field is
+ // set to false if no layer can be moved in the requested direction at all,
+ // and set to true if any layer is moved.
// If the scroll delta hits the root layer, and the layer can no longer move,
// the root overscroll accumulated within this ScrollBegin() scope is reported
- // to the client.
+ // in the return value's |accumulated_overscroll| field.
// Should only be called if ScrollBegin() returned ScrollStarted.
- virtual bool ScrollBy(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta) = 0;
+ virtual InputHandlerScrollResult ScrollBy(
+ const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta) = 0;
virtual bool ScrollVerticallyByPage(const gfx::Point& viewport_point,
ScrollDirection direction) = 0;
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index f608ba7ae9..c56ff8be08 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -35,16 +35,22 @@ void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
Layer::PushPropertiesTo(base_layer);
PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
- if (layer_impl->bounds().IsEmpty()) {
- // Update may not get called for an empty layer, so resize here instead.
- // Using layer_impl because either bounds() or paint_properties().bounds
- // may disagree and either one could have been pushed to layer_impl.
+ int source_frame_number = layer_tree_host()->source_frame_number();
+ gfx::Size impl_bounds = layer_impl->bounds();
+ gfx::Size pile_bounds = pile_.tiling_size();
+
+ // If update called, then pile size must match bounds pushed to impl layer.
+ DCHECK_IMPLIES(update_source_frame_number_ == source_frame_number,
+ impl_bounds == pile_bounds)
+ << " bounds " << impl_bounds.ToString() << " pile "
+ << pile_bounds.ToString();
+
+ if (update_source_frame_number_ != source_frame_number &&
+ pile_bounds != impl_bounds) {
+ // Update may not get called for the layer (if it's not in the viewport
+ // for example, even though it has resized making the pile no longer
+ // valid. In this case just destroy the pile.
pile_.SetEmptyBounds();
- } else {
- // If update called, then pile size must match bounds pushed to impl layer.
- DCHECK_IMPLIES(
- update_source_frame_number_ == layer_tree_host()->source_frame_number(),
- layer_impl->bounds().ToString() == pile_.tiling_size().ToString());
}
// Unlike other properties, invalidation must always be set on layer_impl.
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 9f59263d65..822fcf3dc2 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -173,10 +173,11 @@ void PictureLayerImpl::AppendQuads(RenderPass* render_pass,
AppendQuadsData* append_quads_data) {
DCHECK(!needs_post_commit_initialization_);
// The bounds and the pile size may differ if the pile wasn't updated (ie.
- // PictureLayer::Update didn't happen). But that should never be the case if
- // the layer is part of the visible frame, which is why we're appending quads
- // in the first place
- DCHECK_EQ(bounds().ToString(), pile_->tiling_size().ToString());
+ // PictureLayer::Update didn't happen). In that case the pile will be empty.
+ DCHECK_IMPLIES(!pile_->tiling_size().IsEmpty(),
+ bounds() == pile_->tiling_size())
+ << " bounds " << bounds().ToString() << " pile "
+ << pile_->tiling_size().ToString();
SharedQuadState* shared_quad_state =
render_pass->CreateAndAppendSharedQuadState();
@@ -628,7 +629,7 @@ skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() {
scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling,
const gfx::Rect& content_rect) {
DCHECK(!pile_->is_solid_color());
- if (!pile_->CanRaster(tiling->contents_scale(), content_rect))
+ if (!pile_->CoversRect(content_rect, tiling->contents_scale()))
return scoped_refptr<Tile>();
int flags = 0;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index a46386cf55..4b42eca413 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -658,10 +658,10 @@ TEST_F(PictureLayerImplTest, AddTilesFromNewRecording) {
++iter) {
EXPECT_FALSE(iter.full_tile_geometry_rect().IsEmpty());
// Ensure there is a recording for this tile.
- bool in_pending = pending_pile->CanRaster(tiling->contents_scale(),
- iter.full_tile_geometry_rect());
- bool in_active = active_pile->CanRaster(tiling->contents_scale(),
- iter.full_tile_geometry_rect());
+ bool in_pending = pending_pile->CoversRect(iter.full_tile_geometry_rect(),
+ tiling->contents_scale());
+ bool in_active = active_pile->CoversRect(iter.full_tile_geometry_rect(),
+ tiling->contents_scale());
if (in_pending && !in_active)
EXPECT_EQ(pending_pile.get(), iter->raster_source());
@@ -1132,8 +1132,15 @@ TEST_F(PictureLayerImplTest, DontAddLowResDuringAnimation) {
}
TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) {
- gfx::Size tile_size(host_impl_.settings().default_tile_size);
- SetupDefaultTrees(tile_size);
+ gfx::Size layer_bounds(host_impl_.settings().default_tile_size);
+ gfx::Size tile_size(100, 100);
+
+ scoped_refptr<FakePicturePileImpl> pending_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+ scoped_refptr<FakePicturePileImpl> active_pile =
+ FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+ SetupTrees(pending_pile, active_pile);
float low_res_factor = host_impl_.settings().low_res_contents_scale_factor;
float device_scale = 1.f;
@@ -1181,8 +1188,8 @@ TEST_F(PictureLayerImplTest, DontAddLowResForSmallLayers) {
ResetTilingsAndRasterScales();
// Mask layers dont create low res since they always fit on one tile.
- pending_layer_->pile()->set_is_mask(true);
- active_layer_->pile()->set_is_mask(true);
+ pending_pile->SetIsMask(true);
+ active_pile->SetIsMask(true);
SetContentsScaleOnBothLayers(contents_scale,
device_scale,
page_scale,
@@ -1197,7 +1204,7 @@ TEST_F(PictureLayerImplTest, HugeMasksDontGetTiles) {
scoped_refptr<FakePicturePileImpl> valid_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000));
- valid_pile->set_is_mask(true);
+ valid_pile->SetIsMask(true);
SetupPendingTree(valid_pile);
SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
@@ -1224,7 +1231,7 @@ TEST_F(PictureLayerImplTest, HugeMasksDontGetTiles) {
scoped_refptr<FakePicturePileImpl> huge_pile =
FakePicturePileImpl::CreateFilledPile(
tile_size, gfx::Size(max_texture_size + 1, 10));
- huge_pile->set_is_mask(true);
+ huge_pile->SetIsMask(true);
SetupPendingTree(huge_pile);
SetupDrawPropertiesAndUpdateTiles(pending_layer_, 1.f, 1.f, 1.f, 1.f, false);
@@ -1249,7 +1256,7 @@ TEST_F(PictureLayerImplTest, ScaledMaskLayer) {
scoped_refptr<FakePicturePileImpl> valid_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, gfx::Size(1000, 1000));
- valid_pile->set_is_mask(true);
+ valid_pile->SetIsMask(true);
SetupPendingTree(valid_pile);
float ideal_contents_scale = 1.3f;
@@ -3708,7 +3715,7 @@ TEST_F(PictureLayerImplTest, UpdateTilesForMasksWithNoVisibleContent) {
scoped_refptr<FakePicturePileImpl> pending_pile =
FakePicturePileImpl::CreateFilledPile(tile_size, bounds);
- pending_pile->set_is_mask(true);
+ pending_pile->SetIsMask(true);
scoped_ptr<FakePictureLayerImpl> mask = FakePictureLayerImpl::CreateWithPile(
host_impl_.pending_tree(), 3, pending_pile);
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 78182d9135..ca622aa3c0 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -43,6 +43,10 @@ TEST(PictureLayerTest, NoTilesIfEmptyBounds) {
scoped_ptr<ResourceUpdateQueue> queue(new ResourceUpdateQueue);
layer->Update(queue.get(), &occlusion);
+ EXPECT_EQ(0, host->source_frame_number());
+ host->CommitComplete();
+ EXPECT_EQ(1, host->source_frame_number());
+
layer->SetBounds(gfx::Size(0, 0));
layer->SavePaintProperties();
// Intentionally skipping Update since it would normally be skipped on
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index ba577a00d5..ee376aad4e 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -4,21 +4,61 @@
#include "cc/layers/surface_layer.h"
+#include "cc/base/swap_promise.h"
#include "cc/layers/surface_layer_impl.h"
+#include "cc/trees/layer_tree_host.h"
namespace cc {
-scoped_refptr<SurfaceLayer> SurfaceLayer::Create() {
- return make_scoped_refptr(new SurfaceLayer);
+class SatisfySwapPromise : public SwapPromise {
+ public:
+ SatisfySwapPromise(SurfaceSequence sequence,
+ const SurfaceLayer::SatisfyCallback& satisfy_callback)
+ : sequence_(sequence), satisfy_callback_(satisfy_callback) {}
+
+ ~SatisfySwapPromise() override {}
+
+ private:
+ void DidSwap(CompositorFrameMetadata* metadata) override {
+ metadata->satisfies_sequences.push_back(sequence_.sequence);
+ }
+
+ void DidNotSwap(DidNotSwapReason reason) override {
+ satisfy_callback_.Run(sequence_);
+ }
+ int64 TraceId() const override { return 0; }
+
+ SurfaceSequence sequence_;
+ SurfaceLayer::SatisfyCallback satisfy_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SatisfySwapPromise);
+};
+
+scoped_refptr<SurfaceLayer> SurfaceLayer::Create(
+ const SatisfyCallback& satisfy_callback,
+ const RequireCallback& require_callback) {
+ return make_scoped_refptr(
+ new SurfaceLayer(satisfy_callback, require_callback));
}
-SurfaceLayer::SurfaceLayer() : Layer() {
+SurfaceLayer::SurfaceLayer(const SatisfyCallback& satisfy_callback,
+ const RequireCallback& require_callback)
+ : Layer(),
+ satisfy_callback_(satisfy_callback),
+ require_callback_(require_callback) {
}
-SurfaceLayer::~SurfaceLayer() {}
+SurfaceLayer::~SurfaceLayer() {
+ DCHECK(!layer_tree_host());
+ DCHECK(destroy_sequence_.is_null());
+}
-void SurfaceLayer::SetSurfaceId(SurfaceId surface_id) {
+void SurfaceLayer::SetSurfaceId(SurfaceId surface_id, const gfx::Size& size) {
+ SatisfyDestroySequence();
surface_id_ = surface_id;
+ surface_size_ = size;
+ CreateNewDestroySequence();
+
UpdateDrawsContent(HasDrawableContent());
SetNeedsPushProperties();
}
@@ -31,6 +71,17 @@ bool SurfaceLayer::HasDrawableContent() const {
return !surface_id_.is_null() && Layer::HasDrawableContent();
}
+void SurfaceLayer::SetLayerTreeHost(LayerTreeHost* host) {
+ if (layer_tree_host() == host) {
+ Layer::SetLayerTreeHost(host);
+ return;
+ }
+
+ SatisfyDestroySequence();
+ Layer::SetLayerTreeHost(host);
+ CreateNewDestroySequence();
+}
+
void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) {
Layer::PushPropertiesTo(layer);
SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer);
@@ -38,4 +89,35 @@ void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) {
layer_impl->SetSurfaceId(surface_id_);
}
+void SurfaceLayer::CalculateContentsScale(float ideal_contents_scale,
+ float* contents_scale_x,
+ float* contents_scale_y,
+ gfx::Size* content_bounds) {
+ *content_bounds = surface_size_;
+ *contents_scale_x =
+ bounds().IsEmpty() ? 1.f : static_cast<float>(content_bounds->width()) /
+ bounds().width();
+ *contents_scale_y =
+ bounds().IsEmpty() ? 1.f : static_cast<float>(content_bounds->height()) /
+ bounds().height();
+}
+
+void SurfaceLayer::CreateNewDestroySequence() {
+ DCHECK(destroy_sequence_.is_null());
+ if (layer_tree_host()) {
+ destroy_sequence_ = layer_tree_host()->CreateSurfaceSequence();
+ require_callback_.Run(surface_id_, destroy_sequence_);
+ }
+}
+
+void SurfaceLayer::SatisfyDestroySequence() {
+ if (!layer_tree_host())
+ return;
+ DCHECK(!destroy_sequence_.is_null());
+ scoped_ptr<SatisfySwapPromise> satisfy(
+ new SatisfySwapPromise(destroy_sequence_, satisfy_callback_));
+ layer_tree_host()->QueueSwapPromise(satisfy.Pass());
+ destroy_sequence_ = SurfaceSequence();
+}
+
} // namespace cc
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index 0b886ebe2c..29d821f53d 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -8,6 +8,8 @@
#include "cc/base/cc_export.h"
#include "cc/layers/layer.h"
#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_sequence.h"
+#include "ui/gfx/size.h"
namespace cc {
@@ -15,22 +17,45 @@ namespace cc {
// instance or client.
class CC_EXPORT SurfaceLayer : public Layer {
public:
- static scoped_refptr<SurfaceLayer> Create();
+ // This callback is run when a SurfaceSequence needs to be satisfied, but
+ // the parent compositor is unable to. It can be called on either the main
+ // or impl threads.
+ using SatisfyCallback = base::Callback<void(SurfaceSequence)>;
- void SetSurfaceId(SurfaceId surface_id);
+ // This callback is run to require that a specific SurfaceSequence is
+ // received before a SurfaceId is destroyed.
+ using RequireCallback = base::Callback<void(SurfaceId, SurfaceSequence)>;
+
+ static scoped_refptr<SurfaceLayer> Create(
+ const SatisfyCallback& satisfy_callback,
+ const RequireCallback& require_callback);
+
+ void SetSurfaceId(SurfaceId surface_id, const gfx::Size& size);
// Layer overrides.
scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
+ void SetLayerTreeHost(LayerTreeHost* host) override;
void PushPropertiesTo(LayerImpl* layer) override;
+ void CalculateContentsScale(float ideal_contents_scale,
+ float* contents_scale_x,
+ float* contents_scale_y,
+ gfx::Size* content_bounds) override;
protected:
- SurfaceLayer();
+ SurfaceLayer(const SatisfyCallback& satisfy_callback,
+ const RequireCallback& require_callback);
bool HasDrawableContent() const override;
private:
~SurfaceLayer() override;
+ void CreateNewDestroySequence();
+ void SatisfyDestroySequence();
SurfaceId surface_id_;
+ gfx::Size surface_size_;
+ SurfaceSequence destroy_sequence_;
+ SatisfyCallback satisfy_callback_;
+ RequireCallback require_callback_;
DISALLOW_COPY_AND_ASSIGN(SurfaceLayer);
};
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc
new file mode 100644
index 0000000000..7323bf4c45
--- /dev/null
+++ b/cc/layers/surface_layer_unittest.cc
@@ -0,0 +1,233 @@
+// Copyright 2014 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 "base/message_loop/message_loop_proxy.h"
+#include "cc/layers/solid_color_layer.h"
+#include "cc/layers/surface_layer.h"
+#include "cc/test/fake_impl_proxy.h"
+#include "cc/test/fake_layer_tree_host.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/layer_tree_test.h"
+#include "cc/test/test_shared_bitmap_manager.h"
+#include "cc/trees/layer_tree_host.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+class SurfaceLayerTest : public testing::Test {
+ public:
+ SurfaceLayerTest()
+ : fake_client_(
+ FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
+
+ protected:
+ virtual void SetUp() {
+ layer_tree_host_ = FakeLayerTreeHost::Create(&fake_client_);
+ layer_tree_host_->SetViewportSize(gfx::Size(10, 10));
+ }
+
+ virtual void TearDown() {
+ if (layer_tree_host_) {
+ layer_tree_host_->SetRootLayer(nullptr);
+ layer_tree_host_ = nullptr;
+ }
+ }
+
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host_;
+ FakeLayerTreeHostClient fake_client_;
+ TestSharedBitmapManager shared_bitmap_manager_;
+};
+
+void SatisfyCallback(SurfaceSequence* out, SurfaceSequence in) {
+ *out = in;
+}
+
+void RequireCallback(SurfaceId* out_id,
+ std::set<SurfaceSequence>* out,
+ SurfaceId in_id,
+ SurfaceSequence in) {
+ *out_id = in_id;
+ out->insert(in);
+}
+
+// Check that one surface can be referenced by multiple LayerTreeHosts, and
+// each will create its own SurfaceSequence that's satisfied on destruction.
+TEST_F(SurfaceLayerTest, MultipleFramesOneSurface) {
+ SurfaceSequence blank_change; // Receives sequence if commit doesn't happen.
+
+ SurfaceId required_id;
+ std::set<SurfaceSequence> required_seq;
+ scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create(
+ base::Bind(&SatisfyCallback, &blank_change),
+ base::Bind(&RequireCallback, &required_id, &required_seq)));
+ layer->SetSurfaceId(SurfaceId(1), gfx::Size(1, 1));
+ layer_tree_host_->set_surface_id_namespace(1);
+ layer_tree_host_->SetRootLayer(layer);
+
+ scoped_ptr<FakeLayerTreeHost> layer_tree_host2 =
+ FakeLayerTreeHost::Create(&fake_client_);
+ scoped_refptr<SurfaceLayer> layer2(SurfaceLayer::Create(
+ base::Bind(&SatisfyCallback, &blank_change),
+ base::Bind(&RequireCallback, &required_id, &required_seq)));
+ layer2->SetSurfaceId(SurfaceId(1), gfx::Size(1, 1));
+ layer_tree_host2->set_surface_id_namespace(2);
+ layer_tree_host2->SetRootLayer(layer2);
+
+ // Layers haven't been removed, so no sequence should be satisfied.
+ EXPECT_TRUE(blank_change.is_null());
+
+ SurfaceSequence expected1(1u, 1u);
+ SurfaceSequence expected2(2u, 1u);
+
+ layer_tree_host2->SetRootLayer(nullptr);
+ layer_tree_host2.reset();
+
+ // Layer was removed so sequence from second LayerTreeHost should be
+ // satisfied.
+ EXPECT_TRUE(blank_change == expected2);
+
+ // Set of sequences that need to be satisfied should include sequences from
+ // both trees.
+ EXPECT_TRUE(required_id == SurfaceId(1));
+ EXPECT_EQ(2u, required_seq.size());
+ EXPECT_TRUE(required_seq.count(expected1));
+ EXPECT_TRUE(required_seq.count(expected2));
+
+ layer_tree_host_->SetRootLayer(nullptr);
+ layer_tree_host_.reset();
+
+ // Layer was removed so sequence from first LayerTreeHost should be
+ // satisfied.
+ EXPECT_TRUE(blank_change == expected1);
+
+ // No more SurfaceSequences should have been generated that need to have be
+ // satisfied.
+ EXPECT_EQ(2u, required_seq.size());
+}
+
+// Check that setting content scale on the surface works.
+TEST_F(SurfaceLayerTest, ScaleSurface) {
+ SurfaceSequence blank_change;
+ SurfaceId required_id;
+ std::set<SurfaceSequence> required_seq;
+ scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create(
+ base::Bind(&SatisfyCallback, &blank_change),
+ base::Bind(&RequireCallback, &required_id, &required_seq)));
+ gfx::Size surface_size(10, 15);
+ layer->SetSurfaceId(SurfaceId(1), surface_size);
+ layer->SetBounds(gfx::Size(25, 45));
+
+ float scale_x;
+ float scale_y;
+ gfx::Size bounds;
+ layer->CalculateContentsScale(2.f, &scale_x, &scale_y, &bounds);
+ EXPECT_EQ(10.f / 25.f, scale_x);
+ EXPECT_EQ(15.f / 45.f, scale_y);
+ EXPECT_EQ(surface_size.ToString(), bounds.ToString());
+
+ layer->SetBounds(gfx::Size(0, 0));
+ layer->CalculateContentsScale(2.f, &scale_x, &scale_y, &bounds);
+ EXPECT_EQ(1.f, scale_x);
+ EXPECT_EQ(1.f, scale_y);
+ EXPECT_EQ(surface_size.ToString(), bounds.ToString());
+}
+
+// Check that SurfaceSequence is sent through swap promise.
+class SurfaceLayerSwapPromise : public LayerTreeTest {
+ public:
+ SurfaceLayerSwapPromise()
+ : commit_count_(0), sequence_was_satisfied_(false) {}
+
+ void BeginTest() override {
+ layer_tree_host()->set_surface_id_namespace(1);
+ layer_ = SurfaceLayer::Create(
+ base::Bind(&SatisfyCallback, &satisfied_sequence_),
+ base::Bind(&RequireCallback, &required_id_, &required_set_));
+ layer_->SetSurfaceId(SurfaceId(1), gfx::Size(1, 1));
+
+ // Layer hasn't been added to tree so no SurfaceSequence generated yet.
+ EXPECT_EQ(0u, required_set_.size());
+
+ layer_tree_host()->SetRootLayer(layer_);
+
+ // Should have SurfaceSequence from first tree.
+ SurfaceSequence expected(1u, 1u);
+ EXPECT_TRUE(required_id_ == SurfaceId(1));
+ EXPECT_EQ(1u, required_set_.size());
+ EXPECT_TRUE(required_set_.count(expected));
+
+ gfx::Size bounds(100, 100);
+ layer_tree_host()->SetViewportSize(bounds);
+ PostSetNeedsCommitToMainThread();
+ }
+
+ void DidCommit() override {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE, base::Bind(&SurfaceLayerSwapPromise::ChangeTree,
+ base::Unretained(this)));
+ }
+
+ void ChangeTree() {
+ ++commit_count_;
+ switch (commit_count_) {
+ case 1:
+ // Remove SurfaceLayer from tree to cause SwapPromise to be created.
+ blank_layer_ = SolidColorLayer::Create();
+ blank_layer_->SetIsDrawable(true);
+ blank_layer_->SetBounds(gfx::Size(10, 10));
+ layer_tree_host()->SetRootLayer(blank_layer_);
+ break;
+ case 2:
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override {
+ EXPECT_TRUE(result);
+ std::vector<uint32_t>& satisfied =
+ output_surface()->last_sent_frame().metadata.satisfies_sequences;
+ EXPECT_LE(satisfied.size(), 1u);
+ if (satisfied.size() == 1) {
+ // Eventually the one SurfaceSequence should be satisfied, but only
+ // after the layer was removed from the tree, and only once.
+ EXPECT_EQ(1u, satisfied[0]);
+ EXPECT_LE(1, commit_count_);
+ EXPECT_FALSE(sequence_was_satisfied_);
+ sequence_was_satisfied_ = true;
+ EndTest();
+ }
+ }
+
+ void AfterTest() override {
+ EXPECT_TRUE(required_id_ == SurfaceId(1));
+ EXPECT_EQ(1u, required_set_.size());
+ // Sequence should have been satisfied through Swap, not with the
+ // callback.
+ EXPECT_TRUE(satisfied_sequence_.is_null());
+ }
+
+ private:
+ int commit_count_;
+ bool sequence_was_satisfied_;
+ scoped_refptr<SurfaceLayer> layer_;
+ scoped_refptr<Layer> blank_layer_;
+ SurfaceSequence satisfied_sequence_;
+
+ SurfaceId required_id_;
+ std::set<SurfaceSequence> required_set_;
+};
+
+// TODO(jbauman): Reenable on single thread once http://crbug.com/421923 is
+// fixed.
+MULTI_THREAD_TEST_F(SurfaceLayerSwapPromise);
+
+} // namespace
+} // namespace cc
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 02303ace6c..a472475d23 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -870,7 +870,7 @@ scoped_ptr<ScopedResource>
GLRenderer::ApplyInverseTransformForBackgroundFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
- const gfx::Transform& contents_device_transform_inverse,
+ const gfx::Transform& contents_device_transform,
skia::RefPtr<SkImage> filtered_device_background,
const gfx::Rect& backdrop_bounding_rect) {
// This method draws a background filter, which applies a filter to any pixels
@@ -915,6 +915,12 @@ GLRenderer::ApplyInverseTransformForBackgroundFilters(
if (using_background_texture) {
// Copy the readback pixels from device to the background texture for the
// surface.
+
+ gfx::Transform contents_device_transform_inverse(
+ gfx::Transform::kSkipInitialization);
+ bool did_invert = contents_device_transform.GetInverse(
+ &contents_device_transform_inverse);
+ DCHECK(did_invert);
gfx::Transform device_to_framebuffer_transform;
QuadRectTransform(
&device_to_framebuffer_transform, gfx::Transform(), quad->rect);
@@ -965,20 +971,18 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
contents_device_transform.FlattenTo2d();
// Can only draw surface if device matrix is invertible.
- gfx::Transform contents_device_transform_inverse(
- gfx::Transform::kSkipInitialization);
- if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
+ if (!contents_device_transform.IsInvertible())
return;
- bool clipped = false;
- gfx::QuadF device_quad = MathUtil::MapQuad(
- contents_device_transform, SharedGeometryQuad(), &clipped);
- // Use anti-aliasing programs only when necessary.
- bool use_aa =
- !clipped &&
- (settings_->force_antialiasing || !device_quad.IsRectilinear() ||
- !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
- kAntiAliasingEpsilon));
+ gfx::QuadF surface_quad = SharedGeometryQuad();
+ float edge[24];
+ bool use_aa = settings_->allow_antialiasing &&
+ ShouldAntialiasQuad(contents_device_transform, quad,
+ settings_->force_antialiasing);
+
+ if (use_aa)
+ SetupQuadForAntialiasing(contents_device_transform, quad,
+ &surface_quad, edge);
bool need_background_texture = !CanApplyBlendModeUsingBlendFunc(blend_mode) ||
ShouldApplyBackgroundFilters(frame, quad);
@@ -1021,10 +1025,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
// the quad since the destination texture has bounds matching the quad's
// content.
background_texture = ApplyInverseTransformForBackgroundFilters(
- frame,
- quad,
- contents_device_transform_inverse,
- background_with_filters,
+ frame, quad, contents_device_transform, background_with_filters,
background_rect);
} else if (!CanApplyBlendModeUsingBlendFunc(blend_mode)) {
if (background_with_filters) {
@@ -1090,13 +1091,6 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
flip_vertically);
}
- LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox()));
- LayerQuad device_layer_edges(device_quad);
- if (use_aa) {
- device_layer_bounds.InflateAntiAliasingDistance();
- device_layer_edges.InflateAntiAliasingDistance();
- }
-
scoped_ptr<ResourceProvider::ScopedSamplerGL> mask_resource_lock;
unsigned mask_texture_id = 0;
SamplerType mask_sampler = SamplerTypeNA;
@@ -1360,12 +1354,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
last_texture_unit = 1;
}
- if (shader_edge_location != -1) {
- float edge[24];
- device_layer_edges.ToFloatArray(edge);
- device_layer_bounds.ToFloatArray(&edge[12]);
+ if (shader_edge_location != -1)
GLC(gl_, gl_->Uniform3fv(shader_edge_location, 8, edge));
- }
if (shader_viewport_location != -1) {
float viewport[4] = {static_cast<float>(viewport_.x()),
@@ -1424,12 +1414,6 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
}
}
- // Map device space quad to surface space. contents_device_transform has no 3d
- // component since it was flattened, so we don't need to project.
- gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse,
- device_layer_edges.ToQuadF(),
- &clipped);
-
SetShaderOpacity(quad->opacity(), shader_alpha_location);
SetShaderQuadF(surface_quad, shader_quad_location);
DrawQuadGeometry(
@@ -1464,41 +1448,16 @@ static void SolidColorUniformLocation(T program,
uniforms->color_location = program->fragment_shader().color_location();
}
-// static
-bool GLRenderer::SetupQuadForAntialiasing(
+static gfx::QuadF GetDeviceQuadWithAntialiasingOnExteriorEdges(
+ const LayerQuad& device_layer_edges,
const gfx::Transform& device_transform,
- const DrawQuad* quad,
- gfx::QuadF* local_quad,
- float edge[24]) {
+ const DrawQuad* quad) {
gfx::Rect tile_rect = quad->visible_rect;
-
- bool clipped = false;
- gfx::QuadF device_layer_quad = MathUtil::MapQuad(
- device_transform, gfx::QuadF(quad->visibleContentRect()), &clipped);
-
- bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear();
- bool is_nearest_rect_within_epsilon =
- is_axis_aligned_in_target &&
- gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(),
- kAntiAliasingEpsilon);
- // AAing clipped quads is not supported by the code yet.
- bool use_aa = !clipped && !is_nearest_rect_within_epsilon && quad->IsEdge();
- if (!use_aa)
- return false;
-
- LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox()));
- device_layer_bounds.InflateAntiAliasingDistance();
-
- LayerQuad device_layer_edges(device_layer_quad);
- device_layer_edges.InflateAntiAliasingDistance();
-
- device_layer_edges.ToFloatArray(edge);
- device_layer_bounds.ToFloatArray(&edge[12]);
-
gfx::PointF bottom_right = tile_rect.bottom_right();
gfx::PointF bottom_left = tile_rect.bottom_left();
gfx::PointF top_left = tile_rect.origin();
gfx::PointF top_right = tile_rect.top_right();
+ bool clipped = false;
// Map points to device space. We ignore |clipped|, since the result of
// |MapPoint()| still produces a valid point to draw the quad with. When
@@ -1530,7 +1489,72 @@ bool GLRenderer::SetupQuadForAntialiasing(
right_edge.scale(sign);
// Create device space quad.
- LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge);
+ return LayerQuad(left_edge, top_edge, right_edge, bottom_edge).ToQuadF();
+}
+
+// static
+bool GLRenderer::ShouldAntialiasQuad(const gfx::Transform& device_transform,
+ const DrawQuad* quad,
+ bool force_antialiasing) {
+ bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS);
+ // For render pass quads, |device_transform| already contains quad's rect.
+ // TODO(rosca@adobe.com): remove branching on is_render_pass_quad
+ // crbug.com/429702
+ if (!is_render_pass_quad && !quad->IsEdge())
+ return false;
+ gfx::RectF content_rect =
+ is_render_pass_quad ? QuadVertexRect() : quad->visibleContentRect();
+
+ bool clipped = false;
+ gfx::QuadF device_layer_quad =
+ MathUtil::MapQuad(device_transform, gfx::QuadF(content_rect), &clipped);
+
+ if (device_layer_quad.BoundingBox().IsEmpty())
+ return false;
+
+ bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear();
+ bool is_nearest_rect_within_epsilon =
+ is_axis_aligned_in_target &&
+ gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(),
+ kAntiAliasingEpsilon);
+ // AAing clipped quads is not supported by the code yet.
+ bool use_aa = !clipped && !is_nearest_rect_within_epsilon;
+ return use_aa || force_antialiasing;
+}
+
+// static
+void GLRenderer::SetupQuadForAntialiasing(
+ const gfx::Transform& device_transform,
+ const DrawQuad* quad,
+ gfx::QuadF* local_quad,
+ float edge[24]) {
+ bool is_render_pass_quad = (quad->material == DrawQuad::RENDER_PASS);
+ gfx::RectF content_rect =
+ is_render_pass_quad ? QuadVertexRect() : quad->visibleContentRect();
+
+ bool clipped = false;
+ gfx::QuadF device_layer_quad =
+ MathUtil::MapQuad(device_transform, gfx::QuadF(content_rect), &clipped);
+
+ LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox()));
+ device_layer_bounds.InflateAntiAliasingDistance();
+
+ LayerQuad device_layer_edges(device_layer_quad);
+ device_layer_edges.InflateAntiAliasingDistance();
+
+ device_layer_edges.ToFloatArray(edge);
+ device_layer_bounds.ToFloatArray(&edge[12]);
+
+ bool use_aa_on_all_four_edges =
+ is_render_pass_quad ||
+ (quad->IsTopEdge() && quad->IsLeftEdge() && quad->IsBottomEdge() &&
+ quad->IsRightEdge() && quad->visible_rect == quad->rect);
+
+ gfx::QuadF device_quad =
+ use_aa_on_all_four_edges
+ ? device_layer_edges.ToQuadF()
+ : GetDeviceQuadWithAntialiasingOnExteriorEdges(
+ device_layer_edges, device_transform, quad);
// Map device space quad to local space. device_transform has no 3d
// component since it was flattened, so we don't need to project. We should
@@ -1538,13 +1562,11 @@ bool GLRenderer::SetupQuadForAntialiasing(
gfx::Transform inverse_device_transform(gfx::Transform::kSkipInitialization);
bool did_invert = device_transform.GetInverse(&inverse_device_transform);
DCHECK(did_invert);
- *local_quad = MathUtil::MapQuad(
- inverse_device_transform, device_quad.ToQuadF(), &clipped);
+ *local_quad =
+ MathUtil::MapQuad(inverse_device_transform, device_quad, &clipped);
// We should not DCHECK(!clipped) here, because anti-aliasing inflation may
// cause device_quad to become clipped. To our knowledge this scenario does
// not need to be handled differently than the unclipped case.
-
- return true;
}
void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
@@ -1566,17 +1588,20 @@ void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
if (!device_transform.IsInvertible())
return;
+ bool force_aa = false;
gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
float edge[24];
- bool use_aa =
- settings_->allow_antialiasing && !quad->force_anti_aliasing_off &&
- SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
+ bool use_aa = settings_->allow_antialiasing &&
+ !quad->force_anti_aliasing_off &&
+ ShouldAntialiasQuad(device_transform, quad, force_aa);
SolidColorProgramUniforms uniforms;
- if (use_aa)
+ if (use_aa) {
+ SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms);
- else
+ } else {
SolidColorUniformLocation(GetSolidColorProgram(), &uniforms);
+ }
SetUseProgram(uniforms.program);
GLC(gl_,
@@ -1650,6 +1675,29 @@ void GLRenderer::DrawTileQuad(const DrawingFrame* frame,
void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
const ContentDrawQuadBase* quad,
ResourceProvider::ResourceId resource_id) {
+ gfx::Transform device_transform =
+ frame->window_matrix * frame->projection_matrix * quad->quadTransform();
+ device_transform.FlattenTo2d();
+
+ bool use_aa = settings_->allow_antialiasing &&
+ ShouldAntialiasQuad(device_transform, quad, false);
+
+ // TODO(timav): simplify coordinate transformations in DrawContentQuadAA
+ // similar to the way DrawContentQuadNoAA works and then consider
+ // combining DrawContentQuadAA and DrawContentQuadNoAA into one method.
+ if (use_aa)
+ DrawContentQuadAA(frame, quad, resource_id, device_transform);
+ else
+ DrawContentQuadNoAA(frame, quad, resource_id);
+}
+
+void GLRenderer::DrawContentQuadAA(const DrawingFrame* frame,
+ const ContentDrawQuadBase* quad,
+ ResourceProvider::ResourceId resource_id,
+ const gfx::Transform& device_transform) {
+ if (!device_transform.IsInvertible())
+ return;
+
gfx::Rect tile_rect = quad->visible_rect;
gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
@@ -1689,25 +1737,12 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size);
- gfx::Transform device_transform =
- frame->window_matrix * frame->projection_matrix * quad->quadTransform();
- device_transform.FlattenTo2d();
- if (!device_transform.IsInvertible())
- return;
-
gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
float edge[24];
- bool use_aa =
- settings_->allow_antialiasing &&
- SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
+ SetupQuadForAntialiasing(device_transform, quad, &local_quad, edge);
- bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f);
- GLenum filter = (use_aa || scaled ||
- !quad->quadTransform().IsIdentityOrIntegerTranslation())
- ? GL_LINEAR
- : GL_NEAREST;
ResourceProvider::ScopedSamplerGL quad_resource_lock(
- resource_provider_, resource_id, filter);
+ resource_provider_, resource_id, GL_LINEAR);
SamplerType sampler =
SamplerTypeFromTextureTarget(quad_resource_lock.target());
@@ -1727,81 +1762,41 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
}
TileProgramUniforms uniforms;
- if (use_aa) {
- if (quad->swizzle_contents) {
- TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision, sampler),
- &uniforms);
- } else {
- TileUniformLocation(GetTileProgramAA(tex_coord_precision, sampler),
- &uniforms);
- }
+ if (quad->swizzle_contents) {
+ TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision, sampler),
+ &uniforms);
} else {
- if (quad->ShouldDrawWithBlending()) {
- if (quad->swizzle_contents) {
- TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision, sampler),
- &uniforms);
- } else {
- TileUniformLocation(GetTileProgram(tex_coord_precision, sampler),
- &uniforms);
- }
- } else {
- if (quad->swizzle_contents) {
- TileUniformLocation(
- GetTileProgramSwizzleOpaque(tex_coord_precision, sampler),
- &uniforms);
- } else {
- TileUniformLocation(GetTileProgramOpaque(tex_coord_precision, sampler),
- &uniforms);
- }
- }
+ TileUniformLocation(GetTileProgramAA(tex_coord_precision, sampler),
+ &uniforms);
}
SetUseProgram(uniforms.program);
GLC(gl_, gl_->Uniform1i(uniforms.sampler_location, 0));
- if (use_aa) {
- float viewport[4] = {static_cast<float>(viewport_.x()),
- static_cast<float>(viewport_.y()),
- static_cast<float>(viewport_.width()),
- static_cast<float>(viewport_.height()), };
- GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport));
- GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge));
-
- GLC(gl_,
- gl_->Uniform4f(uniforms.vertex_tex_transform_location,
- vertex_tex_translate_x,
- vertex_tex_translate_y,
- vertex_tex_scale_x,
- vertex_tex_scale_y));
- GLC(gl_,
- gl_->Uniform4f(uniforms.fragment_tex_transform_location,
- fragment_tex_translate_x,
- fragment_tex_translate_y,
- fragment_tex_scale_x,
- fragment_tex_scale_y));
- } else {
- // Move fragment shader transform to vertex shader. We can do this while
- // still producing correct results as fragment_tex_transform_location
- // should always be non-negative when tiles are transformed in a way
- // that could result in sampling outside the layer.
- vertex_tex_scale_x *= fragment_tex_scale_x;
- vertex_tex_scale_y *= fragment_tex_scale_y;
- vertex_tex_translate_x *= fragment_tex_scale_x;
- vertex_tex_translate_y *= fragment_tex_scale_y;
- vertex_tex_translate_x += fragment_tex_translate_x;
- vertex_tex_translate_y += fragment_tex_translate_y;
+ float viewport[4] = {
+ static_cast<float>(viewport_.x()),
+ static_cast<float>(viewport_.y()),
+ static_cast<float>(viewport_.width()),
+ static_cast<float>(viewport_.height()),
+ };
+ GLC(gl_, gl_->Uniform4fv(uniforms.viewport_location, 1, viewport));
+ GLC(gl_, gl_->Uniform3fv(uniforms.edge_location, 8, edge));
- GLC(gl_,
- gl_->Uniform4f(uniforms.vertex_tex_transform_location,
- vertex_tex_translate_x,
- vertex_tex_translate_y,
- vertex_tex_scale_x,
- vertex_tex_scale_y));
- }
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.vertex_tex_transform_location,
+ vertex_tex_translate_x,
+ vertex_tex_translate_y,
+ vertex_tex_scale_x,
+ vertex_tex_scale_y));
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.fragment_tex_transform_location,
+ fragment_tex_translate_x,
+ fragment_tex_translate_y,
+ fragment_tex_scale_x,
+ fragment_tex_scale_y));
- // Enable blending when the quad properties require it or if we decided
- // to use antialiasing.
- SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa);
+ // Blending is required for antialiasing.
+ SetBlendEnabled(true);
// Normalize to tile_rect.
local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
@@ -1820,6 +1815,103 @@ void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
frame, quad->quadTransform(), centered_rect, uniforms.matrix_location);
}
+void GLRenderer::DrawContentQuadNoAA(const DrawingFrame* frame,
+ const ContentDrawQuadBase* quad,
+ ResourceProvider::ResourceId resource_id) {
+ gfx::RectF tex_coord_rect = MathUtil::ScaleRectProportional(
+ quad->tex_coord_rect, quad->rect, quad->visible_rect);
+ float tex_to_geom_scale_x = quad->rect.width() / quad->tex_coord_rect.width();
+ float tex_to_geom_scale_y =
+ quad->rect.height() / quad->tex_coord_rect.height();
+
+ bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f);
+ GLenum filter =
+ (scaled || !quad->quadTransform().IsIdentityOrIntegerTranslation())
+ ? GL_LINEAR
+ : GL_NEAREST;
+
+ ResourceProvider::ScopedSamplerGL quad_resource_lock(
+ resource_provider_, resource_id, filter);
+ SamplerType sampler =
+ SamplerTypeFromTextureTarget(quad_resource_lock.target());
+
+ float vertex_tex_translate_x = tex_coord_rect.x();
+ float vertex_tex_translate_y = tex_coord_rect.y();
+ float vertex_tex_scale_x = tex_coord_rect.width();
+ float vertex_tex_scale_y = tex_coord_rect.height();
+
+ // Map to normalized texture coordinates.
+ if (sampler != SamplerType2DRect) {
+ gfx::Size texture_size = quad->texture_size;
+ DCHECK(!texture_size.IsEmpty());
+ vertex_tex_translate_x /= texture_size.width();
+ vertex_tex_translate_y /= texture_size.height();
+ vertex_tex_scale_x /= texture_size.width();
+ vertex_tex_scale_y /= texture_size.height();
+ }
+
+ TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
+ gl_, &highp_threshold_cache_, highp_threshold_min_, quad->texture_size);
+
+ TileProgramUniforms uniforms;
+ if (quad->ShouldDrawWithBlending()) {
+ if (quad->swizzle_contents) {
+ TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision, sampler),
+ &uniforms);
+ } else {
+ TileUniformLocation(GetTileProgram(tex_coord_precision, sampler),
+ &uniforms);
+ }
+ } else {
+ if (quad->swizzle_contents) {
+ TileUniformLocation(
+ GetTileProgramSwizzleOpaque(tex_coord_precision, sampler), &uniforms);
+ } else {
+ TileUniformLocation(GetTileProgramOpaque(tex_coord_precision, sampler),
+ &uniforms);
+ }
+ }
+
+ SetUseProgram(uniforms.program);
+ GLC(gl_, gl_->Uniform1i(uniforms.sampler_location, 0));
+
+ GLC(gl_,
+ gl_->Uniform4f(uniforms.vertex_tex_transform_location,
+ vertex_tex_translate_x,
+ vertex_tex_translate_y,
+ vertex_tex_scale_x,
+ vertex_tex_scale_y));
+
+ SetBlendEnabled(quad->ShouldDrawWithBlending());
+
+ SetShaderOpacity(quad->opacity(), uniforms.alpha_location);
+
+ // Pass quad coordinates to the uniform in the same order as GeometryBinding
+ // does, then vertices will match the texture mapping in the vertex buffer.
+ // The method SetShaderQuadF() changes the order of vertices and so it's
+ // not used here.
+
+ gfx::RectF tile_rect = quad->visible_rect;
+ float gl_quad[8] = {
+ tile_rect.x(),
+ tile_rect.bottom(),
+ tile_rect.x(),
+ tile_rect.y(),
+ tile_rect.right(),
+ tile_rect.y(),
+ tile_rect.right(),
+ tile_rect.bottom(),
+ };
+ GLC(gl_, gl_->Uniform2fv(uniforms.quad_location, 4, gl_quad));
+
+ static float gl_matrix[16];
+ ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad->quadTransform());
+ GLC(gl_,
+ gl_->UniformMatrix4fv(uniforms.matrix_location, 1, false, &gl_matrix[0]));
+
+ GLC(gl_, gl_->DrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
+}
+
void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
const YUVVideoDrawQuad* quad) {
SetBlendEnabled(quad->ShouldDrawWithBlending());
@@ -2063,7 +2155,7 @@ struct TexTransformTextureProgramBinding : TextureProgramBinding {
void GLRenderer::FlushTextureQuadCache() {
// Check to see if we have anything to draw.
- if (draw_cache_.program_id == 0)
+ if (draw_cache_.program_id == -1)
return;
// Set the correct blending mode.
@@ -2119,7 +2211,7 @@ void GLRenderer::FlushTextureQuadCache() {
0));
// Clear the cache.
- draw_cache_.program_id = 0;
+ draw_cache_.program_id = -1;
draw_cache_.uv_xform_data.resize(0);
draw_cache_.vertex_opacity_data.resize(0);
draw_cache_.matrix_data.resize(0);
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index dc3160a67a..4930204eb4 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -124,13 +124,15 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
scoped_ptr<CopyOutputRequest> request) override;
void FinishDrawingQuadList() override;
- // Check if quad needs antialiasing and if so, inflate the quad and
- // fill edge array for fragment shader. local_quad is set to
- // inflated quad if antialiasing is required, otherwise it is left
- // unchanged. edge array is filled with inflated quad's edge data
- // if antialiasing is required, otherwise it is left unchanged.
// Returns true if quad requires antialiasing and false otherwise.
- static bool SetupQuadForAntialiasing(const gfx::Transform& device_transform,
+ static bool ShouldAntialiasQuad(const gfx::Transform& device_transform,
+ const DrawQuad* quad,
+ bool force_antialiasing);
+
+ // Inflate the quad and fill edge array for fragment shader.
+ // |local_quad| is set to inflated quad. |edge| array is filled with
+ // inflated quad's edge data.
+ static void SetupQuadForAntialiasing(const gfx::Transform& device_transform,
const DrawQuad* quad,
gfx::QuadF* local_quad,
float edge[24]);
@@ -168,7 +170,7 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
scoped_ptr<ScopedResource> ApplyInverseTransformForBackgroundFilters(
DrawingFrame* frame,
const RenderPassDrawQuad* quad,
- const gfx::Transform& contents_device_transform_inverse,
+ const gfx::Transform& contents_device_transform,
skia::RefPtr<SkImage> backdrop_bitmap,
const gfx::Rect& backdrop_bounding_rect);
@@ -186,6 +188,13 @@ class CC_EXPORT GLRenderer : public DirectRenderer {
void DrawContentQuad(const DrawingFrame* frame,
const ContentDrawQuadBase* quad,
ResourceProvider::ResourceId resource_id);
+ void DrawContentQuadAA(const DrawingFrame* frame,
+ const ContentDrawQuadBase* quad,
+ ResourceProvider::ResourceId resource_id,
+ const gfx::Transform& device_transform);
+ void DrawContentQuadNoAA(const DrawingFrame* frame,
+ const ContentDrawQuadBase* quad,
+ ResourceProvider::ResourceId resource_id);
void DrawYUVVideoQuad(const DrawingFrame* frame,
const YUVVideoDrawQuad* quad);
void DrawPictureQuad(const DrawingFrame* frame,
diff --git a/cc/output/gl_renderer_draw_cache.cc b/cc/output/gl_renderer_draw_cache.cc
index 51834c4602..a0004f2a06 100644
--- a/cc/output/gl_renderer_draw_cache.cc
+++ b/cc/output/gl_renderer_draw_cache.cc
@@ -7,7 +7,16 @@
namespace cc {
TexturedQuadDrawCache::TexturedQuadDrawCache()
- : program_id(0) {}
+ : program_id(-1),
+ resource_id(-1),
+ needs_blending(false),
+ background_color(0),
+ uv_xform_location(-1),
+ background_color_location(-1),
+ vertex_opacity_location(-1),
+ matrix_location(-1),
+ sampler_location(-1) {
+}
TexturedQuadDrawCache::~TexturedQuadDrawCache() {}
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index c1728698ba..bdb030f063 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -1759,14 +1759,9 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) {
blue_quad->SetNew(blue_shared_state,
viewport, // Intentionally bigger than clip.
- gfx::Rect(),
- viewport,
- gfx::RectF(viewport),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(blue_pile.get()));
+ gfx::Rect(), viewport, gfx::RectF(viewport),
+ viewport.size(), texture_format, viewport, 1.f,
+ blue_pile.get());
// One viewport-filling green quad.
scoped_refptr<FakePicturePileImpl> green_pile =
@@ -1782,16 +1777,9 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadIdentityScale) {
PictureDrawQuad* green_quad =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- green_quad->SetNew(green_shared_state,
- viewport,
- gfx::Rect(),
- viewport,
- gfx::RectF(0.f, 0.f, 1.f, 1.f),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(green_pile.get()));
+ green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
+ gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
+ texture_format, viewport, 1.f, green_pile.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -1828,16 +1816,9 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
PictureDrawQuad* green_quad =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- green_quad->SetNew(green_shared_state,
- viewport,
- gfx::Rect(),
- viewport,
- gfx::RectF(0, 0, 1, 1),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(green_pile.get()));
+ green_quad->SetNew(green_shared_state, viewport, gfx::Rect(), viewport,
+ gfx::RectF(0, 0, 1, 1), viewport.size(), texture_format,
+ viewport, 1.f, green_pile.get());
// One viewport-filling white quad.
scoped_refptr<FakePicturePileImpl> white_pile =
@@ -1853,16 +1834,9 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadOpacity) {
PictureDrawQuad* white_quad =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- white_quad->SetNew(white_shared_state,
- viewport,
- gfx::Rect(),
- viewport,
- gfx::RectF(0, 0, 1, 1),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(white_pile.get()));
+ white_quad->SetNew(white_shared_state, viewport, gfx::Rect(), viewport,
+ gfx::RectF(0, 0, 1, 1), viewport.size(), texture_format,
+ viewport, 1.f, white_pile.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -1927,16 +1901,9 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadDisableImageFiltering) {
content_to_target_transform, viewport, pass.get());
PictureDrawQuad* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- quad->SetNew(shared_state,
- viewport,
- gfx::Rect(),
- viewport,
- gfx::RectF(0, 0, 2, 2),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(pile.get()));
+ quad->SetNew(shared_state, viewport, gfx::Rect(), viewport,
+ gfx::RectF(0, 0, 2, 2), viewport.size(), texture_format,
+ viewport, 1.f, pile.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
@@ -1984,29 +1951,17 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) {
PictureDrawQuad* green_quad1 =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- green_quad1->SetNew(top_right_green_shared_quad_state,
- green_rect1,
- gfx::Rect(),
- green_rect1,
- gfx::RectF(green_rect1.size()),
- green_rect1.size(),
- texture_format,
- green_rect1,
- 1.f,
- PicturePileImpl::CreateFromOther(green_pile.get()));
+ green_quad1->SetNew(top_right_green_shared_quad_state, green_rect1,
+ gfx::Rect(), green_rect1, gfx::RectF(green_rect1.size()),
+ green_rect1.size(), texture_format, green_rect1, 1.f,
+ green_pile.get());
PictureDrawQuad* green_quad2 =
pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- green_quad2->SetNew(top_right_green_shared_quad_state,
- green_rect2,
- gfx::Rect(),
- green_rect2,
- gfx::RectF(green_rect2.size()),
- green_rect2.size(),
- texture_format,
- green_rect2,
- 1.f,
- PicturePileImpl::CreateFromOther(green_pile.get()));
+ green_quad2->SetNew(top_right_green_shared_quad_state, green_rect2,
+ gfx::Rect(), green_rect2, gfx::RectF(green_rect2.size()),
+ green_rect2.size(), texture_format, green_rect2, 1.f,
+ green_pile.get());
// Add a green clipped checkerboard in the bottom right to help test
// interleaving picture quad content and solid color content.
@@ -2072,16 +2027,10 @@ TYPED_TEST(RendererPixelTest, PictureDrawQuadNonIdentityScale) {
content_to_target_transform, quad_content_rect, pass.get());
PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- blue_quad->SetNew(blue_shared_state,
- quad_content_rect,
- gfx::Rect(),
- quad_content_rect,
- gfx::RectF(quad_content_rect),
- content_union_rect.size(),
- texture_format,
- content_union_rect,
- contents_scale,
- PicturePileImpl::CreateFromOther(pile.get()));
+ blue_quad->SetNew(blue_shared_state, quad_content_rect, gfx::Rect(),
+ quad_content_rect, gfx::RectF(quad_content_rect),
+ content_union_rect.size(), texture_format,
+ content_union_rect, contents_scale, pile.get());
// Fill left half of viewport with green.
gfx::Transform half_green_content_to_target_transform;
@@ -2284,16 +2233,9 @@ TEST_F(GLRendererPixelTest, PictureDrawQuadTexture4444) {
blue_content_to_target_transform, viewport, pass.get());
PictureDrawQuad* blue_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
- blue_quad->SetNew(blue_shared_state,
- viewport,
- gfx::Rect(),
- viewport,
- gfx::RectF(0.f, 0.f, 1.f, 1.f),
- viewport.size(),
- texture_format,
- viewport,
- 1.f,
- PicturePileImpl::CreateFromOther(blue_pile.get()));
+ blue_quad->SetNew(blue_shared_state, viewport, gfx::Rect(), viewport,
+ gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
+ texture_format, viewport, 1.f, blue_pile.get());
RenderPassList pass_list;
pass_list.push_back(pass.Pass());
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index eb5041ac58..b962d4ace9 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -546,6 +546,7 @@ std::string VertexShaderTile::GetShaderString() const {
return VERTEX_SHADER(
// clang-format on
attribute TexCoordPrecision vec4 a_position;
+ attribute TexCoordPrecision vec2 a_texCoord;
attribute float a_index;
uniform mat4 matrix;
uniform TexCoordPrecision vec2 quad[4];
@@ -554,7 +555,7 @@ std::string VertexShaderTile::GetShaderString() const {
void main() {
vec2 pos = quad[int(a_index)]; // NOLINT
gl_Position = matrix * vec4(pos, a_position.z, a_position.w);
- v_texCoord = pos.xy * vertexTexTransform.zw + vertexTexTransform.xy;
+ v_texCoord = a_texCoord * vertexTexTransform.zw + vertexTexTransform.xy;
}
// clang-format off
); // NOLINT(whitespace/parens)
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index e00ed54eab..1ebb1cff15 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -538,9 +538,20 @@ bool PicturePile::UpdateAndExpandInvalidation(
void PicturePile::SetEmptyBounds() {
tiling_.SetTilingSize(gfx::Size());
- picture_map_.clear();
- has_any_recordings_ = false;
- recorded_viewport_ = gfx::Rect();
+ Clear();
+}
+
+bool PicturePile::CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const {
+ bool include_borders = false;
+ for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ return false;
+ if (!map_iter->second.GetPicture())
+ return false;
+ }
+ return true;
}
void PicturePile::DetermineIfSolidColor() {
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index 7cd22296c5..18e1e5273a 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -55,6 +55,11 @@ class CC_EXPORT PicturePile : public PicturePileBase {
void SetPixelRecordDistanceForTesting(int d) { pixel_record_distance_ = d; }
+ protected:
+ // An internal CanRaster check that goes to the picture_map rather than
+ // using the recorded_viewport hint.
+ bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
+
private:
friend class PicturePileImpl;
diff --git a/cc/resources/picture_pile_base.cc b/cc/resources/picture_pile_base.cc
index e7888f799f..1184cf1e2a 100644
--- a/cc/resources/picture_pile_base.cc
+++ b/cc/resources/picture_pile_base.cc
@@ -130,6 +130,8 @@ void PicturePileBase::SetBufferPixels(int new_buffer_pixels) {
void PicturePileBase::Clear() {
picture_map_.clear();
recorded_viewport_ = gfx::Rect();
+ has_any_recordings_ = false;
+ is_solid_color_ = false;
}
bool PicturePileBase::HasRecordingAt(int x, int y) {
@@ -139,39 +141,6 @@ bool PicturePileBase::HasRecordingAt(int x, int y) {
return !!found->second.GetPicture();
}
-bool PicturePileBase::CanRaster(float contents_scale,
- const gfx::Rect& content_rect) const {
- if (tiling_.tiling_size().IsEmpty())
- return false;
- gfx::Rect layer_rect = gfx::ScaleToEnclosingRect(
- content_rect, 1.f / contents_scale);
- layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
-
- // Common case inside of viewport to avoid the slower map lookups.
- if (recorded_viewport_.Contains(layer_rect)) {
- // Sanity check that there are no false positives in recorded_viewport_.
- DCHECK(CanRasterSlowTileCheck(layer_rect));
- return true;
- }
-
- return CanRasterSlowTileCheck(layer_rect);
-}
-
-bool PicturePileBase::CanRasterSlowTileCheck(
- const gfx::Rect& layer_rect) const {
- bool include_borders = false;
- for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
- tile_iter;
- ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- return false;
- if (!map_iter->second.GetPicture())
- return false;
- }
- return true;
-}
-
gfx::Rect PicturePileBase::PaddedRect(const PictureMapKey& key) const {
gfx::Rect tile = tiling_.TileBounds(key.first, key.second);
return PadRect(tile);
@@ -184,25 +153,6 @@ gfx::Rect PicturePileBase::PadRect(const gfx::Rect& rect) const {
return padded_rect;
}
-void PicturePileBase::AsValueInto(base::debug::TracedValue* pictures) const {
- gfx::Rect tiling_rect(tiling_.tiling_size());
- std::set<const void*> appended_pictures;
- bool include_borders = true;
- for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
- tile_iter;
- ++tile_iter) {
- PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
- if (map_iter == picture_map_.end())
- continue;
-
- const Picture* picture = map_iter->second.GetPicture();
- if (picture && (appended_pictures.count(picture) == 0)) {
- appended_pictures.insert(picture);
- TracedValue::AppendIDRef(picture, pictures);
- }
- }
-}
-
PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {}
PicturePileBase::PictureInfo::~PictureInfo() {}
diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h
index 71e5bad185..66d37d81b8 100644
--- a/cc/resources/picture_pile_base.h
+++ b/cc/resources/picture_pile_base.h
@@ -42,16 +42,11 @@ class CC_EXPORT PicturePileBase {
int num_tiles_y() const { return tiling_.num_tiles_y(); }
gfx::Rect tile_bounds(int x, int y) const { return tiling_.TileBounds(x, y); }
bool HasRecordingAt(int x, int y);
- bool CanRaster(float contents_scale, const gfx::Rect& content_rect) const;
-
- // If this pile contains any valid recordings. May have false positives.
- bool HasRecordings() const { return has_any_recordings_; }
bool is_solid_color() const { return is_solid_color_; }
SkColor solid_color() const { return solid_color_; }
void set_is_mask(bool is_mask) { is_mask_ = is_mask; }
- bool is_mask() const { return is_mask_; }
static void ComputeTileGridInfo(const gfx::Size& tile_grid_size,
SkTileGridFactory::TileGridInfo* info);
@@ -59,12 +54,17 @@ class CC_EXPORT PicturePileBase {
void SetTileGridSize(const gfx::Size& tile_grid_size);
TilingData& tiling() { return tiling_; }
- void AsValueInto(base::debug::TracedValue* array) const;
-
SkTileGridFactory::TileGridInfo GetTileGridInfoForTesting() const {
return tile_grid_info_;
}
+ void SetRecordedViewportForTesting(const gfx::Rect& viewport) {
+ recorded_viewport_ = viewport;
+ }
+ void SetHasAnyRecordingsForTesting(bool has_recordings) {
+ has_any_recordings_ = has_recordings;
+ }
+
protected:
class CC_EXPORT PictureInfo {
public:
@@ -104,10 +104,6 @@ class CC_EXPORT PicturePileBase {
gfx::Rect PaddedRect(const PictureMapKey& key) const;
gfx::Rect PadRect(const gfx::Rect& rect) const;
- // An internal CanRaster check that goes to the picture_map rather than
- // using the recorded_viewport hint.
- bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
-
// A picture pile is a tiled set of pictures. The picture map is a map of tile
// indices to picture infos.
PictureMap picture_map_;
@@ -129,6 +125,8 @@ class CC_EXPORT PicturePileBase {
SkColor solid_color_;
private:
+ friend class PicturePileImpl;
+
void SetBufferPixels(int buffer_pixels);
DISALLOW_COPY_AND_ASSIGN(PicturePileBase);
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index 0ad746c853..de25c04721 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -26,11 +26,34 @@ scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromOther(
}
PicturePileImpl::PicturePileImpl()
- : likely_to_be_used_for_transform_animation_(false) {
+ : background_color_(SK_ColorTRANSPARENT),
+ contents_opaque_(false),
+ contents_fill_bounds_completely_(false),
+ is_solid_color_(false),
+ solid_color_(SK_ColorTRANSPARENT),
+ has_any_recordings_(false),
+ is_mask_(false),
+ clear_canvas_with_debug_color_(false),
+ min_contents_scale_(0.f),
+ slow_down_raster_scale_factor_for_debug_(0),
+ likely_to_be_used_for_transform_animation_(false) {
}
PicturePileImpl::PicturePileImpl(const PicturePileBase* other)
- : PicturePileBase(other),
+ : picture_map_(other->picture_map_),
+ tiling_(other->tiling_),
+ background_color_(other->background_color_),
+ contents_opaque_(other->contents_opaque_),
+ contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
+ is_solid_color_(other->is_solid_color_),
+ solid_color_(other->solid_color_),
+ recorded_viewport_(other->recorded_viewport_),
+ has_any_recordings_(other->has_any_recordings_),
+ is_mask_(other->is_mask_),
+ clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
+ min_contents_scale_(other->min_contents_scale_),
+ slow_down_raster_scale_factor_for_debug_(
+ other->slow_down_raster_scale_factor_for_debug_),
likely_to_be_used_for_transform_animation_(false) {
}
@@ -320,13 +343,65 @@ void PicturePileImpl::GatherPixelRefs(
bool PicturePileImpl::CoversRect(const gfx::Rect& content_rect,
float contents_scale) const {
- return CanRaster(contents_scale, content_rect);
+ if (tiling_.tiling_size().IsEmpty())
+ return false;
+ gfx::Rect layer_rect =
+ gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale);
+ layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
+
+ // Common case inside of viewport to avoid the slower map lookups.
+ if (recorded_viewport_.Contains(layer_rect)) {
+ // Sanity check that there are no false positives in recorded_viewport_.
+ DCHECK(CanRasterSlowTileCheck(layer_rect));
+ return true;
+ }
+
+ return CanRasterSlowTileCheck(layer_rect);
+}
+
+gfx::Rect PicturePileImpl::PaddedRect(const PictureMapKey& key) const {
+ gfx::Rect padded_rect = tiling_.TileBounds(key.first, key.second);
+ padded_rect.Inset(-buffer_pixels(), -buffer_pixels(), -buffer_pixels(),
+ -buffer_pixels());
+ return padded_rect;
+}
+
+bool PicturePileImpl::CanRasterSlowTileCheck(
+ const gfx::Rect& layer_rect) const {
+ bool include_borders = false;
+ for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ return false;
+ if (!map_iter->second.GetPicture())
+ return false;
+ }
+ return true;
}
bool PicturePileImpl::SuitableForDistanceFieldText() const {
return likely_to_be_used_for_transform_animation_;
}
+void PicturePileImpl::AsValueInto(base::debug::TracedValue* pictures) const {
+ gfx::Rect tiling_rect(tiling_.tiling_size());
+ std::set<const void*> appended_pictures;
+ bool include_borders = true;
+ for (TilingData::Iterator tile_iter(&tiling_, tiling_rect, include_borders);
+ tile_iter; ++tile_iter) {
+ PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index());
+ if (map_iter == picture_map_.end())
+ continue;
+
+ const Picture* picture = map_iter->second.GetPicture();
+ if (picture && (appended_pictures.count(picture) == 0)) {
+ appended_pictures.insert(picture);
+ TracedValue::AppendIDRef(picture, pictures);
+ }
+ }
+}
+
PicturePileImpl::PixelRefIterator::PixelRefIterator(
const gfx::Rect& content_rect,
float contents_scale,
diff --git a/cc/resources/picture_pile_impl.h b/cc/resources/picture_pile_impl.h
index 9f350a9933..479846bb0f 100644
--- a/cc/resources/picture_pile_impl.h
+++ b/cc/resources/picture_pile_impl.h
@@ -22,7 +22,7 @@
namespace cc {
// TODO(vmpstr): Clean up PicturePileBase and make it a member.
-class CC_EXPORT PicturePileImpl : public PicturePileBase, public RasterSource {
+class CC_EXPORT PicturePileImpl : public RasterSource {
public:
static scoped_refptr<PicturePileImpl> Create();
static scoped_refptr<PicturePileImpl> CreateFromOther(
@@ -59,6 +59,14 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase, public RasterSource {
likely_to_be_used_for_transform_animation_ = true;
}
+ gfx::Size tiling_size() const { return tiling_.tiling_size(); }
+ bool is_solid_color() const { return is_solid_color_; }
+ SkColor solid_color() const { return solid_color_; }
+ // If this pile contains any valid recordings. May have false positives.
+ bool HasRecordings() const { return has_any_recordings_; }
+ void AsValueInto(base::debug::TracedValue* array) const;
+ bool is_mask() const { return is_mask_; }
+
// Iterator used to return SkPixelRefs from this picture pile.
// Public for testing.
class CC_EXPORT PixelRefIterator {
@@ -87,10 +95,32 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase, public RasterSource {
friend class PicturePile;
friend class PixelRefIterator;
+ // TODO(vmpstr): Change this when pictures are split from invalidation info,
+ // and when PicturePileBase goes away.
+ using PictureMapKey = PicturePileBase::PictureMapKey;
+ using PictureMap = PicturePileBase::PictureMap;
+ using PictureInfo = PicturePileBase::PictureInfo;
+
PicturePileImpl();
explicit PicturePileImpl(const PicturePileBase* other);
~PicturePileImpl() override;
+ int buffer_pixels() const { return tiling_.border_texels(); }
+
+ PictureMap picture_map_;
+ TilingData tiling_;
+ SkColor background_color_;
+ bool contents_opaque_;
+ bool contents_fill_bounds_completely_;
+ bool is_solid_color_;
+ SkColor solid_color_;
+ gfx::Rect recorded_viewport_;
+ bool has_any_recordings_;
+ bool is_mask_;
+ bool clear_canvas_with_debug_color_;
+ float min_contents_scale_;
+ int slow_down_raster_scale_factor_for_debug_;
+
private:
typedef std::map<const Picture*, Region> PictureRegionMap;
@@ -112,6 +142,12 @@ class CC_EXPORT PicturePileImpl : public PicturePileBase, public RasterSource {
float contents_scale,
bool is_analysis) const;
+ // An internal CanRaster check that goes to the picture_map rather than
+ // using the recorded_viewport hint.
+ bool CanRasterSlowTileCheck(const gfx::Rect& layer_rect) const;
+
+ gfx::Rect PaddedRect(const PictureMapKey& key) const;
+
bool likely_to_be_used_for_transform_animation_;
DISALLOW_COPY_AND_ASSIGN(PicturePileImpl);
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc
index 98415ca396..60a1f0b71a 100644
--- a/cc/resources/picture_pile_unittest.cc
+++ b/cc/resources/picture_pile_unittest.cc
@@ -26,10 +26,15 @@ class TestPicturePile : public PicturePile {
PictureMap& picture_map() { return picture_map_; }
const gfx::Rect& recorded_viewport() const { return recorded_viewport_; }
- bool CanRasterLayerRect(const gfx::Rect& layer_rect) {
- return CanRaster(1.f, layer_rect);
+ bool CanRasterLayerRect(gfx::Rect layer_rect) {
+ layer_rect.Intersect(gfx::Rect(tiling_.tiling_size()));
+ if (recorded_viewport_.Contains(layer_rect))
+ return true;
+ return CanRasterSlowTileCheck(layer_rect);
}
+ bool HasRecordings() const { return has_any_recordings_; }
+
typedef PicturePile::PictureInfo PictureInfo;
typedef PicturePile::PictureMapKey PictureMapKey;
typedef PicturePile::PictureMap PictureMap;
@@ -1456,5 +1461,17 @@ TEST_F(PicturePileTest, NonSolidRectangleOnOffsettedLayerIsNonSolid) {
EXPECT_FALSE(pile_.is_solid_color());
}
+TEST_F(PicturePileTest, SetEmptyBounds) {
+ EXPECT_TRUE(pile_.is_solid_color());
+ EXPECT_FALSE(pile_.tiling_size().IsEmpty());
+ EXPECT_FALSE(pile_.picture_map().empty());
+ EXPECT_TRUE(pile_.HasRecordings());
+ pile_.SetEmptyBounds();
+ EXPECT_FALSE(pile_.is_solid_color());
+ EXPECT_TRUE(pile_.tiling_size().IsEmpty());
+ EXPECT_TRUE(pile_.picture_map().empty());
+ EXPECT_FALSE(pile_.HasRecordings());
+}
+
} // namespace
} // namespace cc
diff --git a/cc/resources/raster_worker_pool.cc b/cc/resources/raster_worker_pool.cc
index 9229db686e..ca26edd6a4 100644
--- a/cc/resources/raster_worker_pool.cc
+++ b/cc/resources/raster_worker_pool.cc
@@ -12,7 +12,9 @@
#include "base/threading/simple_thread.h"
#include "cc/base/scoped_ptr_deque.h"
#include "cc/resources/raster_source.h"
+#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
namespace cc {
namespace {
@@ -194,51 +196,72 @@ void RasterWorkerPool::InsertNodesForRasterTask(
InsertNodeForTask(graph, raster_task, priority, dependencies);
}
-// static
-void RasterWorkerPool::PlaybackToMemory(void* memory,
- ResourceFormat format,
- const gfx::Size& size,
- int stride,
- const RasterSource* raster_source,
- const gfx::Rect& rect,
- float scale) {
- SkBitmap bitmap;
+static bool IsSupportedPlaybackToMemoryFormat(ResourceFormat format) {
switch (format) {
case RGBA_4444:
- bitmap.allocN32Pixels(size.width(), size.height());
- break;
case RGBA_8888:
- case BGRA_8888: {
- SkImageInfo info =
- SkImageInfo::MakeN32Premul(size.width(), size.height());
- if (!stride)
- stride = info.minRowBytes();
- bitmap.installPixels(info, memory, stride);
- break;
- }
+ case BGRA_8888:
+ return true;
case ALPHA_8:
case LUMINANCE_8:
case RGB_565:
case ETC1:
- NOTREACHED();
- break;
+ return false;
}
+ NOTREACHED();
+ return false;
+}
- SkCanvas canvas(bitmap);
- raster_source->PlaybackToCanvas(&canvas, rect, scale);
+// static
+void RasterWorkerPool::PlaybackToMemory(void* memory,
+ ResourceFormat format,
+ const gfx::Size& size,
+ int stride,
+ const RasterSource* raster_source,
+ const gfx::Rect& rect,
+ float scale) {
+ DCHECK(IsSupportedPlaybackToMemoryFormat(format)) << format;
+ // Uses kPremul_SkAlphaType since the result is not known to be opaque.
+ SkImageInfo info =
+ SkImageInfo::MakeN32(size.width(), size.height(), kPremul_SkAlphaType);
SkColorType buffer_color_type = ResourceFormatToSkColorType(format);
- if (buffer_color_type != bitmap.colorType()) {
- SkImageInfo dst_info = bitmap.info();
- dst_info.fColorType = buffer_color_type;
- // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
- // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
- // is fixed.
- const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
- DCHECK_EQ(0u, dst_row_bytes % 4);
- bool success = bitmap.readPixels(dst_info, memory, dst_row_bytes, 0, 0);
- DCHECK_EQ(true, success);
+ bool needs_copy = buffer_color_type != info.colorType();
+
+ // TODO(danakj): Make a SkSurfaceProps with an SkPixelGeometry to enable or
+ // disable LCD text.
+ // TODO(danakj): Disable LCD text on Mac during layout tests:
+ // https://cs.chromium.org#chromium/src/third_party/WebKit/Source/platform/fonts/mac/FontPlatformDataMac.mm&l=55
+ // TODO(danakj): On Windows when LCD text is disabled, ask skia to draw LCD
+ // text offscreen and downsample it to AA text.
+ // https://cs.chromium.org#chromium/src/third_party/WebKit/Source/platform/fonts/win/FontPlatformDataWin.cpp&l=86
+ SkSurfaceProps* surface_props = nullptr;
+
+ if (!stride)
+ stride = info.minRowBytes();
+
+ if (!needs_copy) {
+ skia::RefPtr<SkSurface> surface = skia::AdoptRef(
+ SkSurface::NewRasterDirect(info, memory, stride, surface_props));
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+ return;
}
+
+ skia::RefPtr<SkSurface> surface =
+ skia::AdoptRef(SkSurface::NewRaster(info, surface_props));
+ skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas());
+ raster_source->PlaybackToCanvas(canvas.get(), rect, scale);
+
+ SkImageInfo dst_info = info;
+ dst_info.fColorType = buffer_color_type;
+ // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the
+ // bitmap data. There will be no need to call SkAlign4 once crbug.com/293728
+ // is fixed.
+ const size_t dst_row_bytes = SkAlign4(dst_info.minRowBytes());
+ DCHECK_EQ(0u, dst_row_bytes % 4);
+ bool success = canvas->readPixels(dst_info, memory, dst_row_bytes, 0, 0);
+ DCHECK_EQ(true, success);
}
} // namespace cc
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc
index 755fe1ab59..8b6a72afc6 100644
--- a/cc/resources/tile_manager.cc
+++ b/cc/resources/tile_manager.cc
@@ -561,6 +561,7 @@ void TileManager::AssignGpuMemoryToTiles(
ManagedTileState& mts = tile->managed_state();
mts.scheduled_priority = schedule_priority++;
+ mts.resolution = priority.resolution;
DCHECK(mts.draw_info.mode() ==
ManagedTileState::DrawInfo::PICTURE_PILE_MODE ||
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index 32e61c5ed7..600455f126 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -9,6 +9,7 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/copy_output_request.h"
#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
namespace cc {
@@ -57,7 +58,8 @@ void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame,
draw_callback_.Run();
draw_callback_ = callback;
factory_->manager()->DidSatisfySequences(
- surface_id_, &current_frame_->metadata.satisfies_sequences);
+ SurfaceIdAllocator::NamespaceForId(surface_id_),
+ &current_frame_->metadata.satisfies_sequences);
}
void Surface::RequestCopyOfOutput(scoped_ptr<CopyOutputRequest> copy_request) {
@@ -111,6 +113,19 @@ void Surface::RunDrawCallbacks() {
}
}
+void Surface::AddDestructionDependency(SurfaceSequence sequence) {
+ destruction_dependencies_.push_back(sequence);
+}
+
+void Surface::SatisfyDestructionDependencies(
+ base::hash_set<SurfaceSequence>* sequences) {
+ destruction_dependencies_.erase(
+ std::remove_if(
+ destruction_dependencies_.begin(), destruction_dependencies_.end(),
+ [sequences](SurfaceSequence seq) { return !!sequences->erase(seq); }),
+ destruction_dependencies_.end());
+}
+
void Surface::ClearCopyRequests() {
if (current_frame_) {
for (const auto& render_pass :
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h
index ffa50420c0..7b3fbc125b 100644
--- a/cc/surfaces/surface.h
+++ b/cc/surfaces/surface.h
@@ -17,6 +17,7 @@
#include "cc/output/copy_output_request.h"
#include "cc/quads/render_pass_id.h"
#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_sequence.h"
#include "cc/surfaces/surfaces_export.h"
#include "ui/gfx/geometry/size.h"
@@ -57,6 +58,18 @@ class CC_SURFACES_EXPORT Surface {
base::WeakPtr<SurfaceFactory> factory() { return factory_; }
+ // Add a SurfaceSequence that must be satisfied before the Surface is
+ // destroyed.
+ void AddDestructionDependency(SurfaceSequence sequence);
+
+ // Satisfy all destruction dependencies that are contained in sequences, and
+ // remove them from sequences.
+ void SatisfyDestructionDependencies(
+ base::hash_set<SurfaceSequence>* sequences);
+ size_t GetDestructionDependencyCount() const {
+ return destruction_dependencies_.size();
+ }
+
private:
void ClearCopyRequests();
@@ -66,6 +79,7 @@ class CC_SURFACES_EXPORT Surface {
// TODO(jamesr): Support multiple frames in flight.
scoped_ptr<CompositorFrame> current_frame_;
int frame_index_;
+ std::vector<SurfaceSequence> destruction_dependencies_;
base::Closure draw_callback_;
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
index 88c54557cb..574f5d1fae 100644
--- a/cc/surfaces/surface_factory.cc
+++ b/cc/surfaces/surface_factory.cc
@@ -25,8 +25,8 @@ SurfaceFactory::~SurfaceFactory() {
}
void SurfaceFactory::DestroyAll() {
- for (auto& surface : surface_map_)
- manager_->DeregisterSurface(surface.first);
+ for (auto it = surface_map_.begin(); it != surface_map_.end(); ++it)
+ manager_->Destroy(surface_map_.take(it));
surface_map_.clear();
}
@@ -41,17 +41,7 @@ void SurfaceFactory::Destroy(SurfaceId surface_id) {
OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
DCHECK(it->second->factory().get() == this);
- manager_->DeregisterSurface(surface_id);
- surface_map_.erase(it);
-}
-
-void SurfaceFactory::DestroyOnSequence(
- SurfaceId surface_id,
- const std::set<SurfaceSequence>& dependency_set) {
- OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
- DCHECK(it != surface_map_.end());
- DCHECK(it->second->factory().get() == this);
- manager_->DestroyOnSequence(surface_map_.take_and_erase(it), dependency_set);
+ manager_->Destroy(surface_map_.take_and_erase(it));
}
void SurfaceFactory::SubmitFrame(SurfaceId surface_id,
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h
index 13d1d63fb1..8e9211c57b 100644
--- a/cc/surfaces/surface_factory.h
+++ b/cc/surfaces/surface_factory.h
@@ -40,8 +40,6 @@ class CC_SURFACES_EXPORT SurfaceFactory
void Create(SurfaceId surface_id, const gfx::Size& size);
void Destroy(SurfaceId surface_id);
- void DestroyOnSequence(SurfaceId surface_id,
- const std::set<SurfaceSequence>& dependency_set);
void DestroyAll();
// A frame can only be submitted to a surface created by this factory,
// although the frame may reference surfaces created by other factories.
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
index e36636c5f1..14a25fdf71 100644
--- a/cc/surfaces/surface_factory_unittest.cc
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -381,9 +381,9 @@ TEST_F(SurfaceFactoryTest, DestroySequence) {
factory_.Create(id2, gfx::Size(5, 5));
// Check that waiting before the sequence is satisfied works.
- std::set<SurfaceSequence> sequence;
- sequence.insert(SurfaceSequence(0, 4));
- factory_.DestroyOnSequence(id2, sequence);
+ manager_.GetSurfaceForId(id2)
+ ->AddDestructionDependency(SurfaceSequence(0, 4));
+ factory_.Destroy(id2);
scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
@@ -396,10 +396,10 @@ TEST_F(SurfaceFactoryTest, DestroySequence) {
// Check that waiting after the sequence is satisfied works.
factory_.Create(id2, gfx::Size(5, 5));
- sequence.clear();
- sequence.insert(SurfaceSequence(0, 6));
DCHECK(manager_.GetSurfaceForId(id2));
- factory_.DestroyOnSequence(id2, sequence);
+ manager_.GetSurfaceForId(id2)
+ ->AddDestructionDependency(SurfaceSequence(0, 6));
+ factory_.Destroy(id2);
DCHECK(!manager_.GetSurfaceForId(id2));
}
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index 920f464cdd..050f04b062 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -19,8 +19,8 @@ SurfaceManager::~SurfaceManager() {
for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin();
it != surfaces_to_destroy_.end();
++it) {
- DeregisterSurface(it->first->surface_id());
- delete it->first;
+ DeregisterSurface((*it)->surface_id());
+ delete *it;
}
}
@@ -38,20 +38,19 @@ void SurfaceManager::DeregisterSurface(SurfaceId surface_id) {
surface_map_.erase(it);
}
-void SurfaceManager::DestroyOnSequence(
- scoped_ptr<Surface> surface,
- const std::set<SurfaceSequence>& dependency_set) {
- surfaces_to_destroy_.push_back(make_pair(surface.release(), dependency_set));
+void SurfaceManager::Destroy(scoped_ptr<Surface> surface) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ surfaces_to_destroy_.push_back(surface.release());
SearchForSatisfaction();
}
-void SurfaceManager::DidSatisfySequences(SurfaceId id,
+void SurfaceManager::DidSatisfySequences(uint32_t id_namespace,
std::vector<uint32_t>* sequence) {
+ DCHECK(thread_checker_.CalledOnValidThread());
for (std::vector<uint32_t>::iterator it = sequence->begin();
it != sequence->end();
++it) {
- satisfied_sequences_.insert(
- SurfaceSequence(SurfaceIdAllocator::NamespaceForId(id), *it));
+ satisfied_sequences_.insert(SurfaceSequence(id_namespace, *it));
}
sequence->clear();
SearchForSatisfaction();
@@ -60,21 +59,9 @@ void SurfaceManager::DidSatisfySequences(SurfaceId id,
void SurfaceManager::SearchForSatisfaction() {
for (SurfaceDestroyList::iterator dest_it = surfaces_to_destroy_.begin();
dest_it != surfaces_to_destroy_.end();) {
- std::set<SurfaceSequence>& dependency_set = dest_it->second;
-
- for (std::set<SurfaceSequence>::iterator it = dependency_set.begin();
- it != dependency_set.end();) {
- if (satisfied_sequences_.count(*it) > 0) {
- satisfied_sequences_.erase(*it);
- std::set<SurfaceSequence>::iterator old_it = it;
- ++it;
- dependency_set.erase(old_it);
- } else {
- ++it;
- }
- }
- if (dependency_set.empty()) {
- scoped_ptr<Surface> surf(dest_it->first);
+ (*dest_it)->SatisfyDestructionDependencies(&satisfied_sequences_);
+ if (!(*dest_it)->GetDestructionDependencyCount()) {
+ scoped_ptr<Surface> surf(*dest_it);
DeregisterSurface(surf->surface_id());
dest_it = surfaces_to_destroy_.erase(dest_it);
} else {
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index 66db9d90ee..d6303523b4 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -6,7 +6,6 @@
#define CC_SURFACES_SURFACE_MANAGER_H_
#include <list>
-#include <set>
#include <vector>
#include "base/containers/hash_tables.h"
@@ -31,8 +30,7 @@ class CC_SURFACES_EXPORT SurfaceManager {
void DeregisterSurface(SurfaceId surface_id);
// Destroy the Surface once a set of sequence numbers has been satisfied.
- void DestroyOnSequence(scoped_ptr<Surface> surface,
- const std::set<SurfaceSequence>& dependency_set);
+ void Destroy(scoped_ptr<Surface> surface);
Surface* GetSurfaceForId(SurfaceId surface_id);
@@ -46,8 +44,10 @@ class CC_SURFACES_EXPORT SurfaceManager {
void SurfaceModified(SurfaceId surface_id);
- // A frame for a surface satisfies a set of sequence numbers.
- void DidSatisfySequences(SurfaceId id, std::vector<uint32_t>* sequence);
+ // A frame for a surface satisfies a set of sequence numbers in a particular
+ // id namespace.
+ void DidSatisfySequences(uint32_t id_namespace,
+ std::vector<uint32_t>* sequence);
private:
void SearchForSatisfaction();
@@ -59,13 +59,12 @@ class CC_SURFACES_EXPORT SurfaceManager {
// List of surfaces to be destroyed, along with what sequences they're still
// waiting on.
- typedef std::list<std::pair<Surface*, std::set<SurfaceSequence>>>
- SurfaceDestroyList;
+ typedef std::list<Surface*> SurfaceDestroyList;
SurfaceDestroyList surfaces_to_destroy_;
// Set of SurfaceSequences that have been satisfied by a frame but not yet
// waited on.
- std::set<SurfaceSequence> satisfied_sequences_;
+ base::hash_set<SurfaceSequence> satisfied_sequences_;
DISALLOW_COPY_AND_ASSIGN(SurfaceManager);
};
diff --git a/cc/surfaces/surface_sequence.h b/cc/surfaces/surface_sequence.h
index 4c99e45858..72f4bc9926 100644
--- a/cc/surfaces/surface_sequence.h
+++ b/cc/surfaces/surface_sequence.h
@@ -5,6 +5,8 @@
#ifndef CC_SURFACES_SURFACE_SEQUENCE_H_
#define CC_SURFACES_SURFACE_SEQUENCE_H_
+#include "base/containers/hash_tables.h"
+
namespace cc {
// A per-surface-namespace sequence number that's used to coordinate
@@ -14,6 +16,7 @@ struct SurfaceSequence {
SurfaceSequence() : id_namespace(0u), sequence(0u) {}
SurfaceSequence(uint32_t id_namespace, uint32_t sequence)
: id_namespace(id_namespace), sequence(sequence) {}
+ bool is_null() const { return id_namespace == 0u && sequence == 0u; }
uint32_t id_namespace;
uint32_t sequence;
@@ -35,4 +38,13 @@ inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) {
} // namespace cc
+namespace BASE_HASH_NAMESPACE {
+template <>
+struct hash<cc::SurfaceSequence> {
+ size_t operator()(cc::SurfaceSequence key) const {
+ return base::HashPair(key.id_namespace, key.sequence);
+ }
+};
+} // namespace BASE_HASH_NAMESPACE
+
#endif // CC_SURFACES_SURFACE_SEQUENCE_H_
diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc
index 32a6589ee9..e688d22020 100644
--- a/cc/test/fake_picture_pile_impl.cc
+++ b/cc/test/fake_picture_pile_impl.cc
@@ -4,9 +4,11 @@
#include "cc/test/fake_picture_pile_impl.h"
+#include <algorithm>
#include <limits>
#include <utility>
+#include "cc/resources/picture_pile.h"
#include "cc/test/impl_side_painting_settings.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,62 +16,71 @@ namespace cc {
FakePicturePileImpl::FakePicturePileImpl() {}
+FakePicturePileImpl::FakePicturePileImpl(const PicturePileBase* other)
+ : PicturePileImpl(other),
+ tile_grid_info_(other->GetTileGridInfoForTesting()) {
+}
+
FakePicturePileImpl::~FakePicturePileImpl() {}
scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateFilledPile(
const gfx::Size& tile_size,
const gfx::Size& layer_bounds) {
- scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl());
- pile->tiling().SetTilingSize(layer_bounds);
- pile->tiling().SetMaxTextureSize(tile_size);
- pile->SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
- pile->recorded_viewport_ = gfx::Rect(layer_bounds);
- pile->has_any_recordings_ = true;
- for (int x = 0; x < pile->tiling().num_tiles_x(); ++x) {
- for (int y = 0; y < pile->tiling().num_tiles_y(); ++y)
- pile->AddRecordingAt(x, y);
+ PicturePile pile;
+ pile.tiling().SetTilingSize(layer_bounds);
+ pile.tiling().SetMaxTextureSize(tile_size);
+ pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
+ pile.SetRecordedViewportForTesting(gfx::Rect(layer_bounds));
+ pile.SetHasAnyRecordingsForTesting(true);
+
+ auto pile_impl = make_scoped_refptr(new FakePicturePileImpl(&pile));
+ for (int x = 0; x < pile_impl->tiling().num_tiles_x(); ++x) {
+ for (int y = 0; y < pile_impl->tiling().num_tiles_y(); ++y)
+ pile_impl->AddRecordingAt(x, y);
}
- return pile;
+ return pile_impl;
}
scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateEmptyPile(
const gfx::Size& tile_size,
const gfx::Size& layer_bounds) {
- scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl());
- pile->tiling().SetTilingSize(layer_bounds);
- pile->tiling().SetMaxTextureSize(tile_size);
- pile->SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
- pile->recorded_viewport_ = gfx::Rect();
- pile->has_any_recordings_ = false;
- return pile;
+ PicturePile pile;
+ pile.tiling().SetTilingSize(layer_bounds);
+ pile.tiling().SetMaxTextureSize(tile_size);
+ pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
+ pile.SetRecordedViewportForTesting(gfx::Rect());
+ pile.SetHasAnyRecordingsForTesting(false);
+ return make_scoped_refptr(new FakePicturePileImpl(&pile));
}
scoped_refptr<FakePicturePileImpl>
FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings(
const gfx::Size& tile_size,
const gfx::Size& layer_bounds) {
- scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl());
- pile->tiling().SetTilingSize(layer_bounds);
- pile->tiling().SetMaxTextureSize(tile_size);
- pile->SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
+ PicturePile pile;
+ pile.tiling().SetTilingSize(layer_bounds);
+ pile.tiling().SetMaxTextureSize(tile_size);
+ pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size);
// This simulates a false positive for this flag.
- pile->recorded_viewport_ = gfx::Rect();
- pile->has_any_recordings_ = true;
- return pile;
+ pile.SetRecordedViewportForTesting(gfx::Rect());
+ pile.SetHasAnyRecordingsForTesting(true);
+ return make_scoped_refptr(new FakePicturePileImpl(&pile));
}
scoped_refptr<FakePicturePileImpl>
FakePicturePileImpl::CreateInfiniteFilledPile() {
- scoped_refptr<FakePicturePileImpl> pile(new FakePicturePileImpl());
+ PicturePile pile;
gfx::Size size(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max());
- pile->tiling().SetTilingSize(size);
- pile->tiling().SetMaxTextureSize(size);
- pile->SetTileGridSize(size);
- pile->recorded_viewport_ = gfx::Rect(size);
- pile->has_any_recordings_ = true;
- pile->AddRecordingAt(0, 0);
- return pile;
+ pile.tiling().SetTilingSize(size);
+ pile.tiling().SetMaxTextureSize(size);
+ pile.SetTileGridSize(size);
+ pile.SetRecordedViewportForTesting(gfx::Rect(size));
+ pile.SetHasAnyRecordingsForTesting(true);
+
+ auto pile_impl = make_scoped_refptr(new FakePicturePileImpl(&pile));
+ pile_impl->AddRecordingAt(0, 0);
+ return pile_impl;
}
void FakePicturePileImpl::AddRecordingAt(int x, int y) {
@@ -103,6 +114,13 @@ void FakePicturePileImpl::RemoveRecordingAt(int x, int y) {
EXPECT_FALSE(HasRecordingAt(x, y));
}
+bool FakePicturePileImpl::HasRecordingAt(int x, int y) const {
+ PictureMap::const_iterator found = picture_map_.find(PictureMapKey(x, y));
+ if (found == picture_map_.end())
+ return false;
+ return !!found->second.GetPicture();
+}
+
void FakePicturePileImpl::RerecordPile() {
for (int y = 0; y < num_tiles_y(); ++y) {
for (int x = 0; x < num_tiles_x(); ++x) {
@@ -112,4 +130,37 @@ void FakePicturePileImpl::RerecordPile() {
}
}
+void FakePicturePileImpl::SetMinContentsScale(float min_contents_scale) {
+ if (min_contents_scale_ == min_contents_scale)
+ return;
+
+ // Picture contents are played back scaled. When the final contents scale is
+ // less than 1 (i.e. low res), then multiple recorded pixels will be used
+ // to raster one final pixel. To avoid splitting a final pixel across
+ // pictures (which would result in incorrect rasterization due to blending), a
+ // buffer margin is added so that any picture can be snapped to integral
+ // final pixels.
+ //
+ // For example, if a 1/4 contents scale is used, then that would be 3 buffer
+ // pixels, since that's the minimum number of pixels to add so that resulting
+ // content can be snapped to a four pixel aligned grid.
+ int buffer_pixels = static_cast<int>(ceil(1 / min_contents_scale) - 1);
+ buffer_pixels = std::max(0, buffer_pixels);
+ SetBufferPixels(buffer_pixels);
+ min_contents_scale_ = min_contents_scale;
+}
+
+void FakePicturePileImpl::SetBufferPixels(int new_buffer_pixels) {
+ if (new_buffer_pixels == buffer_pixels())
+ return;
+
+ Clear();
+ tiling_.SetBorderTexels(new_buffer_pixels);
+}
+
+void FakePicturePileImpl::Clear() {
+ picture_map_.clear();
+ recorded_viewport_ = gfx::Rect();
+}
+
} // namespace cc
diff --git a/cc/test/fake_picture_pile_impl.h b/cc/test/fake_picture_pile_impl.h
index 10c769aefa..ab27238bc7 100644
--- a/cc/test/fake_picture_pile_impl.h
+++ b/cc/test/fake_picture_pile_impl.h
@@ -72,12 +72,24 @@ class FakePicturePileImpl : public PicturePileImpl {
is_solid_color_ = is_solid_color;
}
+ bool HasRecordingAt(int x, int y) const;
+ void SetIsMask(bool mask) { is_mask_ = mask; }
+
+ int num_tiles_x() const { return tiling_.num_tiles_x(); }
+ int num_tiles_y() const { return tiling_.num_tiles_y(); }
+
+ void SetMinContentsScale(float scale);
+ void SetBufferPixels(int new_buffer_pixels);
+ void Clear();
+
protected:
FakePicturePileImpl();
+ explicit FakePicturePileImpl(const PicturePileBase* other);
~FakePicturePileImpl() override;
FakeContentLayerClient client_;
SkPaint default_paint_;
+ SkTileGridFactory::TileGridInfo tile_grid_info_;
};
} // namespace cc
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 3898156776..af7eb5bc96 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -128,7 +128,9 @@ LayerTreeHost::LayerTreeHost(
id_(s_layer_tree_host_sequence_number.GetNext() + 1),
next_commit_forces_redraw_(false),
shared_bitmap_manager_(shared_bitmap_manager),
- gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {
+ gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+ surface_id_namespace_(0u),
+ next_surface_sequence_(1u) {
if (settings_.accelerated_animation_enabled)
animation_registrar_ = AnimationRegistrar::Create();
rendering_stats_instrumentation_->set_record_rendering_stats(
@@ -167,15 +169,15 @@ void LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) {
LayerTreeHost::~LayerTreeHost() {
TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
- DCHECK(swap_promise_monitor_.empty());
-
- BreakSwapPromises(SwapPromise::COMMIT_FAILS);
-
overhang_ui_resource_ = nullptr;
if (root_layer_.get())
root_layer_->SetLayerTreeHost(NULL);
+ DCHECK(swap_promise_monitor_.empty());
+
+ BreakSwapPromises(SwapPromise::COMMIT_FAILS);
+
if (proxy_) {
DCHECK(proxy_->IsMainThread());
proxy_->Stop();
@@ -1336,4 +1338,12 @@ void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
swap_promise_list_.clear();
}
+void LayerTreeHost::set_surface_id_namespace(uint32_t id_namespace) {
+ surface_id_namespace_ = id_namespace;
+}
+
+SurfaceSequence LayerTreeHost::CreateSurfaceSequence() {
+ return SurfaceSequence(surface_id_namespace_, next_surface_sequence_++);
+}
+
} // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 10964160bb..a56a6cd43d 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -34,6 +34,7 @@
#include "cc/output/output_surface.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/scoped_ui_resource.h"
+#include "cc/surfaces/surface_sequence.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_settings.h"
@@ -307,6 +308,9 @@ class CC_EXPORT LayerTreeHost {
size_t num_queued_swap_promises() const { return swap_promise_list_.size(); }
+ void set_surface_id_namespace(uint32_t id_namespace);
+ SurfaceSequence CreateSurfaceSequence();
+
protected:
LayerTreeHost(LayerTreeHostClient* client,
SharedBitmapManager* shared_bitmap_manager,
@@ -464,6 +468,9 @@ class CC_EXPORT LayerTreeHost {
ScopedPtrVector<SwapPromise> swap_promise_list_;
std::set<SwapPromiseMonitor*> swap_promise_monitor_;
+ uint32_t surface_id_namespace_;
+ uint32_t next_surface_sequence_;
+
DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
};
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 20f0c6dfb0..00be57f29e 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -152,8 +152,14 @@ size_t GetMaxTransferBufferUsageBytes(
unsigned GetMapImageTextureTarget(
const ContextProvider::Capabilities& context_capabilities) {
+// TODO(reveman): This should be a setting passed to the compositor instead
+// of hard-coded here. The target that need to be used depends on our choice
+// of GpuMemoryBuffer type. Note: SURFACE_TEXTURE needs EXTERNAL_OES,
+// IO_SURFACE needs RECTANGLE_ARB. crbug.com/431059
+#if defined(OS_ANDROID)
if (context_capabilities.gpu.egl_image_external)
return GL_TEXTURE_EXTERNAL_OES;
+#endif
if (context_capabilities.gpu.texture_rectangle)
return GL_TEXTURE_RECTANGLE_ARB;
@@ -2632,11 +2638,12 @@ bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll(
return false;
}
-bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta) {
+InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
+ const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta) {
TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
if (!CurrentlyScrollingLayer())
- return false;
+ return InputHandlerScrollResult();
gfx::Vector2dF pending_delta = scroll_delta;
gfx::Vector2dF unused_root_delta;
@@ -2757,15 +2764,14 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
accumulated_root_overscroll_.set_x(0);
if (did_scroll_y)
accumulated_root_overscroll_.set_y(0);
-
accumulated_root_overscroll_ += unused_root_delta;
- bool did_overscroll = !unused_root_delta.IsZero();
- if (did_overscroll && input_handler_client_) {
- input_handler_client_->DidOverscroll(
- viewport_point, accumulated_root_overscroll_, unused_root_delta);
- }
- return did_scroll_content || did_scroll_top_controls;
+ InputHandlerScrollResult scroll_result;
+ scroll_result.did_scroll = did_scroll_content || did_scroll_top_controls;
+ scroll_result.did_overscroll_root = !unused_root_delta.IsZero();
+ scroll_result.accumulated_root_overscroll = accumulated_root_overscroll_;
+ scroll_result.unused_scroll_delta = unused_root_delta;
+ return scroll_result;
}
// This implements scrolling by page as described here:
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 157fe00eb6..2309ef77d5 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -136,8 +136,9 @@ class CC_EXPORT LayerTreeHostImpl
InputHandler::ScrollStatus ScrollAnimated(
const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta) override;
- bool ScrollBy(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta) override;
+ InputHandlerScrollResult ScrollBy(
+ const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta) override;
bool ScrollVerticallyByPage(const gfx::Point& viewport_point,
ScrollDirection direction) override;
void SetRootLayerScrollOffsetDelegate(
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 773fd1f878..45d636a547 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -777,27 +777,40 @@ TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
// Trying to scroll to the left/top will not succeed.
- EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
- EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
- EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
+ EXPECT_FALSE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
+ EXPECT_FALSE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
+ EXPECT_FALSE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
// Scrolling to the right/bottom will succeed.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
// Scrolling to left/top will now succeed.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
// Scrolling diagonally against an edge will succeed.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
// Trying to scroll more than the available space will also succeed.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
}
TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
@@ -3710,6 +3723,7 @@ TEST_F(LayerTreeHostImplTest,
}
TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
+ InputHandlerScrollResult scroll_result;
SetupScrollAndContentsLayers(gfx::Size(100, 100));
host_impl_->SetViewportSize(gfx::Size(50, 50));
host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
@@ -3719,38 +3733,105 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
// In-bounds scrolling does not affect overscroll.
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_FALSE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
// Overscroll events are reflected immediately.
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
// In-bounds scrolling resets accumulated overscroll for the scrolled axes.
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_FALSE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
+ EXPECT_FALSE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_FALSE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
// Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
// as no scroll occurs.
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ EXPECT_FALSE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ EXPECT_FALSE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
// Overscroll resets on valid scroll.
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_FALSE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
- host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
+ scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
+ EXPECT_TRUE(scroll_result.did_scroll);
+ EXPECT_TRUE(scroll_result.did_overscroll_root);
+ EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
+ EXPECT_EQ(scroll_result.accumulated_root_overscroll,
+ host_impl_->accumulated_root_overscroll());
+
host_impl_->ScrollEnd();
}
@@ -5964,7 +6045,7 @@ TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
public:
- using GLRenderer::SetupQuadForAntialiasing;
+ using GLRenderer::ShouldAntialiasQuad;
};
TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
@@ -6022,11 +6103,9 @@ TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
- float edge[24];
- gfx::QuadF device_layer_quad;
bool antialiased =
- GLRendererWithSetupQuadForAntialiasing::SetupQuadForAntialiasing(
- quad->quadTransform(), quad, &device_layer_quad, edge);
+ GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
+ quad->quadTransform(), quad, false);
EXPECT_FALSE(antialiased);
host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
@@ -6556,7 +6635,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
gfx::Vector2d scroll_delta(0, -2);
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
// The grand child should have scrolled up to its limit.
scroll_info = host_impl_->ProcessScrollDeltas();
@@ -6566,7 +6645,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
// The child should have received the bubbled delta, but the locked
// scrolling layer should remain set as the grand child.
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
scroll_info = host_impl_->ProcessScrollDeltas();
ASSERT_EQ(2u, scroll_info->scrolls.size());
ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
@@ -6576,7 +6655,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
// The first |ScrollBy| after the fling should re-lock the scrolling
// layer to the first layer that scrolled, which is the child.
EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin());
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
+ EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
// The child should have scrolled up to its limit.
@@ -6586,7 +6665,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
// As the locked layer is at it's limit, no further scrolling can occur.
- EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta));
+ EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
host_impl_->ScrollEnd();
}
@@ -6984,7 +7063,8 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
// Scrolling normally should not trigger any forwarding.
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
host_impl_->ScrollEnd();
EXPECT_EQ(0, set_needs_commit_count);
@@ -6996,7 +7076,8 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
scroll_layer->SetHaveScrollEventHandlers(true);
EXPECT_EQ(InputHandler::ScrollStarted,
host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
host_impl_->ScrollEnd();
EXPECT_EQ(0, set_needs_commit_count);
@@ -7051,7 +7132,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Scroll just the top controls and verify that the scroll succeeds.
const float residue = 10;
float offset = top_controls_height_ - residue;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->TotalScrollOffset().ToString());
@@ -7059,7 +7141,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Scroll across the boundary
const float content_scroll = 20;
offset = residue + content_scroll;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(-top_controls_height_,
host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
@@ -7067,7 +7150,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// Now scroll back to the top of the content
offset = -content_scroll;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(-top_controls_height_,
host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
@@ -7075,13 +7159,15 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
// And scroll the top controls completely into view
offset = -top_controls_height_;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->TotalScrollOffset().ToString());
// And attempt to scroll past the end
- EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_FALSE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->TotalScrollOffset().ToString());
@@ -7105,7 +7191,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
// Scroll the top controls partially.
const float residue = 35;
float offset = top_controls_height_ - residue;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF().ToString(),
scroll_layer->TotalScrollOffset().ToString());
@@ -7173,7 +7260,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
// Scroll the top controls partially.
const float residue = 15;
float offset = top_controls_height_ - residue;
- EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)));
+ EXPECT_TRUE(
+ host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
scroll_layer->TotalScrollOffset().ToString());
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index e922f21712..8e7d220d1a 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1091,13 +1091,6 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient {
*received_stop_flinging_ = true;
}
- void DidOverscroll(const gfx::PointF& causal_event_viewport_point,
- const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta) override {
- if (!task_runner_->BelongsToCurrentThread())
- ADD_FAILURE() << "DidOverscroll called on wrong thread";
- }
-
private:
base::SingleThreadTaskRunner* task_runner_;
bool* received_stop_flinging_;