blob: 4c6fa948a3968eef14bdfe745c4f64228921539b [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]556fd292013-03-18 08:03:045#include "cc/trees/layer_tree_host_impl.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]ac7c7f52012-11-08 06:26:507#include <cmath>
8
[email protected]59cb7b352012-10-30 06:45:489#include "base/bind.h"
[email protected]65bfd9972012-10-19 03:39:3710#include "base/command_line.h"
[email protected]c7278e5b2012-10-11 02:35:4611#include "base/hash_tables.h"
[email protected]681ccff2013-03-18 06:13:5212#include "cc/base/math_util.h"
[email protected]aa0a9d32012-10-24 01:58:1013#include "cc/delegated_renderer_layer_impl.h"
[email protected]d50c6862012-10-23 02:08:3114#include "cc/heads_up_display_layer_impl.h"
[email protected]3052b10f2013-03-18 07:41:2115#include "cc/input/top_controls_manager.h"
[email protected]d50c6862012-10-23 02:08:3116#include "cc/io_surface_layer_impl.h"
17#include "cc/layer_impl.h"
18#include "cc/layer_tiling_data.h"
[email protected]7f0d825f2013-03-18 07:24:3019#include "cc/output/compositor_frame_metadata.h"
20#include "cc/output/gl_renderer.h"
[email protected]55a124d02012-10-22 03:07:1321#include "cc/quad_sink.h"
[email protected]89e8267a2013-03-18 07:50:5622#include "cc/quads/render_pass_draw_quad.h"
23#include "cc/quads/solid_color_draw_quad.h"
24#include "cc/quads/texture_draw_quad.h"
25#include "cc/quads/tile_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4026#include "cc/scrollbar_geometry_fixed_thumb.h"
27#include "cc/scrollbar_layer_impl.h"
[email protected]c2d0c5a2013-02-26 04:43:3628#include "cc/solid_color_layer_impl.h"
[email protected]101441ce2012-10-16 01:45:0329#include "cc/test/animation_test_common.h"
[email protected]a46f32932012-12-07 21:43:1630#include "cc/test/fake_output_surface.h"
[email protected]61de5812012-11-08 07:03:4431#include "cc/test/fake_proxy.h"
[email protected]d993b602013-01-04 02:08:1232#include "cc/test/fake_video_frame_provider.h"
[email protected]101441ce2012-10-16 01:45:0333#include "cc/test/fake_web_scrollbar_theme_geometry.h"
34#include "cc/test/geometry_test_utils.h"
35#include "cc/test/layer_test_common.h"
36#include "cc/test/render_pass_test_common.h"
[email protected]c8756fbe2013-02-12 01:53:4937#include "cc/test/test_web_graphics_context_3d.h"
[email protected]4456eee22012-10-19 18:16:3838#include "cc/texture_layer_impl.h"
[email protected]da2c9122012-10-20 23:13:0639#include "cc/tiled_layer_impl.h"
[email protected]556fd292013-03-18 08:03:0440#include "cc/trees/layer_tree_impl.h"
41#include "cc/trees/single_thread_proxy.h"
[email protected]da2c9122012-10-20 23:13:0642#include "cc/video_layer_impl.h"
[email protected]59cb7b352012-10-30 06:45:4843#include "media/base/media.h"
[email protected]7f0c53db2012-10-02 00:23:1844#include "testing/gmock/include/gmock/gmock.h"
45#include "testing/gtest/include/gtest/gtest.h"
[email protected]aad0a0072012-11-01 18:15:5846#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1347#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1448
[email protected]94f206c12012-08-25 00:09:1449using ::testing::Mock;
50using ::testing::Return;
51using ::testing::AnyNumber;
52using ::testing::AtLeast;
53using ::testing::_;
[email protected]568285b2013-01-07 23:19:1954using media::VideoFrame;
[email protected]94f206c12012-08-25 00:09:1455
[email protected]ba565742012-11-10 09:29:4856namespace cc {
[email protected]94f206c12012-08-25 00:09:1457namespace {
58
[email protected]c2d0c5a2013-02-26 04:43:3659class LayerTreeHostImplTest : public testing::Test,
[email protected]9bdcfd642012-11-14 21:24:2660 public LayerTreeHostImplClient {
[email protected]94f206c12012-08-25 00:09:1461public:
[email protected]96baf3e2012-10-22 23:09:5562 LayerTreeHostImplTest()
[email protected]61de5812012-11-08 07:03:4463 : m_proxy(scoped_ptr<Thread>(NULL))
64 , m_alwaysImplThread(&m_proxy)
65 , m_alwaysMainThreadBlocked(&m_proxy)
66 , m_onCanDrawStateChangedCalled(false)
[email protected]2e7ca422012-12-20 02:57:2767 , m_hasPendingTree(false)
[email protected]8db2213c2012-09-05 22:08:2168 , m_didRequestCommit(false)
[email protected]94f206c12012-08-25 00:09:1469 , m_didRequestRedraw(false)
[email protected]86126792013-03-16 20:07:5470 , m_didUploadVisibleTile(false)
[email protected]b1969fa2012-10-17 20:16:2971 , m_reduceMemoryResult(true)
[email protected]94f206c12012-08-25 00:09:1472 {
[email protected]59cb7b352012-10-30 06:45:4873 media::InitializeMediaLibraryForTesting();
[email protected]1c0c9bc2012-10-08 22:41:4874 }
75
76 virtual void SetUp()
77 {
[email protected]96baf3e2012-10-22 23:09:5578 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:5879 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]94f206c12012-08-25 00:09:1480
[email protected]c1bb5af2013-03-13 19:06:2781 m_hostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
82 m_hostImpl->InitializeRenderer(createOutputSurface());
83 m_hostImpl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
[email protected]94f206c12012-08-25 00:09:1484 }
85
[email protected]1c0c9bc2012-10-08 22:41:4886 virtual void TearDown()
87 {
[email protected]1c0c9bc2012-10-08 22:41:4888 }
89
[email protected]c1bb5af2013-03-13 19:06:2790 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE { }
91 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE { }
92 virtual void OnVSyncParametersChanged(base::TimeTicks, base::TimeDelta) OVERRIDE { }
93 virtual void OnCanDrawStateChanged(bool canDraw) OVERRIDE { m_onCanDrawStateChangedCalled = true; }
94 virtual void OnHasPendingTreeStateChanged(bool hasPendingTree) OVERRIDE { m_hasPendingTree = hasPendingTree; }
95 virtual void SetNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
[email protected]86126792013-03-16 20:07:5496 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE { m_didUploadVisibleTile = true; }
[email protected]c1bb5af2013-03-13 19:06:2797 virtual void SetNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
98 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE { }
99 virtual void PostAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, base::Time wallClockTime) OVERRIDE { }
100 virtual bool ReduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return m_reduceMemoryResult; }
101 virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE { }
102 virtual void SendManagedMemoryStats() OVERRIDE { }
103 virtual bool IsInsideDraw() OVERRIDE { return false; }
104 virtual void RenewTreePriority() OVERRIDE { }
[email protected]0fc818e2013-03-18 06:45:20105 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) OVERRIDE { }
[email protected]b1969fa2012-10-17 20:16:29106
107 void setReduceMemoryResult(bool reduceMemoryResult) { m_reduceMemoryResult = reduceMemoryResult; }
[email protected]94f206c12012-08-25 00:09:14108
[email protected]586d51ed2012-12-07 20:31:45109 void createLayerTreeHost(bool partialSwap, scoped_ptr<OutputSurface> outputSurface)
[email protected]94f206c12012-08-25 00:09:14110 {
[email protected]96baf3e2012-10-22 23:09:55111 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:58112 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]9bdcfd642012-11-14 21:24:26113 settings.partialSwapEnabled = partialSwap;
[email protected]94f206c12012-08-25 00:09:14114
[email protected]c1bb5af2013-03-13 19:06:27115 m_hostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:14116
[email protected]c1bb5af2013-03-13 19:06:27117 m_hostImpl->InitializeRenderer(outputSurface.Pass());
118 m_hostImpl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
[email protected]586d51ed2012-12-07 20:31:45119 }
[email protected]94f206c12012-08-25 00:09:14120
[email protected]586d51ed2012-12-07 20:31:45121 void setupRootLayerImpl(scoped_ptr<LayerImpl> root)
122 {
[email protected]7aba6662013-03-12 10:17:34123 root->SetAnchorPoint(gfx::PointF(0, 0));
124 root->SetPosition(gfx::PointF(0, 0));
125 root->SetBounds(gfx::Size(10, 10));
126 root->SetContentBounds(gfx::Size(10, 10));
127 root->SetDrawsContent(true);
128 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
[email protected]c1bb5af2013-03-13 19:06:27129 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:14130 }
131
[email protected]96baf3e2012-10-22 23:09:55132 static void expectClearedScrollDeltasRecursive(LayerImpl* layer)
[email protected]94f206c12012-08-25 00:09:14133 {
[email protected]7aba6662013-03-12 10:17:34134 ASSERT_EQ(layer->scroll_delta(), gfx::Vector2d());
[email protected]94f206c12012-08-25 00:09:14135 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:03136 expectClearedScrollDeltasRecursive(layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:14137 }
138
[email protected]c9c1ebe2012-11-05 20:46:13139 static void expectContains(const ScrollAndScaleSet& scrollInfo, int id, const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:14140 {
141 int timesEncountered = 0;
142
143 for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
144 if (scrollInfo.scrolls[i].layerId != id)
145 continue;
[email protected]c9c1ebe2012-11-05 20:46:13146 EXPECT_VECTOR_EQ(scrollDelta, scrollInfo.scrolls[i].scrollDelta);
[email protected]94f206c12012-08-25 00:09:14147 timesEncountered++;
148 }
149
150 ASSERT_EQ(timesEncountered, 1);
151 }
152
[email protected]e39bf212012-11-22 21:04:03153 static void expectNone(const ScrollAndScaleSet& scrollInfo, int id)
154 {
155 int timesEncountered = 0;
156
157 for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
158 if (scrollInfo.scrolls[i].layerId != id)
159 continue;
160 timesEncountered++;
161 }
162
163 ASSERT_EQ(0, timesEncountered);
164 }
165
[email protected]aad0a0072012-11-01 18:15:58166 void setupScrollAndContentsLayers(const gfx::Size& contentSize)
[email protected]94f206c12012-08-25 00:09:14167 {
[email protected]c1bb5af2013-03-13 19:06:27168 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:34169 root->SetScrollable(true);
170 root->SetScrollOffset(gfx::Vector2d(0, 0));
171 root->SetMaxScrollOffset(gfx::Vector2d(contentSize.width(), contentSize.height()));
172 root->SetBounds(contentSize);
173 root->SetContentBounds(contentSize);
174 root->SetPosition(gfx::PointF(0, 0));
175 root->SetAnchorPoint(gfx::PointF(0, 0));
[email protected]94f206c12012-08-25 00:09:14176
[email protected]c1bb5af2013-03-13 19:06:27177 scoped_ptr<LayerImpl> contents = LayerImpl::Create(m_hostImpl->active_tree(), 2);
[email protected]7aba6662013-03-12 10:17:34178 contents->SetDrawsContent(true);
179 contents->SetBounds(contentSize);
180 contents->SetContentBounds(contentSize);
181 contents->SetPosition(gfx::PointF(0, 0));
182 contents->SetAnchorPoint(gfx::PointF(0, 0));
183 root->AddChild(contents.Pass());
[email protected]c1bb5af2013-03-13 19:06:27184 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
185 m_hostImpl->active_tree()->DidBecomeActive();
[email protected]94f206c12012-08-25 00:09:14186 }
187
[email protected]586d51ed2012-12-07 20:31:45188 scoped_ptr<LayerImpl> createScrollableLayer(int id, const gfx::Size& size)
[email protected]94f206c12012-08-25 00:09:14189 {
[email protected]c1bb5af2013-03-13 19:06:27190 scoped_ptr<LayerImpl> layer = LayerImpl::Create(m_hostImpl->active_tree(), id);
[email protected]7aba6662013-03-12 10:17:34191 layer->SetScrollable(true);
192 layer->SetDrawsContent(true);
193 layer->SetBounds(size);
194 layer->SetContentBounds(size);
195 layer->SetMaxScrollOffset(gfx::Vector2d(size.width() * 2, size.height() * 2));
[email protected]e0bd43a2012-10-12 16:54:21196 return layer.Pass();
[email protected]94f206c12012-08-25 00:09:14197 }
198
199 void initializeRendererAndDrawFrame()
200 {
[email protected]c1bb5af2013-03-13 19:06:27201 m_hostImpl->InitializeRenderer(createOutputSurface());
[email protected]96baf3e2012-10-22 23:09:55202 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:27203 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:52204 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:27205 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:14206 }
207
[email protected]aeaa50a2012-11-21 20:12:37208 void pinchZoomPanViewportForcesCommitRedraw(const float deviceScaleFactor);
[email protected]e39bf212012-11-22 21:04:03209 void pinchZoomPanViewportTest(const float deviceScaleFactor);
210 void pinchZoomPanViewportAndScrollTest(const float deviceScaleFactor);
211 void pinchZoomPanViewportAndScrollBoundaryTest(const float deviceScaleFactor);
[email protected]aeaa50a2012-11-21 20:12:37212
[email protected]94f206c12012-08-25 00:09:14213protected:
[email protected]ea9d8f22012-12-08 03:39:29214 virtual scoped_ptr<OutputSurface> createOutputSurface() { return createFakeOutputSurface(); }
[email protected]94f206c12012-08-25 00:09:14215
[email protected]2d692992012-12-19 01:19:32216 void drawOneFrame() {
217 LayerTreeHostImpl::FrameData frameData;
[email protected]c1bb5af2013-03-13 19:06:27218 m_hostImpl->PrepareToDraw(&frameData);
219 m_hostImpl->DidDrawAllLayers(frameData);
[email protected]2d692992012-12-19 01:19:32220 }
221
[email protected]61de5812012-11-08 07:03:44222 FakeProxy m_proxy;
[email protected]94f206c12012-08-25 00:09:14223 DebugScopedSetImplThread m_alwaysImplThread;
224 DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked;
225
[email protected]96baf3e2012-10-22 23:09:55226 scoped_ptr<LayerTreeHostImpl> m_hostImpl;
[email protected]8db2213c2012-09-05 22:08:21227 bool m_onCanDrawStateChangedCalled;
[email protected]2e7ca422012-12-20 02:57:27228 bool m_hasPendingTree;
[email protected]94f206c12012-08-25 00:09:14229 bool m_didRequestCommit;
230 bool m_didRequestRedraw;
[email protected]86126792013-03-16 20:07:54231 bool m_didUploadVisibleTile;
[email protected]b1969fa2012-10-17 20:16:29232 bool m_reduceMemoryResult;
[email protected]94f206c12012-08-25 00:09:14233};
234
[email protected]c8756fbe2013-02-12 01:53:49235class TestWebGraphicsContext3DMakeCurrentFails : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:14236public:
237 virtual bool makeContextCurrent() { return false; }
238};
239
[email protected]c2d0c5a2013-02-26 04:43:36240TEST_F(LayerTreeHostImplTest, notifyIfCanDrawChanged)
[email protected]8db2213c2012-09-05 22:08:21241{
242 // Note: It is not possible to disable the renderer once it has been set,
243 // so we do not need to test that disabling the renderer notifies us
244 // that canDraw changed.
[email protected]c1bb5af2013-03-13 19:06:27245 EXPECT_FALSE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21246 m_onCanDrawStateChangedCalled = false;
247
[email protected]aad0a0072012-11-01 18:15:58248 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27249 EXPECT_TRUE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21250 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
251 m_onCanDrawStateChangedCalled = false;
252
253 // Toggle the root layer to make sure it toggles canDraw
[email protected]c1bb5af2013-03-13 19:06:27254 m_hostImpl->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
255 EXPECT_FALSE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21256 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
257 m_onCanDrawStateChangedCalled = false;
258
[email protected]aad0a0072012-11-01 18:15:58259 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27260 EXPECT_TRUE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21261 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
262 m_onCanDrawStateChangedCalled = false;
263
264 // Toggle the device viewport size to make sure it toggles canDraw.
[email protected]c1bb5af2013-03-13 19:06:27265 m_hostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(0, 0));
266 EXPECT_FALSE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21267 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
268 m_onCanDrawStateChangedCalled = false;
269
[email protected]c1bb5af2013-03-13 19:06:27270 m_hostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
271 EXPECT_TRUE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21272 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
273 m_onCanDrawStateChangedCalled = false;
274
[email protected]b1969fa2012-10-17 20:16:29275 // Toggle contents textures purged without causing any evictions,
276 // and make sure that it does not change canDraw.
277 setReduceMemoryResult(false);
[email protected]90ec9872013-03-08 02:28:18278 m_hostImpl->SetManagedMemoryPolicy(ManagedMemoryPolicy(
[email protected]c1bb5af2013-03-13 19:06:27279 m_hostImpl->memory_allocation_limit_bytes() - 1));
280 EXPECT_TRUE(m_hostImpl->CanDraw());
[email protected]b1969fa2012-10-17 20:16:29281 EXPECT_FALSE(m_onCanDrawStateChangedCalled);
282 m_onCanDrawStateChangedCalled = false;
283
284 // Toggle contents textures purged to make sure it toggles canDraw.
285 setReduceMemoryResult(true);
[email protected]90ec9872013-03-08 02:28:18286 m_hostImpl->SetManagedMemoryPolicy(ManagedMemoryPolicy(
[email protected]c1bb5af2013-03-13 19:06:27287 m_hostImpl->memory_allocation_limit_bytes() - 1));
288 EXPECT_FALSE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21289 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
290 m_onCanDrawStateChangedCalled = false;
291
[email protected]c1bb5af2013-03-13 19:06:27292 m_hostImpl->active_tree()->ResetContentsTexturesPurged();
293 EXPECT_TRUE(m_hostImpl->CanDraw());
[email protected]8db2213c2012-09-05 22:08:21294 EXPECT_TRUE(m_onCanDrawStateChangedCalled);
295 m_onCanDrawStateChangedCalled = false;
296}
297
[email protected]c2d0c5a2013-02-26 04:43:36298TEST_F(LayerTreeHostImplTest, scrollDeltaNoLayers)
[email protected]94f206c12012-08-25 00:09:14299{
[email protected]c1bb5af2013-03-13 19:06:27300 ASSERT_FALSE(m_hostImpl->active_tree()->root_layer());
[email protected]94f206c12012-08-25 00:09:14301
[email protected]c1bb5af2013-03-13 19:06:27302 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14303 ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
304}
305
[email protected]c2d0c5a2013-02-26 04:43:36306TEST_F(LayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
[email protected]94f206c12012-08-25 00:09:14307{
308 {
[email protected]c1bb5af2013-03-13 19:06:27309 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
310 root->AddChild(LayerImpl::Create(m_hostImpl->active_tree(), 2));
311 root->AddChild(LayerImpl::Create(m_hostImpl->active_tree(), 3));
312 root->children()[1]->AddChild(LayerImpl::Create(m_hostImpl->active_tree(), 4));
313 root->children()[1]->AddChild(LayerImpl::Create(m_hostImpl->active_tree(), 5));
314 root->children()[1]->children()[0]->AddChild(LayerImpl::Create(m_hostImpl->active_tree(), 6));
315 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:14316 }
[email protected]c1bb5af2013-03-13 19:06:27317 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]94f206c12012-08-25 00:09:14318
319 expectClearedScrollDeltasRecursive(root);
320
[email protected]96baf3e2012-10-22 23:09:55321 scoped_ptr<ScrollAndScaleSet> scrollInfo;
[email protected]94f206c12012-08-25 00:09:14322
[email protected]c1bb5af2013-03-13 19:06:27323 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14324 ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
325 expectClearedScrollDeltasRecursive(root);
326
[email protected]c1bb5af2013-03-13 19:06:27327 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14328 ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
329 expectClearedScrollDeltasRecursive(root);
330}
331
[email protected]c2d0c5a2013-02-26 04:43:36332TEST_F(LayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
[email protected]94f206c12012-08-25 00:09:14333{
[email protected]c9c1ebe2012-11-05 20:46:13334 gfx::Vector2d scrollOffset(20, 30);
335 gfx::Vector2d scrollDelta(11, -15);
[email protected]94f206c12012-08-25 00:09:14336 {
[email protected]c1bb5af2013-03-13 19:06:27337 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:34338 root->SetScrollOffset(scrollOffset);
339 root->SetScrollable(true);
340 root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
341 root->ScrollBy(scrollDelta);
[email protected]c1bb5af2013-03-13 19:06:27342 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:14343 }
[email protected]c1bb5af2013-03-13 19:06:27344 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]94f206c12012-08-25 00:09:14345
[email protected]96baf3e2012-10-22 23:09:55346 scoped_ptr<ScrollAndScaleSet> scrollInfo;
[email protected]94f206c12012-08-25 00:09:14347
[email protected]c1bb5af2013-03-13 19:06:27348 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14349 ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
[email protected]7aba6662013-03-12 10:17:34350 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scrollDelta);
[email protected]94f206c12012-08-25 00:09:14351 expectContains(*scrollInfo, root->id(), scrollDelta);
352
[email protected]c9c1ebe2012-11-05 20:46:13353 gfx::Vector2d scrollDelta2(-5, 27);
[email protected]7aba6662013-03-12 10:17:34354 root->ScrollBy(scrollDelta2);
[email protected]c1bb5af2013-03-13 19:06:27355 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14356 ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
[email protected]7aba6662013-03-12 10:17:34357 EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scrollDelta + scrollDelta2);
[email protected]94f206c12012-08-25 00:09:14358 expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
359
[email protected]7aba6662013-03-12 10:17:34360 root->ScrollBy(gfx::Vector2d());
[email protected]c1bb5af2013-03-13 19:06:27361 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]7aba6662013-03-12 10:17:34362 EXPECT_EQ(root->sent_scroll_delta(), scrollDelta + scrollDelta2);
[email protected]94f206c12012-08-25 00:09:14363}
364
[email protected]c2d0c5a2013-02-26 04:43:36365TEST_F(LayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
[email protected]94f206c12012-08-25 00:09:14366{
[email protected]aad0a0072012-11-01 18:15:58367 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27368 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14369 initializeRendererAndDrawFrame();
370
[email protected]c1bb5af2013-03-13 19:06:27371 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
372 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
373 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:14374 EXPECT_TRUE(m_didRequestRedraw);
375 EXPECT_TRUE(m_didRequestCommit);
376}
377
[email protected]c2d0c5a2013-02-26 04:43:36378TEST_F(LayerTreeHostImplTest, scrollWithoutRootLayer)
[email protected]94f206c12012-08-25 00:09:14379{
380 // We should not crash when trying to scroll an empty layer tree.
[email protected]c1bb5af2013-03-13 19:06:27381 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollIgnored);
[email protected]94f206c12012-08-25 00:09:14382}
383
[email protected]c2d0c5a2013-02-26 04:43:36384TEST_F(LayerTreeHostImplTest, scrollWithoutRenderer)
[email protected]94f206c12012-08-25 00:09:14385{
[email protected]96baf3e2012-10-22 23:09:55386 LayerTreeSettings settings;
[email protected]c1bb5af2013-03-13 19:06:27387 m_hostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:14388
389 // Initialization will fail here.
[email protected]c1bb5af2013-03-13 19:06:27390 m_hostImpl->InitializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new TestWebGraphicsContext3DMakeCurrentFails)).PassAs<OutputSurface>());
391 m_hostImpl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
[email protected]94f206c12012-08-25 00:09:14392
[email protected]aad0a0072012-11-01 18:15:58393 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:14394
395 // We should not crash when trying to scroll after the renderer initialization fails.
[email protected]c1bb5af2013-03-13 19:06:27396 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollIgnored);
[email protected]94f206c12012-08-25 00:09:14397}
398
[email protected]c2d0c5a2013-02-26 04:43:36399TEST_F(LayerTreeHostImplTest, replaceTreeWhileScrolling)
[email protected]94f206c12012-08-25 00:09:14400{
401 const int scrollLayerId = 1;
402
[email protected]aad0a0072012-11-01 18:15:58403 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27404 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14405 initializeRendererAndDrawFrame();
406
407 // We should not crash if the tree is replaced while we are scrolling.
[email protected]c1bb5af2013-03-13 19:06:27408 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
409 m_hostImpl->active_tree()->DetachLayerTree();
[email protected]94f206c12012-08-25 00:09:14410
[email protected]aad0a0072012-11-01 18:15:58411 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:14412
413 // We should still be scrolling, because the scrolled layer also exists in the new tree.
[email protected]c9c1ebe2012-11-05 20:46:13414 gfx::Vector2d scrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:27415 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
416 m_hostImpl->ScrollEnd();
417 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14418 expectContains(*scrollInfo, scrollLayerId, scrollDelta);
419}
420
[email protected]c2d0c5a2013-02-26 04:43:36421TEST_F(LayerTreeHostImplTest, clearRootRenderSurfaceAndScroll)
[email protected]94f206c12012-08-25 00:09:14422{
[email protected]aad0a0072012-11-01 18:15:58423 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27424 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14425 initializeRendererAndDrawFrame();
426
427 // We should be able to scroll even if the root layer loses its render surface after the most
428 // recent render.
[email protected]c1bb5af2013-03-13 19:06:27429 m_hostImpl->active_tree()->root_layer()->ClearRenderSurface();
430 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]0ede3bb2012-12-09 09:14:39431
[email protected]c1bb5af2013-03-13 19:06:27432 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
[email protected]94f206c12012-08-25 00:09:14433}
434
[email protected]c2d0c5a2013-02-26 04:43:36435TEST_F(LayerTreeHostImplTest, wheelEventHandlers)
[email protected]94f206c12012-08-25 00:09:14436{
[email protected]aad0a0072012-11-01 18:15:58437 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27438 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14439 initializeRendererAndDrawFrame();
[email protected]c1bb5af2013-03-13 19:06:27440 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]94f206c12012-08-25 00:09:14441
[email protected]7aba6662013-03-12 10:17:34442 root->SetHaveWheelEventHandlers(true);
[email protected]94f206c12012-08-25 00:09:14443
444 // With registered event handlers, wheel scrolls have to go to the main thread.
[email protected]c1bb5af2013-03-13 19:06:27445 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollOnMainThread);
[email protected]94f206c12012-08-25 00:09:14446
447 // But gesture scrolls can still be handled.
[email protected]c1bb5af2013-03-13 19:06:27448 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
[email protected]94f206c12012-08-25 00:09:14449}
450
[email protected]c2d0c5a2013-02-26 04:43:36451TEST_F(LayerTreeHostImplTest, shouldScrollOnMainThread)
[email protected]94f206c12012-08-25 00:09:14452{
[email protected]aad0a0072012-11-01 18:15:58453 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27454 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14455 initializeRendererAndDrawFrame();
[email protected]c1bb5af2013-03-13 19:06:27456 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]94f206c12012-08-25 00:09:14457
[email protected]7aba6662013-03-12 10:17:34458 root->SetShouldScrollOnMainThread(true);
[email protected]94f206c12012-08-25 00:09:14459
[email protected]c1bb5af2013-03-13 19:06:27460 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollOnMainThread);
461 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollOnMainThread);
[email protected]94f206c12012-08-25 00:09:14462}
463
[email protected]c2d0c5a2013-02-26 04:43:36464TEST_F(LayerTreeHostImplTest, nonFastScrollableRegionBasic)
[email protected]94f206c12012-08-25 00:09:14465{
[email protected]aad0a0072012-11-01 18:15:58466 setupScrollAndContentsLayers(gfx::Size(200, 200));
[email protected]c1bb5af2013-03-13 19:06:27467 m_hostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:14468
[email protected]c1bb5af2013-03-13 19:06:27469 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]7aba6662013-03-12 10:17:34470 root->SetContentsScale(2, 2);
471 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
[email protected]94f206c12012-08-25 00:09:14472
[email protected]a90aa702012-11-07 04:48:24473 initializeRendererAndDrawFrame();
474
[email protected]94f206c12012-08-25 00:09:14475 // All scroll types inside the non-fast scrollable region should fail.
[email protected]c1bb5af2013-03-13 19:06:27476 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(25, 25), InputHandlerClient::Wheel), InputHandlerClient::ScrollOnMainThread);
477 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(25, 25), InputHandlerClient::Gesture), InputHandlerClient::ScrollOnMainThread);
[email protected]94f206c12012-08-25 00:09:14478
479 // All scroll types outside this region should succeed.
[email protected]c1bb5af2013-03-13 19:06:27480 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(75, 75), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
481 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
482 m_hostImpl->ScrollEnd();
483 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(75, 75), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
484 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
485 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:14486}
487
[email protected]c2d0c5a2013-02-26 04:43:36488TEST_F(LayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
[email protected]94f206c12012-08-25 00:09:14489{
[email protected]aad0a0072012-11-01 18:15:58490 setupScrollAndContentsLayers(gfx::Size(200, 200));
[email protected]c1bb5af2013-03-13 19:06:27491 m_hostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:14492
[email protected]c1bb5af2013-03-13 19:06:27493 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]7aba6662013-03-12 10:17:34494 root->SetContentsScale(2, 2);
495 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
496 root->SetPosition(gfx::PointF(-25, 0));
[email protected]a90aa702012-11-07 04:48:24497
[email protected]94f206c12012-08-25 00:09:14498 initializeRendererAndDrawFrame();
499
500 // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
[email protected]c1bb5af2013-03-13 19:06:27501 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(40, 10), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
502 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
503 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:14504
505 // This point is still inside the non-fast region.
[email protected]c1bb5af2013-03-13 19:06:27506 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(10, 10), InputHandlerClient::Wheel), InputHandlerClient::ScrollOnMainThread);
[email protected]94f206c12012-08-25 00:09:14507}
508
[email protected]c2d0c5a2013-02-26 04:43:36509TEST_F(LayerTreeHostImplTest, scrollByReturnsCorrectValue)
[email protected]a9710962012-11-14 20:11:02510{
511 setupScrollAndContentsLayers(gfx::Size(200, 200));
[email protected]c1bb5af2013-03-13 19:06:27512 m_hostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
[email protected]a9710962012-11-14 20:11:02513
514 initializeRendererAndDrawFrame();
515
516 EXPECT_EQ(InputHandlerClient::ScrollStarted,
[email protected]c1bb5af2013-03-13 19:06:27517 m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture));
[email protected]a9710962012-11-14 20:11:02518
519 // Trying to scroll to the left/top will not succeed.
[email protected]c1bb5af2013-03-13 19:06:27520 EXPECT_FALSE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
521 EXPECT_FALSE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
522 EXPECT_FALSE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
[email protected]a9710962012-11-14 20:11:02523
524 // Scrolling to the right/bottom will succeed.
[email protected]c1bb5af2013-03-13 19:06:27525 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
526 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
527 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
[email protected]a9710962012-11-14 20:11:02528
529 // Scrolling to left/top will now succeed.
[email protected]c1bb5af2013-03-13 19:06:27530 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
531 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
532 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
[email protected]a9710962012-11-14 20:11:02533
[email protected]1ca52a3a2012-12-04 22:47:10534 // Scrolling diagonally against an edge will succeed.
[email protected]c1bb5af2013-03-13 19:06:27535 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
536 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
537 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
[email protected]1ca52a3a2012-12-04 22:47:10538
[email protected]a9710962012-11-14 20:11:02539 // Trying to scroll more than the available space will also succeed.
[email protected]c1bb5af2013-03-13 19:06:27540 EXPECT_TRUE(m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
[email protected]a9710962012-11-14 20:11:02541}
542
[email protected]c2d0c5a2013-02-26 04:43:36543TEST_F(LayerTreeHostImplTest, clearRootRenderSurfaceAndHitTestTouchHandlerRegion)
[email protected]df8f44f2013-01-08 08:00:31544{
545 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27546 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]df8f44f2013-01-08 08:00:31547 initializeRendererAndDrawFrame();
548
549 // We should be able to hit test for touch event handlers even if the root layer loses
550 // its render surface after the most recent render.
[email protected]c1bb5af2013-03-13 19:06:27551 m_hostImpl->active_tree()->root_layer()->ClearRenderSurface();
552 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]df8f44f2013-01-08 08:00:31553
[email protected]c1bb5af2013-03-13 19:06:27554 EXPECT_EQ(m_hostImpl->HaveTouchEventHandlersAt(gfx::Point(0, 0)), false);
[email protected]df8f44f2013-01-08 08:00:31555}
556
[email protected]c2d0c5a2013-02-26 04:43:36557TEST_F(LayerTreeHostImplTest, implPinchZoom)
[email protected]1c0c9bc2012-10-08 22:41:48558{
[email protected]aad0a0072012-11-01 18:15:58559 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27560 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]1c0c9bc2012-10-08 22:41:48561 initializeRendererAndDrawFrame();
562
[email protected]c1bb5af2013-03-13 19:06:27563 LayerImpl* scrollLayer = m_hostImpl->RootScrollLayer();
[email protected]1d993172012-10-18 18:15:04564 DCHECK(scrollLayer);
[email protected]1c0c9bc2012-10-08 22:41:48565
566 const float minPageScale = 1, maxPageScale = 4;
[email protected]c8686a02012-11-27 08:29:00567 const gfx::Transform identityScaleTransform;
[email protected]1c0c9bc2012-10-08 22:41:48568
[email protected]c60279472013-01-30 12:10:51569 // The impl-based pinch zoom should adjust the max scroll position.
570 {
[email protected]c1bb5af2013-03-13 19:06:27571 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
572 m_hostImpl->active_tree()->SetPageScaleDelta(1);
[email protected]7aba6662013-03-12 10:17:34573 scrollLayer->SetImplTransform(identityScaleTransform);
574 scrollLayer->SetScrollDelta(gfx::Vector2d());
[email protected]c60279472013-01-30 12:10:51575
576 float pageScaleDelta = 2;
[email protected]c1bb5af2013-03-13 19:06:27577 m_hostImpl->PinchGestureBegin();
578 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(50, 50));
579 m_hostImpl->PinchGestureEnd();
[email protected]c60279472013-01-30 12:10:51580 EXPECT_TRUE(m_didRequestRedraw);
581 EXPECT_TRUE(m_didRequestCommit);
582
[email protected]c1bb5af2013-03-13 19:06:27583 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]c60279472013-01-30 12:10:51584 EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
585
[email protected]c1bb5af2013-03-13 19:06:27586 EXPECT_EQ(gfx::Vector2d(75, 75), m_hostImpl->active_tree()->root_layer()->max_scroll_offset());
[email protected]c60279472013-01-30 12:10:51587 }
588
[email protected]1c0c9bc2012-10-08 22:41:48589 // Scrolling after a pinch gesture should always be in local space. The scroll deltas do not
590 // have the page scale factor applied.
591 {
[email protected]c1bb5af2013-03-13 19:06:27592 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
593 m_hostImpl->active_tree()->SetPageScaleDelta(1);
[email protected]7aba6662013-03-12 10:17:34594 scrollLayer->SetImplTransform(identityScaleTransform);
595 scrollLayer->SetScrollDelta(gfx::Vector2d());
[email protected]1c0c9bc2012-10-08 22:41:48596
597 float pageScaleDelta = 2;
[email protected]c1bb5af2013-03-13 19:06:27598 m_hostImpl->PinchGestureBegin();
599 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(0, 0));
600 m_hostImpl->PinchGestureEnd();
[email protected]1c0c9bc2012-10-08 22:41:48601
[email protected]c9c1ebe2012-11-05 20:46:13602 gfx::Vector2d scrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:27603 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
604 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
605 m_hostImpl->ScrollEnd();
[email protected]1c0c9bc2012-10-08 22:41:48606
[email protected]c1bb5af2013-03-13 19:06:27607 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
608 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:48609 }
610}
611
[email protected]c2d0c5a2013-02-26 04:43:36612TEST_F(LayerTreeHostImplTest, pinchGesture)
[email protected]94f206c12012-08-25 00:09:14613{
[email protected]aad0a0072012-11-01 18:15:58614 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27615 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14616 initializeRendererAndDrawFrame();
617
[email protected]c1bb5af2013-03-13 19:06:27618 LayerImpl* scrollLayer = m_hostImpl->RootScrollLayer();
[email protected]1d993172012-10-18 18:15:04619 DCHECK(scrollLayer);
[email protected]94f206c12012-08-25 00:09:14620
[email protected]c2d0c5a2013-02-26 04:43:36621 const float minPageScale = 1;
[email protected]1c0c9bc2012-10-08 22:41:48622 const float maxPageScale = 4;
[email protected]c8686a02012-11-27 08:29:00623 const gfx::Transform identityScaleTransform;
[email protected]94f206c12012-08-25 00:09:14624
625 // Basic pinch zoom in gesture
626 {
[email protected]c1bb5af2013-03-13 19:06:27627 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34628 scrollLayer->SetImplTransform(identityScaleTransform);
629 scrollLayer->SetScrollDelta(gfx::Vector2d());
[email protected]94f206c12012-08-25 00:09:14630
631 float pageScaleDelta = 2;
[email protected]c1bb5af2013-03-13 19:06:27632 m_hostImpl->PinchGestureBegin();
633 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(50, 50));
634 m_hostImpl->PinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:14635 EXPECT_TRUE(m_didRequestRedraw);
636 EXPECT_TRUE(m_didRequestCommit);
637
[email protected]c1bb5af2013-03-13 19:06:27638 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14639 EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
640 }
641
642 // Zoom-in clamping
643 {
[email protected]c1bb5af2013-03-13 19:06:27644 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34645 scrollLayer->SetImplTransform(identityScaleTransform);
646 scrollLayer->SetScrollDelta(gfx::Vector2d());
[email protected]94f206c12012-08-25 00:09:14647 float pageScaleDelta = 10;
648
[email protected]c1bb5af2013-03-13 19:06:27649 m_hostImpl->PinchGestureBegin();
650 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(50, 50));
651 m_hostImpl->PinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:14652
[email protected]c1bb5af2013-03-13 19:06:27653 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14654 EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
655 }
656
657 // Zoom-out clamping
658 {
[email protected]c1bb5af2013-03-13 19:06:27659 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34660 scrollLayer->SetImplTransform(identityScaleTransform);
661 scrollLayer->SetScrollDelta(gfx::Vector2d());
662 scrollLayer->SetScrollOffset(gfx::Vector2d(50, 50));
[email protected]94f206c12012-08-25 00:09:14663
664 float pageScaleDelta = 0.1f;
[email protected]c1bb5af2013-03-13 19:06:27665 m_hostImpl->PinchGestureBegin();
666 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(0, 0));
667 m_hostImpl->PinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:14668
[email protected]c1bb5af2013-03-13 19:06:27669 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14670 EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
671
[email protected]c2d0c5a2013-02-26 04:43:36672 EXPECT_TRUE(scrollInfo->scrolls.empty());
[email protected]94f206c12012-08-25 00:09:14673 }
674
[email protected]c77745d2012-11-20 04:11:57675 // Two-finger panning should not happen based on pinch events only
[email protected]94f206c12012-08-25 00:09:14676 {
[email protected]c1bb5af2013-03-13 19:06:27677 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34678 scrollLayer->SetImplTransform(identityScaleTransform);
679 scrollLayer->SetScrollDelta(gfx::Vector2d());
680 scrollLayer->SetScrollOffset(gfx::Vector2d(20, 20));
[email protected]94f206c12012-08-25 00:09:14681
682 float pageScaleDelta = 1;
[email protected]c1bb5af2013-03-13 19:06:27683 m_hostImpl->PinchGestureBegin();
684 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(10, 10));
685 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(20, 20));
686 m_hostImpl->PinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:14687
[email protected]c1bb5af2013-03-13 19:06:27688 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14689 EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
[email protected]c77745d2012-11-20 04:11:57690 EXPECT_TRUE(scrollInfo->scrolls.empty());
691 }
692
693 // Two-finger panning should work with interleaved scroll events
694 {
[email protected]c1bb5af2013-03-13 19:06:27695 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34696 scrollLayer->SetImplTransform(identityScaleTransform);
697 scrollLayer->SetScrollDelta(gfx::Vector2d());
698 scrollLayer->SetScrollOffset(gfx::Vector2d(20, 20));
[email protected]c77745d2012-11-20 04:11:57699
700 float pageScaleDelta = 1;
[email protected]c1bb5af2013-03-13 19:06:27701 m_hostImpl->ScrollBegin(gfx::Point(10, 10), InputHandlerClient::Wheel);
702 m_hostImpl->PinchGestureBegin();
703 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(10, 10));
704 m_hostImpl->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
705 m_hostImpl->PinchGestureUpdate(pageScaleDelta, gfx::Point(20, 20));
706 m_hostImpl->PinchGestureEnd();
707 m_hostImpl->ScrollEnd();
[email protected]c77745d2012-11-20 04:11:57708
[email protected]c1bb5af2013-03-13 19:06:27709 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]c77745d2012-11-20 04:11:57710 EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:13711 expectContains(*scrollInfo, scrollLayer->id(), gfx::Vector2d(-10, -10));
[email protected]94f206c12012-08-25 00:09:14712 }
713}
714
[email protected]c2d0c5a2013-02-26 04:43:36715TEST_F(LayerTreeHostImplTest, pageScaleAnimation)
[email protected]94f206c12012-08-25 00:09:14716{
[email protected]aad0a0072012-11-01 18:15:58717 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27718 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]94f206c12012-08-25 00:09:14719 initializeRendererAndDrawFrame();
720
[email protected]c1bb5af2013-03-13 19:06:27721 LayerImpl* scrollLayer = m_hostImpl->RootScrollLayer();
[email protected]1d993172012-10-18 18:15:04722 DCHECK(scrollLayer);
[email protected]94f206c12012-08-25 00:09:14723
[email protected]f6250742012-11-09 04:46:56724 const float minPageScale = 0.5;
[email protected]1c0c9bc2012-10-08 22:41:48725 const float maxPageScale = 4;
[email protected]30faac92012-10-29 00:06:29726 const base::TimeTicks startTime = base::TimeTicks() + base::TimeDelta::FromSeconds(1);
727 const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
728 const base::TimeTicks halfwayThroughAnimation = startTime + duration / 2;
729 const base::TimeTicks endTime = startTime + duration;
[email protected]c8686a02012-11-27 08:29:00730 const gfx::Transform identityScaleTransform;
[email protected]94f206c12012-08-25 00:09:14731
732 // Non-anchor zoom-in
733 {
[email protected]c1bb5af2013-03-13 19:06:27734 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34735 scrollLayer->SetImplTransform(identityScaleTransform);
736 scrollLayer->SetScrollOffset(gfx::Vector2d(50, 50));
[email protected]94f206c12012-08-25 00:09:14737
[email protected]c1bb5af2013-03-13 19:06:27738 m_hostImpl->StartPageScaleAnimation(gfx::Vector2d(0, 0), false, 2, startTime, duration);
739 m_hostImpl->Animate(halfwayThroughAnimation, base::Time());
[email protected]94f206c12012-08-25 00:09:14740 EXPECT_TRUE(m_didRequestRedraw);
[email protected]c1bb5af2013-03-13 19:06:27741 m_hostImpl->Animate(endTime, base::Time());
[email protected]94f206c12012-08-25 00:09:14742 EXPECT_TRUE(m_didRequestCommit);
743
[email protected]c1bb5af2013-03-13 19:06:27744 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14745 EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
[email protected]c9c1ebe2012-11-05 20:46:13746 expectContains(*scrollInfo, scrollLayer->id(), gfx::Vector2d(-50, -50));
[email protected]94f206c12012-08-25 00:09:14747 }
748
749 // Anchor zoom-out
750 {
[email protected]c1bb5af2013-03-13 19:06:27751 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34752 scrollLayer->SetImplTransform(identityScaleTransform);
753 scrollLayer->SetScrollOffset(gfx::Vector2d(50, 50));
[email protected]94f206c12012-08-25 00:09:14754
[email protected]c1bb5af2013-03-13 19:06:27755 m_hostImpl->StartPageScaleAnimation(gfx::Vector2d(25, 25), true, minPageScale, startTime, duration);
756 m_hostImpl->Animate(endTime, base::Time());
[email protected]94f206c12012-08-25 00:09:14757 EXPECT_TRUE(m_didRequestRedraw);
758 EXPECT_TRUE(m_didRequestCommit);
759
[email protected]c1bb5af2013-03-13 19:06:27760 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:14761 EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
762 // Pushed to (0,0) via clamping against contents layer size.
[email protected]c9c1ebe2012-11-05 20:46:13763 expectContains(*scrollInfo, scrollLayer->id(), gfx::Vector2d(-50, -50));
[email protected]94f206c12012-08-25 00:09:14764 }
765}
766
[email protected]c2d0c5a2013-02-26 04:43:36767TEST_F(LayerTreeHostImplTest, pageScaleAnimationNoOp)
[email protected]f350449c2013-01-31 21:20:36768{
769 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27770 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
[email protected]f350449c2013-01-31 21:20:36771 initializeRendererAndDrawFrame();
772
[email protected]c1bb5af2013-03-13 19:06:27773 LayerImpl* scrollLayer = m_hostImpl->RootScrollLayer();
[email protected]f350449c2013-01-31 21:20:36774 DCHECK(scrollLayer);
775
776 const float minPageScale = 0.5;
777 const float maxPageScale = 4;
778 const base::TimeTicks startTime = base::TimeTicks() + base::TimeDelta::FromSeconds(1);
779 const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
780 const base::TimeTicks halfwayThroughAnimation = startTime + duration / 2;
781 const base::TimeTicks endTime = startTime + duration;
782 const gfx::Transform identityScaleTransform;
783
784 // Anchor zoom with unchanged page scale should not change scroll or scale.
785 {
[email protected]c1bb5af2013-03-13 19:06:27786 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
[email protected]7aba6662013-03-12 10:17:34787 scrollLayer->SetImplTransform(identityScaleTransform);
788 scrollLayer->SetScrollOffset(gfx::Vector2d(50, 50));
[email protected]f350449c2013-01-31 21:20:36789
[email protected]c1bb5af2013-03-13 19:06:27790 m_hostImpl->StartPageScaleAnimation(gfx::Vector2d(0, 0), true, 1, startTime, duration);
791 m_hostImpl->Animate(halfwayThroughAnimation, base::Time());
[email protected]f350449c2013-01-31 21:20:36792 EXPECT_TRUE(m_didRequestRedraw);
[email protected]c1bb5af2013-03-13 19:06:27793 m_hostImpl->Animate(endTime, base::Time());
[email protected]f350449c2013-01-31 21:20:36794 EXPECT_TRUE(m_didRequestCommit);
795
[email protected]c1bb5af2013-03-13 19:06:27796 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]f350449c2013-01-31 21:20:36797 EXPECT_EQ(scrollInfo->pageScaleDelta, 1);
798 expectNone(*scrollInfo, scrollLayer->id());
799 }
800}
801
[email protected]c2d0c5a2013-02-26 04:43:36802TEST_F(LayerTreeHostImplTest, compositorFrameMetadata)
[email protected]f2b5a5be2013-01-08 00:34:36803{
804 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]c1bb5af2013-03-13 19:06:27805 m_hostImpl->SetViewportSize(gfx::Size(50, 50), gfx::Size(50, 50));
806 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1.0f, 0.5f, 4.0f);
[email protected]f2b5a5be2013-01-08 00:34:36807 initializeRendererAndDrawFrame();
808
809 {
[email protected]90ec9872013-03-08 02:28:18810 CompositorFrameMetadata metadata = m_hostImpl->MakeCompositorFrameMetadata();
[email protected]f2b5a5be2013-01-08 00:34:36811 EXPECT_EQ(gfx::Vector2dF(0.0f, 0.0f), metadata.root_scroll_offset);
812 EXPECT_EQ(1.0f, metadata.page_scale_factor);
813 EXPECT_EQ(gfx::SizeF(50.0f, 50.0f), metadata.viewport_size);
814 EXPECT_EQ(gfx::SizeF(100.0f, 100.0f), metadata.root_layer_size);
815 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
816 EXPECT_EQ(4.0f, metadata.max_page_scale_factor);
817 }
818
819 // Scrolling should update metadata immediately.
[email protected]c1bb5af2013-03-13 19:06:27820 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
821 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
[email protected]f2b5a5be2013-01-08 00:34:36822 {
[email protected]90ec9872013-03-08 02:28:18823 CompositorFrameMetadata metadata = m_hostImpl->MakeCompositorFrameMetadata();
[email protected]f2b5a5be2013-01-08 00:34:36824 EXPECT_EQ(gfx::Vector2dF(0.0f, 10.0f), metadata.root_scroll_offset);
825 }
[email protected]c1bb5af2013-03-13 19:06:27826 m_hostImpl->ScrollEnd();
[email protected]f2b5a5be2013-01-08 00:34:36827
828 {
[email protected]90ec9872013-03-08 02:28:18829 CompositorFrameMetadata metadata = m_hostImpl->MakeCompositorFrameMetadata();
[email protected]f2b5a5be2013-01-08 00:34:36830 EXPECT_EQ(gfx::Vector2dF(0.0f, 10.0f), metadata.root_scroll_offset);
831 }
832
833 // Page scale should update metadata correctly (shrinking only the viewport).
[email protected]c1bb5af2013-03-13 19:06:27834 m_hostImpl->PinchGestureBegin();
835 m_hostImpl->PinchGestureUpdate(2.0f, gfx::Point(0, 0));
836 m_hostImpl->PinchGestureEnd();
[email protected]f2b5a5be2013-01-08 00:34:36837
838 {
[email protected]90ec9872013-03-08 02:28:18839 CompositorFrameMetadata metadata = m_hostImpl->MakeCompositorFrameMetadata();
[email protected]f2b5a5be2013-01-08 00:34:36840 EXPECT_EQ(gfx::Vector2dF(0.0f, 10.0f), metadata.root_scroll_offset);
841 EXPECT_EQ(2, metadata.page_scale_factor);
842 EXPECT_EQ(gfx::SizeF(25.0f, 25.0f), metadata.viewport_size);
843 EXPECT_EQ(gfx::SizeF(100.0f, 100.0f), metadata.root_layer_size);
844 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
845 EXPECT_EQ(4.0f, metadata.max_page_scale_factor);
846 }
847
848 // Likewise if set from the main thread.
[email protected]c1bb5af2013-03-13 19:06:27849 m_hostImpl->ProcessScrollDeltas();
850 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(4.0f, 0.5f, 4.0f);
851 m_hostImpl->active_tree()->SetPageScaleDelta(1.0f);
[email protected]f2b5a5be2013-01-08 00:34:36852 {
[email protected]90ec9872013-03-08 02:28:18853 CompositorFrameMetadata metadata = m_hostImpl->MakeCompositorFrameMetadata();
[email protected]f2b5a5be2013-01-08 00:34:36854 EXPECT_EQ(gfx::Vector2dF(0.0f, 10.0f), metadata.root_scroll_offset);
855 EXPECT_EQ(4.0f, metadata.page_scale_factor);
856 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
857 EXPECT_EQ(gfx::SizeF(100.0f, 100.0f), metadata.root_layer_size);
858 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
859 EXPECT_EQ(4.0f, metadata.max_page_scale_factor);
860 }
861}
862
[email protected]96baf3e2012-10-22 23:09:55863class DidDrawCheckLayer : public TiledLayerImpl {
[email protected]94f206c12012-08-25 00:09:14864public:
[email protected]7aba6662013-03-12 10:17:34865 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* treeImpl, int id) { return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(treeImpl, id)); }
[email protected]94f206c12012-08-25 00:09:14866
[email protected]7aba6662013-03-12 10:17:34867 virtual void DidDraw(ResourceProvider*) OVERRIDE
[email protected]94f206c12012-08-25 00:09:14868 {
869 m_didDrawCalled = true;
870 }
871
[email protected]7aba6662013-03-12 10:17:34872 virtual void WillDraw(ResourceProvider*) OVERRIDE
[email protected]94f206c12012-08-25 00:09:14873 {
874 m_willDrawCalled = true;
875 }
876
877 bool didDrawCalled() const { return m_didDrawCalled; }
878 bool willDrawCalled() const { return m_willDrawCalled; }
879
880 void clearDidDrawCheck()
881 {
882 m_didDrawCalled = false;
883 m_willDrawCalled = false;
884 }
885
886protected:
[email protected]8bef40572012-12-11 21:38:08887 DidDrawCheckLayer(LayerTreeImpl* treeImpl, int id)
888 : TiledLayerImpl(treeImpl, id)
[email protected]94f206c12012-08-25 00:09:14889 , m_didDrawCalled(false)
890 , m_willDrawCalled(false)
891 {
[email protected]7aba6662013-03-12 10:17:34892 SetAnchorPoint(gfx::PointF(0, 0));
893 SetBounds(gfx::Size(10, 10));
894 SetContentBounds(gfx::Size(10, 10));
895 SetDrawsContent(true);
[email protected]fa4b57f2013-03-17 21:39:09896 set_skips_draw(false);
[email protected]7aba6662013-03-12 10:17:34897 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
[email protected]94f206c12012-08-25 00:09:14898
[email protected]32eee892013-03-18 06:41:13899 scoped_ptr<LayerTilingData> tiler = LayerTilingData::Create(gfx::Size(100, 100), LayerTilingData::HAS_BORDER_TEXELS);
900 tiler->SetBounds(content_bounds());
[email protected]fa4b57f2013-03-17 21:39:09901 SetTilingData(*tiler.get());
[email protected]94f206c12012-08-25 00:09:14902 }
903
904private:
905 bool m_didDrawCalled;
906 bool m_willDrawCalled;
907};
908
[email protected]c2d0c5a2013-02-26 04:43:36909TEST_F(LayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
[email protected]94f206c12012-08-25 00:09:14910{
911 // The root layer is always drawn, so run this test on a child layer that
912 // will be masked out by the root layer's bounds.
[email protected]c1bb5af2013-03-13 19:06:27913 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 1));
914 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
[email protected]7aba6662013-03-12 10:17:34915 root->SetMasksToBounds(true);
[email protected]94f206c12012-08-25 00:09:14916
[email protected]c1bb5af2013-03-13 19:06:27917 root->AddChild(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 2));
[email protected]0920e24f2012-09-20 03:34:03918 DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0]);
[email protected]94f206c12012-08-25 00:09:14919 // Ensure visibleContentRect for layer is empty
[email protected]7aba6662013-03-12 10:17:34920 layer->SetPosition(gfx::PointF(100, 100));
921 layer->SetBounds(gfx::Size(10, 10));
922 layer->SetContentBounds(gfx::Size(10, 10));
[email protected]94f206c12012-08-25 00:09:14923
[email protected]96baf3e2012-10-22 23:09:55924 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:14925
926 EXPECT_FALSE(layer->willDrawCalled());
927 EXPECT_FALSE(layer->didDrawCalled());
928
[email protected]c1bb5af2013-03-13 19:06:27929 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:52930 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:27931 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:14932
933 EXPECT_FALSE(layer->willDrawCalled());
934 EXPECT_FALSE(layer->didDrawCalled());
935
[email protected]7aba6662013-03-12 10:17:34936 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
[email protected]94f206c12012-08-25 00:09:14937
938 // Ensure visibleContentRect for layer layer is not empty
[email protected]7aba6662013-03-12 10:17:34939 layer->SetPosition(gfx::PointF(0, 0));
[email protected]94f206c12012-08-25 00:09:14940
941 EXPECT_FALSE(layer->willDrawCalled());
942 EXPECT_FALSE(layer->didDrawCalled());
943
[email protected]c1bb5af2013-03-13 19:06:27944 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:52945 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:27946 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:14947
948 EXPECT_TRUE(layer->willDrawCalled());
949 EXPECT_TRUE(layer->didDrawCalled());
950
[email protected]7aba6662013-03-12 10:17:34951 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
[email protected]94f206c12012-08-25 00:09:14952}
953
[email protected]c2d0c5a2013-02-26 04:43:36954TEST_F(LayerTreeHostImplTest, willDrawNotCalledOnOccludedLayer)
[email protected]94f206c12012-08-25 00:09:14955{
[email protected]aad0a0072012-11-01 18:15:58956 gfx::Size bigSize(1000, 1000);
[email protected]c1bb5af2013-03-13 19:06:27957 m_hostImpl->SetViewportSize(bigSize, bigSize);
[email protected]94f206c12012-08-25 00:09:14958
[email protected]c1bb5af2013-03-13 19:06:27959 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 1));
960 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
[email protected]94f206c12012-08-25 00:09:14961
[email protected]c1bb5af2013-03-13 19:06:27962 root->AddChild(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 2));
[email protected]0920e24f2012-09-20 03:34:03963 DidDrawCheckLayer* occludedLayer = static_cast<DidDrawCheckLayer*>(root->children()[0]);
[email protected]94f206c12012-08-25 00:09:14964
[email protected]c1bb5af2013-03-13 19:06:27965 root->AddChild(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 3));
[email protected]0920e24f2012-09-20 03:34:03966 DidDrawCheckLayer* topLayer = static_cast<DidDrawCheckLayer*>(root->children()[1]);
[email protected]94f206c12012-08-25 00:09:14967 // This layer covers the occludedLayer above. Make this layer large so it can occlude.
[email protected]7aba6662013-03-12 10:17:34968 topLayer->SetBounds(bigSize);
969 topLayer->SetContentBounds(bigSize);
970 topLayer->SetContentsOpaque(true);
[email protected]94f206c12012-08-25 00:09:14971
[email protected]96baf3e2012-10-22 23:09:55972 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:14973
974 EXPECT_FALSE(occludedLayer->willDrawCalled());
975 EXPECT_FALSE(occludedLayer->didDrawCalled());
976 EXPECT_FALSE(topLayer->willDrawCalled());
977 EXPECT_FALSE(topLayer->didDrawCalled());
978
[email protected]c1bb5af2013-03-13 19:06:27979 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:52980 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:27981 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:14982
983 EXPECT_FALSE(occludedLayer->willDrawCalled());
984 EXPECT_FALSE(occludedLayer->didDrawCalled());
985 EXPECT_TRUE(topLayer->willDrawCalled());
986 EXPECT_TRUE(topLayer->didDrawCalled());
987}
988
[email protected]c2d0c5a2013-02-26 04:43:36989TEST_F(LayerTreeHostImplTest, didDrawCalledOnAllLayers)
[email protected]94f206c12012-08-25 00:09:14990{
[email protected]c1bb5af2013-03-13 19:06:27991 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 1));
992 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
[email protected]94f206c12012-08-25 00:09:14993
[email protected]c1bb5af2013-03-13 19:06:27994 root->AddChild(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 2));
[email protected]0920e24f2012-09-20 03:34:03995 DidDrawCheckLayer* layer1 = static_cast<DidDrawCheckLayer*>(root->children()[0]);
[email protected]94f206c12012-08-25 00:09:14996
[email protected]c1bb5af2013-03-13 19:06:27997 layer1->AddChild(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 3));
[email protected]0920e24f2012-09-20 03:34:03998 DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
[email protected]94f206c12012-08-25 00:09:14999
[email protected]7aba6662013-03-12 10:17:341000 layer1->SetOpacity(0.3f);
1001 layer1->SetPreserves3d(false);
[email protected]94f206c12012-08-25 00:09:141002
1003 EXPECT_FALSE(root->didDrawCalled());
1004 EXPECT_FALSE(layer1->didDrawCalled());
1005 EXPECT_FALSE(layer2->didDrawCalled());
1006
[email protected]96baf3e2012-10-22 23:09:551007 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:271008 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521009 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271010 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141011
1012 EXPECT_TRUE(root->didDrawCalled());
1013 EXPECT_TRUE(layer1->didDrawCalled());
1014 EXPECT_TRUE(layer2->didDrawCalled());
1015
[email protected]7aba6662013-03-12 10:17:341016 EXPECT_NE(root->render_surface(), layer1->render_surface());
1017 EXPECT_TRUE(!!layer1->render_surface());
[email protected]94f206c12012-08-25 00:09:141018}
1019
1020class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
1021public:
[email protected]7aba6662013-03-12 10:17:341022 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* treeImpl, int id, bool tileMissing, bool skipsDraw, bool animating, ResourceProvider* resourceProvider)
[email protected]e0bd43a2012-10-12 16:54:211023 {
[email protected]8bef40572012-12-11 21:38:081024 return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(treeImpl, id, tileMissing, skipsDraw, animating, resourceProvider));
[email protected]e0bd43a2012-10-12 16:54:211025 }
[email protected]94f206c12012-08-25 00:09:141026
1027private:
[email protected]8bef40572012-12-11 21:38:081028 MissingTextureAnimatingLayer(LayerTreeImpl* treeImpl, int id, bool tileMissing, bool skipsDraw, bool animating, ResourceProvider* resourceProvider)
1029 : DidDrawCheckLayer(treeImpl, id)
[email protected]94f206c12012-08-25 00:09:141030 {
[email protected]32eee892013-03-18 06:41:131031 scoped_ptr<LayerTilingData> tilingData = LayerTilingData::Create(gfx::Size(10, 10), LayerTilingData::NO_BORDER_TEXELS);
1032 tilingData->SetBounds(bounds());
[email protected]fa4b57f2013-03-17 21:39:091033 SetTilingData(*tilingData.get());
1034 set_skips_draw(skipsDraw);
[email protected]94f206c12012-08-25 00:09:141035 if (!tileMissing) {
[email protected]f53da3972013-03-07 08:38:411036 ResourceProvider::ResourceId resource = resourceProvider->CreateResource(gfx::Size(), GL_RGBA, ResourceProvider::TextureUsageAny);
1037 resourceProvider->AllocateForTesting(resource);
[email protected]fa4b57f2013-03-17 21:39:091038 PushTileProperties(0, 0, resource, gfx::Rect(), false);
[email protected]94f206c12012-08-25 00:09:141039 }
1040 if (animating)
1041 addAnimatedTransformToLayer(*this, 10, 3, 0);
1042 }
1043};
1044
[email protected]c2d0c5a2013-02-26 04:43:361045TEST_F(LayerTreeHostImplTest, prepareToDrawFailsWhenAnimationUsesCheckerboard)
[email protected]94f206c12012-08-25 00:09:141046{
1047 // When the texture is not missing, we draw as usual.
[email protected]c1bb5af2013-03-13 19:06:271048 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 1));
1049 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
1050 root->AddChild(MissingTextureAnimatingLayer::Create(m_hostImpl->active_tree(), 2, false, false, true, m_hostImpl->resource_provider()));
[email protected]94f206c12012-08-25 00:09:141051
[email protected]96baf3e2012-10-22 23:09:551052 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:141053
[email protected]c1bb5af2013-03-13 19:06:271054 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521055 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271056 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141057
1058 // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
[email protected]c1bb5af2013-03-13 19:06:271059 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 3));
1060 root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
1061 root->AddChild(MissingTextureAnimatingLayer::Create(m_hostImpl->active_tree(), 4, true, false, false, m_hostImpl->resource_provider()));
[email protected]94f206c12012-08-25 00:09:141062
[email protected]c1bb5af2013-03-13 19:06:271063 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521064 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271065 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141066
1067 // When a texture is missing and we're animating, we don't want to draw anything.
[email protected]c1bb5af2013-03-13 19:06:271068 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 5));
1069 root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
1070 root->AddChild(MissingTextureAnimatingLayer::Create(m_hostImpl->active_tree(), 6, true, false, true, m_hostImpl->resource_provider()));
[email protected]94f206c12012-08-25 00:09:141071
[email protected]c1bb5af2013-03-13 19:06:271072 EXPECT_FALSE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521073 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271074 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141075
1076 // When the layer skips draw and we're animating, we still draw the frame.
[email protected]c1bb5af2013-03-13 19:06:271077 m_hostImpl->active_tree()->SetRootLayer(DidDrawCheckLayer::Create(m_hostImpl->active_tree(), 7));
1078 root = static_cast<DidDrawCheckLayer*>(m_hostImpl->active_tree()->root_layer());
1079 root->AddChild(MissingTextureAnimatingLayer::Create(m_hostImpl->active_tree(), 8, false, true, true, m_hostImpl->resource_provider()));
[email protected]94f206c12012-08-25 00:09:141080
[email protected]c1bb5af2013-03-13 19:06:271081 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521082 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271083 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141084}
1085
[email protected]c2d0c5a2013-02-26 04:43:361086TEST_F(LayerTreeHostImplTest, scrollRootIgnored)
[email protected]94f206c12012-08-25 00:09:141087{
[email protected]c1bb5af2013-03-13 19:06:271088 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341089 root->SetScrollable(false);
[email protected]c1bb5af2013-03-13 19:06:271090 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:141091 initializeRendererAndDrawFrame();
1092
1093 // Scroll event is ignored because layer is not scrollable.
[email protected]c1bb5af2013-03-13 19:06:271094 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollIgnored);
[email protected]94f206c12012-08-25 00:09:141095 EXPECT_FALSE(m_didRequestRedraw);
1096 EXPECT_FALSE(m_didRequestCommit);
1097}
1098
[email protected]c2d0c5a2013-02-26 04:43:361099TEST_F(LayerTreeHostImplTest, scrollNonScrollableRootWithTopControls)
[email protected]c8415bf92013-02-17 18:57:271100{
1101 LayerTreeSettings settings;
1102 settings.calculateTopControlsPosition = true;
1103 settings.topControlsHeight = 50;
1104
[email protected]c1bb5af2013-03-13 19:06:271105 m_hostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
1106 m_hostImpl->InitializeRenderer(createOutputSurface());
1107 m_hostImpl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
[email protected]c8415bf92013-02-17 18:57:271108
1109 gfx::Size layerSize(5, 5);
[email protected]c1bb5af2013-03-13 19:06:271110 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341111 root->SetScrollable(true);
1112 root->SetMaxScrollOffset(gfx::Vector2d(layerSize.width(), layerSize.height()));
1113 root->SetBounds(layerSize);
1114 root->SetContentBounds(layerSize);
1115 root->SetPosition(gfx::PointF(0, 0));
1116 root->SetAnchorPoint(gfx::PointF(0, 0));
[email protected]c1bb5af2013-03-13 19:06:271117 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1118 m_hostImpl->active_tree()->FindRootScrollLayer();
[email protected]c8415bf92013-02-17 18:57:271119 initializeRendererAndDrawFrame();
1120
[email protected]c1bb5af2013-03-13 19:06:271121 EXPECT_EQ(InputHandlerClient::ScrollIgnored, m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture));
[email protected]c8415bf92013-02-17 18:57:271122
[email protected]c1bb5af2013-03-13 19:06:271123 m_hostImpl->top_controls_manager()->ScrollBegin();
1124 m_hostImpl->top_controls_manager()->ScrollBy(gfx::Vector2dF(0, 50));
1125 m_hostImpl->top_controls_manager()->ScrollEnd();
1126 EXPECT_EQ(m_hostImpl->top_controls_manager()->content_top_offset(), 0.f);
[email protected]c8415bf92013-02-17 18:57:271127
[email protected]c1bb5af2013-03-13 19:06:271128 EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture));
[email protected]c8415bf92013-02-17 18:57:271129}
1130
[email protected]c2d0c5a2013-02-26 04:43:361131TEST_F(LayerTreeHostImplTest, scrollNonCompositedRoot)
[email protected]94f206c12012-08-25 00:09:141132{
1133 // Test the configuration where a non-composited root layer is embedded in a
1134 // scrollable outer layer.
[email protected]aad0a0072012-11-01 18:15:581135 gfx::Size surfaceSize(10, 10);
[email protected]94f206c12012-08-25 00:09:141136
[email protected]c1bb5af2013-03-13 19:06:271137 scoped_ptr<LayerImpl> contentLayer = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341138 contentLayer->SetDrawsContent(true);
1139 contentLayer->SetPosition(gfx::PointF(0, 0));
1140 contentLayer->SetAnchorPoint(gfx::PointF(0, 0));
1141 contentLayer->SetBounds(surfaceSize);
1142 contentLayer->SetContentBounds(gfx::Size(surfaceSize.width() * 2, surfaceSize.height() * 2));
1143 contentLayer->SetContentsScale(2, 2);
[email protected]94f206c12012-08-25 00:09:141144
[email protected]c1bb5af2013-03-13 19:06:271145 scoped_ptr<LayerImpl> scrollLayer = LayerImpl::Create(m_hostImpl->active_tree(), 2);
[email protected]7aba6662013-03-12 10:17:341146 scrollLayer->SetScrollable(true);
1147 scrollLayer->SetMaxScrollOffset(gfx::Vector2d(surfaceSize.width(), surfaceSize.height()));
1148 scrollLayer->SetBounds(surfaceSize);
1149 scrollLayer->SetContentBounds(surfaceSize);
1150 scrollLayer->SetPosition(gfx::PointF(0, 0));
1151 scrollLayer->SetAnchorPoint(gfx::PointF(0, 0));
1152 scrollLayer->AddChild(contentLayer.Pass());
[email protected]94f206c12012-08-25 00:09:141153
[email protected]c1bb5af2013-03-13 19:06:271154 m_hostImpl->active_tree()->SetRootLayer(scrollLayer.Pass());
1155 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141156 initializeRendererAndDrawFrame();
1157
[email protected]c1bb5af2013-03-13 19:06:271158 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1159 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1160 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141161 EXPECT_TRUE(m_didRequestRedraw);
1162 EXPECT_TRUE(m_didRequestCommit);
1163}
1164
[email protected]c2d0c5a2013-02-26 04:43:361165TEST_F(LayerTreeHostImplTest, scrollChildCallsCommitAndRedraw)
[email protected]94f206c12012-08-25 00:09:141166{
[email protected]aad0a0072012-11-01 18:15:581167 gfx::Size surfaceSize(10, 10);
[email protected]c1bb5af2013-03-13 19:06:271168 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341169 root->SetBounds(surfaceSize);
1170 root->SetContentBounds(surfaceSize);
1171 root->AddChild(createScrollableLayer(2, surfaceSize));
[email protected]c1bb5af2013-03-13 19:06:271172 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1173 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141174 initializeRendererAndDrawFrame();
1175
[email protected]c1bb5af2013-03-13 19:06:271176 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1177 m_hostImpl->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1178 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141179 EXPECT_TRUE(m_didRequestRedraw);
1180 EXPECT_TRUE(m_didRequestCommit);
1181}
1182
[email protected]c2d0c5a2013-02-26 04:43:361183TEST_F(LayerTreeHostImplTest, scrollMissesChild)
[email protected]94f206c12012-08-25 00:09:141184{
[email protected]aad0a0072012-11-01 18:15:581185 gfx::Size surfaceSize(10, 10);
[email protected]c1bb5af2013-03-13 19:06:271186 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341187 root->AddChild(createScrollableLayer(2, surfaceSize));
[email protected]c1bb5af2013-03-13 19:06:271188 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1189 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141190 initializeRendererAndDrawFrame();
1191
1192 // Scroll event is ignored because the input coordinate is outside the layer boundaries.
[email protected]c1bb5af2013-03-13 19:06:271193 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(15, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollIgnored);
[email protected]94f206c12012-08-25 00:09:141194 EXPECT_FALSE(m_didRequestRedraw);
1195 EXPECT_FALSE(m_didRequestCommit);
1196}
1197
[email protected]c2d0c5a2013-02-26 04:43:361198TEST_F(LayerTreeHostImplTest, scrollMissesBackfacingChild)
[email protected]94f206c12012-08-25 00:09:141199{
[email protected]aad0a0072012-11-01 18:15:581200 gfx::Size surfaceSize(10, 10);
[email protected]c1bb5af2013-03-13 19:06:271201 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]96baf3e2012-10-22 23:09:551202 scoped_ptr<LayerImpl> child = createScrollableLayer(2, surfaceSize);
[email protected]c1bb5af2013-03-13 19:06:271203 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141204
[email protected]c8686a02012-11-27 08:29:001205 gfx::Transform matrix;
[email protected]78634b0c2013-01-15 07:49:401206 matrix.RotateAboutXAxis(180);
[email protected]7aba6662013-03-12 10:17:341207 child->SetTransform(matrix);
1208 child->SetDoubleSided(false);
[email protected]94f206c12012-08-25 00:09:141209
[email protected]7aba6662013-03-12 10:17:341210 root->AddChild(child.Pass());
[email protected]c1bb5af2013-03-13 19:06:271211 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:141212 initializeRendererAndDrawFrame();
1213
1214 // Scroll event is ignored because the scrollable layer is not facing the viewer and there is
1215 // nothing scrollable behind it.
[email protected]c1bb5af2013-03-13 19:06:271216 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollIgnored);
[email protected]94f206c12012-08-25 00:09:141217 EXPECT_FALSE(m_didRequestRedraw);
1218 EXPECT_FALSE(m_didRequestCommit);
1219}
1220
[email protected]c2d0c5a2013-02-26 04:43:361221TEST_F(LayerTreeHostImplTest, scrollBlockedByContentLayer)
[email protected]94f206c12012-08-25 00:09:141222{
[email protected]aad0a0072012-11-01 18:15:581223 gfx::Size surfaceSize(10, 10);
[email protected]96baf3e2012-10-22 23:09:551224 scoped_ptr<LayerImpl> contentLayer = createScrollableLayer(1, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341225 contentLayer->SetShouldScrollOnMainThread(true);
1226 contentLayer->SetScrollable(false);
[email protected]94f206c12012-08-25 00:09:141227
[email protected]96baf3e2012-10-22 23:09:551228 scoped_ptr<LayerImpl> scrollLayer = createScrollableLayer(2, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341229 scrollLayer->AddChild(contentLayer.Pass());
[email protected]94f206c12012-08-25 00:09:141230
[email protected]c1bb5af2013-03-13 19:06:271231 m_hostImpl->active_tree()->SetRootLayer(scrollLayer.Pass());
1232 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141233 initializeRendererAndDrawFrame();
1234
1235 // Scrolling fails because the content layer is asking to be scrolled on the main thread.
[email protected]c1bb5af2013-03-13 19:06:271236 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollOnMainThread);
[email protected]94f206c12012-08-25 00:09:141237}
1238
[email protected]c2d0c5a2013-02-26 04:43:361239TEST_F(LayerTreeHostImplTest, scrollRootAndChangePageScaleOnMainThread)
[email protected]94f206c12012-08-25 00:09:141240{
[email protected]aad0a0072012-11-01 18:15:581241 gfx::Size surfaceSize(10, 10);
[email protected]94f206c12012-08-25 00:09:141242 float pageScale = 2;
[email protected]96baf3e2012-10-22 23:09:551243 scoped_ptr<LayerImpl> root = createScrollableLayer(1, surfaceSize);
[email protected]c1bb5af2013-03-13 19:06:271244 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1245 m_hostImpl->active_tree()->DidBecomeActive();
1246 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141247 initializeRendererAndDrawFrame();
1248
[email protected]c9c1ebe2012-11-05 20:46:131249 gfx::Vector2d scrollDelta(0, 10);
1250 gfx::Vector2d expectedScrollDelta(scrollDelta);
[email protected]c1bb5af2013-03-13 19:06:271251 gfx::Vector2d expectedMaxScroll(m_hostImpl->active_tree()->root_layer()->max_scroll_offset());
1252 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1253 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1254 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141255
1256 // Set new page scale from main thread.
[email protected]c1bb5af2013-03-13 19:06:271257 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(pageScale, pageScale, pageScale);
[email protected]94f206c12012-08-25 00:09:141258
[email protected]c1bb5af2013-03-13 19:06:271259 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
1260 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), expectedScrollDelta);
[email protected]94f206c12012-08-25 00:09:141261
1262 // The scroll range should also have been updated.
[email protected]c1bb5af2013-03-13 19:06:271263 EXPECT_EQ(m_hostImpl->active_tree()->root_layer()->max_scroll_offset(), expectedMaxScroll);
[email protected]94f206c12012-08-25 00:09:141264
1265 // The page scale delta remains constant because the impl thread did not scale.
[email protected]c8686a02012-11-27 08:29:001266 // TODO: If possible, use gfx::Transform() or Skia equality functions. At
1267 // the moment we avoid that because skia does exact bit-wise equality
1268 // checking that does not consider -0 == +0.
1269 // http://code.google.com/p/chromium/issues/detail?id=162747
[email protected]c1bb5af2013-03-13 19:06:271270 EXPECT_EQ(1.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(0, 0));
1271 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(0, 1));
1272 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(0, 2));
1273 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(0, 3));
1274 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(1, 0));
1275 EXPECT_EQ(1.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(1, 1));
1276 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(1, 2));
1277 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(1, 3));
1278 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(2, 0));
1279 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(2, 1));
1280 EXPECT_EQ(1.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(2, 2));
1281 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(2, 3));
1282 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(3, 0));
1283 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(3, 1));
1284 EXPECT_EQ(0.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(3, 2));
1285 EXPECT_EQ(1.0, m_hostImpl->active_tree()->root_layer()->impl_transform().matrix().getDouble(3, 3));
[email protected]94f206c12012-08-25 00:09:141286}
1287
[email protected]c2d0c5a2013-02-26 04:43:361288TEST_F(LayerTreeHostImplTest, scrollRootAndChangePageScaleOnImplThread)
[email protected]94f206c12012-08-25 00:09:141289{
[email protected]aad0a0072012-11-01 18:15:581290 gfx::Size surfaceSize(10, 10);
[email protected]94f206c12012-08-25 00:09:141291 float pageScale = 2;
[email protected]96baf3e2012-10-22 23:09:551292 scoped_ptr<LayerImpl> root = createScrollableLayer(1, surfaceSize);
[email protected]c1bb5af2013-03-13 19:06:271293 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1294 m_hostImpl->active_tree()->DidBecomeActive();
1295 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
1296 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(1, 1, pageScale);
[email protected]94f206c12012-08-25 00:09:141297 initializeRendererAndDrawFrame();
1298
[email protected]c9c1ebe2012-11-05 20:46:131299 gfx::Vector2d scrollDelta(0, 10);
1300 gfx::Vector2d expectedScrollDelta(scrollDelta);
[email protected]c1bb5af2013-03-13 19:06:271301 gfx::Vector2d expectedMaxScroll(m_hostImpl->active_tree()->root_layer()->max_scroll_offset());
1302 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1303 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1304 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141305
1306 // Set new page scale on impl thread by pinching.
[email protected]c1bb5af2013-03-13 19:06:271307 m_hostImpl->PinchGestureBegin();
1308 m_hostImpl->PinchGestureUpdate(pageScale, gfx::Point());
1309 m_hostImpl->PinchGestureEnd();
[email protected]2d692992012-12-19 01:19:321310 drawOneFrame();
[email protected]94f206c12012-08-25 00:09:141311
1312 // The scroll delta is not scaled because the main thread did not scale.
[email protected]c1bb5af2013-03-13 19:06:271313 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
1314 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), expectedScrollDelta);
[email protected]94f206c12012-08-25 00:09:141315
1316 // The scroll range should also have been updated.
[email protected]c1bb5af2013-03-13 19:06:271317 EXPECT_EQ(m_hostImpl->active_tree()->root_layer()->max_scroll_offset(), expectedMaxScroll);
[email protected]94f206c12012-08-25 00:09:141318
1319 // The page scale delta should match the new scale on the impl side.
[email protected]c8686a02012-11-27 08:29:001320 gfx::Transform expectedScale;
1321 expectedScale.Scale(pageScale, pageScale);
[email protected]c1bb5af2013-03-13 19:06:271322 EXPECT_EQ(m_hostImpl->active_tree()->root_layer()->impl_transform(), expectedScale);
[email protected]94f206c12012-08-25 00:09:141323}
1324
[email protected]c2d0c5a2013-02-26 04:43:361325TEST_F(LayerTreeHostImplTest, pageScaleDeltaAppliedToRootScrollLayerOnly)
[email protected]94f206c12012-08-25 00:09:141326{
[email protected]aad0a0072012-11-01 18:15:581327 gfx::Size surfaceSize(10, 10);
[email protected]94f206c12012-08-25 00:09:141328 float defaultPageScale = 1;
[email protected]c8686a02012-11-27 08:29:001329 gfx::Transform defaultPageScaleMatrix;
[email protected]1c0c9bc2012-10-08 22:41:481330
[email protected]94f206c12012-08-25 00:09:141331 float newPageScale = 2;
[email protected]c8686a02012-11-27 08:29:001332 gfx::Transform newPageScaleMatrix;
1333 newPageScaleMatrix.Scale(newPageScale, newPageScale);
[email protected]94f206c12012-08-25 00:09:141334
1335 // Create a normal scrollable root layer and another scrollable child layer.
1336 setupScrollAndContentsLayers(surfaceSize);
[email protected]c1bb5af2013-03-13 19:06:271337 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]96baf3e2012-10-22 23:09:551338 LayerImpl* child = root->children()[0];
[email protected]94f206c12012-08-25 00:09:141339
[email protected]96baf3e2012-10-22 23:09:551340 scoped_ptr<LayerImpl> scrollableChild = createScrollableLayer(3, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341341 child->AddChild(scrollableChild.Pass());
[email protected]96baf3e2012-10-22 23:09:551342 LayerImpl* grandChild = child->children()[0];
[email protected]94f206c12012-08-25 00:09:141343
1344 // Set new page scale on impl thread by pinching.
[email protected]c1bb5af2013-03-13 19:06:271345 m_hostImpl->PinchGestureBegin();
1346 m_hostImpl->PinchGestureUpdate(newPageScale, gfx::Point());
1347 m_hostImpl->PinchGestureEnd();
[email protected]2d692992012-12-19 01:19:321348 drawOneFrame();
[email protected]94f206c12012-08-25 00:09:141349
1350 // The page scale delta should only be applied to the scrollable root layer.
[email protected]7aba6662013-03-12 10:17:341351 EXPECT_EQ(root->impl_transform(), newPageScaleMatrix);
1352 EXPECT_EQ(child->impl_transform(), defaultPageScaleMatrix);
1353 EXPECT_EQ(grandChild->impl_transform(), defaultPageScaleMatrix);
[email protected]94f206c12012-08-25 00:09:141354
1355 // Make sure all the layers are drawn with the page scale delta applied, i.e., the page scale
1356 // delta on the root layer is applied hierarchically.
[email protected]96baf3e2012-10-22 23:09:551357 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:271358 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521359 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:271360 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141361
[email protected]7aba6662013-03-12 10:17:341362 EXPECT_EQ(root->draw_transform().matrix().getDouble(0, 0), newPageScale);
1363 EXPECT_EQ(root->draw_transform().matrix().getDouble(1, 1), newPageScale);
1364 EXPECT_EQ(child->draw_transform().matrix().getDouble(0, 0), newPageScale);
1365 EXPECT_EQ(child->draw_transform().matrix().getDouble(1, 1), newPageScale);
1366 EXPECT_EQ(grandChild->draw_transform().matrix().getDouble(0, 0), newPageScale);
1367 EXPECT_EQ(grandChild->draw_transform().matrix().getDouble(1, 1), newPageScale);
[email protected]94f206c12012-08-25 00:09:141368}
1369
[email protected]c2d0c5a2013-02-26 04:43:361370TEST_F(LayerTreeHostImplTest, scrollChildAndChangePageScaleOnMainThread)
[email protected]94f206c12012-08-25 00:09:141371{
[email protected]aad0a0072012-11-01 18:15:581372 gfx::Size surfaceSize(10, 10);
[email protected]c1bb5af2013-03-13 19:06:271373 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341374 root->SetBounds(surfaceSize);
1375 root->SetContentBounds(surfaceSize);
[email protected]94f206c12012-08-25 00:09:141376 // Also mark the root scrollable so it becomes the root scroll layer.
[email protected]7aba6662013-03-12 10:17:341377 root->SetScrollable(true);
[email protected]94f206c12012-08-25 00:09:141378 int scrollLayerId = 2;
[email protected]7aba6662013-03-12 10:17:341379 root->AddChild(createScrollableLayer(scrollLayerId, surfaceSize));
[email protected]c1bb5af2013-03-13 19:06:271380 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1381 m_hostImpl->active_tree()->DidBecomeActive();
1382 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141383 initializeRendererAndDrawFrame();
1384
[email protected]c1bb5af2013-03-13 19:06:271385 LayerImpl* child = m_hostImpl->active_tree()->root_layer()->children()[0];
[email protected]94f206c12012-08-25 00:09:141386
[email protected]c9c1ebe2012-11-05 20:46:131387 gfx::Vector2d scrollDelta(0, 10);
1388 gfx::Vector2d expectedScrollDelta(scrollDelta);
[email protected]7aba6662013-03-12 10:17:341389 gfx::Vector2d expectedMaxScroll(child->max_scroll_offset());
[email protected]c1bb5af2013-03-13 19:06:271390 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1391 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1392 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141393
1394 float pageScale = 2;
[email protected]c1bb5af2013-03-13 19:06:271395 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(pageScale, 1, pageScale);
[email protected]94f206c12012-08-25 00:09:141396
[email protected]2d692992012-12-19 01:19:321397 drawOneFrame();
[email protected]1c0c9bc2012-10-08 22:41:481398
[email protected]c1bb5af2013-03-13 19:06:271399 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:141400 expectContains(*scrollInfo.get(), scrollLayerId, expectedScrollDelta);
1401
1402 // The scroll range should not have changed.
[email protected]7aba6662013-03-12 10:17:341403 EXPECT_EQ(child->max_scroll_offset(), expectedMaxScroll);
[email protected]94f206c12012-08-25 00:09:141404
1405 // The page scale delta remains constant because the impl thread did not scale.
[email protected]c8686a02012-11-27 08:29:001406 gfx::Transform identityTransform;
[email protected]7aba6662013-03-12 10:17:341407 EXPECT_EQ(child->impl_transform(), gfx::Transform());
[email protected]94f206c12012-08-25 00:09:141408}
1409
[email protected]c2d0c5a2013-02-26 04:43:361410TEST_F(LayerTreeHostImplTest, scrollChildBeyondLimit)
[email protected]94f206c12012-08-25 00:09:141411{
1412 // Scroll a child layer beyond its maximum scroll range and make sure the
1413 // parent layer is scrolled on the axis on which the child was unable to
1414 // scroll.
[email protected]aad0a0072012-11-01 18:15:581415 gfx::Size surfaceSize(10, 10);
[email protected]96baf3e2012-10-22 23:09:551416 scoped_ptr<LayerImpl> root = createScrollableLayer(1, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141417
[email protected]96baf3e2012-10-22 23:09:551418 scoped_ptr<LayerImpl> grandChild = createScrollableLayer(3, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341419 grandChild->SetScrollOffset(gfx::Vector2d(0, 5));
[email protected]94f206c12012-08-25 00:09:141420
[email protected]96baf3e2012-10-22 23:09:551421 scoped_ptr<LayerImpl> child = createScrollableLayer(2, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341422 child->SetScrollOffset(gfx::Vector2d(3, 0));
1423 child->AddChild(grandChild.Pass());
[email protected]94f206c12012-08-25 00:09:141424
[email protected]7aba6662013-03-12 10:17:341425 root->AddChild(child.Pass());
[email protected]c1bb5af2013-03-13 19:06:271426 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1427 m_hostImpl->active_tree()->DidBecomeActive();
1428 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141429 initializeRendererAndDrawFrame();
1430 {
[email protected]c9c1ebe2012-11-05 20:46:131431 gfx::Vector2d scrollDelta(-8, -7);
[email protected]c1bb5af2013-03-13 19:06:271432 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1433 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1434 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141435
[email protected]c1bb5af2013-03-13 19:06:271436 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:141437
1438 // The grand child should have scrolled up to its limit.
[email protected]c1bb5af2013-03-13 19:06:271439 LayerImpl* child = m_hostImpl->active_tree()->root_layer()->children()[0];
[email protected]96baf3e2012-10-22 23:09:551440 LayerImpl* grandChild = child->children()[0];
[email protected]c9c1ebe2012-11-05 20:46:131441 expectContains(*scrollInfo.get(), grandChild->id(), gfx::Vector2d(0, -5));
[email protected]94f206c12012-08-25 00:09:141442
1443 // The child should have only scrolled on the other axis.
[email protected]c9c1ebe2012-11-05 20:46:131444 expectContains(*scrollInfo.get(), child->id(), gfx::Vector2d(-3, 0));
[email protected]94f206c12012-08-25 00:09:141445 }
1446}
1447
[email protected]c2d0c5a2013-02-26 04:43:361448TEST_F(LayerTreeHostImplTest, scrollWithoutBubbling)
[email protected]7dfa6862013-01-31 01:29:091449{
1450 // Scroll a child layer beyond its maximum scroll range and make sure the
1451 // the scroll doesn't bubble up to the parent layer.
1452 gfx::Size surfaceSize(10, 10);
1453 scoped_ptr<LayerImpl> root = createScrollableLayer(1, surfaceSize);
1454
1455 scoped_ptr<LayerImpl> grandChild = createScrollableLayer(3, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341456 grandChild->SetScrollOffset(gfx::Vector2d(0, 2));
[email protected]7dfa6862013-01-31 01:29:091457
1458 scoped_ptr<LayerImpl> child = createScrollableLayer(2, surfaceSize);
[email protected]7aba6662013-03-12 10:17:341459 child->SetScrollOffset(gfx::Vector2d(0, 3));
1460 child->AddChild(grandChild.Pass());
[email protected]7dfa6862013-01-31 01:29:091461
[email protected]7aba6662013-03-12 10:17:341462 root->AddChild(child.Pass());
[email protected]c1bb5af2013-03-13 19:06:271463 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1464 m_hostImpl->active_tree()->DidBecomeActive();
1465 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]7dfa6862013-01-31 01:29:091466 initializeRendererAndDrawFrame();
1467 {
1468 gfx::Vector2d scrollDelta(0, -10);
[email protected]c1bb5af2013-03-13 19:06:271469 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::NonBubblingGesture), InputHandlerClient::ScrollStarted);
1470 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1471 m_hostImpl->ScrollEnd();
[email protected]7dfa6862013-01-31 01:29:091472
[email protected]c1bb5af2013-03-13 19:06:271473 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]7dfa6862013-01-31 01:29:091474
1475 // The grand child should have scrolled up to its limit.
[email protected]c1bb5af2013-03-13 19:06:271476 LayerImpl* child = m_hostImpl->active_tree()->root_layer()->children()[0];
[email protected]7dfa6862013-01-31 01:29:091477 LayerImpl* grandChild = child->children()[0];
1478 expectContains(*scrollInfo.get(), grandChild->id(), gfx::Vector2d(0, -2));
1479
1480 // The child should not have scrolled.
1481 expectNone(*scrollInfo.get(), child->id());
1482
1483 // The next time we scroll we should only scroll the parent.
1484 scrollDelta = gfx::Vector2d(0, -3);
[email protected]c1bb5af2013-03-13 19:06:271485 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::NonBubblingGesture), InputHandlerClient::ScrollStarted);
1486 EXPECT_EQ(m_hostImpl->CurrentlyScrollingLayer(), grandChild);
1487 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1488 EXPECT_EQ(m_hostImpl->CurrentlyScrollingLayer(), child);
1489 m_hostImpl->ScrollEnd();
[email protected]7dfa6862013-01-31 01:29:091490
[email protected]c1bb5af2013-03-13 19:06:271491 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]7dfa6862013-01-31 01:29:091492
1493 // The child should have scrolled up to its limit.
1494 expectContains(*scrollInfo.get(), child->id(), gfx::Vector2d(0, -3));
1495
1496 // The grand child should not have scrolled.
1497 expectContains(*scrollInfo.get(), grandChild->id(), gfx::Vector2d(0, -2));
1498
1499 // After scrolling the parent, another scroll on the opposite direction
1500 // should still scroll the child.
1501 scrollDelta = gfx::Vector2d(0, 7);
[email protected]c1bb5af2013-03-13 19:06:271502 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::NonBubblingGesture), InputHandlerClient::ScrollStarted);
1503 EXPECT_EQ(m_hostImpl->CurrentlyScrollingLayer(), grandChild);
1504 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1505 EXPECT_EQ(m_hostImpl->CurrentlyScrollingLayer(), grandChild);
1506 m_hostImpl->ScrollEnd();
[email protected]7dfa6862013-01-31 01:29:091507
[email protected]c1bb5af2013-03-13 19:06:271508 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]7dfa6862013-01-31 01:29:091509
1510 // The grand child should have scrolled.
1511 expectContains(*scrollInfo.get(), grandChild->id(), gfx::Vector2d(0, 5));
1512
1513 // The child should not have scrolled.
1514 expectContains(*scrollInfo.get(), child->id(), gfx::Vector2d(0, -3));
[email protected]f4937272013-02-07 05:54:501515
1516
1517 // Scrolling should be adjusted from viewport space.
[email protected]c1bb5af2013-03-13 19:06:271518 m_hostImpl->active_tree()->SetPageScaleFactorAndLimits(2, 2, 2);
1519 m_hostImpl->active_tree()->SetPageScaleDelta(1);
[email protected]f4937272013-02-07 05:54:501520 gfx::Transform scaleTransform;
1521 scaleTransform.Scale(2, 2);
[email protected]c1bb5af2013-03-13 19:06:271522 m_hostImpl->active_tree()->root_layer()->SetImplTransform(scaleTransform);
[email protected]f4937272013-02-07 05:54:501523
1524 scrollDelta = gfx::Vector2d(0, -2);
[email protected]c1bb5af2013-03-13 19:06:271525 EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->ScrollBegin(gfx::Point(1, 1), InputHandlerClient::NonBubblingGesture));
1526 EXPECT_EQ(grandChild, m_hostImpl->CurrentlyScrollingLayer());
1527 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1528 m_hostImpl->ScrollEnd();
[email protected]f4937272013-02-07 05:54:501529
[email protected]c1bb5af2013-03-13 19:06:271530 scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]f4937272013-02-07 05:54:501531
1532 // Should have scrolled by half the amount in layer space (5 - 2/2)
1533 expectContains(*scrollInfo.get(), grandChild->id(), gfx::Vector2d(0, 4));
[email protected]7dfa6862013-01-31 01:29:091534 }
1535}
1536
[email protected]c2d0c5a2013-02-26 04:43:361537TEST_F(LayerTreeHostImplTest, scrollEventBubbling)
[email protected]94f206c12012-08-25 00:09:141538{
1539 // When we try to scroll a non-scrollable child layer, the scroll delta
1540 // should be applied to one of its ancestors if possible.
[email protected]aad0a0072012-11-01 18:15:581541 gfx::Size surfaceSize(10, 10);
[email protected]69b50ec2013-01-19 04:58:011542 gfx::Size contentSize(20, 20);
1543 scoped_ptr<LayerImpl> root = createScrollableLayer(1, contentSize);
1544 scoped_ptr<LayerImpl> child = createScrollableLayer(2, contentSize);
[email protected]94f206c12012-08-25 00:09:141545
[email protected]7aba6662013-03-12 10:17:341546 child->SetScrollable(false);
1547 root->AddChild(child.Pass());
[email protected]94f206c12012-08-25 00:09:141548
[email protected]c1bb5af2013-03-13 19:06:271549 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
1550 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
1551 m_hostImpl->active_tree()->DidBecomeActive();
[email protected]94f206c12012-08-25 00:09:141552 initializeRendererAndDrawFrame();
1553 {
[email protected]c9c1ebe2012-11-05 20:46:131554 gfx::Vector2d scrollDelta(0, 4);
[email protected]c1bb5af2013-03-13 19:06:271555 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1556 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1557 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141558
[email protected]c1bb5af2013-03-13 19:06:271559 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:141560
1561 // Only the root should have scrolled.
1562 ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
[email protected]c1bb5af2013-03-13 19:06:271563 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), scrollDelta);
[email protected]94f206c12012-08-25 00:09:141564 }
1565}
1566
[email protected]c2d0c5a2013-02-26 04:43:361567TEST_F(LayerTreeHostImplTest, scrollBeforeRedraw)
[email protected]94f206c12012-08-25 00:09:141568{
[email protected]aad0a0072012-11-01 18:15:581569 gfx::Size surfaceSize(10, 10);
[email protected]c1bb5af2013-03-13 19:06:271570 m_hostImpl->active_tree()->SetRootLayer(createScrollableLayer(1, surfaceSize));
1571 m_hostImpl->active_tree()->DidBecomeActive();
1572 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141573
1574 // Draw one frame and then immediately rebuild the layer tree to mimic a tree synchronization.
1575 initializeRendererAndDrawFrame();
[email protected]c1bb5af2013-03-13 19:06:271576 m_hostImpl->active_tree()->DetachLayerTree();
1577 m_hostImpl->active_tree()->SetRootLayer(createScrollableLayer(2, surfaceSize));
1578 m_hostImpl->active_tree()->DidBecomeActive();
[email protected]94f206c12012-08-25 00:09:141579
1580 // Scrolling should still work even though we did not draw yet.
[email protected]c1bb5af2013-03-13 19:06:271581 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(5, 5), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
[email protected]94f206c12012-08-25 00:09:141582}
1583
[email protected]c2d0c5a2013-02-26 04:43:361584TEST_F(LayerTreeHostImplTest, scrollAxisAlignedRotatedLayer)
[email protected]94f206c12012-08-25 00:09:141585{
[email protected]aad0a0072012-11-01 18:15:581586 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:141587
1588 // Rotate the root layer 90 degrees counter-clockwise about its center.
[email protected]c8686a02012-11-27 08:29:001589 gfx::Transform rotateTransform;
1590 rotateTransform.Rotate(-90);
[email protected]c1bb5af2013-03-13 19:06:271591 m_hostImpl->active_tree()->root_layer()->SetTransform(rotateTransform);
[email protected]94f206c12012-08-25 00:09:141592
[email protected]aad0a0072012-11-01 18:15:581593 gfx::Size surfaceSize(50, 50);
[email protected]c1bb5af2013-03-13 19:06:271594 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141595 initializeRendererAndDrawFrame();
1596
1597 // Scroll to the right in screen coordinates with a gesture.
[email protected]c9c1ebe2012-11-05 20:46:131598 gfx::Vector2d gestureScrollDelta(10, 0);
[email protected]c1bb5af2013-03-13 19:06:271599 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
1600 m_hostImpl->ScrollBy(gfx::Point(), gestureScrollDelta);
1601 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141602
1603 // The layer should have scrolled down in its local coordinates.
[email protected]c1bb5af2013-03-13 19:06:271604 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
1605 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), gfx::Vector2d(0, gestureScrollDelta.x()));
[email protected]94f206c12012-08-25 00:09:141606
1607 // Reset and scroll down with the wheel.
[email protected]c1bb5af2013-03-13 19:06:271608 m_hostImpl->active_tree()->root_layer()->SetScrollDelta(gfx::Vector2dF());
[email protected]c9c1ebe2012-11-05 20:46:131609 gfx::Vector2d wheelScrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:271610 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1611 m_hostImpl->ScrollBy(gfx::Point(), wheelScrollDelta);
1612 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141613
1614 // The layer should have scrolled down in its local coordinates.
[email protected]c1bb5af2013-03-13 19:06:271615 scrollInfo = m_hostImpl->ProcessScrollDeltas();
1616 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), wheelScrollDelta);
[email protected]94f206c12012-08-25 00:09:141617}
1618
[email protected]c2d0c5a2013-02-26 04:43:361619TEST_F(LayerTreeHostImplTest, scrollNonAxisAlignedRotatedLayer)
[email protected]94f206c12012-08-25 00:09:141620{
[email protected]aad0a0072012-11-01 18:15:581621 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:141622 int childLayerId = 3;
1623 float childLayerAngle = -20;
1624
1625 // Create a child layer that is rotated to a non-axis-aligned angle.
[email protected]c1bb5af2013-03-13 19:06:271626 scoped_ptr<LayerImpl> child = createScrollableLayer(childLayerId, m_hostImpl->active_tree()->root_layer()->content_bounds());
[email protected]c8686a02012-11-27 08:29:001627 gfx::Transform rotateTransform;
1628 rotateTransform.Translate(-50, -50);
1629 rotateTransform.Rotate(childLayerAngle);
1630 rotateTransform.Translate(50, 50);
[email protected]7aba6662013-03-12 10:17:341631 child->SetTransform(rotateTransform);
[email protected]94f206c12012-08-25 00:09:141632
1633 // Only allow vertical scrolling.
[email protected]7aba6662013-03-12 10:17:341634 child->SetMaxScrollOffset(gfx::Vector2d(0, child->content_bounds().height()));
[email protected]c1bb5af2013-03-13 19:06:271635 m_hostImpl->active_tree()->root_layer()->AddChild(child.Pass());
[email protected]94f206c12012-08-25 00:09:141636
[email protected]aad0a0072012-11-01 18:15:581637 gfx::Size surfaceSize(50, 50);
[email protected]c1bb5af2013-03-13 19:06:271638 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141639 initializeRendererAndDrawFrame();
1640
1641 {
1642 // Scroll down in screen coordinates with a gesture.
[email protected]c9c1ebe2012-11-05 20:46:131643 gfx::Vector2d gestureScrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:271644 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
1645 m_hostImpl->ScrollBy(gfx::Point(), gestureScrollDelta);
1646 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141647
1648 // The child layer should have scrolled down in its local coordinates an amount proportional to
1649 // the angle between it and the input scroll delta.
[email protected]ac7c7f52012-11-08 06:26:501650 gfx::Vector2d expectedScrollDelta(0, gestureScrollDelta.y() * std::cos(MathUtil::Deg2Rad(childLayerAngle)));
[email protected]c1bb5af2013-03-13 19:06:271651 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:141652 expectContains(*scrollInfo.get(), childLayerId, expectedScrollDelta);
1653
1654 // The root layer should not have scrolled, because the input delta was close to the layer's
1655 // axis of movement.
1656 EXPECT_EQ(scrollInfo->scrolls.size(), 1u);
1657 }
1658
1659 {
1660 // Now reset and scroll the same amount horizontally.
[email protected]c1bb5af2013-03-13 19:06:271661 m_hostImpl->active_tree()->root_layer()->children()[1]->SetScrollDelta(gfx::Vector2dF());
[email protected]c9c1ebe2012-11-05 20:46:131662 gfx::Vector2d gestureScrollDelta(10, 0);
[email protected]c1bb5af2013-03-13 19:06:271663 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
1664 m_hostImpl->ScrollBy(gfx::Point(), gestureScrollDelta);
1665 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141666
1667 // The child layer should have scrolled down in its local coordinates an amount proportional to
1668 // the angle between it and the input scroll delta.
[email protected]ac7c7f52012-11-08 06:26:501669 gfx::Vector2d expectedScrollDelta(0, -gestureScrollDelta.x() * std::sin(MathUtil::Deg2Rad(childLayerAngle)));
[email protected]c1bb5af2013-03-13 19:06:271670 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
[email protected]94f206c12012-08-25 00:09:141671 expectContains(*scrollInfo.get(), childLayerId, expectedScrollDelta);
1672
1673 // The root layer should have scrolled more, since the input scroll delta was mostly
1674 // orthogonal to the child layer's vertical scroll axis.
[email protected]ac7c7f52012-11-08 06:26:501675 gfx::Vector2d expectedRootScrollDelta(gestureScrollDelta.x() * std::pow(std::cos(MathUtil::Deg2Rad(childLayerAngle)), 2), 0);
[email protected]c1bb5af2013-03-13 19:06:271676 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), expectedRootScrollDelta);
[email protected]94f206c12012-08-25 00:09:141677 }
1678}
1679
[email protected]c2d0c5a2013-02-26 04:43:361680TEST_F(LayerTreeHostImplTest, scrollScaledLayer)
[email protected]94f206c12012-08-25 00:09:141681{
[email protected]aad0a0072012-11-01 18:15:581682 setupScrollAndContentsLayers(gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:141683
1684 // Scale the layer to twice its normal size.
1685 int scale = 2;
[email protected]c8686a02012-11-27 08:29:001686 gfx::Transform scaleTransform;
1687 scaleTransform.Scale(scale, scale);
[email protected]c1bb5af2013-03-13 19:06:271688 m_hostImpl->active_tree()->root_layer()->SetTransform(scaleTransform);
[email protected]94f206c12012-08-25 00:09:141689
[email protected]aad0a0072012-11-01 18:15:581690 gfx::Size surfaceSize(50, 50);
[email protected]c1bb5af2013-03-13 19:06:271691 m_hostImpl->SetViewportSize(surfaceSize, surfaceSize);
[email protected]94f206c12012-08-25 00:09:141692 initializeRendererAndDrawFrame();
1693
1694 // Scroll down in screen coordinates with a gesture.
[email protected]c9c1ebe2012-11-05 20:46:131695 gfx::Vector2d scrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:271696 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture), InputHandlerClient::ScrollStarted);
1697 m_hostImpl->ScrollBy(gfx::Point(), scrollDelta);
1698 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141699
1700 // The layer should have scrolled down in its local coordinates, but half he amount.
[email protected]c1bb5af2013-03-13 19:06:271701 scoped_ptr<ScrollAndScaleSet> scrollInfo = m_hostImpl->ProcessScrollDeltas();
1702 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), gfx::Vector2d(0, scrollDelta.y() / scale));
[email protected]94f206c12012-08-25 00:09:141703
1704 // Reset and scroll down with the wheel.
[email protected]c1bb5af2013-03-13 19:06:271705 m_hostImpl->active_tree()->root_layer()->SetScrollDelta(gfx::Vector2dF());
[email protected]c9c1ebe2012-11-05 20:46:131706 gfx::Vector2d wheelScrollDelta(0, 10);
[email protected]c1bb5af2013-03-13 19:06:271707 EXPECT_EQ(m_hostImpl->ScrollBegin(gfx::Point(0, 0), InputHandlerClient::Wheel), InputHandlerClient::ScrollStarted);
1708 m_hostImpl->ScrollBy(gfx::Point(), wheelScrollDelta);
1709 m_hostImpl->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141710
1711 // The scale should not have been applied to the scroll delta.
[email protected]c1bb5af2013-03-13 19:06:271712 scrollInfo = m_hostImpl->ProcessScrollDeltas();
1713 expectContains(*scrollInfo.get(), m_hostImpl->active_tree()->root_layer()->id(), wheelScrollDelta);
[email protected]94f206c12012-08-25 00:09:141714}
1715
[email protected]c8756fbe2013-02-12 01:53:491716class BlendStateTrackerContext: public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:141717public:
1718 BlendStateTrackerContext() : m_blend(false) { }
1719
[email protected]009dc072012-12-16 20:32:131720 virtual void enable(WebKit::WGC3Denum cap)
[email protected]94f206c12012-08-25 00:09:141721 {
[email protected]d9c28522012-10-18 23:35:431722 if (cap == GL_BLEND)
[email protected]94f206c12012-08-25 00:09:141723 m_blend = true;
1724 }
1725
[email protected]009dc072012-12-16 20:32:131726 virtual void disable(WebKit::WGC3Denum cap)
[email protected]94f206c12012-08-25 00:09:141727 {
[email protected]d9c28522012-10-18 23:35:431728 if (cap == GL_BLEND)
[email protected]94f206c12012-08-25 00:09:141729 m_blend = false;
1730 }
1731
1732 bool blend() const { return m_blend; }
1733
1734private:
1735 bool m_blend;
1736};
1737
[email protected]96baf3e2012-10-22 23:09:551738class BlendStateCheckLayer : public LayerImpl {
[email protected]94f206c12012-08-25 00:09:141739public:
[email protected]7aba6662013-03-12 10:17:341740 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* treeImpl, int id, ResourceProvider* resourceProvider) { return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(treeImpl, id, resourceProvider)); }
[email protected]94f206c12012-08-25 00:09:141741
[email protected]7aba6662013-03-12 10:17:341742 virtual void AppendQuads(QuadSink* quadSink, AppendQuadsData* appendQuadsData) OVERRIDE
[email protected]94f206c12012-08-25 00:09:141743 {
1744 m_quadsAppended = true;
1745
[email protected]aad0a0072012-11-01 18:15:581746 gfx::Rect opaqueRect;
[email protected]7aba6662013-03-12 10:17:341747 if (contents_opaque())
[email protected]94f206c12012-08-25 00:09:141748 opaqueRect = m_quadRect;
1749 else
1750 opaqueRect = m_opaqueContentRect;
1751
[email protected]c7e95b42013-03-18 01:13:491752 SharedQuadState* sharedQuadState = quadSink->UseSharedQuadState(CreateSharedQuadState());
[email protected]c22418b2012-11-20 23:06:261753 scoped_ptr<TileDrawQuad> testBlendingDrawQuad = TileDrawQuad::Create();
[email protected]f902bf92013-03-04 18:33:271754 testBlendingDrawQuad->SetNew(sharedQuadState, m_quadRect, opaqueRect, m_resourceId, gfx::RectF(0, 0, 1, 1), gfx::Size(1, 1), false);
[email protected]1bc93f62012-11-17 19:29:501755 testBlendingDrawQuad->visible_rect = m_quadVisibleRect;
[email protected]9cd20a32012-11-17 14:11:271756 EXPECT_EQ(m_blend, testBlendingDrawQuad->ShouldDrawWithBlending());
[email protected]7aba6662013-03-12 10:17:341757 EXPECT_EQ(m_hasRenderSurface, !!render_surface());
[email protected]c7e95b42013-03-18 01:13:491758 quadSink->Append(testBlendingDrawQuad.PassAs<DrawQuad>(), appendQuadsData);
[email protected]94f206c12012-08-25 00:09:141759 }
1760
1761 void setExpectation(bool blend, bool hasRenderSurface)
1762 {
1763 m_blend = blend;
1764 m_hasRenderSurface = hasRenderSurface;
1765 m_quadsAppended = false;
1766 }
1767
1768 bool quadsAppended() const { return m_quadsAppended; }
1769
[email protected]aad0a0072012-11-01 18:15:581770 void setQuadRect(const gfx::Rect& rect) { m_quadRect = rect; }
1771 void setQuadVisibleRect(const gfx::Rect& rect) { m_quadVisibleRect = rect; }
1772 void setOpaqueContentRect(const gfx::Rect& rect) { m_opaqueContentRect = rect; }
[email protected]94f206c12012-08-25 00:09:141773
1774private:
[email protected]8bef40572012-12-11 21:38:081775 BlendStateCheckLayer(LayerTreeImpl* treeImpl, int id, ResourceProvider* resourceProvider)
1776 : LayerImpl(treeImpl, id)
[email protected]94f206c12012-08-25 00:09:141777 , m_blend(false)
1778 , m_hasRenderSurface(false)
1779 , m_quadsAppended(false)
[email protected]94f206c12012-08-25 00:09:141780 , m_quadRect(5, 5, 5, 5)
1781 , m_quadVisibleRect(5, 5, 5, 5)
[email protected]f53da3972013-03-07 08:38:411782 , m_resourceId(resourceProvider->CreateResource(gfx::Size(1, 1), GL_RGBA, ResourceProvider::TextureUsageAny))
[email protected]94f206c12012-08-25 00:09:141783 {
[email protected]f53da3972013-03-07 08:38:411784 resourceProvider->AllocateForTesting(m_resourceId);
[email protected]7aba6662013-03-12 10:17:341785 SetAnchorPoint(gfx::PointF(0, 0));
1786 SetBounds(gfx::Size(10, 10));
1787 SetContentBounds(gfx::Size(10, 10));
1788 SetDrawsContent(true);
[email protected]94f206c12012-08-25 00:09:141789 }
1790
1791 bool m_blend;
1792 bool m_hasRenderSurface;
1793 bool m_quadsAppended;
[email protected]aad0a0072012-11-01 18:15:581794 gfx::Rect m_quadRect;
1795 gfx::Rect m_opaqueContentRect;
1796 gfx::Rect m_quadVisibleRect;
[email protected]96baf3e2012-10-22 23:09:551797 ResourceProvider::ResourceId m_resourceId;
[email protected]94f206c12012-08-25 00:09:141798};
1799
[email protected]c2d0c5a2013-02-26 04:43:361800TEST_F(LayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
[email protected]94f206c12012-08-25 00:09:141801{
1802 {
[email protected]c1bb5af2013-03-13 19:06:271803 scoped_ptr<LayerImpl> root = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:341804 root->SetAnchorPoint(gfx::PointF(0, 0));
1805 root->SetBounds(gfx::Size(10, 10));
1806 root->SetContentBounds(root->bounds());
1807 root->SetDrawsContent(false);
[email protected]c1bb5af2013-03-13 19:06:271808 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:141809 }
[email protected]c1bb5af2013-03-13 19:06:271810 LayerImpl* root = m_hostImpl->active_tree()->root_layer();
[email protected]94f206c12012-08-25 00:09:141811
[email protected]c1bb5af2013-03-13 19:06:271812 root->AddChild(BlendStateCheckLayer::Create(m_hostImpl->active_tree(), 2, m_hostImpl->resource_provider()));
[email protected]0920e24f2012-09-20 03:34:031813 BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0]);
[email protected]7aba6662013-03-12 10:17:341814 layer1->SetPosition(gfx::PointF(2, 2));
[email protected]94f206c12012-08-25 00:09:141815
[email protected]96baf3e2012-10-22 23:09:551816 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:141817
1818 // Opaque layer, drawn without blending.
[email protected]7aba6662013-03-12 10:17:341819 layer1->SetContentsOpaque(true);
[email protected]94f206c12012-08-25 00:09:141820 layer1->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271821 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521822 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141823 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271824 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141825
1826 // Layer with translucent content and painting, so drawn with blending.
[email protected]7aba6662013-03-12 10:17:341827 layer1->SetContentsOpaque(false);
[email protected]94f206c12012-08-25 00:09:141828 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271829 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521830 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141831 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271832 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141833
1834 // Layer with translucent opacity, drawn with blending.
[email protected]7aba6662013-03-12 10:17:341835 layer1->SetContentsOpaque(true);
1836 layer1->SetOpacity(0.5);
[email protected]94f206c12012-08-25 00:09:141837 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271838 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521839 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141840 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271841 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141842
1843 // Layer with translucent opacity and painting, drawn with blending.
[email protected]7aba6662013-03-12 10:17:341844 layer1->SetContentsOpaque(true);
1845 layer1->SetOpacity(0.5);
[email protected]94f206c12012-08-25 00:09:141846 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271847 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521848 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141849 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271850 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141851
[email protected]c1bb5af2013-03-13 19:06:271852 layer1->AddChild(BlendStateCheckLayer::Create(m_hostImpl->active_tree(), 3, m_hostImpl->resource_provider()));
[email protected]0920e24f2012-09-20 03:34:031853 BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
[email protected]7aba6662013-03-12 10:17:341854 layer2->SetPosition(gfx::PointF(4, 4));
[email protected]94f206c12012-08-25 00:09:141855
1856 // 2 opaque layers, drawn without blending.
[email protected]7aba6662013-03-12 10:17:341857 layer1->SetContentsOpaque(true);
1858 layer1->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141859 layer1->setExpectation(false, false);
[email protected]7aba6662013-03-12 10:17:341860 layer2->SetContentsOpaque(true);
1861 layer2->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141862 layer2->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271863 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521864 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141865 EXPECT_TRUE(layer1->quadsAppended());
1866 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271867 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141868
1869 // Parent layer with translucent content, drawn with blending.
1870 // Child layer with opaque content, drawn without blending.
[email protected]7aba6662013-03-12 10:17:341871 layer1->SetContentsOpaque(false);
[email protected]94f206c12012-08-25 00:09:141872 layer1->setExpectation(true, false);
1873 layer2->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271874 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521875 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141876 EXPECT_TRUE(layer1->quadsAppended());
1877 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271878 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141879
1880 // Parent layer with translucent content but opaque painting, drawn without blending.
1881 // Child layer with opaque content, drawn without blending.
[email protected]7aba6662013-03-12 10:17:341882 layer1->SetContentsOpaque(true);
[email protected]94f206c12012-08-25 00:09:141883 layer1->setExpectation(false, false);
1884 layer2->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271885 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521886 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141887 EXPECT_TRUE(layer1->quadsAppended());
1888 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271889 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141890
1891 // Parent layer with translucent opacity and opaque content. Since it has a
1892 // drawing child, it's drawn to a render surface which carries the opacity,
1893 // so it's itself drawn without blending.
1894 // Child layer with opaque content, drawn without blending (parent surface
1895 // carries the inherited opacity).
[email protected]7aba6662013-03-12 10:17:341896 layer1->SetContentsOpaque(true);
1897 layer1->SetOpacity(0.5);
[email protected]94f206c12012-08-25 00:09:141898 layer1->setExpectation(false, true);
1899 layer2->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271900 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521901 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141902 EXPECT_TRUE(layer1->quadsAppended());
1903 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271904 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141905
1906 // Draw again, but with child non-opaque, to make sure
1907 // layer1 not culled.
[email protected]7aba6662013-03-12 10:17:341908 layer1->SetContentsOpaque(true);
1909 layer1->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141910 layer1->setExpectation(false, false);
[email protected]7aba6662013-03-12 10:17:341911 layer2->SetContentsOpaque(true);
1912 layer2->SetOpacity(0.5);
[email protected]94f206c12012-08-25 00:09:141913 layer2->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271914 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521915 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141916 EXPECT_TRUE(layer1->quadsAppended());
1917 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271918 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141919
1920 // A second way of making the child non-opaque.
[email protected]7aba6662013-03-12 10:17:341921 layer1->SetContentsOpaque(true);
1922 layer1->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141923 layer1->setExpectation(false, false);
[email protected]7aba6662013-03-12 10:17:341924 layer2->SetContentsOpaque(false);
1925 layer2->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141926 layer2->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271927 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521928 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141929 EXPECT_TRUE(layer1->quadsAppended());
1930 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271931 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141932
1933 // And when the layer says its not opaque but is painted opaque, it is not blended.
[email protected]7aba6662013-03-12 10:17:341934 layer1->SetContentsOpaque(true);
1935 layer1->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141936 layer1->setExpectation(false, false);
[email protected]7aba6662013-03-12 10:17:341937 layer2->SetContentsOpaque(true);
1938 layer2->SetOpacity(1);
[email protected]94f206c12012-08-25 00:09:141939 layer2->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271940 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521941 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141942 EXPECT_TRUE(layer1->quadsAppended());
1943 EXPECT_TRUE(layer2->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271944 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141945
1946 // Layer with partially opaque contents, drawn with blending.
[email protected]7aba6662013-03-12 10:17:341947 layer1->SetContentsOpaque(false);
[email protected]aad0a0072012-11-01 18:15:581948 layer1->setQuadRect(gfx::Rect(5, 5, 5, 5));
1949 layer1->setQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
1950 layer1->setOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
[email protected]94f206c12012-08-25 00:09:141951 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271952 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521953 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141954 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271955 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141956
1957 // Layer with partially opaque contents partially culled, drawn with blending.
[email protected]7aba6662013-03-12 10:17:341958 layer1->SetContentsOpaque(false);
[email protected]aad0a0072012-11-01 18:15:581959 layer1->setQuadRect(gfx::Rect(5, 5, 5, 5));
1960 layer1->setQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
1961 layer1->setOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
[email protected]94f206c12012-08-25 00:09:141962 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271963 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521964 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141965 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271966 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141967
1968 // Layer with partially opaque contents culled, drawn with blending.
[email protected]7aba6662013-03-12 10:17:341969 layer1->SetContentsOpaque(false);
[email protected]aad0a0072012-11-01 18:15:581970 layer1->setQuadRect(gfx::Rect(5, 5, 5, 5));
1971 layer1->setQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
1972 layer1->setOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
[email protected]94f206c12012-08-25 00:09:141973 layer1->setExpectation(true, false);
[email protected]c1bb5af2013-03-13 19:06:271974 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521975 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141976 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271977 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141978
1979 // Layer with partially opaque contents and translucent contents culled, drawn without blending.
[email protected]7aba6662013-03-12 10:17:341980 layer1->SetContentsOpaque(false);
[email protected]aad0a0072012-11-01 18:15:581981 layer1->setQuadRect(gfx::Rect(5, 5, 5, 5));
1982 layer1->setQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
1983 layer1->setOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
[email protected]94f206c12012-08-25 00:09:141984 layer1->setExpectation(false, false);
[email protected]c1bb5af2013-03-13 19:06:271985 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:521986 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:141987 EXPECT_TRUE(layer1->quadsAppended());
[email protected]c1bb5af2013-03-13 19:06:271988 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:141989
1990}
1991
[email protected]c2d0c5a2013-02-26 04:43:361992TEST_F(LayerTreeHostImplTest, viewportCovered)
[email protected]94f206c12012-08-25 00:09:141993{
[email protected]c1bb5af2013-03-13 19:06:271994 m_hostImpl->InitializeRenderer(createOutputSurface());
1995 m_hostImpl->active_tree()->set_background_color(SK_ColorGRAY);
[email protected]94f206c12012-08-25 00:09:141996
[email protected]aad0a0072012-11-01 18:15:581997 gfx::Size viewportSize(1000, 1000);
[email protected]c1bb5af2013-03-13 19:06:271998 m_hostImpl->SetViewportSize(viewportSize, viewportSize);
[email protected]94f206c12012-08-25 00:09:141999
[email protected]c1bb5af2013-03-13 19:06:272000 m_hostImpl->active_tree()->SetRootLayer(LayerImpl::Create(m_hostImpl->active_tree(), 1));
2001 m_hostImpl->active_tree()->root_layer()->AddChild(BlendStateCheckLayer::Create(m_hostImpl->active_tree(), 2, m_hostImpl->resource_provider()));
2002 BlendStateCheckLayer* child = static_cast<BlendStateCheckLayer*>(m_hostImpl->active_tree()->root_layer()->children()[0]);
[email protected]ecc12622012-10-30 20:45:422003 child->setExpectation(false, false);
[email protected]7aba6662013-03-12 10:17:342004 child->SetContentsOpaque(true);
[email protected]94f206c12012-08-25 00:09:142005
2006 // No gutter rects
2007 {
[email protected]aad0a0072012-11-01 18:15:582008 gfx::Rect layerRect(0, 0, 1000, 1000);
[email protected]7aba6662013-03-12 10:17:342009 child->SetPosition(layerRect.origin());
2010 child->SetBounds(layerRect.size());
2011 child->SetContentBounds(layerRect.size());
[email protected]aad0a0072012-11-01 18:15:582012 child->setQuadRect(gfx::Rect(gfx::Point(), layerRect.size()));
2013 child->setQuadVisibleRect(gfx::Rect(gfx::Point(), layerRect.size()));
[email protected]94f206c12012-08-25 00:09:142014
[email protected]96baf3e2012-10-22 23:09:552015 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272016 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
2017 ASSERT_EQ(1u, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142018
2019 size_t numGutterQuads = 0;
[email protected]c1bb5af2013-03-13 19:06:272020 for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
2021 numGutterQuads += (frame.render_passes[0]->quad_list[i]->material == DrawQuad::SOLID_COLOR) ? 1 : 0;
[email protected]94f206c12012-08-25 00:09:142022 EXPECT_EQ(0u, numGutterQuads);
[email protected]c1bb5af2013-03-13 19:06:272023 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142024
[email protected]c1bb5af2013-03-13 19:06:272025 LayerTestCommon::verifyQuadsExactlyCoverRect(frame.render_passes[0]->quad_list, gfx::Rect(gfx::Point(), viewportSize));
2026 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142027 }
2028
2029 // Empty visible content area (fullscreen gutter rect)
2030 {
[email protected]aad0a0072012-11-01 18:15:582031 gfx::Rect layerRect(0, 0, 0, 0);
[email protected]7aba6662013-03-12 10:17:342032 child->SetPosition(layerRect.origin());
2033 child->SetBounds(layerRect.size());
2034 child->SetContentBounds(layerRect.size());
[email protected]aad0a0072012-11-01 18:15:582035 child->setQuadRect(gfx::Rect(gfx::Point(), layerRect.size()));
2036 child->setQuadVisibleRect(gfx::Rect(gfx::Point(), layerRect.size()));
[email protected]94f206c12012-08-25 00:09:142037
[email protected]96baf3e2012-10-22 23:09:552038 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272039 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
2040 ASSERT_EQ(1u, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142041
2042 size_t numGutterQuads = 0;
[email protected]c1bb5af2013-03-13 19:06:272043 for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
2044 numGutterQuads += (frame.render_passes[0]->quad_list[i]->material == DrawQuad::SOLID_COLOR) ? 1 : 0;
[email protected]94f206c12012-08-25 00:09:142045 EXPECT_EQ(1u, numGutterQuads);
[email protected]c1bb5af2013-03-13 19:06:272046 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142047
[email protected]c1bb5af2013-03-13 19:06:272048 LayerTestCommon::verifyQuadsExactlyCoverRect(frame.render_passes[0]->quad_list, gfx::Rect(gfx::Point(), viewportSize));
2049 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142050 }
2051
2052 // Content area in middle of clip rect (four surrounding gutter rects)
2053 {
[email protected]aad0a0072012-11-01 18:15:582054 gfx::Rect layerRect(500, 500, 200, 200);
[email protected]7aba6662013-03-12 10:17:342055 child->SetPosition(layerRect.origin());
2056 child->SetBounds(layerRect.size());
2057 child->SetContentBounds(layerRect.size());
[email protected]aad0a0072012-11-01 18:15:582058 child->setQuadRect(gfx::Rect(gfx::Point(), layerRect.size()));
2059 child->setQuadVisibleRect(gfx::Rect(gfx::Point(), layerRect.size()));
[email protected]94f206c12012-08-25 00:09:142060
[email protected]96baf3e2012-10-22 23:09:552061 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272062 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
2063 ASSERT_EQ(1u, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142064
2065 size_t numGutterQuads = 0;
[email protected]c1bb5af2013-03-13 19:06:272066 for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
2067 numGutterQuads += (frame.render_passes[0]->quad_list[i]->material == DrawQuad::SOLID_COLOR) ? 1 : 0;
[email protected]94f206c12012-08-25 00:09:142068 EXPECT_EQ(4u, numGutterQuads);
[email protected]c1bb5af2013-03-13 19:06:272069 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142070
[email protected]c1bb5af2013-03-13 19:06:272071 LayerTestCommon::verifyQuadsExactlyCoverRect(frame.render_passes[0]->quad_list, gfx::Rect(gfx::Point(), viewportSize));
2072 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142073 }
2074
2075}
2076
2077
[email protected]c8756fbe2013-02-12 01:53:492078class ReshapeTrackerContext: public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142079public:
2080 ReshapeTrackerContext() : m_reshapeCalled(false) { }
2081
2082 virtual void reshape(int width, int height)
2083 {
2084 m_reshapeCalled = true;
2085 }
2086
2087 bool reshapeCalled() const { return m_reshapeCalled; }
2088
2089private:
2090 bool m_reshapeCalled;
2091};
2092
[email protected]96baf3e2012-10-22 23:09:552093class FakeDrawableLayerImpl: public LayerImpl {
[email protected]94f206c12012-08-25 00:09:142094public:
[email protected]7aba6662013-03-12 10:17:342095 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* treeImpl, int id) { return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(treeImpl, id)); }
[email protected]e0bd43a2012-10-12 16:54:212096protected:
[email protected]8bef40572012-12-11 21:38:082097 FakeDrawableLayerImpl(LayerTreeImpl* treeImpl, int id) : LayerImpl(treeImpl, id) { }
[email protected]94f206c12012-08-25 00:09:142098};
2099
2100// Only reshape when we know we are going to draw. Otherwise, the reshape
2101// can leave the window at the wrong size if we never draw and the proper
2102// viewport size is never set.
[email protected]c2d0c5a2013-02-26 04:43:362103TEST_F(LayerTreeHostImplTest, reshapeNotCalledUntilDraw)
[email protected]94f206c12012-08-25 00:09:142104{
[email protected]a46f32932012-12-07 21:43:162105 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new ReshapeTrackerContext)).PassAs<OutputSurface>();
[email protected]79a1be52013-02-13 23:59:502106 ReshapeTrackerContext* reshapeTracker = static_cast<ReshapeTrackerContext*>(outputSurface->context3d());
[email protected]c1bb5af2013-03-13 19:06:272107 m_hostImpl->InitializeRenderer(outputSurface.Pass());
[email protected]94f206c12012-08-25 00:09:142108
[email protected]c1bb5af2013-03-13 19:06:272109 scoped_ptr<LayerImpl> root = FakeDrawableLayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:342110 root->SetAnchorPoint(gfx::PointF(0, 0));
2111 root->SetBounds(gfx::Size(10, 10));
2112 root->SetDrawsContent(true);
[email protected]c1bb5af2013-03-13 19:06:272113 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142114 EXPECT_FALSE(reshapeTracker->reshapeCalled());
2115
[email protected]96baf3e2012-10-22 23:09:552116 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272117 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522118 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:142119 EXPECT_TRUE(reshapeTracker->reshapeCalled());
[email protected]c1bb5af2013-03-13 19:06:272120 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142121}
2122
[email protected]c8756fbe2013-02-12 01:53:492123class PartialSwapTrackerContext : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142124public:
2125 virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
2126 {
[email protected]aad0a0072012-11-01 18:15:582127 m_partialSwapRect = gfx::Rect(x, y, width, height);
[email protected]94f206c12012-08-25 00:09:142128 }
2129
[email protected]009dc072012-12-16 20:32:132130 virtual WebKit::WebString getString(WebKit::WGC3Denum name)
[email protected]94f206c12012-08-25 00:09:142131 {
[email protected]d9c28522012-10-18 23:35:432132 if (name == GL_EXTENSIONS)
[email protected]009dc072012-12-16 20:32:132133 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
[email protected]94f206c12012-08-25 00:09:142134
[email protected]009dc072012-12-16 20:32:132135 return WebKit::WebString();
[email protected]94f206c12012-08-25 00:09:142136 }
2137
[email protected]aad0a0072012-11-01 18:15:582138 gfx::Rect partialSwapRect() const { return m_partialSwapRect; }
[email protected]94f206c12012-08-25 00:09:142139
2140private:
[email protected]aad0a0072012-11-01 18:15:582141 gfx::Rect m_partialSwapRect;
[email protected]94f206c12012-08-25 00:09:142142};
2143
2144// Make sure damage tracking propagates all the way to the graphics context,
2145// where it should request to swap only the subBuffer that is damaged.
[email protected]c2d0c5a2013-02-26 04:43:362146TEST_F(LayerTreeHostImplTest, partialSwapReceivesDamageRect)
[email protected]94f206c12012-08-25 00:09:142147{
[email protected]a46f32932012-12-07 21:43:162148 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapTrackerContext)).PassAs<OutputSurface>();
[email protected]79a1be52013-02-13 23:59:502149 PartialSwapTrackerContext* partialSwapTracker = static_cast<PartialSwapTrackerContext*>(outputSurface->context3d());
[email protected]94f206c12012-08-25 00:09:142150
[email protected]96baf3e2012-10-22 23:09:552151 // This test creates its own LayerTreeHostImpl, so
[email protected]94f206c12012-08-25 00:09:142152 // that we can force partial swap enabled.
[email protected]96baf3e2012-10-22 23:09:552153 LayerTreeSettings settings;
[email protected]9bdcfd642012-11-14 21:24:262154 settings.partialSwapEnabled = true;
[email protected]c1bb5af2013-03-13 19:06:272155 scoped_ptr<LayerTreeHostImpl> layerTreeHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
2156 layerTreeHostImpl->InitializeRenderer(outputSurface.Pass());
2157 layerTreeHostImpl->SetViewportSize(gfx::Size(500, 500), gfx::Size(500, 500));
[email protected]94f206c12012-08-25 00:09:142158
[email protected]c1bb5af2013-03-13 19:06:272159 scoped_ptr<LayerImpl> root = FakeDrawableLayerImpl::Create(layerTreeHostImpl->active_tree(), 1);
2160 scoped_ptr<LayerImpl> child = FakeDrawableLayerImpl::Create(layerTreeHostImpl->active_tree(), 2);
[email protected]7aba6662013-03-12 10:17:342161 child->SetPosition(gfx::PointF(12, 13));
2162 child->SetAnchorPoint(gfx::PointF(0, 0));
2163 child->SetBounds(gfx::Size(14, 15));
2164 child->SetContentBounds(gfx::Size(14, 15));
2165 child->SetDrawsContent(true);
2166 root->SetAnchorPoint(gfx::PointF(0, 0));
2167 root->SetBounds(gfx::Size(500, 500));
2168 root->SetContentBounds(gfx::Size(500, 500));
2169 root->SetDrawsContent(true);
2170 root->AddChild(child.Pass());
[email protected]c1bb5af2013-03-13 19:06:272171 layerTreeHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142172
[email protected]96baf3e2012-10-22 23:09:552173 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:142174
2175 // First frame, the entire screen should get swapped.
[email protected]c1bb5af2013-03-13 19:06:272176 EXPECT_TRUE(layerTreeHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522177 layerTreeHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272178 layerTreeHostImpl->DidDrawAllLayers(frame);
2179 layerTreeHostImpl->SwapBuffers();
[email protected]aad0a0072012-11-01 18:15:582180 gfx::Rect actualSwapRect = partialSwapTracker->partialSwapRect();
2181 gfx::Rect expectedSwapRect = gfx::Rect(gfx::Point(), gfx::Size(500, 500));
[email protected]94f206c12012-08-25 00:09:142182 EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
2183 EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
2184 EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
2185 EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
2186
2187 // Second frame, only the damaged area should get swapped. Damage should be the union
2188 // of old and new child rects.
[email protected]aad0a0072012-11-01 18:15:582189 // expected damage rect: gfx::Rect(gfx::Point(), gfx::Size(26, 28));
[email protected]94f206c12012-08-25 00:09:142190 // expected swap rect: vertically flipped, with origin at bottom left corner.
[email protected]c1bb5af2013-03-13 19:06:272191 layerTreeHostImpl->active_tree()->root_layer()->children()[0]->SetPosition(gfx::PointF(0, 0));
2192 EXPECT_TRUE(layerTreeHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522193 layerTreeHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272194 m_hostImpl->DidDrawAllLayers(frame);
2195 layerTreeHostImpl->SwapBuffers();
[email protected]94f206c12012-08-25 00:09:142196 actualSwapRect = partialSwapTracker->partialSwapRect();
[email protected]aad0a0072012-11-01 18:15:582197 expectedSwapRect = gfx::Rect(gfx::Point(0, 500-28), gfx::Size(26, 28));
[email protected]94f206c12012-08-25 00:09:142198 EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
2199 EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
2200 EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
2201 EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
2202
2203 // Make sure that partial swap is constrained to the viewport dimensions
[email protected]aad0a0072012-11-01 18:15:582204 // expected damage rect: gfx::Rect(gfx::Point(), gfx::Size(500, 500));
[email protected]94f206c12012-08-25 00:09:142205 // expected swap rect: flipped damage rect, but also clamped to viewport
[email protected]c1bb5af2013-03-13 19:06:272206 layerTreeHostImpl->SetViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
2207 layerTreeHostImpl->active_tree()->root_layer()->SetOpacity(0.7f); // this will damage everything
2208 EXPECT_TRUE(layerTreeHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522209 layerTreeHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272210 m_hostImpl->DidDrawAllLayers(frame);
2211 layerTreeHostImpl->SwapBuffers();
[email protected]94f206c12012-08-25 00:09:142212 actualSwapRect = partialSwapTracker->partialSwapRect();
[email protected]aad0a0072012-11-01 18:15:582213 expectedSwapRect = gfx::Rect(gfx::Point(), gfx::Size(10, 10));
[email protected]94f206c12012-08-25 00:09:142214 EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
2215 EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
2216 EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
2217 EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
2218}
2219
[email protected]c2d0c5a2013-02-26 04:43:362220TEST_F(LayerTreeHostImplTest, rootLayerDoesntCreateExtraSurface)
[email protected]94f206c12012-08-25 00:09:142221{
[email protected]c1bb5af2013-03-13 19:06:272222 scoped_ptr<LayerImpl> root = FakeDrawableLayerImpl::Create(m_hostImpl->active_tree(), 1);
2223 scoped_ptr<LayerImpl> child = FakeDrawableLayerImpl::Create(m_hostImpl->active_tree(), 2);
[email protected]7aba6662013-03-12 10:17:342224 child->SetAnchorPoint(gfx::PointF(0, 0));
2225 child->SetBounds(gfx::Size(10, 10));
2226 child->SetContentBounds(gfx::Size(10, 10));
2227 child->SetDrawsContent(true);
2228 root->SetAnchorPoint(gfx::PointF(0, 0));
2229 root->SetBounds(gfx::Size(10, 10));
2230 root->SetContentBounds(gfx::Size(10, 10));
2231 root->SetDrawsContent(true);
2232 root->SetOpacity(0.7f);
2233 root->AddChild(child.Pass());
[email protected]94f206c12012-08-25 00:09:142234
[email protected]c1bb5af2013-03-13 19:06:272235 m_hostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142236
[email protected]96baf3e2012-10-22 23:09:552237 LayerTreeHostImpl::FrameData frame;
[email protected]94f206c12012-08-25 00:09:142238
[email protected]c1bb5af2013-03-13 19:06:272239 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
2240 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
2241 EXPECT_EQ(1u, frame.render_passes.size());
2242 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142243}
2244
[email protected]96baf3e2012-10-22 23:09:552245class FakeLayerWithQuads : public LayerImpl {
[email protected]94f206c12012-08-25 00:09:142246public:
[email protected]7aba6662013-03-12 10:17:342247 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* treeImpl, int id) { return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(treeImpl, id)); }
[email protected]94f206c12012-08-25 00:09:142248
[email protected]7aba6662013-03-12 10:17:342249 virtual void AppendQuads(QuadSink* quadSink, AppendQuadsData* appendQuadsData) OVERRIDE
[email protected]94f206c12012-08-25 00:09:142250 {
[email protected]c7e95b42013-03-18 01:13:492251 SharedQuadState* sharedQuadState = quadSink->UseSharedQuadState(CreateSharedQuadState());
[email protected]94f206c12012-08-25 00:09:142252
2253 SkColor gray = SkColorSetRGB(100, 100, 100);
[email protected]7aba6662013-03-12 10:17:342254 gfx::Rect quadRect(gfx::Point(0, 0), content_bounds());
[email protected]c22418b2012-11-20 23:06:262255 scoped_ptr<SolidColorDrawQuad> myQuad = SolidColorDrawQuad::Create();
2256 myQuad->SetNew(sharedQuadState, quadRect, gray);
[email protected]c7e95b42013-03-18 01:13:492257 quadSink->Append(myQuad.PassAs<DrawQuad>(), appendQuadsData);
[email protected]94f206c12012-08-25 00:09:142258 }
2259
2260private:
[email protected]8bef40572012-12-11 21:38:082261 FakeLayerWithQuads(LayerTreeImpl* treeImpl, int id)
2262 : LayerImpl(treeImpl, id)
[email protected]94f206c12012-08-25 00:09:142263 {
2264 }
2265};
2266
[email protected]c8756fbe2013-02-12 01:53:492267class MockContext : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142268public:
[email protected]009dc072012-12-16 20:32:132269 MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
2270 MOCK_METHOD5(uniform4f, void(WebKit::WGC3Dint location, WebKit::WGC3Dfloat x, WebKit::WGC3Dfloat y, WebKit::WGC3Dfloat z, WebKit::WGC3Dfloat w));
2271 MOCK_METHOD4(uniformMatrix4fv, void(WebKit::WGC3Dint location, WebKit::WGC3Dsizei count, WebKit::WGC3Dboolean transpose, const WebKit::WGC3Dfloat* value));
2272 MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode, WebKit::WGC3Dsizei count, WebKit::WGC3Denum type, WebKit::WGC3Dintptr offset));
2273 MOCK_METHOD1(getString, WebKit::WebString(WebKit::WGC3Denum name));
2274 MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebKit::WebString());
2275 MOCK_METHOD1(enable, void(WebKit::WGC3Denum cap));
2276 MOCK_METHOD1(disable, void(WebKit::WGC3Denum cap));
2277 MOCK_METHOD4(scissor, void(WebKit::WGC3Dint x, WebKit::WGC3Dint y, WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height));
[email protected]94f206c12012-08-25 00:09:142278};
2279
2280class MockContextHarness {
2281private:
2282 MockContext* m_context;
2283public:
2284 MockContextHarness(MockContext* context)
2285 : m_context(context)
2286 {
2287 // Catch "uninteresting" calls
2288 EXPECT_CALL(*m_context, useProgram(_))
2289 .Times(0);
2290
2291 EXPECT_CALL(*m_context, drawElements(_, _, _, _))
2292 .Times(0);
2293
2294 // These are not asserted
2295 EXPECT_CALL(*m_context, uniformMatrix4fv(_, _, _, _))
2296 .WillRepeatedly(Return());
2297
2298 EXPECT_CALL(*m_context, uniform4f(_, _, _, _, _))
2299 .WillRepeatedly(Return());
2300
2301 // Any other strings are empty
2302 EXPECT_CALL(*m_context, getString(_))
[email protected]009dc072012-12-16 20:32:132303 .WillRepeatedly(Return(WebKit::WebString()));
[email protected]94f206c12012-08-25 00:09:142304
2305 // Support for partial swap, if needed
[email protected]d9c28522012-10-18 23:35:432306 EXPECT_CALL(*m_context, getString(GL_EXTENSIONS))
[email protected]009dc072012-12-16 20:32:132307 .WillRepeatedly(Return(WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
[email protected]94f206c12012-08-25 00:09:142308
2309 EXPECT_CALL(*m_context, getRequestableExtensionsCHROMIUM())
[email protected]009dc072012-12-16 20:32:132310 .WillRepeatedly(Return(WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
[email protected]94f206c12012-08-25 00:09:142311
2312 // Any un-sanctioned calls to enable() are OK
2313 EXPECT_CALL(*m_context, enable(_))
2314 .WillRepeatedly(Return());
2315
2316 // Any un-sanctioned calls to disable() are OK
2317 EXPECT_CALL(*m_context, disable(_))
2318 .WillRepeatedly(Return());
2319 }
2320
2321 void mustDrawSolidQuad()
2322 {
[email protected]d9c28522012-10-18 23:35:432323 EXPECT_CALL(*m_context, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
[email protected]94f206c12012-08-25 00:09:142324 .WillOnce(Return())
2325 .RetiresOnSaturation();
2326
[email protected]d993b602013-01-04 02:08:122327 EXPECT_CALL(*m_context, useProgram(_))
[email protected]94f206c12012-08-25 00:09:142328 .WillOnce(Return())
2329 .RetiresOnSaturation();
2330
2331 }
2332
2333 void mustSetScissor(int x, int y, int width, int height)
2334 {
[email protected]d9c28522012-10-18 23:35:432335 EXPECT_CALL(*m_context, enable(GL_SCISSOR_TEST))
[email protected]94f206c12012-08-25 00:09:142336 .WillRepeatedly(Return());
2337
2338 EXPECT_CALL(*m_context, scissor(x, y, width, height))
2339 .Times(AtLeast(1))
2340 .WillRepeatedly(Return());
2341 }
2342
2343 void mustSetNoScissor()
2344 {
[email protected]d9c28522012-10-18 23:35:432345 EXPECT_CALL(*m_context, disable(GL_SCISSOR_TEST))
[email protected]94f206c12012-08-25 00:09:142346 .WillRepeatedly(Return());
2347
[email protected]d9c28522012-10-18 23:35:432348 EXPECT_CALL(*m_context, enable(GL_SCISSOR_TEST))
[email protected]94f206c12012-08-25 00:09:142349 .Times(0);
2350
2351 EXPECT_CALL(*m_context, scissor(_, _, _, _))
2352 .Times(0);
2353 }
2354};
2355
[email protected]c2d0c5a2013-02-26 04:43:362356TEST_F(LayerTreeHostImplTest, noPartialSwap)
[email protected]94f206c12012-08-25 00:09:142357{
[email protected]009dc072012-12-16 20:32:132358 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new MockContext)).PassAs<OutputSurface>();
[email protected]79a1be52013-02-13 23:59:502359 MockContext* mockContext = static_cast<MockContext*>(outputSurface->context3d());
[email protected]94f206c12012-08-25 00:09:142360 MockContextHarness harness(mockContext);
2361
[email protected]94f206c12012-08-25 00:09:142362 // Run test case
[email protected]586d51ed2012-12-07 20:31:452363 createLayerTreeHost(false, outputSurface.Pass());
[email protected]c1bb5af2013-03-13 19:06:272364 setupRootLayerImpl(FakeLayerWithQuads::Create(m_hostImpl->active_tree(), 1));
[email protected]94f206c12012-08-25 00:09:142365
[email protected]dc462d782012-11-21 21:43:012366 // without partial swap, and no clipping, no scissor is set.
2367 harness.mustDrawSolidQuad();
2368 harness.mustSetNoScissor();
2369 {
2370 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272371 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522372 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272373 m_hostImpl->DidDrawAllLayers(frame);
[email protected]dc462d782012-11-21 21:43:012374 }
2375 Mock::VerifyAndClearExpectations(&mockContext);
2376
2377 // without partial swap, but a layer does clip its subtree, one scissor is set.
[email protected]c1bb5af2013-03-13 19:06:272378 m_hostImpl->active_tree()->root_layer()->SetMasksToBounds(true);
[email protected]dc462d782012-11-21 21:43:012379 harness.mustDrawSolidQuad();
2380 harness.mustSetScissor(0, 0, 10, 10);
2381 {
2382 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272383 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522384 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272385 m_hostImpl->DidDrawAllLayers(frame);
[email protected]dc462d782012-11-21 21:43:012386 }
[email protected]94f206c12012-08-25 00:09:142387 Mock::VerifyAndClearExpectations(&mockContext);
2388}
2389
[email protected]c2d0c5a2013-02-26 04:43:362390TEST_F(LayerTreeHostImplTest, partialSwap)
[email protected]94f206c12012-08-25 00:09:142391{
[email protected]a46f32932012-12-07 21:43:162392 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new MockContext)).PassAs<OutputSurface>();
[email protected]79a1be52013-02-13 23:59:502393 MockContext* mockContext = static_cast<MockContext*>(outputSurface->context3d());
[email protected]94f206c12012-08-25 00:09:142394 MockContextHarness harness(mockContext);
2395
[email protected]586d51ed2012-12-07 20:31:452396 createLayerTreeHost(true, outputSurface.Pass());
[email protected]c1bb5af2013-03-13 19:06:272397 setupRootLayerImpl(FakeLayerWithQuads::Create(m_hostImpl->active_tree(), 1));
[email protected]94f206c12012-08-25 00:09:142398
2399 // The first frame is not a partially-swapped one.
2400 harness.mustSetScissor(0, 0, 10, 10);
2401 harness.mustDrawSolidQuad();
2402 {
[email protected]96baf3e2012-10-22 23:09:552403 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272404 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522405 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272406 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142407 }
2408 Mock::VerifyAndClearExpectations(&mockContext);
2409
2410 // Damage a portion of the frame.
[email protected]c1bb5af2013-03-13 19:06:272411 m_hostImpl->active_tree()->root_layer()->set_update_rect(gfx::Rect(0, 0, 2, 3));
[email protected]94f206c12012-08-25 00:09:142412
2413 // The second frame will be partially-swapped (the y coordinates are flipped).
2414 harness.mustSetScissor(0, 7, 2, 3);
2415 harness.mustDrawSolidQuad();
2416 {
[email protected]96baf3e2012-10-22 23:09:552417 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272418 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522419 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272420 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142421 }
2422 Mock::VerifyAndClearExpectations(&mockContext);
2423}
2424
[email protected]c8756fbe2013-02-12 01:53:492425class PartialSwapContext : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142426public:
[email protected]9f930272013-02-06 09:51:552427 virtual WebKit::WebString getString(WebKit::WGC3Denum name)
[email protected]94f206c12012-08-25 00:09:142428 {
[email protected]d9c28522012-10-18 23:35:432429 if (name == GL_EXTENSIONS)
[email protected]009dc072012-12-16 20:32:132430 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
2431 return WebKit::WebString();
[email protected]94f206c12012-08-25 00:09:142432 }
2433
[email protected]9f930272013-02-06 09:51:552434 virtual WebKit::WebString getRequestableExtensionsCHROMIUM()
[email protected]94f206c12012-08-25 00:09:142435 {
[email protected]009dc072012-12-16 20:32:132436 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
[email protected]94f206c12012-08-25 00:09:142437 }
2438
2439 // Unlimited texture size.
[email protected]009dc072012-12-16 20:32:132440 virtual void getIntegerv(WebKit::WGC3Denum pname, WebKit::WGC3Dint* value)
[email protected]94f206c12012-08-25 00:09:142441 {
[email protected]d9c28522012-10-18 23:35:432442 if (pname == GL_MAX_TEXTURE_SIZE)
[email protected]94f206c12012-08-25 00:09:142443 *value = 8192;
2444 }
2445};
2446
[email protected]61de5812012-11-08 07:03:442447static scoped_ptr<LayerTreeHostImpl> setupLayersForOpacity(bool partialSwap, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:142448{
[email protected]a46f32932012-12-07 21:43:162449 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:142450
[email protected]96baf3e2012-10-22 23:09:552451 LayerTreeSettings settings;
[email protected]9bdcfd642012-11-14 21:24:262452 settings.partialSwapEnabled = partialSwap;
[email protected]c1bb5af2013-03-13 19:06:272453 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, client, proxy);
2454 myHostImpl->InitializeRenderer(outputSurface.Pass());
2455 myHostImpl->SetViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:142456
2457 /*
2458 Layers are created as follows:
2459
2460 +--------------------+
2461 | 1 |
2462 | +-----------+ |
2463 | | 2 | |
2464 | | +-------------------+
2465 | | | 3 |
2466 | | +-------------------+
2467 | | | |
2468 | +-----------+ |
2469 | |
2470 | |
2471 +--------------------+
2472
2473 Layers 1, 2 have render surfaces
2474 */
[email protected]c1bb5af2013-03-13 19:06:272475 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
2476 scoped_ptr<LayerImpl> child = LayerImpl::Create(myHostImpl->active_tree(), 2);
2477 scoped_ptr<LayerImpl> grandChild = FakeLayerWithQuads::Create(myHostImpl->active_tree(), 3);
[email protected]94f206c12012-08-25 00:09:142478
[email protected]aad0a0072012-11-01 18:15:582479 gfx::Rect rootRect(0, 0, 100, 100);
2480 gfx::Rect childRect(10, 10, 50, 50);
2481 gfx::Rect grandChildRect(5, 5, 150, 150);
[email protected]94f206c12012-08-25 00:09:142482
[email protected]7aba6662013-03-12 10:17:342483 root->CreateRenderSurface();
2484 root->SetAnchorPoint(gfx::PointF(0, 0));
2485 root->SetPosition(gfx::PointF(rootRect.x(), rootRect.y()));
2486 root->SetBounds(gfx::Size(rootRect.width(), rootRect.height()));
2487 root->SetContentBounds(root->bounds());
2488 root->draw_properties().visible_content_rect = rootRect;
2489 root->SetDrawsContent(false);
2490 root->render_surface()->SetContentRect(gfx::Rect(gfx::Point(), gfx::Size(rootRect.width(), rootRect.height())));
[email protected]94f206c12012-08-25 00:09:142491
[email protected]7aba6662013-03-12 10:17:342492 child->SetAnchorPoint(gfx::PointF(0, 0));
2493 child->SetPosition(gfx::PointF(childRect.x(), childRect.y()));
2494 child->SetOpacity(0.5f);
2495 child->SetBounds(gfx::Size(childRect.width(), childRect.height()));
2496 child->SetContentBounds(child->bounds());
2497 child->draw_properties().visible_content_rect = childRect;
2498 child->SetDrawsContent(false);
2499 child->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:142500
[email protected]7aba6662013-03-12 10:17:342501 grandChild->SetAnchorPoint(gfx::PointF(0, 0));
2502 grandChild->SetPosition(gfx::Point(grandChildRect.x(), grandChildRect.y()));
2503 grandChild->SetBounds(gfx::Size(grandChildRect.width(), grandChildRect.height()));
2504 grandChild->SetContentBounds(grandChild->bounds());
2505 grandChild->draw_properties().visible_content_rect = grandChildRect;
2506 grandChild->SetDrawsContent(true);
[email protected]94f206c12012-08-25 00:09:142507
[email protected]7aba6662013-03-12 10:17:342508 child->AddChild(grandChild.Pass());
2509 root->AddChild(child.Pass());
[email protected]94f206c12012-08-25 00:09:142510
[email protected]c1bb5af2013-03-13 19:06:272511 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]519281762012-10-06 20:06:392512 return myHostImpl.Pass();
[email protected]94f206c12012-08-25 00:09:142513}
2514
[email protected]c2d0c5a2013-02-26 04:43:362515TEST_F(LayerTreeHostImplTest, contributingLayerEmptyScissorPartialSwap)
[email protected]94f206c12012-08-25 00:09:142516{
[email protected]61de5812012-11-08 07:03:442517 scoped_ptr<LayerTreeHostImpl> myHostImpl = setupLayersForOpacity(true, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:142518
2519 {
[email protected]96baf3e2012-10-22 23:09:552520 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272521 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142522
[email protected]94f206c12012-08-25 00:09:142523 // Verify all quads have been computed
[email protected]c1bb5af2013-03-13 19:06:272524 ASSERT_EQ(2U, frame.render_passes.size());
2525 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
2526 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
2527 EXPECT_EQ(DrawQuad::SOLID_COLOR, frame.render_passes[0]->quad_list[0]->material);
2528 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
[email protected]85167c72012-12-04 03:56:072529
[email protected]f0c2a242013-03-15 19:34:522530 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272531 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142532 }
2533}
2534
[email protected]c2d0c5a2013-02-26 04:43:362535TEST_F(LayerTreeHostImplTest, contributingLayerEmptyScissorNoPartialSwap)
[email protected]94f206c12012-08-25 00:09:142536{
[email protected]61de5812012-11-08 07:03:442537 scoped_ptr<LayerTreeHostImpl> myHostImpl = setupLayersForOpacity(false, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:142538
2539 {
[email protected]96baf3e2012-10-22 23:09:552540 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272541 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142542
[email protected]94f206c12012-08-25 00:09:142543 // Verify all quads have been computed
[email protected]c1bb5af2013-03-13 19:06:272544 ASSERT_EQ(2U, frame.render_passes.size());
2545 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
2546 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
2547 EXPECT_EQ(DrawQuad::SOLID_COLOR, frame.render_passes[0]->quad_list[0]->material);
2548 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
[email protected]85167c72012-12-04 03:56:072549
[email protected]f0c2a242013-03-15 19:34:522550 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272551 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142552 }
2553}
2554
[email protected]009dc072012-12-16 20:32:132555// Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
[email protected]c8756fbe2013-02-12 01:53:492556class TrackingWebGraphicsContext3D : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142557public:
2558 TrackingWebGraphicsContext3D()
[email protected]c8756fbe2013-02-12 01:53:492559 : TestWebGraphicsContext3D()
[email protected]94f206c12012-08-25 00:09:142560 , m_numTextures(0)
2561 { }
2562
[email protected]009dc072012-12-16 20:32:132563 virtual WebKit::WebGLId createTexture() OVERRIDE
[email protected]94f206c12012-08-25 00:09:142564 {
[email protected]c8756fbe2013-02-12 01:53:492565 WebKit::WebGLId id = TestWebGraphicsContext3D::createTexture();
[email protected]94f206c12012-08-25 00:09:142566
[email protected]357b5172012-10-18 17:39:332567 m_textures[id] = true;
[email protected]94f206c12012-08-25 00:09:142568 ++m_numTextures;
2569 return id;
2570 }
2571
[email protected]009dc072012-12-16 20:32:132572 virtual void deleteTexture(WebKit::WebGLId id) OVERRIDE
[email protected]94f206c12012-08-25 00:09:142573 {
[email protected]357b5172012-10-18 17:39:332574 if (m_textures.find(id) == m_textures.end())
[email protected]94f206c12012-08-25 00:09:142575 return;
2576
[email protected]357b5172012-10-18 17:39:332577 m_textures[id] = false;
[email protected]94f206c12012-08-25 00:09:142578 --m_numTextures;
2579 }
2580
[email protected]009dc072012-12-16 20:32:132581 virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE
[email protected]94f206c12012-08-25 00:09:142582 {
[email protected]d9c28522012-10-18 23:35:432583 if (name == GL_EXTENSIONS)
[email protected]009dc072012-12-16 20:32:132584 return WebKit::WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
[email protected]94f206c12012-08-25 00:09:142585
[email protected]009dc072012-12-16 20:32:132586 return WebKit::WebString();
[email protected]94f206c12012-08-25 00:09:142587 }
2588
2589 unsigned numTextures() const { return m_numTextures; }
2590
2591private:
[email protected]009dc072012-12-16 20:32:132592 base::hash_map<WebKit::WebGLId, bool> m_textures;
[email protected]94f206c12012-08-25 00:09:142593 unsigned m_numTextures;
2594};
2595
[email protected]d993b602013-01-04 02:08:122596static unsigned createResourceId(ResourceProvider* resourceProvider)
2597{
[email protected]f53da3972013-03-07 08:38:412598 return resourceProvider->CreateResource(
[email protected]d993b602013-01-04 02:08:122599 gfx::Size(20, 12),
[email protected]f53da3972013-03-07 08:38:412600 resourceProvider->best_texture_format(),
[email protected]d993b602013-01-04 02:08:122601 ResourceProvider::TextureUsageAny);
2602}
2603
2604static unsigned createTextureId(ResourceProvider* resourceProvider)
2605{
2606 return ResourceProvider::ScopedReadLockGL(
[email protected]f53da3972013-03-07 08:38:412607 resourceProvider, createResourceId(resourceProvider)).texture_id();
[email protected]d993b602013-01-04 02:08:122608}
2609
[email protected]c2d0c5a2013-02-26 04:43:362610TEST_F(LayerTreeHostImplTest, layersFreeTextures)
[email protected]94f206c12012-08-25 00:09:142611{
[email protected]c8756fbe2013-02-12 01:53:492612 scoped_ptr<TestWebGraphicsContext3D> context =
2613 TestWebGraphicsContext3D::Create();
2614 TestWebGraphicsContext3D* context3d = context.get();
[email protected]d993b602013-01-04 02:08:122615 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(
2616 context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
[email protected]c1bb5af2013-03-13 19:06:272617 m_hostImpl->InitializeRenderer(outputSurface.Pass());
[email protected]d993b602013-01-04 02:08:122618
[email protected]c1bb5af2013-03-13 19:06:272619 scoped_ptr<LayerImpl> rootLayer(LayerImpl::Create(m_hostImpl->active_tree(), 1));
[email protected]7aba6662013-03-12 10:17:342620 rootLayer->SetBounds(gfx::Size(10, 10));
2621 rootLayer->SetAnchorPoint(gfx::PointF());
[email protected]94f206c12012-08-25 00:09:142622
[email protected]568285b2013-01-07 23:19:192623 scoped_refptr<VideoFrame> softwareFrame(media::VideoFrame::CreateColorFrame(
[email protected]d993b602013-01-04 02:08:122624 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()));
[email protected]94f206c12012-08-25 00:09:142625 FakeVideoFrameProvider provider;
[email protected]568285b2013-01-07 23:19:192626 provider.set_frame(softwareFrame);
[email protected]c1bb5af2013-03-13 19:06:272627 scoped_ptr<VideoLayerImpl> videoLayer = VideoLayerImpl::Create(m_hostImpl->active_tree(), 4, &provider);
[email protected]7aba6662013-03-12 10:17:342628 videoLayer->SetBounds(gfx::Size(10, 10));
2629 videoLayer->SetAnchorPoint(gfx::PointF(0, 0));
2630 videoLayer->SetContentBounds(gfx::Size(10, 10));
2631 videoLayer->SetDrawsContent(true);
2632 rootLayer->AddChild(videoLayer.PassAs<LayerImpl>());
[email protected]94f206c12012-08-25 00:09:142633
[email protected]c1bb5af2013-03-13 19:06:272634 scoped_ptr<IOSurfaceLayerImpl> ioSurfaceLayer = IOSurfaceLayerImpl::Create(m_hostImpl->active_tree(), 5);
[email protected]7aba6662013-03-12 10:17:342635 ioSurfaceLayer->SetBounds(gfx::Size(10, 10));
2636 ioSurfaceLayer->SetAnchorPoint(gfx::PointF(0, 0));
2637 ioSurfaceLayer->SetContentBounds(gfx::Size(10, 10));
2638 ioSurfaceLayer->SetDrawsContent(true);
[email protected]844a9632013-03-17 21:01:252639 ioSurfaceLayer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
[email protected]7aba6662013-03-12 10:17:342640 rootLayer->AddChild(ioSurfaceLayer.PassAs<LayerImpl>());
[email protected]94f206c12012-08-25 00:09:142641
[email protected]c1bb5af2013-03-13 19:06:272642 m_hostImpl->active_tree()->SetRootLayer(rootLayer.Pass());
[email protected]94f206c12012-08-25 00:09:142643
[email protected]d993b602013-01-04 02:08:122644 EXPECT_EQ(0u, context3d->NumTextures());
2645
[email protected]96baf3e2012-10-22 23:09:552646 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272647 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522648 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272649 m_hostImpl->DidDrawAllLayers(frame);
2650 m_hostImpl->SwapBuffers();
[email protected]94f206c12012-08-25 00:09:142651
[email protected]d993b602013-01-04 02:08:122652 EXPECT_GT(context3d->NumTextures(), 0u);
[email protected]94f206c12012-08-25 00:09:142653
2654 // Kill the layer tree.
[email protected]c1bb5af2013-03-13 19:06:272655 m_hostImpl->active_tree()->SetRootLayer(LayerImpl::Create(m_hostImpl->active_tree(), 100));
[email protected]94f206c12012-08-25 00:09:142656 // There should be no textures left in use after.
[email protected]d993b602013-01-04 02:08:122657 EXPECT_EQ(0u, context3d->NumTextures());
[email protected]94f206c12012-08-25 00:09:142658}
2659
[email protected]c8756fbe2013-02-12 01:53:492660class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
[email protected]94f206c12012-08-25 00:09:142661public:
[email protected]009dc072012-12-16 20:32:132662 MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
2663 MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode, WebKit::WGC3Dsizei count, WebKit::WGC3Denum type, WebKit::WGC3Dintptr offset));
[email protected]94f206c12012-08-25 00:09:142664};
2665
[email protected]c2d0c5a2013-02-26 04:43:362666TEST_F(LayerTreeHostImplTest, hasTransparentBackground)
[email protected]94f206c12012-08-25 00:09:142667{
[email protected]a46f32932012-12-07 21:43:162668 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new MockDrawQuadsToFillScreenContext)).PassAs<OutputSurface>();
[email protected]79a1be52013-02-13 23:59:502669 MockDrawQuadsToFillScreenContext* mockContext = static_cast<MockDrawQuadsToFillScreenContext*>(outputSurface->context3d());
[email protected]94f206c12012-08-25 00:09:142670
2671 // Run test case
[email protected]586d51ed2012-12-07 20:31:452672 createLayerTreeHost(false, outputSurface.Pass());
[email protected]c1bb5af2013-03-13 19:06:272673 setupRootLayerImpl(LayerImpl::Create(m_hostImpl->active_tree(), 1));
2674 m_hostImpl->active_tree()->set_background_color(SK_ColorWHITE);
[email protected]94f206c12012-08-25 00:09:142675
2676 // Verify one quad is drawn when transparent background set is not set.
[email protected]c1bb5af2013-03-13 19:06:272677 m_hostImpl->active_tree()->set_has_transparent_background(false);
[email protected]94f206c12012-08-25 00:09:142678 EXPECT_CALL(*mockContext, useProgram(_))
2679 .Times(1);
2680 EXPECT_CALL(*mockContext, drawElements(_, _, _, _))
2681 .Times(1);
[email protected]96baf3e2012-10-22 23:09:552682 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272683 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522684 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272685 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142686 Mock::VerifyAndClearExpectations(&mockContext);
2687
2688 // Verify no quads are drawn when transparent background is set.
[email protected]c1bb5af2013-03-13 19:06:272689 m_hostImpl->active_tree()->set_has_transparent_background(true);
2690 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:522691 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272692 m_hostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142693 Mock::VerifyAndClearExpectations(&mockContext);
2694}
2695
[email protected]aad0a0072012-11-01 18:15:582696static void addDrawingLayerTo(LayerImpl* parent, int id, const gfx::Rect& layerRect, LayerImpl** result)
[email protected]94f206c12012-08-25 00:09:142697{
[email protected]7aba6662013-03-12 10:17:342698 scoped_ptr<LayerImpl> layer = FakeLayerWithQuads::Create(parent->layer_tree_impl(), id);
[email protected]96baf3e2012-10-22 23:09:552699 LayerImpl* layerPtr = layer.get();
[email protected]7aba6662013-03-12 10:17:342700 layerPtr->SetAnchorPoint(gfx::PointF(0, 0));
2701 layerPtr->SetPosition(gfx::PointF(layerRect.origin()));
2702 layerPtr->SetBounds(layerRect.size());
2703 layerPtr->SetContentBounds(layerRect.size());
2704 layerPtr->SetDrawsContent(true); // only children draw content
2705 layerPtr->SetContentsOpaque(true);
2706 parent->AddChild(layer.Pass());
[email protected]94f206c12012-08-25 00:09:142707 if (result)
2708 *result = layerPtr;
2709}
2710
[email protected]aad0a0072012-11-01 18:15:582711static void setupLayersForTextureCaching(LayerTreeHostImpl* layerTreeHostImpl, LayerImpl*& rootPtr, LayerImpl*& intermediateLayerPtr, LayerImpl*& surfaceLayerPtr, LayerImpl*& childPtr, const gfx::Size& rootSize)
[email protected]94f206c12012-08-25 00:09:142712{
[email protected]a46f32932012-12-07 21:43:162713 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:142714
[email protected]c1bb5af2013-03-13 19:06:272715 layerTreeHostImpl->InitializeRenderer(outputSurface.Pass());
2716 layerTreeHostImpl->SetViewportSize(rootSize, rootSize);
[email protected]94f206c12012-08-25 00:09:142717
[email protected]c1bb5af2013-03-13 19:06:272718 scoped_ptr<LayerImpl> root = LayerImpl::Create(layerTreeHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:142719 rootPtr = root.get();
2720
[email protected]7aba6662013-03-12 10:17:342721 root->SetAnchorPoint(gfx::PointF(0, 0));
2722 root->SetPosition(gfx::PointF(0, 0));
2723 root->SetBounds(rootSize);
2724 root->SetContentBounds(rootSize);
2725 root->SetDrawsContent(true);
[email protected]c1bb5af2013-03-13 19:06:272726 layerTreeHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142727
[email protected]aad0a0072012-11-01 18:15:582728 addDrawingLayerTo(rootPtr, 2, gfx::Rect(10, 10, rootSize.width(), rootSize.height()), &intermediateLayerPtr);
[email protected]7aba6662013-03-12 10:17:342729 intermediateLayerPtr->SetDrawsContent(false); // only children draw content
[email protected]94f206c12012-08-25 00:09:142730
2731 // Surface layer is the layer that changes its opacity
2732 // It will contain other layers that draw content.
[email protected]aad0a0072012-11-01 18:15:582733 addDrawingLayerTo(intermediateLayerPtr, 3, gfx::Rect(10, 10, rootSize.width(), rootSize.height()), &surfaceLayerPtr);
[email protected]7aba6662013-03-12 10:17:342734 surfaceLayerPtr->SetDrawsContent(false); // only children draw content
2735 surfaceLayerPtr->SetOpacity(0.5f);
2736 surfaceLayerPtr->SetForceRenderSurface(true); // This will cause it to have a surface
[email protected]94f206c12012-08-25 00:09:142737
2738 // Child of the surface layer will produce some quads
[email protected]aad0a0072012-11-01 18:15:582739 addDrawingLayerTo(surfaceLayerPtr, 4, gfx::Rect(5, 5, rootSize.width() - 25, rootSize.height() - 25), &childPtr);
[email protected]94f206c12012-08-25 00:09:142740}
2741
[email protected]96baf3e2012-10-22 23:09:552742class GLRendererWithReleaseTextures : public GLRenderer {
[email protected]94f206c12012-08-25 00:09:142743public:
[email protected]faa48f32013-03-13 11:10:472744 using GLRenderer::ReleaseRenderPassTextures;
[email protected]94f206c12012-08-25 00:09:142745};
2746
[email protected]c2d0c5a2013-02-26 04:43:362747TEST_F(LayerTreeHostImplTest, textureCachingWithOcclusion)
[email protected]94f206c12012-08-25 00:09:142748{
[email protected]96baf3e2012-10-22 23:09:552749 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:582750 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]09dc0d4b2013-02-13 06:17:202751 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:272752 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:142753
2754 // Layers are structure as follows:
2755 //
2756 // R +-- S1 +- L10 (owning)
2757 // | +- L11
2758 // | +- L12
2759 // |
2760 // +-- S2 +- L20 (owning)
2761 // +- L21
2762 //
2763 // Occlusion:
2764 // L12 occludes L11 (internal)
2765 // L20 occludes L10 (external)
2766 // L21 occludes L20 (internal)
2767
[email protected]96baf3e2012-10-22 23:09:552768 LayerImpl* rootPtr;
2769 LayerImpl* layerS1Ptr;
2770 LayerImpl* layerS2Ptr;
[email protected]94f206c12012-08-25 00:09:142771
[email protected]a46f32932012-12-07 21:43:162772 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:142773
[email protected]aad0a0072012-11-01 18:15:582774 gfx::Size rootSize(1000, 1000);
[email protected]94f206c12012-08-25 00:09:142775
[email protected]c1bb5af2013-03-13 19:06:272776 myHostImpl->InitializeRenderer(outputSurface.Pass());
2777 myHostImpl->SetViewportSize(gfx::Size(rootSize.width(), rootSize.height()), gfx::Size(rootSize.width(), rootSize.height()));
[email protected]94f206c12012-08-25 00:09:142778
[email protected]c1bb5af2013-03-13 19:06:272779 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:142780 rootPtr = root.get();
2781
[email protected]7aba6662013-03-12 10:17:342782 root->SetAnchorPoint(gfx::PointF(0, 0));
2783 root->SetPosition(gfx::PointF(0, 0));
2784 root->SetBounds(rootSize);
2785 root->SetContentBounds(rootSize);
2786 root->SetDrawsContent(true);
2787 root->SetMasksToBounds(true);
[email protected]c1bb5af2013-03-13 19:06:272788 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142789
[email protected]aad0a0072012-11-01 18:15:582790 addDrawingLayerTo(rootPtr, 2, gfx::Rect(300, 300, 300, 300), &layerS1Ptr);
[email protected]7aba6662013-03-12 10:17:342791 layerS1Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:142792
[email protected]aad0a0072012-11-01 18:15:582793 addDrawingLayerTo(layerS1Ptr, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
2794 addDrawingLayerTo(layerS1Ptr, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
[email protected]94f206c12012-08-25 00:09:142795
[email protected]aad0a0072012-11-01 18:15:582796 addDrawingLayerTo(rootPtr, 5, gfx::Rect(550, 250, 300, 400), &layerS2Ptr);
[email protected]7aba6662013-03-12 10:17:342797 layerS2Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:142798
[email protected]aad0a0072012-11-01 18:15:582799 addDrawingLayerTo(layerS2Ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
[email protected]94f206c12012-08-25 00:09:142800
2801 // Initial draw - must receive all quads
2802 {
[email protected]96baf3e2012-10-22 23:09:552803 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272804 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142805
2806 // Must receive 3 render passes.
2807 // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded); for S2, there is 2 quads.
[email protected]c1bb5af2013-03-13 19:06:272808 ASSERT_EQ(3U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142809
[email protected]c1bb5af2013-03-13 19:06:272810 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
2811 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
2812 EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142813
[email protected]f0c2a242013-03-15 19:34:522814 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272815 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142816 }
2817
2818 // "Unocclude" surface S1 and repeat draw.
2819 // Must remove S2's render pass since it's cached;
2820 // Must keep S1 quads because texture contained external occlusion.
[email protected]c8686a02012-11-27 08:29:002821 gfx::Transform transform = layerS2Ptr->transform();
2822 transform.Translate(150, 150);
[email protected]7aba6662013-03-12 10:17:342823 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:142824 {
[email protected]96baf3e2012-10-22 23:09:552825 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272826 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142827
2828 // Must receive 2 render passes.
2829 // For Root, there are 2 quads
2830 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
2831 // For S2, there is no render pass
[email protected]c1bb5af2013-03-13 19:06:272832 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142833
[email protected]c1bb5af2013-03-13 19:06:272834 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
2835 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142836
[email protected]f0c2a242013-03-15 19:34:522837 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272838 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142839 }
2840
2841 // "Re-occlude" surface S1 and repeat draw.
2842 // Must remove S1's render pass since it is now available in full.
2843 // S2 has no change so must also be removed.
2844 transform = layerS2Ptr->transform();
[email protected]c8686a02012-11-27 08:29:002845 transform.Translate(-15, -15);
[email protected]7aba6662013-03-12 10:17:342846 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:142847 {
[email protected]96baf3e2012-10-22 23:09:552848 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272849 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142850
2851 // Must receive 1 render pass - for the root.
[email protected]c1bb5af2013-03-13 19:06:272852 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142853
[email protected]c1bb5af2013-03-13 19:06:272854 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142855
[email protected]f0c2a242013-03-15 19:34:522856 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272857 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142858 }
2859
2860}
2861
[email protected]c2d0c5a2013-02-26 04:43:362862TEST_F(LayerTreeHostImplTest, textureCachingWithOcclusionEarlyOut)
[email protected]94f206c12012-08-25 00:09:142863{
[email protected]96baf3e2012-10-22 23:09:552864 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:582865 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]09dc0d4b2013-02-13 06:17:202866 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:272867 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:142868
2869 // Layers are structure as follows:
2870 //
2871 // R +-- S1 +- L10 (owning, non drawing)
2872 // | +- L11 (corner, unoccluded)
2873 // | +- L12 (corner, unoccluded)
2874 // | +- L13 (corner, unoccluded)
2875 // | +- L14 (corner, entirely occluded)
2876 // |
2877 // +-- S2 +- L20 (owning, drawing)
2878 //
2879
[email protected]96baf3e2012-10-22 23:09:552880 LayerImpl* rootPtr;
2881 LayerImpl* layerS1Ptr;
2882 LayerImpl* layerS2Ptr;
[email protected]94f206c12012-08-25 00:09:142883
[email protected]a46f32932012-12-07 21:43:162884 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:142885
[email protected]aad0a0072012-11-01 18:15:582886 gfx::Size rootSize(1000, 1000);
[email protected]94f206c12012-08-25 00:09:142887
[email protected]c1bb5af2013-03-13 19:06:272888 myHostImpl->InitializeRenderer(outputSurface.Pass());
2889 myHostImpl->SetViewportSize(gfx::Size(rootSize.width(), rootSize.height()), gfx::Size(rootSize.width(), rootSize.height()));
[email protected]94f206c12012-08-25 00:09:142890
[email protected]c1bb5af2013-03-13 19:06:272891 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:142892 rootPtr = root.get();
2893
[email protected]7aba6662013-03-12 10:17:342894 root->SetAnchorPoint(gfx::PointF(0, 0));
2895 root->SetPosition(gfx::PointF(0, 0));
2896 root->SetBounds(rootSize);
2897 root->SetContentBounds(rootSize);
2898 root->SetDrawsContent(true);
2899 root->SetMasksToBounds(true);
[email protected]c1bb5af2013-03-13 19:06:272900 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:142901
[email protected]aad0a0072012-11-01 18:15:582902 addDrawingLayerTo(rootPtr, 2, gfx::Rect(0, 0, 800, 800), &layerS1Ptr);
[email protected]7aba6662013-03-12 10:17:342903 layerS1Ptr->SetForceRenderSurface(true);
2904 layerS1Ptr->SetDrawsContent(false);
[email protected]94f206c12012-08-25 00:09:142905
[email protected]aad0a0072012-11-01 18:15:582906 addDrawingLayerTo(layerS1Ptr, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
2907 addDrawingLayerTo(layerS1Ptr, 4, gfx::Rect(0, 500, 300, 300), 0); // L12
2908 addDrawingLayerTo(layerS1Ptr, 5, gfx::Rect(500, 0, 300, 300), 0); // L13
2909 addDrawingLayerTo(layerS1Ptr, 6, gfx::Rect(500, 500, 300, 300), 0); // L14
2910 addDrawingLayerTo(layerS1Ptr, 9, gfx::Rect(500, 500, 300, 300), 0); // L14
[email protected]94f206c12012-08-25 00:09:142911
[email protected]aad0a0072012-11-01 18:15:582912 addDrawingLayerTo(rootPtr, 7, gfx::Rect(450, 450, 450, 450), &layerS2Ptr);
[email protected]7aba6662013-03-12 10:17:342913 layerS2Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:142914
2915 // Initial draw - must receive all quads
2916 {
[email protected]96baf3e2012-10-22 23:09:552917 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272918 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142919
2920 // Must receive 3 render passes.
2921 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
[email protected]c1bb5af2013-03-13 19:06:272922 ASSERT_EQ(3U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142923
[email protected]c1bb5af2013-03-13 19:06:272924 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142925
2926 // L14 is culled, so only 3 quads.
[email protected]c1bb5af2013-03-13 19:06:272927 EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
2928 EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142929
[email protected]f0c2a242013-03-15 19:34:522930 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272931 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142932 }
2933
2934 // "Unocclude" surface S1 and repeat draw.
2935 // Must remove S2's render pass since it's cached;
2936 // Must keep S1 quads because texture contained external occlusion.
[email protected]c8686a02012-11-27 08:29:002937 gfx::Transform transform = layerS2Ptr->transform();
2938 transform.Translate(100, 100);
[email protected]7aba6662013-03-12 10:17:342939 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:142940 {
[email protected]96baf3e2012-10-22 23:09:552941 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272942 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142943
2944 // Must receive 2 render passes.
2945 // For Root, there are 2 quads
2946 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
2947 // For S2, there is no render pass
[email protected]c1bb5af2013-03-13 19:06:272948 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142949
[email protected]c1bb5af2013-03-13 19:06:272950 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
2951 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142952
[email protected]f0c2a242013-03-15 19:34:522953 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272954 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142955 }
2956
2957 // "Re-occlude" surface S1 and repeat draw.
2958 // Must remove S1's render pass since it is now available in full.
2959 // S2 has no change so must also be removed.
2960 transform = layerS2Ptr->transform();
[email protected]c8686a02012-11-27 08:29:002961 transform.Translate(-15, -15);
[email protected]7aba6662013-03-12 10:17:342962 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:142963 {
[email protected]96baf3e2012-10-22 23:09:552964 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:272965 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:142966
2967 // Must receive 1 render pass - for the root.
[email protected]c1bb5af2013-03-13 19:06:272968 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:142969
[email protected]c1bb5af2013-03-13 19:06:272970 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:142971
[email protected]f0c2a242013-03-15 19:34:522972 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:272973 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:142974 }
2975}
2976
[email protected]c2d0c5a2013-02-26 04:43:362977TEST_F(LayerTreeHostImplTest, textureCachingWithOcclusionExternalOverInternal)
[email protected]94f206c12012-08-25 00:09:142978{
[email protected]96baf3e2012-10-22 23:09:552979 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:582980 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]09dc0d4b2013-02-13 06:17:202981 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:272982 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:142983
2984 // Layers are structured as follows:
2985 //
2986 // R +-- S1 +- L10 (owning, drawing)
2987 // | +- L11 (corner, occluded by L12)
2988 // | +- L12 (opposite corner)
2989 // |
2990 // +-- S2 +- L20 (owning, drawing)
2991 //
2992
[email protected]96baf3e2012-10-22 23:09:552993 LayerImpl* rootPtr;
2994 LayerImpl* layerS1Ptr;
2995 LayerImpl* layerS2Ptr;
[email protected]94f206c12012-08-25 00:09:142996
[email protected]a46f32932012-12-07 21:43:162997 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:142998
[email protected]aad0a0072012-11-01 18:15:582999 gfx::Size rootSize(1000, 1000);
[email protected]94f206c12012-08-25 00:09:143000
[email protected]c1bb5af2013-03-13 19:06:273001 myHostImpl->InitializeRenderer(outputSurface.Pass());
3002 myHostImpl->SetViewportSize(gfx::Size(rootSize.width(), rootSize.height()), gfx::Size(rootSize.width(), rootSize.height()));
[email protected]94f206c12012-08-25 00:09:143003
[email protected]c1bb5af2013-03-13 19:06:273004 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:143005 rootPtr = root.get();
3006
[email protected]7aba6662013-03-12 10:17:343007 root->SetAnchorPoint(gfx::PointF(0, 0));
3008 root->SetPosition(gfx::PointF(0, 0));
3009 root->SetBounds(rootSize);
3010 root->SetContentBounds(rootSize);
3011 root->SetDrawsContent(true);
3012 root->SetMasksToBounds(true);
[email protected]c1bb5af2013-03-13 19:06:273013 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:143014
[email protected]aad0a0072012-11-01 18:15:583015 addDrawingLayerTo(rootPtr, 2, gfx::Rect(0, 0, 400, 400), &layerS1Ptr);
[email protected]7aba6662013-03-12 10:17:343016 layerS1Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:143017
[email protected]aad0a0072012-11-01 18:15:583018 addDrawingLayerTo(layerS1Ptr, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
3019 addDrawingLayerTo(layerS1Ptr, 4, gfx::Rect(100, 0, 300, 300), 0); // L12
[email protected]94f206c12012-08-25 00:09:143020
[email protected]aad0a0072012-11-01 18:15:583021 addDrawingLayerTo(rootPtr, 7, gfx::Rect(200, 0, 300, 300), &layerS2Ptr);
[email protected]7aba6662013-03-12 10:17:343022 layerS2Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:143023
3024 // Initial draw - must receive all quads
3025 {
[email protected]96baf3e2012-10-22 23:09:553026 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273027 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143028
3029 // Must receive 3 render passes.
3030 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
[email protected]c1bb5af2013-03-13 19:06:273031 ASSERT_EQ(3U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143032
[email protected]c1bb5af2013-03-13 19:06:273033 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3034 EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
3035 EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143036
[email protected]f0c2a242013-03-15 19:34:523037 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273038 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143039 }
3040
3041 // "Unocclude" surface S1 and repeat draw.
3042 // Must remove S2's render pass since it's cached;
3043 // Must keep S1 quads because texture contained external occlusion.
[email protected]c8686a02012-11-27 08:29:003044 gfx::Transform transform = layerS2Ptr->transform();
3045 transform.Translate(300, 0);
[email protected]7aba6662013-03-12 10:17:343046 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143047 {
[email protected]96baf3e2012-10-22 23:09:553048 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273049 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143050
3051 // Must receive 2 render passes.
3052 // For Root, there are 2 quads
3053 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
3054 // For S2, there is no render pass
[email protected]c1bb5af2013-03-13 19:06:273055 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143056
[email protected]c1bb5af2013-03-13 19:06:273057 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
3058 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143059
[email protected]f0c2a242013-03-15 19:34:523060 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273061 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143062 }
3063}
3064
[email protected]c2d0c5a2013-02-26 04:43:363065TEST_F(LayerTreeHostImplTest, textureCachingWithOcclusionExternalNotAligned)
[email protected]94f206c12012-08-25 00:09:143066{
[email protected]96baf3e2012-10-22 23:09:553067 LayerTreeSettings settings;
[email protected]09dc0d4b2013-02-13 06:17:203068 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:273069 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:143070
3071 // Layers are structured as follows:
3072 //
3073 // R +-- S1 +- L10 (rotated, drawing)
3074 // +- L11 (occupies half surface)
3075
[email protected]96baf3e2012-10-22 23:09:553076 LayerImpl* rootPtr;
3077 LayerImpl* layerS1Ptr;
[email protected]94f206c12012-08-25 00:09:143078
[email protected]a46f32932012-12-07 21:43:163079 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:143080
[email protected]aad0a0072012-11-01 18:15:583081 gfx::Size rootSize(1000, 1000);
[email protected]94f206c12012-08-25 00:09:143082
[email protected]c1bb5af2013-03-13 19:06:273083 myHostImpl->InitializeRenderer(outputSurface.Pass());
3084 myHostImpl->SetViewportSize(gfx::Size(rootSize.width(), rootSize.height()), gfx::Size(rootSize.width(), rootSize.height()));
[email protected]94f206c12012-08-25 00:09:143085
[email protected]c1bb5af2013-03-13 19:06:273086 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:143087 rootPtr = root.get();
3088
[email protected]7aba6662013-03-12 10:17:343089 root->SetAnchorPoint(gfx::PointF(0, 0));
3090 root->SetPosition(gfx::PointF(0, 0));
3091 root->SetBounds(rootSize);
3092 root->SetContentBounds(rootSize);
3093 root->SetDrawsContent(true);
3094 root->SetMasksToBounds(true);
[email protected]c1bb5af2013-03-13 19:06:273095 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:143096
[email protected]aad0a0072012-11-01 18:15:583097 addDrawingLayerTo(rootPtr, 2, gfx::Rect(0, 0, 400, 400), &layerS1Ptr);
[email protected]7aba6662013-03-12 10:17:343098 layerS1Ptr->SetForceRenderSurface(true);
[email protected]c8686a02012-11-27 08:29:003099 gfx::Transform transform = layerS1Ptr->transform();
3100 transform.Translate(200, 200);
3101 transform.Rotate(45);
3102 transform.Translate(-200, -200);
[email protected]7aba6662013-03-12 10:17:343103 layerS1Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143104
[email protected]aad0a0072012-11-01 18:15:583105 addDrawingLayerTo(layerS1Ptr, 3, gfx::Rect(200, 0, 200, 400), 0); // L11
[email protected]94f206c12012-08-25 00:09:143106
3107 // Initial draw - must receive all quads
3108 {
[email protected]96baf3e2012-10-22 23:09:553109 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273110 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143111
3112 // Must receive 2 render passes.
[email protected]c1bb5af2013-03-13 19:06:273113 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143114
[email protected]c1bb5af2013-03-13 19:06:273115 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3116 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143117
[email protected]f0c2a242013-03-15 19:34:523118 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273119 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143120 }
3121
3122 // Change opacity and draw. Verify we used cached texture.
[email protected]7aba6662013-03-12 10:17:343123 layerS1Ptr->SetOpacity(0.2f);
[email protected]94f206c12012-08-25 00:09:143124 {
[email protected]96baf3e2012-10-22 23:09:553125 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273126 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143127
3128 // One render pass must be gone due to cached texture.
[email protected]c1bb5af2013-03-13 19:06:273129 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143130
[email protected]c1bb5af2013-03-13 19:06:273131 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143132
[email protected]f0c2a242013-03-15 19:34:523133 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273134 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143135 }
3136}
3137
[email protected]c2d0c5a2013-02-26 04:43:363138TEST_F(LayerTreeHostImplTest, textureCachingWithOcclusionPartialSwap)
[email protected]94f206c12012-08-25 00:09:143139{
[email protected]96baf3e2012-10-22 23:09:553140 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:583141 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]9bdcfd642012-11-14 21:24:263142 settings.partialSwapEnabled = true;
[email protected]09dc0d4b2013-02-13 06:17:203143 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:273144 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:143145
3146 // Layers are structure as follows:
3147 //
3148 // R +-- S1 +- L10 (owning)
3149 // | +- L11
3150 // | +- L12
3151 // |
3152 // +-- S2 +- L20 (owning)
3153 // +- L21
3154 //
3155 // Occlusion:
3156 // L12 occludes L11 (internal)
3157 // L20 occludes L10 (external)
3158 // L21 occludes L20 (internal)
3159
[email protected]96baf3e2012-10-22 23:09:553160 LayerImpl* rootPtr;
3161 LayerImpl* layerS1Ptr;
3162 LayerImpl* layerS2Ptr;
[email protected]94f206c12012-08-25 00:09:143163
[email protected]a46f32932012-12-07 21:43:163164 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]94f206c12012-08-25 00:09:143165
[email protected]aad0a0072012-11-01 18:15:583166 gfx::Size rootSize(1000, 1000);
[email protected]94f206c12012-08-25 00:09:143167
[email protected]c1bb5af2013-03-13 19:06:273168 myHostImpl->InitializeRenderer(outputSurface.Pass());
3169 myHostImpl->SetViewportSize(gfx::Size(rootSize.width(), rootSize.height()), gfx::Size(rootSize.width(), rootSize.height()));
[email protected]94f206c12012-08-25 00:09:143170
[email protected]c1bb5af2013-03-13 19:06:273171 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
[email protected]94f206c12012-08-25 00:09:143172 rootPtr = root.get();
3173
[email protected]7aba6662013-03-12 10:17:343174 root->SetAnchorPoint(gfx::PointF(0, 0));
3175 root->SetPosition(gfx::PointF(0, 0));
3176 root->SetBounds(rootSize);
3177 root->SetContentBounds(rootSize);
3178 root->SetDrawsContent(true);
3179 root->SetMasksToBounds(true);
[email protected]c1bb5af2013-03-13 19:06:273180 myHostImpl->active_tree()->SetRootLayer(root.Pass());
[email protected]94f206c12012-08-25 00:09:143181
[email protected]aad0a0072012-11-01 18:15:583182 addDrawingLayerTo(rootPtr, 2, gfx::Rect(300, 300, 300, 300), &layerS1Ptr);
[email protected]7aba6662013-03-12 10:17:343183 layerS1Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:143184
[email protected]aad0a0072012-11-01 18:15:583185 addDrawingLayerTo(layerS1Ptr, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
3186 addDrawingLayerTo(layerS1Ptr, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
[email protected]94f206c12012-08-25 00:09:143187
[email protected]aad0a0072012-11-01 18:15:583188 addDrawingLayerTo(rootPtr, 5, gfx::Rect(550, 250, 300, 400), &layerS2Ptr);
[email protected]7aba6662013-03-12 10:17:343189 layerS2Ptr->SetForceRenderSurface(true);
[email protected]94f206c12012-08-25 00:09:143190
[email protected]aad0a0072012-11-01 18:15:583191 addDrawingLayerTo(layerS2Ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
[email protected]94f206c12012-08-25 00:09:143192
3193 // Initial draw - must receive all quads
3194 {
[email protected]96baf3e2012-10-22 23:09:553195 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273196 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143197
3198 // Must receive 3 render passes.
3199 // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded); for S2, there is 2 quads.
[email protected]c1bb5af2013-03-13 19:06:273200 ASSERT_EQ(3U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143201
[email protected]c1bb5af2013-03-13 19:06:273202 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3203 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
3204 EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143205
[email protected]f0c2a242013-03-15 19:34:523206 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273207 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143208 }
3209
3210 // "Unocclude" surface S1 and repeat draw.
3211 // Must remove S2's render pass since it's cached;
3212 // Must keep S1 quads because texture contained external occlusion.
[email protected]c8686a02012-11-27 08:29:003213 gfx::Transform transform = layerS2Ptr->transform();
3214 transform.Translate(150, 150);
[email protected]7aba6662013-03-12 10:17:343215 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143216 {
[email protected]96baf3e2012-10-22 23:09:553217 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273218 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143219
3220 // Must receive 2 render passes.
3221 // For Root, there are 2 quads.
3222 // For S1, there are 2 quads.
3223 // For S2, there is no render pass
[email protected]c1bb5af2013-03-13 19:06:273224 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143225
[email protected]c1bb5af2013-03-13 19:06:273226 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3227 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143228
[email protected]f0c2a242013-03-15 19:34:523229 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273230 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143231 }
3232
3233 // "Re-occlude" surface S1 and repeat draw.
3234 // Must remove S1's render pass since it is now available in full.
3235 // S2 has no change so must also be removed.
3236 transform = layerS2Ptr->transform();
[email protected]c8686a02012-11-27 08:29:003237 transform.Translate(-15, -15);
[email protected]7aba6662013-03-12 10:17:343238 layerS2Ptr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143239 {
[email protected]96baf3e2012-10-22 23:09:553240 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273241 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143242
3243 // Root render pass only.
[email protected]c1bb5af2013-03-13 19:06:273244 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143245
[email protected]f0c2a242013-03-15 19:34:523246 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273247 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143248 }
3249}
3250
[email protected]c2d0c5a2013-02-26 04:43:363251TEST_F(LayerTreeHostImplTest, textureCachingWithScissor)
[email protected]94f206c12012-08-25 00:09:143252{
[email protected]96baf3e2012-10-22 23:09:553253 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:583254 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]09dc0d4b2013-02-13 06:17:203255 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:273256 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:143257
3258 /*
3259 Layers are created as follows:
3260
3261 +--------------------+
3262 | 1 |
3263 | +-----------+ |
3264 | | 2 | |
3265 | | +-------------------+
3266 | | | 3 |
3267 | | +-------------------+
3268 | | | |
3269 | +-----------+ |
3270 | |
3271 | |
3272 +--------------------+
3273
3274 Layers 1, 2 have render surfaces
3275 */
[email protected]c1bb5af2013-03-13 19:06:273276 scoped_ptr<LayerImpl> root = LayerImpl::Create(myHostImpl->active_tree(), 1);
3277 scoped_ptr<TiledLayerImpl> child = TiledLayerImpl::Create(myHostImpl->active_tree(), 2);
3278 scoped_ptr<LayerImpl> grandChild = LayerImpl::Create(myHostImpl->active_tree(), 3);
[email protected]94f206c12012-08-25 00:09:143279
[email protected]aad0a0072012-11-01 18:15:583280 gfx::Rect rootRect(0, 0, 100, 100);
3281 gfx::Rect childRect(10, 10, 50, 50);
3282 gfx::Rect grandChildRect(5, 5, 150, 150);
[email protected]94f206c12012-08-25 00:09:143283
[email protected]a46f32932012-12-07 21:43:163284 scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new PartialSwapContext)).PassAs<OutputSurface>();
[email protected]c1bb5af2013-03-13 19:06:273285 myHostImpl->InitializeRenderer(outputSurface.Pass());
[email protected]94f206c12012-08-25 00:09:143286
[email protected]7aba6662013-03-12 10:17:343287 root->SetAnchorPoint(gfx::PointF(0, 0));
3288 root->SetPosition(gfx::PointF(rootRect.x(), rootRect.y()));
3289 root->SetBounds(gfx::Size(rootRect.width(), rootRect.height()));
3290 root->SetContentBounds(root->bounds());
3291 root->SetDrawsContent(true);
3292 root->SetMasksToBounds(true);
[email protected]94f206c12012-08-25 00:09:143293
[email protected]7aba6662013-03-12 10:17:343294 child->SetAnchorPoint(gfx::PointF(0, 0));
3295 child->SetPosition(gfx::PointF(childRect.x(), childRect.y()));
3296 child->SetOpacity(0.5);
3297 child->SetBounds(gfx::Size(childRect.width(), childRect.height()));
3298 child->SetContentBounds(child->bounds());
3299 child->SetDrawsContent(true);
[email protected]fa4b57f2013-03-17 21:39:093300 child->set_skips_draw(false);
[email protected]94f206c12012-08-25 00:09:143301
3302 // child layer has 10x10 tiles.
[email protected]32eee892013-03-18 06:41:133303 scoped_ptr<LayerTilingData> tiler = LayerTilingData::Create(gfx::Size(10, 10), LayerTilingData::HAS_BORDER_TEXELS);
3304 tiler->SetBounds(child->content_bounds());
[email protected]fa4b57f2013-03-17 21:39:093305 child->SetTilingData(*tiler.get());
[email protected]94f206c12012-08-25 00:09:143306
[email protected]7aba6662013-03-12 10:17:343307 grandChild->SetAnchorPoint(gfx::PointF(0, 0));
3308 grandChild->SetPosition(gfx::Point(grandChildRect.x(), grandChildRect.y()));
3309 grandChild->SetBounds(gfx::Size(grandChildRect.width(), grandChildRect.height()));
3310 grandChild->SetContentBounds(grandChild->bounds());
3311 grandChild->SetDrawsContent(true);
[email protected]94f206c12012-08-25 00:09:143312
[email protected]96baf3e2012-10-22 23:09:553313 TiledLayerImpl* childPtr = child.get();
3314 RenderPass::Id childPassId(childPtr->id(), 0);
[email protected]94f206c12012-08-25 00:09:143315
[email protected]7aba6662013-03-12 10:17:343316 child->AddChild(grandChild.Pass());
3317 root->AddChild(child.PassAs<LayerImpl>());
[email protected]c1bb5af2013-03-13 19:06:273318 myHostImpl->active_tree()->SetRootLayer(root.Pass());
3319 myHostImpl->SetViewportSize(rootRect.size(), rootRect.size());
[email protected]94f206c12012-08-25 00:09:143320
[email protected]90ec9872013-03-08 02:28:183321 EXPECT_FALSE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(childPassId));
[email protected]94f206c12012-08-25 00:09:143322
3323 {
[email protected]96baf3e2012-10-22 23:09:553324 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273325 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:523326 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273327 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143328 }
3329
3330 // We should have cached textures for surface 2.
[email protected]90ec9872013-03-08 02:28:183331 EXPECT_TRUE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(childPassId));
[email protected]94f206c12012-08-25 00:09:143332
3333 {
[email protected]96baf3e2012-10-22 23:09:553334 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273335 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:523336 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273337 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143338 }
3339
3340 // We should still have cached textures for surface 2 after drawing with no damage.
[email protected]90ec9872013-03-08 02:28:183341 EXPECT_TRUE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(childPassId));
[email protected]94f206c12012-08-25 00:09:143342
3343 // Damage a single tile of surface 2.
[email protected]7aba6662013-03-12 10:17:343344 childPtr->set_update_rect(gfx::Rect(10, 10, 10, 10));
[email protected]94f206c12012-08-25 00:09:143345
3346 {
[email protected]96baf3e2012-10-22 23:09:553347 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273348 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]f0c2a242013-03-15 19:34:523349 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273350 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143351 }
3352
3353 // We should have a cached texture for surface 2 again even though it was damaged.
[email protected]90ec9872013-03-08 02:28:183354 EXPECT_TRUE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(childPassId));
[email protected]94f206c12012-08-25 00:09:143355}
3356
[email protected]c2d0c5a2013-02-26 04:43:363357TEST_F(LayerTreeHostImplTest, surfaceTextureCaching)
[email protected]94f206c12012-08-25 00:09:143358{
[email protected]96baf3e2012-10-22 23:09:553359 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:583360 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]9bdcfd642012-11-14 21:24:263361 settings.partialSwapEnabled = true;
[email protected]09dc0d4b2013-02-13 06:17:203362 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:273363 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:143364
[email protected]96baf3e2012-10-22 23:09:553365 LayerImpl* rootPtr;
3366 LayerImpl* intermediateLayerPtr;
3367 LayerImpl* surfaceLayerPtr;
3368 LayerImpl* childPtr;
[email protected]94f206c12012-08-25 00:09:143369
[email protected]aad0a0072012-11-01 18:15:583370 setupLayersForTextureCaching(myHostImpl.get(), rootPtr, intermediateLayerPtr, surfaceLayerPtr, childPtr, gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:143371
3372 {
[email protected]96baf3e2012-10-22 23:09:553373 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273374 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143375
3376 // Must receive two render passes, each with one quad
[email protected]c1bb5af2013-03-13 19:06:273377 ASSERT_EQ(2U, frame.render_passes.size());
3378 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3379 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143380
[email protected]c1bb5af2013-03-13 19:06:273381 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3382 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3383 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]20062042012-12-21 22:16:363384 ASSERT_TRUE(targetPass);
[email protected]f57bbc02012-11-21 07:02:153385 EXPECT_FALSE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143386
[email protected]f0c2a242013-03-15 19:34:523387 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273388 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143389 }
3390
3391 // Draw without any change
3392 {
[email protected]96baf3e2012-10-22 23:09:553393 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273394 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143395
3396 // Must receive one render pass, as the other one should be culled
[email protected]c1bb5af2013-03-13 19:06:273397 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143398
[email protected]c1bb5af2013-03-13 19:06:273399 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3400 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3401 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3402 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143403
[email protected]f0c2a242013-03-15 19:34:523404 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273405 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143406 }
3407
3408 // Change opacity and draw
[email protected]7aba6662013-03-12 10:17:343409 surfaceLayerPtr->SetOpacity(0.6f);
[email protected]94f206c12012-08-25 00:09:143410 {
[email protected]96baf3e2012-10-22 23:09:553411 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273412 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143413
3414 // Must receive one render pass, as the other one should be culled
[email protected]c1bb5af2013-03-13 19:06:273415 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143416
[email protected]c1bb5af2013-03-13 19:06:273417 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3418 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3419 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3420 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143421
[email protected]f0c2a242013-03-15 19:34:523422 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273423 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143424 }
3425
3426 // Change less benign property and draw - should have contents changed flag
[email protected]7aba6662013-03-12 10:17:343427 surfaceLayerPtr->SetStackingOrderChanged(true);
[email protected]94f206c12012-08-25 00:09:143428 {
[email protected]96baf3e2012-10-22 23:09:553429 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273430 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143431
3432 // Must receive two render passes, each with one quad
[email protected]c1bb5af2013-03-13 19:06:273433 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143434
[email protected]c1bb5af2013-03-13 19:06:273435 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3436 EXPECT_EQ(DrawQuad::SOLID_COLOR, frame.render_passes[0]->quad_list[0]->material);
[email protected]94f206c12012-08-25 00:09:143437
[email protected]c1bb5af2013-03-13 19:06:273438 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3439 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3440 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]20062042012-12-21 22:16:363441 ASSERT_TRUE(targetPass);
[email protected]f57bbc02012-11-21 07:02:153442 EXPECT_FALSE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143443
[email protected]f0c2a242013-03-15 19:34:523444 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273445 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143446 }
3447
3448 // Change opacity again, and evict the cached surface texture.
[email protected]7aba6662013-03-12 10:17:343449 surfaceLayerPtr->SetOpacity(0.5f);
[email protected]faa48f32013-03-13 11:10:473450 static_cast<GLRendererWithReleaseTextures*>(myHostImpl->renderer())->ReleaseRenderPassTextures();
[email protected]94f206c12012-08-25 00:09:143451
3452 // Change opacity and draw
[email protected]7aba6662013-03-12 10:17:343453 surfaceLayerPtr->SetOpacity(0.6f);
[email protected]94f206c12012-08-25 00:09:143454 {
[email protected]96baf3e2012-10-22 23:09:553455 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273456 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143457
3458 // Must receive two render passes
[email protected]c1bb5af2013-03-13 19:06:273459 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143460
3461 // Even though not enough properties changed, the entire thing must be
3462 // redrawn as we don't have cached textures
[email protected]c1bb5af2013-03-13 19:06:273463 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3464 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143465
[email protected]c1bb5af2013-03-13 19:06:273466 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3467 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3468 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]20062042012-12-21 22:16:363469 ASSERT_TRUE(targetPass);
[email protected]f57bbc02012-11-21 07:02:153470 EXPECT_TRUE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143471
3472 // Was our surface evicted?
[email protected]90ec9872013-03-08 02:28:183473 EXPECT_FALSE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(targetPass->id));
[email protected]94f206c12012-08-25 00:09:143474
[email protected]f0c2a242013-03-15 19:34:523475 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273476 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143477 }
3478
3479 // Draw without any change, to make sure the state is clear
3480 {
[email protected]96baf3e2012-10-22 23:09:553481 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273482 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143483
3484 // Must receive one render pass, as the other one should be culled
[email protected]c1bb5af2013-03-13 19:06:273485 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143486
[email protected]c1bb5af2013-03-13 19:06:273487 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3488 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3489 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3490 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143491
[email protected]f0c2a242013-03-15 19:34:523492 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273493 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143494 }
3495
[email protected]518ee582012-10-24 18:29:443496 // Change location of the intermediate layer
[email protected]c8686a02012-11-27 08:29:003497 gfx::Transform transform = intermediateLayerPtr->transform();
3498 transform.matrix().setDouble(0, 3, 1.0001);
[email protected]7aba6662013-03-12 10:17:343499 intermediateLayerPtr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143500 {
[email protected]96baf3e2012-10-22 23:09:553501 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273502 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143503
3504 // Must receive one render pass, as the other one should be culled.
[email protected]c1bb5af2013-03-13 19:06:273505 ASSERT_EQ(1U, frame.render_passes.size());
3506 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143507
[email protected]c1bb5af2013-03-13 19:06:273508 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3509 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3510 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143511
[email protected]f0c2a242013-03-15 19:34:523512 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273513 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143514 }
3515}
3516
[email protected]c2d0c5a2013-02-26 04:43:363517TEST_F(LayerTreeHostImplTest, surfaceTextureCachingNoPartialSwap)
[email protected]94f206c12012-08-25 00:09:143518{
[email protected]96baf3e2012-10-22 23:09:553519 LayerTreeSettings settings;
[email protected]aad0a0072012-11-01 18:15:583520 settings.minimumOcclusionTrackingSize = gfx::Size();
[email protected]09dc0d4b2013-02-13 06:17:203521 settings.cacheRenderPassContents = true;
[email protected]c1bb5af2013-03-13 19:06:273522 scoped_ptr<LayerTreeHostImpl> myHostImpl = LayerTreeHostImpl::Create(settings, this, &m_proxy);
[email protected]94f206c12012-08-25 00:09:143523
[email protected]96baf3e2012-10-22 23:09:553524 LayerImpl* rootPtr;
3525 LayerImpl* intermediateLayerPtr;
3526 LayerImpl* surfaceLayerPtr;
3527 LayerImpl* childPtr;
[email protected]94f206c12012-08-25 00:09:143528
[email protected]aad0a0072012-11-01 18:15:583529 setupLayersForTextureCaching(myHostImpl.get(), rootPtr, intermediateLayerPtr, surfaceLayerPtr, childPtr, gfx::Size(100, 100));
[email protected]94f206c12012-08-25 00:09:143530
3531 {
[email protected]96baf3e2012-10-22 23:09:553532 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273533 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143534
3535 // Must receive two render passes, each with one quad
[email protected]c1bb5af2013-03-13 19:06:273536 ASSERT_EQ(2U, frame.render_passes.size());
3537 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3538 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143539
[email protected]c1bb5af2013-03-13 19:06:273540 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3541 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3542 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]f57bbc02012-11-21 07:02:153543 EXPECT_FALSE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143544
[email protected]c1bb5af2013-03-13 19:06:273545 EXPECT_FALSE(frame.render_passes[0]->damage_rect.IsEmpty());
3546 EXPECT_FALSE(frame.render_passes[1]->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143547
[email protected]c1bb5af2013-03-13 19:06:273548 EXPECT_FALSE(frame.render_passes[0]->has_occlusion_from_outside_target_surface);
3549 EXPECT_FALSE(frame.render_passes[1]->has_occlusion_from_outside_target_surface);
[email protected]94f206c12012-08-25 00:09:143550
[email protected]f0c2a242013-03-15 19:34:523551 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273552 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143553 }
3554
3555 // Draw without any change
3556 {
[email protected]96baf3e2012-10-22 23:09:553557 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273558 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143559
3560 // Even though there was no change, we set the damage to entire viewport.
3561 // One of the passes should be culled as a result, since contents didn't change
3562 // and we have cached texture.
[email protected]c1bb5af2013-03-13 19:06:273563 ASSERT_EQ(1U, frame.render_passes.size());
3564 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143565
[email protected]c1bb5af2013-03-13 19:06:273566 EXPECT_TRUE(frame.render_passes[0]->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143567
[email protected]f0c2a242013-03-15 19:34:523568 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273569 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143570 }
3571
3572 // Change opacity and draw
[email protected]7aba6662013-03-12 10:17:343573 surfaceLayerPtr->SetOpacity(0.6f);
[email protected]94f206c12012-08-25 00:09:143574 {
[email protected]96baf3e2012-10-22 23:09:553575 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273576 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143577
3578 // Must receive one render pass, as the other one should be culled
[email protected]c1bb5af2013-03-13 19:06:273579 ASSERT_EQ(1U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143580
[email protected]c1bb5af2013-03-13 19:06:273581 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3582 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3583 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3584 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143585
[email protected]f0c2a242013-03-15 19:34:523586 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273587 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143588 }
3589
3590 // Change less benign property and draw - should have contents changed flag
[email protected]7aba6662013-03-12 10:17:343591 surfaceLayerPtr->SetStackingOrderChanged(true);
[email protected]94f206c12012-08-25 00:09:143592 {
[email protected]96baf3e2012-10-22 23:09:553593 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273594 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143595
3596 // Must receive two render passes, each with one quad
[email protected]c1bb5af2013-03-13 19:06:273597 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143598
[email protected]c1bb5af2013-03-13 19:06:273599 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3600 EXPECT_EQ(DrawQuad::SOLID_COLOR, frame.render_passes[0]->quad_list[0]->material);
[email protected]94f206c12012-08-25 00:09:143601
[email protected]c1bb5af2013-03-13 19:06:273602 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3603 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3604 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]20062042012-12-21 22:16:363605 ASSERT_TRUE(targetPass);
[email protected]f57bbc02012-11-21 07:02:153606 EXPECT_FALSE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143607
[email protected]f0c2a242013-03-15 19:34:523608 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273609 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143610 }
3611
3612 // Change opacity again, and evict the cached surface texture.
[email protected]7aba6662013-03-12 10:17:343613 surfaceLayerPtr->SetOpacity(0.5f);
[email protected]faa48f32013-03-13 11:10:473614 static_cast<GLRendererWithReleaseTextures*>(myHostImpl->renderer())->ReleaseRenderPassTextures();
[email protected]94f206c12012-08-25 00:09:143615
3616 // Change opacity and draw
[email protected]7aba6662013-03-12 10:17:343617 surfaceLayerPtr->SetOpacity(0.6f);
[email protected]94f206c12012-08-25 00:09:143618 {
[email protected]96baf3e2012-10-22 23:09:553619 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273620 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143621
3622 // Must receive two render passes
[email protected]c1bb5af2013-03-13 19:06:273623 ASSERT_EQ(2U, frame.render_passes.size());
[email protected]94f206c12012-08-25 00:09:143624
3625 // Even though not enough properties changed, the entire thing must be
3626 // redrawn as we don't have cached textures
[email protected]c1bb5af2013-03-13 19:06:273627 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3628 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143629
[email protected]c1bb5af2013-03-13 19:06:273630 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[1]->quad_list[0]->material);
3631 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
3632 RenderPass* targetPass = frame.render_passes_by_id[quad->render_pass_id];
[email protected]20062042012-12-21 22:16:363633 ASSERT_TRUE(targetPass);
[email protected]f57bbc02012-11-21 07:02:153634 EXPECT_TRUE(targetPass->damage_rect.IsEmpty());
[email protected]94f206c12012-08-25 00:09:143635
3636 // Was our surface evicted?
[email protected]90ec9872013-03-08 02:28:183637 EXPECT_FALSE(myHostImpl->renderer()->HaveCachedResourcesForRenderPassId(targetPass->id));
[email protected]94f206c12012-08-25 00:09:143638
[email protected]f0c2a242013-03-15 19:34:523639 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273640 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143641 }
3642
3643 // Draw without any change, to make sure the state is clear
3644 {
[email protected]96baf3e2012-10-22 23:09:553645 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273646 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143647
3648 // Even though there was no change, we set the damage to entire viewport.
3649 // One of the passes should be culled as a result, since contents didn't change
3650 // and we have cached texture.
[email protected]c1bb5af2013-03-13 19:06:273651 ASSERT_EQ(1U, frame.render_passes.size());
3652 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143653
[email protected]f0c2a242013-03-15 19:34:523654 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273655 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143656 }
3657
[email protected]518ee582012-10-24 18:29:443658 // Change location of the intermediate layer
[email protected]c8686a02012-11-27 08:29:003659 gfx::Transform transform = intermediateLayerPtr->transform();
3660 transform.matrix().setDouble(0, 3, 1.0001);
[email protected]7aba6662013-03-12 10:17:343661 intermediateLayerPtr->SetTransform(transform);
[email protected]94f206c12012-08-25 00:09:143662 {
[email protected]96baf3e2012-10-22 23:09:553663 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:273664 EXPECT_TRUE(myHostImpl->PrepareToDraw(&frame));
[email protected]94f206c12012-08-25 00:09:143665
3666 // Must receive one render pass, as the other one should be culled.
[email protected]c1bb5af2013-03-13 19:06:273667 ASSERT_EQ(1U, frame.render_passes.size());
3668 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
[email protected]94f206c12012-08-25 00:09:143669
[email protected]c1bb5af2013-03-13 19:06:273670 EXPECT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
3671 const RenderPassDrawQuad* quad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
3672 EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) == frame.render_passes_by_id.end());
[email protected]94f206c12012-08-25 00:09:143673
[email protected]f0c2a242013-03-15 19:34:523674 myHostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:273675 myHostImpl->DidDrawAllLayers(frame);
[email protected]94f206c12012-08-25 00:09:143676 }
3677}
3678
[email protected]c2d0c5a2013-02-26 04:43:363679TEST_F(LayerTreeHostImplTest, releaseContentsTextureShouldTriggerCommit)
[email protected]94f206c12012-08-25 00:09:143680{
[email protected]b1969fa2012-10-17 20:16:293681 setReduceMemoryResult(false);
3682
3683 // Even if changing the memory limit didn't result in anything being
3684 // evicted, we need to re-commit because the new value may result in us
3685 // drawing something different than before.
3686 setReduceMemoryResult(false);
[email protected]90ec9872013-03-08 02:28:183687 m_hostImpl->SetManagedMemoryPolicy(ManagedMemoryPolicy(
[email protected]c1bb5af2013-03-13 19:06:273688 m_hostImpl->memory_allocation_limit_bytes() - 1));
[email protected]94f206c12012-08-25 00:09:143689 EXPECT_TRUE(m_didRequestCommit);
[email protected]b1969fa2012-10-17 20:16:293690 m_didRequestCommit = false;
3691
3692 // Especially if changing the memory limit caused evictions, we need
3693 // to re-commit.
3694 setReduceMemoryResult(true);
[email protected]90ec9872013-03-08 02:28:183695 m_hostImpl->SetManagedMemoryPolicy(ManagedMemoryPolicy(
[email protected]c1bb5af2013-03-13 19:06:273696 m_hostImpl->memory_allocation_limit_bytes() - 1));
[email protected]b1969fa2012-10-17 20:16:293697 EXPECT_TRUE(m_didRequestCommit);
3698 m_didRequestCommit = false;
3699
3700 // But if we set it to the same value that it was before, we shouldn't
3701 // re-commit.
[email protected]90ec9872013-03-08 02:28:183702 m_hostImpl->SetManagedMemoryPolicy(ManagedMemoryPolicy(
[email protected]c1bb5af2013-03-13 19:06:273703 m_hostImpl->memory_allocation_limit_bytes()));
[email protected]b1969fa2012-10-17 20:16:293704 EXPECT_FALSE(m_didRequestCommit);
[email protected]94f206c12012-08-25 00:09:143705}
3706
[email protected]96baf3e2012-10-22 23:09:553707struct RenderPassRemovalTestData : public LayerTreeHostImpl::FrameData {
[email protected]1044a252012-10-23 18:51:323708 ScopedPtrHashMap<RenderPass::Id, TestRenderPass> renderPassCache;
[email protected]96baf3e2012-10-22 23:09:553709 scoped_ptr<SharedQuadState> sharedQuadState;
[email protected]94f206c12012-08-25 00:09:143710};
3711
[email protected]96baf3e2012-10-22 23:09:553712class TestRenderer : public GLRenderer, public RendererClient {
[email protected]94f206c12012-08-25 00:09:143713public:
[email protected]7aba6662013-03-12 10:17:343714 static scoped_ptr<TestRenderer> Create(ResourceProvider* resourceProvider, OutputSurface* outputSurface, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:143715 {
[email protected]bf189f62012-12-18 03:42:113716 scoped_ptr<TestRenderer> renderer(new TestRenderer(resourceProvider, outputSurface, proxy));
[email protected]faa48f32013-03-13 11:10:473717 if (!renderer->Initialize())
[email protected]96baf3e2012-10-22 23:09:553718 return scoped_ptr<TestRenderer>();
[email protected]94f206c12012-08-25 00:09:143719
[email protected]a7aa5562012-10-17 14:12:443720 return renderer.Pass();
[email protected]94f206c12012-08-25 00:09:143721 }
3722
3723 void clearCachedTextures() { m_textures.clear(); }
[email protected]96baf3e2012-10-22 23:09:553724 void setHaveCachedResourcesForRenderPassId(RenderPass::Id id) { m_textures.insert(id); }
[email protected]94f206c12012-08-25 00:09:143725
[email protected]90ec9872013-03-08 02:28:183726 virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const OVERRIDE { return m_textures.count(id); }
[email protected]94f206c12012-08-25 00:09:143727
[email protected]96baf3e2012-10-22 23:09:553728 // RendererClient implementation.
[email protected]90ec9872013-03-08 02:28:183729 virtual gfx::Size DeviceViewportSize() const OVERRIDE { return m_viewportSize; }
3730 virtual const LayerTreeSettings& Settings() const OVERRIDE { return m_settings; }
3731 virtual void DidLoseOutputSurface() OVERRIDE { }
3732 virtual void OnSwapBuffersComplete() OVERRIDE { }
3733 virtual void SetFullRootLayerDamage() OVERRIDE { }
3734 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { }
3735 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { }
3736 virtual bool HasImplThread() const OVERRIDE { return false; }
3737 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
3738 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const
[email protected]bf189f62012-12-18 03:42:113739 OVERRIDE { return CompositorFrameMetadata(); }
[email protected]94f206c12012-08-25 00:09:143740
3741protected:
[email protected]bf189f62012-12-18 03:42:113742 TestRenderer(ResourceProvider* resourceProvider, OutputSurface* outputSurface, Proxy* proxy) : GLRenderer(this, outputSurface, resourceProvider) { }
[email protected]94f206c12012-08-25 00:09:143743
3744private:
[email protected]96baf3e2012-10-22 23:09:553745 LayerTreeSettings m_settings;
[email protected]aad0a0072012-11-01 18:15:583746 gfx::Size m_viewportSize;
[email protected]96baf3e2012-10-22 23:09:553747 base::hash_set<RenderPass::Id> m_textures;
[email protected]94f206c12012-08-25 00:09:143748};
3749
[email protected]96baf3e2012-10-22 23:09:553750static void configureRenderPassTestData(const char* testScript, RenderPassRemovalTestData& testData, TestRenderer* renderer)
[email protected]94f206c12012-08-25 00:09:143751{
3752 renderer->clearCachedTextures();
3753
3754 // One shared state for all quads - we don't need the correct details
[email protected]cb7af742012-11-21 04:02:243755 testData.sharedQuadState = SharedQuadState::Create();
[email protected]f902bf92013-03-04 18:33:273756 testData.sharedQuadState->SetAll(gfx::Transform(), gfx::Size(), gfx::Rect(), gfx::Rect(), false, 1.0);
[email protected]94f206c12012-08-25 00:09:143757
3758 const char* currentChar = testScript;
3759
3760 // Pre-create root pass
[email protected]96baf3e2012-10-22 23:09:553761 RenderPass::Id rootRenderPassId = RenderPass::Id(testScript[0], testScript[1]);
[email protected]f57bbc02012-11-21 07:02:153762 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
[email protected]c8686a02012-11-27 08:29:003763 pass->SetNew(rootRenderPassId, gfx::Rect(), gfx::Rect(), gfx::Transform());
[email protected]f57bbc02012-11-21 07:02:153764 testData.renderPassCache.add(rootRenderPassId, pass.Pass());
[email protected]94f206c12012-08-25 00:09:143765 while (*currentChar) {
[email protected]0f077a52012-09-08 01:45:243766 int layerId = *currentChar;
[email protected]94f206c12012-08-25 00:09:143767 currentChar++;
[email protected]0f077a52012-09-08 01:45:243768 ASSERT_TRUE(currentChar);
3769 int index = *currentChar;
3770 currentChar++;
3771
[email protected]96baf3e2012-10-22 23:09:553772 RenderPass::Id renderPassId = RenderPass::Id(layerId, index);
[email protected]94f206c12012-08-25 00:09:143773
[email protected]94f206c12012-08-25 00:09:143774 bool isReplica = false;
[email protected]87cea5372012-09-26 18:59:563775 if (!testData.renderPassCache.contains(renderPassId))
[email protected]94f206c12012-08-25 00:09:143776 isReplica = true;
3777
[email protected]1044a252012-10-23 18:51:323778 scoped_ptr<TestRenderPass> renderPass = testData.renderPassCache.take(renderPassId);
[email protected]94f206c12012-08-25 00:09:143779
3780 // Cycle through quad data and create all quads
3781 while (*currentChar && *currentChar != '\n') {
3782 if (*currentChar == 's') {
3783 // Solid color draw quad
[email protected]c22418b2012-11-20 23:06:263784 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
3785 quad->SetNew(testData.sharedQuadState.get(), gfx::Rect(0, 0, 10, 10), SK_ColorWHITE);
[email protected]4c91aec2012-12-15 20:17:183786
[email protected]f57bbc02012-11-21 07:02:153787 renderPass->AppendQuad(quad.PassAs<DrawQuad>());
[email protected]94f206c12012-08-25 00:09:143788 currentChar++;
3789 } else if ((*currentChar >= 'A') && (*currentChar <= 'Z')) {
3790 // RenderPass draw quad
[email protected]0f077a52012-09-08 01:45:243791 int layerId = *currentChar;
[email protected]94f206c12012-08-25 00:09:143792 currentChar++;
[email protected]0f077a52012-09-08 01:45:243793 ASSERT_TRUE(currentChar);
3794 int index = *currentChar;
3795 currentChar++;
[email protected]96baf3e2012-10-22 23:09:553796 RenderPass::Id newRenderPassId = RenderPass::Id(layerId, index);
[email protected]0f077a52012-09-08 01:45:243797 ASSERT_NE(rootRenderPassId, newRenderPassId);
[email protected]94f206c12012-08-25 00:09:143798 bool hasTexture = false;
3799 bool contentsChanged = true;
[email protected]4c91aec2012-12-15 20:17:183800
[email protected]94f206c12012-08-25 00:09:143801 if (*currentChar == '[') {
3802 currentChar++;
3803 while (*currentChar && *currentChar != ']') {
3804 switch (*currentChar) {
3805 case 'c':
3806 contentsChanged = false;
3807 break;
3808 case 't':
3809 hasTexture = true;
3810 break;
3811 }
3812 currentChar++;
3813 }
3814 if (*currentChar == ']')
3815 currentChar++;
3816 }
3817
3818 if (testData.renderPassCache.find(newRenderPassId) == testData.renderPassCache.end()) {
3819 if (hasTexture)
3820 renderer->setHaveCachedResourcesForRenderPassId(newRenderPassId);
3821
[email protected]f57bbc02012-11-21 07:02:153822 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
[email protected]c8686a02012-11-27 08:29:003823 pass->SetNew(newRenderPassId, gfx::Rect(), gfx::Rect(), gfx::Transform());
[email protected]f57bbc02012-11-21 07:02:153824 testData.renderPassCache.add(newRenderPassId, pass.Pass());
[email protected]94f206c12012-08-25 00:09:143825 }
3826
[email protected]aad0a0072012-11-01 18:15:583827 gfx::Rect quadRect = gfx::Rect(0, 0, 1, 1);
3828 gfx::Rect contentsChangedRect = contentsChanged ? quadRect : gfx::Rect();
[email protected]c22418b2012-11-20 23:06:263829 scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create();
[email protected]20062042012-12-21 22:16:363830 quad->SetNew(testData.sharedQuadState.get(), quadRect, newRenderPassId, isReplica, 1, contentsChangedRect, gfx::RectF(0, 0, 1, 1), WebKit::WebFilterOperations(), skia::RefPtr<SkImageFilter>(), WebKit::WebFilterOperations());
[email protected]f57bbc02012-11-21 07:02:153831 renderPass->AppendQuad(quad.PassAs<DrawQuad>());
[email protected]94f206c12012-08-25 00:09:143832 }
3833 }
[email protected]c1bb5af2013-03-13 19:06:273834 testData.render_passes_by_id[renderPassId] = renderPass.get();
3835 testData.render_passes.insert(testData.render_passes.begin(), renderPass.PassAs<RenderPass>());
[email protected]94f206c12012-08-25 00:09:143836 if (*currentChar)
3837 currentChar++;
3838 }
3839}
3840
3841void dumpRenderPassTestData(const RenderPassRemovalTestData& testData, char* buffer)
3842{
3843 char* pos = buffer;
[email protected]c1bb5af2013-03-13 19:06:273844 for (RenderPassList::const_reverse_iterator it = testData.render_passes.rbegin(); it != testData.render_passes.rend(); ++it) {
[email protected]96baf3e2012-10-22 23:09:553845 const RenderPass* currentPass = *it;
[email protected]f57bbc02012-11-21 07:02:153846 *pos = currentPass->id.layer_id;
[email protected]0f077a52012-09-08 01:45:243847 pos++;
[email protected]f57bbc02012-11-21 07:02:153848 *pos = currentPass->id.index;
[email protected]94f206c12012-08-25 00:09:143849 pos++;
3850
[email protected]f57bbc02012-11-21 07:02:153851 QuadList::const_iterator quadListIterator = currentPass->quad_list.begin();
3852 while (quadListIterator != currentPass->quad_list.end()) {
[email protected]96baf3e2012-10-22 23:09:553853 DrawQuad* currentQuad = *quadListIterator;
[email protected]1bc93f62012-11-17 19:29:503854 switch (currentQuad->material) {
[email protected]e48727e2012-11-16 22:10:023855 case DrawQuad::SOLID_COLOR:
[email protected]94f206c12012-08-25 00:09:143856 *pos = 's';
3857 pos++;
3858 break;
[email protected]e48727e2012-11-16 22:10:023859 case DrawQuad::RENDER_PASS:
[email protected]f57bbc02012-11-21 07:02:153860 *pos = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id.layer_id;
[email protected]0f077a52012-09-08 01:45:243861 pos++;
[email protected]c22418b2012-11-20 23:06:263862 *pos = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id.index;
[email protected]94f206c12012-08-25 00:09:143863 pos++;
3864 break;
3865 default:
3866 *pos = 'x';
3867 pos++;
3868 break;
3869 }
[email protected]4c91aec2012-12-15 20:17:183870
[email protected]94f206c12012-08-25 00:09:143871 quadListIterator++;
3872 }
3873 *pos = '\n';
3874 pos++;
3875 }
3876 *pos = '\0';
3877}
3878
[email protected]96baf3e2012-10-22 23:09:553879// Each RenderPassList is represented by a string which describes the configuration.
[email protected]94f206c12012-08-25 00:09:143880// The syntax of the string is as follows:
3881//
3882// RsssssX[c]ssYsssZ[t]ssW[ct]
3883// Identifies the render pass---------------------------^ ^^^ ^ ^ ^ ^ ^
3884// These are solid color quads-----------------------------+ | | | | |
3885// Identifies RenderPassDrawQuad's RenderPass-----------------+ | | | |
3886// This quad's contents didn't change---------------------------+ | | |
3887// This quad's contents changed and it has no texture---------------+ | |
3888// This quad has texture but its contents changed-------------------------+ |
3889// This quad's contents didn't change and it has texture - will be removed------+
3890//
3891// Expected results have exactly the same syntax, except they do not use square brackets,
3892// since we only check the structure, not attributes.
3893//
3894// Test case configuration consists of initialization script and expected results,
3895// all in the same format.
3896struct TestCase {
3897 const char* name;
3898 const char* initScript;
3899 const char* expectedResult;
3900};
3901
3902TestCase removeRenderPassesCases[] =
3903 {
3904 {
3905 "Single root pass",
[email protected]0f077a52012-09-08 01:45:243906 "R0ssss\n",
3907 "R0ssss\n"
[email protected]94f206c12012-08-25 00:09:143908 }, {
3909 "Single pass - no quads",
[email protected]0f077a52012-09-08 01:45:243910 "R0\n",
3911 "R0\n"
[email protected]94f206c12012-08-25 00:09:143912 }, {
3913 "Two passes, no removal",
[email protected]0f077a52012-09-08 01:45:243914 "R0ssssA0sss\n"
3915 "A0ssss\n",
3916 "R0ssssA0sss\n"
3917 "A0ssss\n"
[email protected]94f206c12012-08-25 00:09:143918 }, {
3919 "Two passes, remove last",
[email protected]0f077a52012-09-08 01:45:243920 "R0ssssA0[ct]sss\n"
3921 "A0ssss\n",
3922 "R0ssssA0sss\n"
[email protected]94f206c12012-08-25 00:09:143923 }, {
3924 "Have texture but contents changed - leave pass",
[email protected]0f077a52012-09-08 01:45:243925 "R0ssssA0[t]sss\n"
3926 "A0ssss\n",
3927 "R0ssssA0sss\n"
3928 "A0ssss\n"
[email protected]94f206c12012-08-25 00:09:143929 }, {
3930 "Contents didn't change but no texture - leave pass",
[email protected]0f077a52012-09-08 01:45:243931 "R0ssssA0[c]sss\n"
3932 "A0ssss\n",
3933 "R0ssssA0sss\n"
3934 "A0ssss\n"
[email protected]94f206c12012-08-25 00:09:143935 }, {
3936 "Replica: two quads reference the same pass; remove",
[email protected]0f077a52012-09-08 01:45:243937 "R0ssssA0[ct]A0[ct]sss\n"
3938 "A0ssss\n",
3939 "R0ssssA0A0sss\n"
[email protected]94f206c12012-08-25 00:09:143940 }, {
3941 "Replica: two quads reference the same pass; leave",
[email protected]0f077a52012-09-08 01:45:243942 "R0ssssA0[c]A0[c]sss\n"
3943 "A0ssss\n",
3944 "R0ssssA0A0sss\n"
3945 "A0ssss\n",
[email protected]94f206c12012-08-25 00:09:143946 }, {
3947 "Many passes, remove all",
[email protected]0f077a52012-09-08 01:45:243948 "R0ssssA0[ct]sss\n"
3949 "A0sssB0[ct]C0[ct]s\n"
3950 "B0sssD0[ct]ssE0[ct]F0[ct]\n"
3951 "E0ssssss\n"
3952 "C0G0[ct]\n"
3953 "D0sssssss\n"
3954 "F0sssssss\n"
3955 "G0sss\n",
[email protected]94f206c12012-08-25 00:09:143956
[email protected]0f077a52012-09-08 01:45:243957 "R0ssssA0sss\n"
[email protected]94f206c12012-08-25 00:09:143958 }, {
3959 "Deep recursion, remove all",
3960
[email protected]0f077a52012-09-08 01:45:243961 "R0sssssA0[ct]ssss\n"
3962 "A0ssssB0sss\n"
3963 "B0C0\n"
3964 "C0D0\n"
3965 "D0E0\n"
3966 "E0F0\n"
3967 "F0G0\n"
3968 "G0H0\n"
3969 "H0sssI0sss\n"
3970 "I0J0\n"
3971 "J0ssss\n",
[email protected]4c91aec2012-12-15 20:17:183972
[email protected]0f077a52012-09-08 01:45:243973 "R0sssssA0ssss\n"
[email protected]94f206c12012-08-25 00:09:143974 }, {
3975 "Wide recursion, remove all",
[email protected]0f077a52012-09-08 01:45:243976 "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
3977 "A0s\n"
3978 "B0s\n"
3979 "C0ssss\n"
3980 "D0ssss\n"
3981 "E0s\n"
3982 "F0\n"
3983 "G0s\n"
3984 "H0s\n"
3985 "I0s\n"
3986 "J0ssss\n",
[email protected]4c91aec2012-12-15 20:17:183987
[email protected]0f077a52012-09-08 01:45:243988 "R0A0B0C0D0E0F0G0H0I0J0\n"
[email protected]94f206c12012-08-25 00:09:143989 }, {
3990 "Remove passes regardless of cache state",
[email protected]0f077a52012-09-08 01:45:243991 "R0ssssA0[ct]sss\n"
3992 "A0sssB0C0s\n"
3993 "B0sssD0[c]ssE0[t]F0\n"
3994 "E0ssssss\n"
3995 "C0G0\n"
3996 "D0sssssss\n"
3997 "F0sssssss\n"
3998 "G0sss\n",
[email protected]94f206c12012-08-25 00:09:143999
[email protected]0f077a52012-09-08 01:45:244000 "R0ssssA0sss\n"
[email protected]94f206c12012-08-25 00:09:144001 }, {
4002 "Leave some passes, remove others",
4003
[email protected]0f077a52012-09-08 01:45:244004 "R0ssssA0[c]sss\n"
4005 "A0sssB0[t]C0[ct]s\n"
4006 "B0sssD0[c]ss\n"
4007 "C0G0\n"
4008 "D0sssssss\n"
4009 "G0sss\n",
[email protected]94f206c12012-08-25 00:09:144010
[email protected]0f077a52012-09-08 01:45:244011 "R0ssssA0sss\n"
4012 "A0sssB0C0s\n"
4013 "B0sssD0ss\n"
4014 "D0sssssss\n"
[email protected]94f206c12012-08-25 00:09:144015 }, {
4016 0, 0, 0
4017 }
4018 };
4019
4020static void verifyRenderPassTestData(TestCase& testCase, RenderPassRemovalTestData& testData)
4021{
4022 char actualResult[1024];
4023 dumpRenderPassTestData(testData, actualResult);
4024 EXPECT_STREQ(testCase.expectedResult, actualResult) << "In test case: " << testCase.name;
4025}
4026
[email protected]c2d0c5a2013-02-26 04:43:364027TEST_F(LayerTreeHostImplTest, testRemoveRenderPasses)
[email protected]94f206c12012-08-25 00:09:144028{
[email protected]3be2171d2012-12-06 06:13:204029 scoped_ptr<OutputSurface> outputSurface(createOutputSurface());
[email protected]79a1be52013-02-13 23:59:504030 ASSERT_TRUE(outputSurface->context3d());
[email protected]f53da3972013-03-07 08:38:414031 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outputSurface.get()));
[email protected]94f206c12012-08-25 00:09:144032
[email protected]7aba6662013-03-12 10:17:344033 scoped_ptr<TestRenderer> renderer(TestRenderer::Create(resourceProvider.get(), outputSurface.get(), &m_proxy));
[email protected]94f206c12012-08-25 00:09:144034
4035 int testCaseIndex = 0;
4036 while (removeRenderPassesCases[testCaseIndex].name) {
4037 RenderPassRemovalTestData testData;
4038 configureRenderPassTestData(removeRenderPassesCases[testCaseIndex].initScript, testData, renderer.get());
[email protected]c1bb5af2013-03-13 19:06:274039 LayerTreeHostImpl::RemoveRenderPasses(LayerTreeHostImpl::CullRenderPassesWithCachedTextures(*renderer), &testData);
[email protected]94f206c12012-08-25 00:09:144040 verifyRenderPassTestData(removeRenderPassesCases[testCaseIndex], testData);
4041 testCaseIndex++;
4042 }
4043}
4044
[email protected]ea9d8f22012-12-08 03:39:294045class LayerTreeHostImplTestWithDelegatingRenderer : public LayerTreeHostImplTest {
4046protected:
[email protected]9f930272013-02-06 09:51:554047 virtual scoped_ptr<OutputSurface> createOutputSurface() OVERRIDE
[email protected]ea9d8f22012-12-08 03:39:294048 {
4049 // Creates an output surface with a parent to use a delegating renderer.
4050 WebKit::WebGraphicsContext3D::Attributes attrs;
[email protected]c8756fbe2013-02-12 01:53:494051 return FakeOutputSurface::CreateDelegating3d(TestWebGraphicsContext3D::Create(attrs).PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
[email protected]ea9d8f22012-12-08 03:39:294052 }
4053
4054 void drawFrameAndTestDamage(const gfx::RectF& expectedDamage) {
4055 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274056 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
4057 ASSERT_EQ(1u, frame.render_passes.size());
[email protected]ea9d8f22012-12-08 03:39:294058
4059 // Verify the damage rect for the root render pass.
[email protected]c1bb5af2013-03-13 19:06:274060 const RenderPass* rootRenderPass = frame.render_passes.back();
[email protected]ea9d8f22012-12-08 03:39:294061 EXPECT_RECT_EQ(expectedDamage, rootRenderPass->damage_rect);
4062
4063 // Verify the root layer's quad is generated and not being culled.
4064 ASSERT_EQ(1u, rootRenderPass->quad_list.size());
[email protected]c1bb5af2013-03-13 19:06:274065 gfx::Rect expectedVisibleRect(m_hostImpl->active_tree()->root_layer()->content_bounds());
[email protected]ea9d8f22012-12-08 03:39:294066 EXPECT_RECT_EQ(expectedVisibleRect, rootRenderPass->quad_list[0]->visible_rect);
4067
[email protected]f0c2a242013-03-15 19:34:524068 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274069 m_hostImpl->DidDrawAllLayers(frame);
[email protected]ea9d8f22012-12-08 03:39:294070 }
4071};
4072
[email protected]c2d0c5a2013-02-26 04:43:364073TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect)
[email protected]ea9d8f22012-12-08 03:39:294074{
[email protected]c1bb5af2013-03-13 19:06:274075 scoped_ptr<SolidColorLayerImpl> root = SolidColorLayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]7aba6662013-03-12 10:17:344076 root->SetAnchorPoint(gfx::PointF(0.f, 0.f));
4077 root->SetPosition(gfx::PointF(0.f, 0.f));
4078 root->SetBounds(gfx::Size(10, 10));
4079 root->SetContentBounds(gfx::Size(10, 10));
4080 root->SetDrawsContent(true);
[email protected]c1bb5af2013-03-13 19:06:274081 m_hostImpl->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
[email protected]c2d0c5a2013-02-26 04:43:364082
[email protected]ea9d8f22012-12-08 03:39:294083 // Draw a frame. In the first frame, the entire viewport should be damaged.
[email protected]c1bb5af2013-03-13 19:06:274084 gfx::Rect fullFrameDamage = gfx::Rect(m_hostImpl->device_viewport_size());
[email protected]ea9d8f22012-12-08 03:39:294085 drawFrameAndTestDamage(fullFrameDamage);
4086
4087 // The second frame should have no damage, but the quads should still be generated.
[email protected]c2d0c5a2013-02-26 04:43:364088 gfx::Rect noDamage = gfx::Rect();
[email protected]ea9d8f22012-12-08 03:39:294089 drawFrameAndTestDamage(noDamage);
4090}
4091
[email protected]05dea302013-01-15 08:30:414092class FakeMaskLayerImpl : public LayerImpl {
4093public:
[email protected]7aba6662013-03-12 10:17:344094 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* treeImpl, int id)
[email protected]05dea302013-01-15 08:30:414095 {
4096 return make_scoped_ptr(new FakeMaskLayerImpl(treeImpl, id));
4097 }
4098
[email protected]7aba6662013-03-12 10:17:344099 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE { return 0; }
[email protected]05dea302013-01-15 08:30:414100
4101private:
4102 FakeMaskLayerImpl(LayerTreeImpl* treeImpl, int id) : LayerImpl(treeImpl, id) { }
4103};
4104
[email protected]c2d0c5a2013-02-26 04:43:364105TEST_F(LayerTreeHostImplTest, maskLayerWithScaling)
[email protected]05dea302013-01-15 08:30:414106{
4107 // Root
4108 // |
4109 // +-- Scaling Layer (adds a 2x scale)
4110 // |
4111 // +-- Content Layer
4112 // +--Mask
[email protected]c1bb5af2013-03-13 19:06:274113 scoped_ptr<LayerImpl> scopedRoot = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]05dea302013-01-15 08:30:414114 LayerImpl* root = scopedRoot.get();
[email protected]c1bb5af2013-03-13 19:06:274115 m_hostImpl->active_tree()->SetRootLayer(scopedRoot.Pass());
[email protected]05dea302013-01-15 08:30:414116
[email protected]c1bb5af2013-03-13 19:06:274117 scoped_ptr<LayerImpl> scopedScalingLayer = LayerImpl::Create(m_hostImpl->active_tree(), 2);
[email protected]05dea302013-01-15 08:30:414118 LayerImpl* scalingLayer = scopedScalingLayer.get();
[email protected]7aba6662013-03-12 10:17:344119 root->AddChild(scopedScalingLayer.Pass());
[email protected]05dea302013-01-15 08:30:414120
[email protected]c1bb5af2013-03-13 19:06:274121 scoped_ptr<LayerImpl> scopedContentLayer = LayerImpl::Create(m_hostImpl->active_tree(), 3);
[email protected]05dea302013-01-15 08:30:414122 LayerImpl* contentLayer = scopedContentLayer.get();
[email protected]7aba6662013-03-12 10:17:344123 scalingLayer->AddChild(scopedContentLayer.Pass());
[email protected]05dea302013-01-15 08:30:414124
[email protected]c1bb5af2013-03-13 19:06:274125 scoped_ptr<FakeMaskLayerImpl> scopedMaskLayer = FakeMaskLayerImpl::Create(m_hostImpl->active_tree(), 4);
[email protected]05dea302013-01-15 08:30:414126 FakeMaskLayerImpl* maskLayer = scopedMaskLayer.get();
[email protected]7aba6662013-03-12 10:17:344127 contentLayer->SetMaskLayer(scopedMaskLayer.PassAs<LayerImpl>());
[email protected]05dea302013-01-15 08:30:414128
4129 gfx::Size rootSize(100, 100);
[email protected]7aba6662013-03-12 10:17:344130 root->SetBounds(rootSize);
4131 root->SetContentBounds(rootSize);
4132 root->SetPosition(gfx::PointF());
4133 root->SetAnchorPoint(gfx::PointF());
[email protected]05dea302013-01-15 08:30:414134
4135 gfx::Size scalingLayerSize(50, 50);
[email protected]7aba6662013-03-12 10:17:344136 scalingLayer->SetBounds(scalingLayerSize);
4137 scalingLayer->SetContentBounds(scalingLayerSize);
4138 scalingLayer->SetPosition(gfx::PointF());
4139 scalingLayer->SetAnchorPoint(gfx::PointF());
[email protected]05dea302013-01-15 08:30:414140 gfx::Transform scale;
4141 scale.Scale(2.0, 2.0);
[email protected]7aba6662013-03-12 10:17:344142 scalingLayer->SetTransform(scale);
[email protected]05dea302013-01-15 08:30:414143
[email protected]7aba6662013-03-12 10:17:344144 contentLayer->SetBounds(scalingLayerSize);
4145 contentLayer->SetContentBounds(scalingLayerSize);
4146 contentLayer->SetPosition(gfx::PointF());
4147 contentLayer->SetAnchorPoint(gfx::PointF());
4148 contentLayer->SetDrawsContent(true);
[email protected]05dea302013-01-15 08:30:414149
[email protected]7aba6662013-03-12 10:17:344150 maskLayer->SetBounds(scalingLayerSize);
4151 maskLayer->SetContentBounds(scalingLayerSize);
4152 maskLayer->SetPosition(gfx::PointF());
4153 maskLayer->SetAnchorPoint(gfx::PointF());
4154 maskLayer->SetDrawsContent(true);
[email protected]05dea302013-01-15 08:30:414155
4156
4157 // Check that the tree scaling is correctly taken into account for the mask,
4158 // that should fully map onto the quad.
4159 float deviceScaleFactor = 1.f;
[email protected]c1bb5af2013-03-13 19:06:274160 m_hostImpl->SetViewportSize(rootSize, rootSize);
4161 m_hostImpl->SetDeviceScaleFactor(deviceScaleFactor);
[email protected]05dea302013-01-15 08:30:414162 {
4163 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274164 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]05dea302013-01-15 08:30:414165
[email protected]c1bb5af2013-03-13 19:06:274166 ASSERT_EQ(1u, frame.render_passes.size());
4167 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4168 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4169 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554170 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
4171 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
[email protected]05dea302013-01-15 08:30:414172
[email protected]f0c2a242013-03-15 19:34:524173 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274174 m_hostImpl->DidDrawAllLayers(frame);
[email protected]05dea302013-01-15 08:30:414175 }
4176
4177
4178 // Applying a DSF should change the render surface size, but won't affect
4179 // which part of the mask is used.
4180 deviceScaleFactor = 2.f;
4181 gfx::Size deviceViewport(gfx::ToFlooredSize(gfx::ScaleSize(rootSize, deviceScaleFactor)));
[email protected]c1bb5af2013-03-13 19:06:274182 m_hostImpl->SetViewportSize(rootSize, deviceViewport);
4183 m_hostImpl->SetDeviceScaleFactor(deviceScaleFactor);
4184 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]05dea302013-01-15 08:30:414185 {
4186 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274187 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]05dea302013-01-15 08:30:414188
[email protected]c1bb5af2013-03-13 19:06:274189 ASSERT_EQ(1u, frame.render_passes.size());
4190 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4191 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4192 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554193 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), renderPassQuad->rect.ToString());
4194 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
[email protected]05dea302013-01-15 08:30:414195
[email protected]f0c2a242013-03-15 19:34:524196 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274197 m_hostImpl->DidDrawAllLayers(frame);
[email protected]05dea302013-01-15 08:30:414198 }
4199
4200
4201 // Applying an equivalent content scale on the content layer and the mask
4202 // should still result in the same part of the mask being used.
4203 gfx::Size contentsBounds(gfx::ToRoundedSize(gfx::ScaleSize(scalingLayerSize, deviceScaleFactor)));
[email protected]7aba6662013-03-12 10:17:344204 contentLayer->SetContentBounds(contentsBounds);
4205 contentLayer->SetContentsScale(deviceScaleFactor, deviceScaleFactor);
4206 maskLayer->SetContentBounds(contentsBounds);
4207 maskLayer->SetContentsScale(deviceScaleFactor, deviceScaleFactor);
[email protected]c1bb5af2013-03-13 19:06:274208 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]05dea302013-01-15 08:30:414209 {
4210 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274211 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]05dea302013-01-15 08:30:414212
[email protected]c1bb5af2013-03-13 19:06:274213 ASSERT_EQ(1u, frame.render_passes.size());
4214 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4215 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4216 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554217 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(), renderPassQuad->rect.ToString());
4218 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
4219
[email protected]f0c2a242013-03-15 19:34:524220 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274221 m_hostImpl->DidDrawAllLayers(frame);
[email protected]8611f012013-01-17 03:44:554222 }
4223}
4224
[email protected]c2d0c5a2013-02-26 04:43:364225TEST_F(LayerTreeHostImplTest, maskLayerWithDifferentBounds)
[email protected]8611f012013-01-17 03:44:554226{
4227 // The mask layer has bounds 100x100 but is attached to a layer with bounds 50x50.
4228
[email protected]c1bb5af2013-03-13 19:06:274229 scoped_ptr<LayerImpl> scopedRoot = LayerImpl::Create(m_hostImpl->active_tree(), 1);
[email protected]8611f012013-01-17 03:44:554230 LayerImpl* root = scopedRoot.get();
[email protected]c1bb5af2013-03-13 19:06:274231 m_hostImpl->active_tree()->SetRootLayer(scopedRoot.Pass());
[email protected]8611f012013-01-17 03:44:554232
[email protected]c1bb5af2013-03-13 19:06:274233 scoped_ptr<LayerImpl> scopedContentLayer = LayerImpl::Create(m_hostImpl->active_tree(), 3);
[email protected]8611f012013-01-17 03:44:554234 LayerImpl* contentLayer = scopedContentLayer.get();
[email protected]7aba6662013-03-12 10:17:344235 root->AddChild(scopedContentLayer.Pass());
[email protected]8611f012013-01-17 03:44:554236
[email protected]c1bb5af2013-03-13 19:06:274237 scoped_ptr<FakeMaskLayerImpl> scopedMaskLayer = FakeMaskLayerImpl::Create(m_hostImpl->active_tree(), 4);
[email protected]8611f012013-01-17 03:44:554238 FakeMaskLayerImpl* maskLayer = scopedMaskLayer.get();
[email protected]7aba6662013-03-12 10:17:344239 contentLayer->SetMaskLayer(scopedMaskLayer.PassAs<LayerImpl>());
[email protected]8611f012013-01-17 03:44:554240
4241 gfx::Size rootSize(100, 100);
[email protected]7aba6662013-03-12 10:17:344242 root->SetBounds(rootSize);
4243 root->SetContentBounds(rootSize);
4244 root->SetPosition(gfx::PointF());
4245 root->SetAnchorPoint(gfx::PointF());
[email protected]8611f012013-01-17 03:44:554246
4247 gfx::Size layerSize(50, 50);
[email protected]7aba6662013-03-12 10:17:344248 contentLayer->SetBounds(layerSize);
4249 contentLayer->SetContentBounds(layerSize);
4250 contentLayer->SetPosition(gfx::PointF());
4251 contentLayer->SetAnchorPoint(gfx::PointF());
4252 contentLayer->SetDrawsContent(true);
[email protected]8611f012013-01-17 03:44:554253
4254 gfx::Size maskSize(100, 100);
[email protected]7aba6662013-03-12 10:17:344255 maskLayer->SetBounds(maskSize);
4256 maskLayer->SetContentBounds(maskSize);
4257 maskLayer->SetPosition(gfx::PointF());
4258 maskLayer->SetAnchorPoint(gfx::PointF());
4259 maskLayer->SetDrawsContent(true);
[email protected]8611f012013-01-17 03:44:554260
4261
4262 // Check that the mask fills the surface.
4263 float deviceScaleFactor = 1.f;
[email protected]c1bb5af2013-03-13 19:06:274264 m_hostImpl->SetViewportSize(rootSize, rootSize);
4265 m_hostImpl->SetDeviceScaleFactor(deviceScaleFactor);
[email protected]8611f012013-01-17 03:44:554266 {
4267 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274268 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]8611f012013-01-17 03:44:554269
[email protected]c1bb5af2013-03-13 19:06:274270 ASSERT_EQ(1u, frame.render_passes.size());
4271 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4272 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4273 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554274 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), renderPassQuad->rect.ToString());
4275 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
4276
[email protected]f0c2a242013-03-15 19:34:524277 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274278 m_hostImpl->DidDrawAllLayers(frame);
[email protected]8611f012013-01-17 03:44:554279 }
4280
4281
4282 // Applying a DSF should change the render surface size, but won't affect
4283 // which part of the mask is used.
4284 deviceScaleFactor = 2.f;
4285 gfx::Size deviceViewport(gfx::ToFlooredSize(gfx::ScaleSize(rootSize, deviceScaleFactor)));
[email protected]c1bb5af2013-03-13 19:06:274286 m_hostImpl->SetViewportSize(rootSize, deviceViewport);
4287 m_hostImpl->SetDeviceScaleFactor(deviceScaleFactor);
4288 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]8611f012013-01-17 03:44:554289 {
4290 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274291 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]8611f012013-01-17 03:44:554292
[email protected]c1bb5af2013-03-13 19:06:274293 ASSERT_EQ(1u, frame.render_passes.size());
4294 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4295 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4296 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554297 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
4298 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
4299
[email protected]f0c2a242013-03-15 19:34:524300 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274301 m_hostImpl->DidDrawAllLayers(frame);
[email protected]8611f012013-01-17 03:44:554302 }
4303
4304
4305 // Applying an equivalent content scale on the content layer and the mask
4306 // should still result in the same part of the mask being used.
4307 gfx::Size layerSizeLarge(gfx::ToRoundedSize(gfx::ScaleSize(layerSize, deviceScaleFactor)));
[email protected]7aba6662013-03-12 10:17:344308 contentLayer->SetContentBounds(layerSizeLarge);
4309 contentLayer->SetContentsScale(deviceScaleFactor, deviceScaleFactor);
[email protected]8611f012013-01-17 03:44:554310 gfx::Size maskSizeLarge(gfx::ToRoundedSize(gfx::ScaleSize(maskSize, deviceScaleFactor)));
[email protected]7aba6662013-03-12 10:17:344311 maskLayer->SetContentBounds(maskSizeLarge);
4312 maskLayer->SetContentsScale(deviceScaleFactor, deviceScaleFactor);
[email protected]c1bb5af2013-03-13 19:06:274313 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]8611f012013-01-17 03:44:554314 {
4315 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274316 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]8611f012013-01-17 03:44:554317
[email protected]c1bb5af2013-03-13 19:06:274318 ASSERT_EQ(1u, frame.render_passes.size());
4319 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4320 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4321 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554322 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
4323 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
4324
[email protected]f0c2a242013-03-15 19:34:524325 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274326 m_hostImpl->DidDrawAllLayers(frame);
[email protected]8611f012013-01-17 03:44:554327 }
4328
4329 // Applying a different contents scale to the mask layer will still result
4330 // in the mask covering the owning layer.
[email protected]7aba6662013-03-12 10:17:344331 maskLayer->SetContentBounds(maskSize);
4332 maskLayer->SetContentsScale(deviceScaleFactor, deviceScaleFactor);
[email protected]c1bb5af2013-03-13 19:06:274333 m_hostImpl->active_tree()->set_needs_update_draw_properties();
[email protected]8611f012013-01-17 03:44:554334 {
4335 LayerTreeHostImpl::FrameData frame;
[email protected]c1bb5af2013-03-13 19:06:274336 EXPECT_TRUE(m_hostImpl->PrepareToDraw(&frame));
[email protected]8611f012013-01-17 03:44:554337
[email protected]c1bb5af2013-03-13 19:06:274338 ASSERT_EQ(1u, frame.render_passes.size());
4339 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
4340 ASSERT_EQ(DrawQuad::RENDER_PASS, frame.render_passes[0]->quad_list[0]->material);
4341 const RenderPassDrawQuad* renderPassQuad = RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
[email protected]8611f012013-01-17 03:44:554342 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), renderPassQuad->rect.ToString());
4343 EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), renderPassQuad->mask_uv_rect.ToString());
[email protected]05dea302013-01-15 08:30:414344
[email protected]f0c2a242013-03-15 19:34:524345 m_hostImpl->DrawLayers(&frame, base::TimeTicks::Now());
[email protected]c1bb5af2013-03-13 19:06:274346 m_hostImpl->DidDrawAllLayers(frame);
[email protected]05dea302013-01-15 08:30:414347 }
4348}
4349
[email protected]ba565742012-11-10 09:29:484350} // namespace
4351} // namespace cc