OLD | NEW |
| (Empty) |
1 // 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 | |
5 #include "cc/layers/tiled_layer.h" | |
6 | |
7 #include <limits> | |
8 #include <vector> | |
9 | |
10 #include "base/run_loop.h" | |
11 #include "cc/resources/bitmap_content_layer_updater.h" | |
12 #include "cc/resources/layer_painter.h" | |
13 #include "cc/resources/prioritized_resource_manager.h" | |
14 #include "cc/resources/resource_update_controller.h" | |
15 #include "cc/test/animation_test_common.h" | |
16 #include "cc/test/fake_layer_tree_host_client.h" | |
17 #include "cc/test/fake_layer_tree_host_impl.h" | |
18 #include "cc/test/fake_output_surface.h" | |
19 #include "cc/test/fake_output_surface_client.h" | |
20 #include "cc/test/fake_proxy.h" | |
21 #include "cc/test/geometry_test_utils.h" | |
22 #include "cc/test/test_shared_bitmap_manager.h" | |
23 #include "cc/test/tiled_layer_test_common.h" | |
24 #include "cc/trees/occlusion_tracker.h" | |
25 #include "cc/trees/single_thread_proxy.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 #include "ui/gfx/geometry/rect_conversions.h" | |
28 #include "ui/gfx/transform.h" | |
29 | |
30 namespace cc { | |
31 namespace { | |
32 | |
33 class TestOcclusionTracker : public OcclusionTracker<Layer> { | |
34 public: | |
35 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) { | |
36 stack_.push_back(StackObject()); | |
37 } | |
38 | |
39 void SetRenderTarget(Layer* render_target) { | |
40 stack_.back().target = render_target; | |
41 } | |
42 | |
43 void SetOcclusion(const SimpleEnclosedRegion& occlusion) { | |
44 stack_.back().occlusion_from_inside_target = occlusion; | |
45 } | |
46 }; | |
47 | |
48 class SynchronousOutputSurfaceClient : public FakeLayerTreeHostClient { | |
49 public: | |
50 SynchronousOutputSurfaceClient() | |
51 : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {} | |
52 | |
53 bool EnsureOutputSurfaceCreated() { | |
54 base::MessageLoop::current()->PostDelayedTask( | |
55 FROM_HERE, | |
56 run_loop_.QuitClosure(), | |
57 base::TimeDelta::FromSeconds(5)); | |
58 run_loop_.Run(); | |
59 return output_surface_created_; | |
60 } | |
61 | |
62 void DidInitializeOutputSurface() override { | |
63 FakeLayerTreeHostClient::DidInitializeOutputSurface(); | |
64 output_surface_created_ = true; | |
65 run_loop_.Quit(); | |
66 } | |
67 | |
68 void DidFailToInitializeOutputSurface() override { | |
69 FakeLayerTreeHostClient::DidFailToInitializeOutputSurface(); | |
70 output_surface_created_ = false; | |
71 run_loop_.Quit(); | |
72 } | |
73 | |
74 private: | |
75 bool output_surface_created_; | |
76 base::RunLoop run_loop_; | |
77 }; | |
78 | |
79 class TiledLayerTest : public testing::Test { | |
80 public: | |
81 TiledLayerTest() | |
82 : proxy_(nullptr), | |
83 output_surface_(FakeOutputSurface::Create3d()), | |
84 queue_(make_scoped_ptr(new ResourceUpdateQueue)), | |
85 impl_thread_("ImplThread"), | |
86 occlusion_(nullptr) { | |
87 settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max(); | |
88 settings_.layer_transforms_should_scale_layer_contents = true; | |
89 settings_.verify_property_trees = true; | |
90 settings_.impl_side_painting = false; | |
91 } | |
92 | |
93 void SetUp() override { | |
94 impl_thread_.Start(); | |
95 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); | |
96 layer_tree_host_ = LayerTreeHost::CreateThreaded( | |
97 &synchonous_output_surface_client_, shared_bitmap_manager_.get(), | |
98 nullptr, nullptr, settings_, base::MessageLoopProxy::current(), | |
99 impl_thread_.message_loop_proxy(), nullptr); | |
100 synchonous_output_surface_client_.SetLayerTreeHost(layer_tree_host_.get()); | |
101 proxy_ = layer_tree_host_->proxy(); | |
102 resource_manager_ = PrioritizedResourceManager::Create(proxy_); | |
103 layer_tree_host_->SetLayerTreeHostClientReady(); | |
104 CHECK(synchonous_output_surface_client_.EnsureOutputSurfaceCreated()); | |
105 | |
106 layer_tree_host_->SetRootLayer(Layer::Create()); | |
107 | |
108 CHECK(output_surface_->BindToClient(&output_surface_client_)); | |
109 | |
110 DebugScopedSetImplThreadAndMainThreadBlocked | |
111 impl_thread_and_main_thread_blocked(proxy_); | |
112 resource_provider_ = ResourceProvider::Create(output_surface_.get(), | |
113 shared_bitmap_manager_.get(), | |
114 nullptr, | |
115 nullptr, | |
116 0, | |
117 false, | |
118 1); | |
119 host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl( | |
120 proxy_, shared_bitmap_manager_.get(), nullptr)); | |
121 } | |
122 | |
123 ~TiledLayerTest() override { | |
124 ResourceManagerClearAllMemory(resource_manager_.get(), | |
125 resource_provider_.get()); | |
126 | |
127 DebugScopedSetImplThreadAndMainThreadBlocked | |
128 impl_thread_and_main_thread_blocked(proxy_); | |
129 resource_provider_ = nullptr; | |
130 host_impl_ = nullptr; | |
131 } | |
132 | |
133 void ResourceManagerClearAllMemory( | |
134 PrioritizedResourceManager* resource_manager, | |
135 ResourceProvider* resource_provider) { | |
136 { | |
137 DebugScopedSetImplThreadAndMainThreadBlocked | |
138 impl_thread_and_main_thread_blocked(proxy_); | |
139 resource_manager->ClearAllMemory(resource_provider); | |
140 resource_manager->ReduceMemory(resource_provider); | |
141 } | |
142 resource_manager->UnlinkAndClearEvictedBackings(); | |
143 } | |
144 | |
145 void UpdateTextures() { | |
146 DebugScopedSetImplThreadAndMainThreadBlocked | |
147 impl_thread_and_main_thread_blocked(proxy_); | |
148 DCHECK(queue_); | |
149 scoped_ptr<ResourceUpdateController> update_controller = | |
150 ResourceUpdateController::Create(nullptr, | |
151 proxy_->ImplThreadTaskRunner(), | |
152 queue_.Pass(), | |
153 resource_provider_.get()); | |
154 update_controller->Finalize(); | |
155 queue_ = make_scoped_ptr(new ResourceUpdateQueue); | |
156 } | |
157 | |
158 void LayerPushPropertiesTo(FakeTiledLayer* layer, | |
159 FakeTiledLayerImpl* layer_impl) { | |
160 DebugScopedSetImplThreadAndMainThreadBlocked | |
161 impl_thread_and_main_thread_blocked(proxy_); | |
162 layer->PushPropertiesTo(layer_impl); | |
163 layer->ResetNumDependentsNeedPushProperties(); | |
164 } | |
165 | |
166 void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) { | |
167 DebugScopedSetMainThread main_thread(proxy_); | |
168 layer->Update(queue_.get(), occluded); | |
169 } | |
170 | |
171 void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) { | |
172 if (occlusion_) | |
173 occlusion_->SetRenderTarget(layer_tree_host_->root_layer()); | |
174 | |
175 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( | |
176 layer_tree_host_->root_layer(), | |
177 layer_tree_host_->device_viewport_size(), | |
178 render_surface_layer_list); | |
179 inputs.device_scale_factor = layer_tree_host_->device_scale_factor(); | |
180 inputs.max_texture_size = | |
181 layer_tree_host_->GetRendererCapabilities().max_texture_size; | |
182 inputs.can_adjust_raster_scales = true; | |
183 LayerTreeHostCommon::CalculateDrawProperties(&inputs); | |
184 } | |
185 | |
186 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, | |
187 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) { | |
188 scoped_refptr<FakeTiledLayer> layer2; | |
189 scoped_ptr<FakeTiledLayerImpl> layer_impl2; | |
190 return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); | |
191 } | |
192 | |
193 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, | |
194 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1, | |
195 const scoped_refptr<FakeTiledLayer>& layer2, | |
196 const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) { | |
197 // Get textures | |
198 resource_manager_->ClearPriorities(); | |
199 if (layer1.get()) | |
200 layer1->SetTexturePriorities(priority_calculator_); | |
201 if (layer2.get()) | |
202 layer2->SetTexturePriorities(priority_calculator_); | |
203 resource_manager_->PrioritizeTextures(); | |
204 | |
205 // Save paint properties | |
206 if (layer1.get()) | |
207 layer1->SavePaintProperties(); | |
208 if (layer2.get()) | |
209 layer2->SavePaintProperties(); | |
210 | |
211 // Update content | |
212 if (layer1.get()) | |
213 layer1->Update(queue_.get(), occlusion_); | |
214 if (layer2.get()) | |
215 layer2->Update(queue_.get(), occlusion_); | |
216 | |
217 bool needs_update = false; | |
218 if (layer1.get()) | |
219 needs_update |= layer1->NeedsIdlePaint(); | |
220 if (layer2.get()) | |
221 needs_update |= layer2->NeedsIdlePaint(); | |
222 | |
223 // Update textures and push. | |
224 UpdateTextures(); | |
225 if (layer1.get()) | |
226 LayerPushPropertiesTo(layer1.get(), layer_impl1.get()); | |
227 if (layer2.get()) | |
228 LayerPushPropertiesTo(layer2.get(), layer_impl2.get()); | |
229 | |
230 return needs_update; | |
231 } | |
232 | |
233 public: | |
234 Proxy* proxy_; | |
235 LayerTreeSettings settings_; | |
236 FakeOutputSurfaceClient output_surface_client_; | |
237 scoped_ptr<OutputSurface> output_surface_; | |
238 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; | |
239 scoped_ptr<ResourceProvider> resource_provider_; | |
240 scoped_ptr<ResourceUpdateQueue> queue_; | |
241 PriorityCalculator priority_calculator_; | |
242 base::Thread impl_thread_; | |
243 SynchronousOutputSurfaceClient synchonous_output_surface_client_; | |
244 scoped_ptr<LayerTreeHost> layer_tree_host_; | |
245 scoped_ptr<FakeLayerTreeHostImpl> host_impl_; | |
246 scoped_ptr<PrioritizedResourceManager> resource_manager_; | |
247 TestOcclusionTracker* occlusion_; | |
248 }; | |
249 | |
250 TEST_F(TiledLayerTest, PushDirtyTiles) { | |
251 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); | |
252 | |
253 scoped_refptr<FakeTiledLayer> layer = | |
254 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
255 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
256 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
257 RenderSurfaceLayerList render_surface_layer_list; | |
258 | |
259 layer_tree_host_->root_layer()->AddChild(layer); | |
260 | |
261 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
262 layer->SetBounds(gfx::Size(100, 200)); | |
263 CalcDrawProps(&render_surface_layer_list); | |
264 UpdateAndPush(layer, layer_impl); | |
265 | |
266 // We should have both tiles on the impl side. | |
267 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
268 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
269 | |
270 // Invalidates both tiles, but then only update one of them. | |
271 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200)); | |
272 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); | |
273 UpdateAndPush(layer, layer_impl); | |
274 | |
275 // We should only have the first tile since the other tile was invalidated but | |
276 // not painted. | |
277 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
278 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
279 } | |
280 | |
281 TEST_F(TiledLayerTest, Scale) { | |
282 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); | |
283 | |
284 layer_tree_host_->SetDeviceScaleFactor(1.5); | |
285 | |
286 scoped_refptr<FakeTiledLayer> layer = | |
287 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
288 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
289 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
290 RenderSurfaceLayerList render_surface_layer_list; | |
291 | |
292 layer_tree_host_->root_layer()->AddChild(layer); | |
293 | |
294 layer->SetBounds(gfx::Size(100, 200)); | |
295 CalcDrawProps(&render_surface_layer_list); | |
296 | |
297 // Change the width so that it doesn't divide cleanly by the scale. | |
298 layer->SetBounds(gfx::Size(101, 200)); | |
299 UpdateAndPush(layer, layer_impl); | |
300 | |
301 EXPECT_EQ(1.5, layer->fake_layer_updater()->last_contents_width_scale()); | |
302 } | |
303 | |
304 TEST_F(TiledLayerTest, PushOccludedDirtyTiles) { | |
305 scoped_refptr<FakeTiledLayer> layer = | |
306 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
307 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
308 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
309 TestOcclusionTracker occluded; | |
310 occlusion_ = &occluded; | |
311 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); | |
312 | |
313 layer_tree_host_->root_layer()->AddChild(layer); | |
314 | |
315 { | |
316 RenderSurfaceLayerList render_surface_layer_list; | |
317 | |
318 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
319 layer->SetBounds(gfx::Size(100, 200)); | |
320 CalcDrawProps(&render_surface_layer_list); | |
321 UpdateAndPush(layer, layer_impl); | |
322 | |
323 // We should have both tiles on the impl side. | |
324 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
325 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
326 } | |
327 | |
328 { | |
329 RenderSurfaceLayerList render_surface_layer_list; | |
330 | |
331 // Invalidates part of the top tile... | |
332 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); | |
333 // ....but the area is occluded. | |
334 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50))); | |
335 CalcDrawProps(&render_surface_layer_list); | |
336 UpdateAndPush(layer, layer_impl); | |
337 | |
338 // We should still have both tiles, as part of the top tile is still | |
339 // unoccluded. | |
340 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
341 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
342 } | |
343 } | |
344 | |
345 TEST_F(TiledLayerTest, PushDeletedTiles) { | |
346 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); | |
347 | |
348 scoped_refptr<FakeTiledLayer> layer = | |
349 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
350 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
351 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
352 RenderSurfaceLayerList render_surface_layer_list; | |
353 | |
354 layer_tree_host_->root_layer()->AddChild(layer); | |
355 | |
356 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
357 layer->SetBounds(gfx::Size(100, 200)); | |
358 CalcDrawProps(&render_surface_layer_list); | |
359 UpdateAndPush(layer, layer_impl); | |
360 | |
361 // We should have both tiles on the impl side. | |
362 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
363 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
364 | |
365 resource_manager_->ClearPriorities(); | |
366 ResourceManagerClearAllMemory(resource_manager_.get(), | |
367 resource_provider_.get()); | |
368 resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024); | |
369 | |
370 // This should drop the tiles on the impl thread. | |
371 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
372 | |
373 // We should now have no textures on the impl thread. | |
374 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
375 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
376 | |
377 // This should recreate and update one of the deleted textures. | |
378 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); | |
379 UpdateAndPush(layer, layer_impl); | |
380 | |
381 // We should have one tiles on the impl side. | |
382 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
383 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
384 } | |
385 | |
386 TEST_F(TiledLayerTest, PushIdlePaintTiles) { | |
387 scoped_refptr<FakeTiledLayer> layer = | |
388 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
389 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
390 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
391 RenderSurfaceLayerList render_surface_layer_list; | |
392 | |
393 layer_tree_host_->root_layer()->AddChild(layer); | |
394 | |
395 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the | |
396 // center. This paints 1 visible of the 25 invalid tiles. | |
397 layer->SetBounds(gfx::Size(500, 500)); | |
398 CalcDrawProps(&render_surface_layer_list); | |
399 layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100); | |
400 bool needs_update = UpdateAndPush(layer, layer_impl); | |
401 // We should need idle-painting for surrounding tiles. | |
402 EXPECT_TRUE(needs_update); | |
403 | |
404 // We should have one tile on the impl side. | |
405 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2)); | |
406 | |
407 // For the next four updates, we should detect we still need idle painting. | |
408 for (int i = 0; i < 4; i++) { | |
409 needs_update = UpdateAndPush(layer, layer_impl); | |
410 EXPECT_TRUE(needs_update); | |
411 } | |
412 | |
413 // We should always finish painting eventually. | |
414 for (int i = 0; i < 20; i++) | |
415 needs_update = UpdateAndPush(layer, layer_impl); | |
416 | |
417 // We should have pre-painted all of the surrounding tiles. | |
418 for (int i = 0; i < 5; i++) { | |
419 for (int j = 0; j < 5; j++) | |
420 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); | |
421 } | |
422 | |
423 EXPECT_FALSE(needs_update); | |
424 } | |
425 | |
426 TEST_F(TiledLayerTest, PredictivePainting) { | |
427 scoped_refptr<FakeTiledLayer> layer = | |
428 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
429 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
430 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
431 | |
432 layer_tree_host_->root_layer()->AddChild(layer); | |
433 | |
434 // Prepainting should occur in the scroll direction first, and the | |
435 // visible rect should be extruded only along the dominant axis. | |
436 gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0), | |
437 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10), | |
438 gfx::Vector2d(10, 20), | |
439 gfx::Vector2d(-20, 10) }; | |
440 // We should push all tiles that touch the extruded visible rect. | |
441 gfx::Rect pushed_visible_tiles[6] = { | |
442 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2), | |
443 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1) | |
444 }; | |
445 // The first pre-paint should also paint first in the scroll | |
446 // direction so we should find one additional tile in the scroll direction. | |
447 gfx::Rect pushed_prepaint_tiles[6] = { | |
448 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3), | |
449 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1) | |
450 }; | |
451 for (int k = 0; k < 6; k++) { | |
452 // The tile size is 100x100. Setup 5x5 tiles with one visible tile | |
453 // in the center. | |
454 gfx::Size bounds = gfx::Size(500, 500); | |
455 gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100); | |
456 gfx::Rect previous_visible_rect = | |
457 gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size()); | |
458 gfx::Rect next_visible_rect = | |
459 gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size()); | |
460 | |
461 // Setup. Use the previous_visible_rect to setup the prediction for next | |
462 // frame. | |
463 layer->SetBounds(bounds); | |
464 | |
465 RenderSurfaceLayerList render_surface_layer_list; | |
466 CalcDrawProps(&render_surface_layer_list); | |
467 layer->draw_properties().visible_content_rect = previous_visible_rect; | |
468 bool needs_update = UpdateAndPush(layer, layer_impl); | |
469 | |
470 // Invalidate and move the visible_rect in the scroll direction. | |
471 // Check that the correct tiles have been painted in the visible pass. | |
472 layer->SetNeedsDisplay(); | |
473 layer->draw_properties().visible_content_rect = visible_rect; | |
474 needs_update = UpdateAndPush(layer, layer_impl); | |
475 for (int i = 0; i < 5; i++) { | |
476 for (int j = 0; j < 5; j++) | |
477 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), | |
478 pushed_visible_tiles[k].Contains(i, j)); | |
479 } | |
480 | |
481 // Move the transform in the same direction without invalidating. | |
482 // Check that non-visible pre-painting occured in the correct direction. | |
483 // Ignore diagonal scrolls here (k > 3) as these have new visible content | |
484 // now. | |
485 if (k <= 3) { | |
486 layer->draw_properties().visible_content_rect = next_visible_rect; | |
487 needs_update = UpdateAndPush(layer, layer_impl); | |
488 for (int i = 0; i < 5; i++) { | |
489 for (int j = 0; j < 5; j++) | |
490 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), | |
491 pushed_prepaint_tiles[k].Contains(i, j)); | |
492 } | |
493 } | |
494 | |
495 // We should always finish painting eventually. | |
496 for (int i = 0; i < 20; i++) | |
497 needs_update = UpdateAndPush(layer, layer_impl); | |
498 EXPECT_FALSE(needs_update); | |
499 } | |
500 } | |
501 | |
502 TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) { | |
503 // Start with 2mb of memory, but the test is going to try to use just more | |
504 // than 1mb, so we reduce to 1mb later. | |
505 resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024); | |
506 scoped_refptr<FakeTiledLayer> layer1 = | |
507 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
508 scoped_ptr<FakeTiledLayerImpl> layer_impl1 = | |
509 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
510 scoped_refptr<FakeTiledLayer> layer2 = | |
511 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
512 scoped_ptr<FakeTiledLayerImpl> layer_impl2 = | |
513 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); | |
514 RenderSurfaceLayerList render_surface_layer_list; | |
515 | |
516 layer_tree_host_->root_layer()->AddChild(layer1); | |
517 layer_tree_host_->root_layer()->AddChild(layer2); | |
518 | |
519 // For this test we have two layers. layer1 exhausts most texture memory, | |
520 // leaving room for 2 more tiles from layer2, but not all three tiles. First | |
521 // we paint layer1, and one tile from layer2. Then when we idle paint layer2, | |
522 // we will fail on the third tile of layer2, and this should not leave the | |
523 // second tile in a bad state. | |
524 | |
525 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough | |
526 // for 2 tiles only in the other layer. | |
527 gfx::Rect layer1_rect(0, 0, 100, 2400); | |
528 | |
529 // This requires 4*30000 bytes of memory. | |
530 gfx::Rect layer2_rect(0, 0, 100, 300); | |
531 | |
532 // Paint a single tile in layer2 so that it will idle paint. | |
533 layer1->SetBounds(layer1_rect.size()); | |
534 layer2->SetBounds(layer2_rect.size()); | |
535 CalcDrawProps(&render_surface_layer_list); | |
536 layer1->draw_properties().visible_content_rect = layer1_rect; | |
537 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); | |
538 bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); | |
539 // We should need idle-painting for both remaining tiles in layer2. | |
540 EXPECT_TRUE(needs_update); | |
541 | |
542 // Reduce our memory limits to 1mb. | |
543 resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024); | |
544 | |
545 // Now idle paint layer2. We are going to run out of memory though! | |
546 // Oh well, commit the frame and push. | |
547 for (int i = 0; i < 4; i++) { | |
548 needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); | |
549 } | |
550 | |
551 // Sanity check, we should have textures for the big layer. | |
552 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0)); | |
553 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23)); | |
554 | |
555 // We should only have the first two tiles from layer2 since | |
556 // it failed to idle update the last tile. | |
557 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); | |
558 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); | |
559 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); | |
560 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); | |
561 | |
562 EXPECT_FALSE(needs_update); | |
563 EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2)); | |
564 } | |
565 | |
566 TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) { | |
567 scoped_refptr<FakeTiledLayer> layer = | |
568 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
569 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
570 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
571 RenderSurfaceLayerList render_surface_layer_list; | |
572 TestOcclusionTracker occluded; | |
573 occlusion_ = &occluded; | |
574 | |
575 layer_tree_host_->root_layer()->AddChild(layer); | |
576 | |
577 // The tile size is 100x100, so this invalidates one occluded tile, culls it | |
578 // during paint, but prepaints it. | |
579 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100))); | |
580 | |
581 layer->SetBounds(gfx::Size(100, 100)); | |
582 CalcDrawProps(&render_surface_layer_list); | |
583 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); | |
584 UpdateAndPush(layer, layer_impl); | |
585 | |
586 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
587 } | |
588 | |
589 TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) { | |
590 scoped_refptr<FakeTiledLayer> layer = | |
591 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
592 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
593 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
594 RenderSurfaceLayerList render_surface_layer_list; | |
595 | |
596 layer_tree_host_->root_layer()->AddChild(layer); | |
597 | |
598 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
599 // However, during the paint, we invalidate one of the tiles. This should | |
600 // not prevent the tile from being pushed. | |
601 layer->fake_layer_updater()->SetRectToInvalidate( | |
602 gfx::Rect(0, 50, 100, 50), layer.get()); | |
603 layer->SetBounds(gfx::Size(100, 200)); | |
604 CalcDrawProps(&render_surface_layer_list); | |
605 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
606 UpdateAndPush(layer, layer_impl); | |
607 | |
608 // We should have both tiles on the impl side. | |
609 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
610 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
611 } | |
612 | |
613 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) { | |
614 scoped_refptr<FakeTiledLayer> layer1 = | |
615 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
616 scoped_refptr<FakeTiledLayer> layer2 = | |
617 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
618 scoped_ptr<FakeTiledLayerImpl> layer1_impl = | |
619 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
620 scoped_ptr<FakeTiledLayerImpl> layer2_impl = | |
621 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); | |
622 RenderSurfaceLayerList render_surface_layer_list; | |
623 | |
624 layer_tree_host_->root_layer()->AddChild(layer1); | |
625 layer_tree_host_->root_layer()->AddChild(layer2); | |
626 | |
627 // Invalidate a tile on layer1, during update of layer 2. | |
628 layer2->fake_layer_updater()->SetRectToInvalidate( | |
629 gfx::Rect(0, 50, 100, 50), layer1.get()); | |
630 layer1->SetBounds(gfx::Size(100, 200)); | |
631 layer2->SetBounds(gfx::Size(100, 200)); | |
632 CalcDrawProps(&render_surface_layer_list); | |
633 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
634 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
635 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); | |
636 | |
637 // We should have both tiles on the impl side for all layers. | |
638 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); | |
639 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); | |
640 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); | |
641 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); | |
642 } | |
643 | |
644 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) { | |
645 scoped_refptr<FakeTiledLayer> layer1 = | |
646 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
647 scoped_refptr<FakeTiledLayer> layer2 = | |
648 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
649 scoped_ptr<FakeTiledLayerImpl> layer1_impl = | |
650 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
651 scoped_ptr<FakeTiledLayerImpl> layer2_impl = | |
652 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); | |
653 RenderSurfaceLayerList render_surface_layer_list; | |
654 | |
655 layer_tree_host_->root_layer()->AddChild(layer1); | |
656 layer_tree_host_->root_layer()->AddChild(layer2); | |
657 | |
658 layer1->fake_layer_updater()->SetRectToInvalidate( | |
659 gfx::Rect(0, 50, 100, 50), layer2.get()); | |
660 layer1->SetBounds(gfx::Size(100, 200)); | |
661 layer2->SetBounds(gfx::Size(100, 200)); | |
662 CalcDrawProps(&render_surface_layer_list); | |
663 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
664 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
665 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); | |
666 | |
667 // We should have both tiles on the impl side for all layers. | |
668 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); | |
669 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); | |
670 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); | |
671 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); | |
672 } | |
673 | |
674 TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) { | |
675 // Create a LayerTreeHost that has the right viewportsize, | |
676 // so the layer is considered small enough. | |
677 bool run_out_of_memory[2] = { false, true }; | |
678 for (int i = 0; i < 2; i++) { | |
679 // Create a layer with 5x5 tiles, with 4x4 size viewport. | |
680 int viewport_width = 4 * FakeTiledLayer::tile_size().width(); | |
681 int viewport_height = 4 * FakeTiledLayer::tile_size().width(); | |
682 int layer_width = 5 * FakeTiledLayer::tile_size().width(); | |
683 int layer_height = 5 * FakeTiledLayer::tile_size().height(); | |
684 int memory_for_layer = layer_width * layer_height * 4; | |
685 layer_tree_host_->SetViewportSize( | |
686 gfx::Size(viewport_width, viewport_height)); | |
687 | |
688 // Use 10x5 tiles to run out of memory. | |
689 if (run_out_of_memory[i]) | |
690 layer_width *= 2; | |
691 | |
692 resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer); | |
693 | |
694 scoped_refptr<FakeTiledLayer> layer = | |
695 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
696 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
697 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
698 RenderSurfaceLayerList render_surface_layer_list; | |
699 | |
700 layer_tree_host_->root_layer()->AddChild(layer); | |
701 | |
702 // Full size layer with half being visible. | |
703 layer->SetBounds(gfx::Size(layer_width, layer_height)); | |
704 gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height); | |
705 CalcDrawProps(&render_surface_layer_list); | |
706 | |
707 // Pretend the layer is animating. | |
708 layer->draw_properties().target_space_transform_is_animating = true; | |
709 layer->draw_properties().visible_content_rect = visible_rect; | |
710 layer->SetLayerTreeHost(layer_tree_host_.get()); | |
711 | |
712 // The layer should paint its entire contents on the first paint | |
713 // if it is close to the viewport size and has the available memory. | |
714 layer->SetTexturePriorities(priority_calculator_); | |
715 resource_manager_->PrioritizeTextures(); | |
716 layer->SavePaintProperties(); | |
717 layer->Update(queue_.get(), nullptr); | |
718 UpdateTextures(); | |
719 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
720 | |
721 // We should have all the tiles for the small animated layer. | |
722 // We should still have the visible tiles when we didn't | |
723 // have enough memory for all the tiles. | |
724 if (!run_out_of_memory[i]) { | |
725 for (int i = 0; i < 5; ++i) { | |
726 for (int j = 0; j < 5; ++j) | |
727 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); | |
728 } | |
729 } else { | |
730 for (int i = 0; i < 10; ++i) { | |
731 for (int j = 0; j < 5; ++j) | |
732 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5); | |
733 } | |
734 } | |
735 | |
736 layer->RemoveFromParent(); | |
737 } | |
738 } | |
739 | |
740 TEST_F(TiledLayerTest, IdlePaintOutOfMemory) { | |
741 scoped_refptr<FakeTiledLayer> layer = | |
742 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
743 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
744 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
745 RenderSurfaceLayerList render_surface_layer_list; | |
746 | |
747 layer_tree_host_->root_layer()->AddChild(layer); | |
748 | |
749 // We have enough memory for only the visible rect, so we will run out of | |
750 // memory in first idle paint. | |
751 int memory_limit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel. | |
752 resource_manager_->SetMaxMemoryLimitBytes(memory_limit); | |
753 | |
754 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
755 bool needs_update = false; | |
756 layer->SetBounds(gfx::Size(300, 300)); | |
757 CalcDrawProps(&render_surface_layer_list); | |
758 layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100); | |
759 for (int i = 0; i < 2; i++) | |
760 needs_update = UpdateAndPush(layer, layer_impl); | |
761 | |
762 // Idle-painting should see no more priority tiles for painting. | |
763 EXPECT_FALSE(needs_update); | |
764 | |
765 // We should have one tile on the impl side. | |
766 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); | |
767 } | |
768 | |
769 TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) { | |
770 scoped_refptr<FakeTiledLayer> layer = | |
771 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
772 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
773 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
774 | |
775 layer_tree_host_->root_layer()->AddChild(layer); | |
776 | |
777 bool animating[2] = { false, true }; | |
778 for (int i = 0; i < 2; i++) { | |
779 // Pretend the layer is animating. | |
780 layer->draw_properties().target_space_transform_is_animating = animating[i]; | |
781 | |
782 // The layer's bounds are empty. | |
783 // Empty layers don't paint or idle-paint. | |
784 layer->SetBounds(gfx::Size()); | |
785 | |
786 RenderSurfaceLayerList render_surface_layer_list; | |
787 CalcDrawProps(&render_surface_layer_list); | |
788 layer->draw_properties().visible_content_rect = gfx::Rect(); | |
789 bool needs_update = UpdateAndPush(layer, layer_impl); | |
790 | |
791 // Empty layers don't have tiles. | |
792 EXPECT_EQ(0u, layer->NumPaintedTiles()); | |
793 | |
794 // Empty layers don't need prepaint. | |
795 EXPECT_FALSE(needs_update); | |
796 | |
797 // Empty layers don't have tiles. | |
798 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
799 } | |
800 } | |
801 | |
802 TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) { | |
803 scoped_refptr<FakeTiledLayer> layer = | |
804 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
805 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
806 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
807 | |
808 // Alternate between not visible and visible. | |
809 gfx::Rect v(0, 0, 100, 100); | |
810 gfx::Rect nv(0, 0, 0, 0); | |
811 gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv }; | |
812 bool invalidate[10] = { true, true, true, true, true, true, true, true, false, | |
813 false }; | |
814 | |
815 // We should not have any tiles except for when the layer was visible | |
816 // or after the layer was visible and we didn't invalidate. | |
817 bool have_tile[10] = { false, false, true, true, false, false, true, true, | |
818 true, true }; | |
819 | |
820 layer_tree_host_->root_layer()->AddChild(layer); | |
821 | |
822 for (int i = 0; i < 10; i++) { | |
823 layer->SetBounds(gfx::Size(100, 100)); | |
824 | |
825 RenderSurfaceLayerList render_surface_layer_list; | |
826 CalcDrawProps(&render_surface_layer_list); | |
827 layer->draw_properties().visible_content_rect = visible_rect[i]; | |
828 | |
829 if (invalidate[i]) | |
830 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100)); | |
831 bool needs_update = UpdateAndPush(layer, layer_impl); | |
832 | |
833 // We should never signal idle paint, as we painted the entire layer | |
834 // or the layer was not visible. | |
835 EXPECT_FALSE(needs_update); | |
836 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]); | |
837 } | |
838 } | |
839 | |
840 TEST_F(TiledLayerTest, InvalidateFromPrepare) { | |
841 scoped_refptr<FakeTiledLayer> layer = | |
842 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
843 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
844 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
845 RenderSurfaceLayerList render_surface_layer_list; | |
846 | |
847 layer_tree_host_->root_layer()->AddChild(layer); | |
848 | |
849 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
850 layer->SetBounds(gfx::Size(100, 200)); | |
851 CalcDrawProps(&render_surface_layer_list); | |
852 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); | |
853 UpdateAndPush(layer, layer_impl); | |
854 | |
855 // We should have both tiles on the impl side. | |
856 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
857 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
858 | |
859 layer->fake_layer_updater()->ClearPrepareCount(); | |
860 // Invoke update again. As the layer is valid update shouldn't be invoked on | |
861 // the LayerUpdater. | |
862 UpdateAndPush(layer, layer_impl); | |
863 EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count()); | |
864 | |
865 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from | |
866 // update. | |
867 layer->fake_layer_updater()->SetRectToInvalidate( | |
868 gfx::Rect(25, 25, 50, 50), layer.get()); | |
869 layer->fake_layer_updater()->ClearPrepareCount(); | |
870 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); | |
871 UpdateAndPush(layer, layer_impl); | |
872 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); | |
873 layer->fake_layer_updater()->ClearPrepareCount(); | |
874 | |
875 // The layer should still be invalid as update invoked invalidate. | |
876 UpdateAndPush(layer, layer_impl); // visible | |
877 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); | |
878 } | |
879 | |
880 TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) { | |
881 // The update rect (that indicates what was actually painted) should be in | |
882 // layer space, not the content space. | |
883 scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr( | |
884 new FakeTiledLayerWithScaledBounds(resource_manager_.get())); | |
885 | |
886 layer_tree_host_->root_layer()->AddChild(layer); | |
887 | |
888 gfx::Rect layer_bounds(0, 0, 300, 200); | |
889 gfx::Rect content_bounds(0, 0, 150, 250); | |
890 | |
891 layer->SetBounds(layer_bounds.size()); | |
892 layer->SetContentBounds(content_bounds.size()); | |
893 layer->draw_properties().visible_content_rect = content_bounds; | |
894 layer->draw_properties().contents_scale_x = .5f; | |
895 layer->draw_properties().contents_scale_y = 1.25f; | |
896 | |
897 // On first update, the update_rect includes all tiles, even beyond the | |
898 // boundaries of the layer. | |
899 // However, it should still be in layer space, not content space. | |
900 layer->InvalidateContentRect(content_bounds); | |
901 | |
902 layer->SetTexturePriorities(priority_calculator_); | |
903 resource_manager_->PrioritizeTextures(); | |
904 layer->SavePaintProperties(); | |
905 layer->Update(queue_.get(), nullptr); | |
906 | |
907 // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240. | |
908 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer->update_rect()); | |
909 UpdateTextures(); | |
910 | |
911 // After the tiles are updated once, another invalidate only needs to update | |
912 // the bounds of the layer. | |
913 layer->SetTexturePriorities(priority_calculator_); | |
914 resource_manager_->PrioritizeTextures(); | |
915 layer->InvalidateContentRect(content_bounds); | |
916 layer->SavePaintProperties(); | |
917 layer->Update(queue_.get(), nullptr); | |
918 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect()); | |
919 UpdateTextures(); | |
920 | |
921 // Partial re-paint should also be represented by the update rect in layer | |
922 // space, not content space. | |
923 gfx::Rect partial_damage(30, 100, 10, 10); | |
924 layer->InvalidateContentRect(partial_damage); | |
925 layer->SetTexturePriorities(priority_calculator_); | |
926 resource_manager_->PrioritizeTextures(); | |
927 layer->SavePaintProperties(); | |
928 layer->Update(queue_.get(), nullptr); | |
929 EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer->update_rect()); | |
930 } | |
931 | |
932 TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) { | |
933 scoped_refptr<FakeTiledLayer> layer = | |
934 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
935 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
936 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
937 RenderSurfaceLayerList render_surface_layer_list; | |
938 | |
939 layer_tree_host_->root_layer()->AddChild(layer); | |
940 | |
941 // Create a layer with one tile. | |
942 layer->SetBounds(gfx::Size(100, 100)); | |
943 CalcDrawProps(&render_surface_layer_list); | |
944 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); | |
945 layer->Update(queue_.get(), nullptr); | |
946 UpdateTextures(); | |
947 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), | |
948 layer->last_needs_display_rect()); | |
949 | |
950 // Push the tiles to the impl side and check that there is exactly one. | |
951 layer->SetTexturePriorities(priority_calculator_); | |
952 resource_manager_->PrioritizeTextures(); | |
953 layer->SavePaintProperties(); | |
954 layer->Update(queue_.get(), nullptr); | |
955 UpdateTextures(); | |
956 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
957 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
958 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
959 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); | |
960 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); | |
961 | |
962 layer->SetNeedsDisplayRect(gfx::Rect()); | |
963 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect()); | |
964 | |
965 // Change the contents scale. | |
966 layer->UpdateContentsScale(2.f); | |
967 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200); | |
968 | |
969 // The impl side should get 2x2 tiles now. | |
970 layer->SetTexturePriorities(priority_calculator_); | |
971 resource_manager_->PrioritizeTextures(); | |
972 layer->SavePaintProperties(); | |
973 layer->Update(queue_.get(), nullptr); | |
974 UpdateTextures(); | |
975 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
976 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
977 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
978 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0)); | |
979 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); | |
980 | |
981 // Verify that changing the contents scale caused invalidation, and | |
982 // that the layer-space rectangle requiring painting is not scaled. | |
983 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), | |
984 layer->last_needs_display_rect()); | |
985 | |
986 // Invalidate the entire layer again, but do not paint. All tiles should be | |
987 // gone now from the impl side. | |
988 layer->SetNeedsDisplay(); | |
989 layer->SetTexturePriorities(priority_calculator_); | |
990 resource_manager_->PrioritizeTextures(); | |
991 | |
992 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
993 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); | |
994 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); | |
995 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); | |
996 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); | |
997 } | |
998 | |
999 TEST_F(TiledLayerTest, SkipsDrawGetsReset) { | |
1000 // Create two 300 x 300 tiled layers. | |
1001 gfx::Size content_bounds(300, 300); | |
1002 gfx::Rect content_rect(content_bounds); | |
1003 | |
1004 // We have enough memory for only one of the two layers. | |
1005 int memory_limit = 4 * 300 * 300; // 4 bytes per pixel. | |
1006 | |
1007 scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr( | |
1008 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1009 scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr( | |
1010 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1011 root_layer->AddChild(child_layer); | |
1012 | |
1013 root_layer->SetBounds(content_bounds); | |
1014 root_layer->draw_properties().visible_content_rect = content_rect; | |
1015 root_layer->SetPosition(gfx::PointF(0, 0)); | |
1016 child_layer->SetBounds(content_bounds); | |
1017 child_layer->draw_properties().visible_content_rect = content_rect; | |
1018 child_layer->SetPosition(gfx::PointF(0, 0)); | |
1019 root_layer->InvalidateContentRect(content_rect); | |
1020 child_layer->InvalidateContentRect(content_rect); | |
1021 | |
1022 layer_tree_host_->SetRootLayer(root_layer); | |
1023 layer_tree_host_->SetViewportSize(gfx::Size(300, 300)); | |
1024 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( | |
1025 memory_limit); | |
1026 | |
1027 layer_tree_host_->UpdateLayers(queue_.get()); | |
1028 | |
1029 // We'll skip the root layer. | |
1030 EXPECT_TRUE(root_layer->SkipsDraw()); | |
1031 EXPECT_FALSE(child_layer->SkipsDraw()); | |
1032 | |
1033 layer_tree_host_->CommitComplete(); | |
1034 | |
1035 // Remove the child layer. | |
1036 root_layer->RemoveAllChildren(); | |
1037 | |
1038 layer_tree_host_->UpdateLayers(queue_.get()); | |
1039 EXPECT_FALSE(root_layer->SkipsDraw()); | |
1040 | |
1041 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), | |
1042 resource_provider_.get()); | |
1043 layer_tree_host_->SetRootLayer(nullptr); | |
1044 } | |
1045 | |
1046 TEST_F(TiledLayerTest, ResizeToSmaller) { | |
1047 scoped_refptr<FakeTiledLayer> layer = | |
1048 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1049 | |
1050 layer_tree_host_->root_layer()->AddChild(layer); | |
1051 | |
1052 layer->SetBounds(gfx::Size(700, 700)); | |
1053 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); | |
1054 layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700)); | |
1055 | |
1056 layer->SetTexturePriorities(priority_calculator_); | |
1057 resource_manager_->PrioritizeTextures(); | |
1058 layer->SavePaintProperties(); | |
1059 layer->Update(queue_.get(), nullptr); | |
1060 | |
1061 layer->SetBounds(gfx::Size(200, 200)); | |
1062 layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200)); | |
1063 } | |
1064 | |
1065 TEST_F(TiledLayerTest, HugeLayerUpdateCrash) { | |
1066 scoped_refptr<FakeTiledLayer> layer = | |
1067 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1068 | |
1069 layer_tree_host_->root_layer()->AddChild(layer); | |
1070 | |
1071 int size = 1 << 30; | |
1072 layer->SetBounds(gfx::Size(size, size)); | |
1073 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); | |
1074 layer->InvalidateContentRect(gfx::Rect(0, 0, size, size)); | |
1075 | |
1076 // Ensure no crash for bounds where size * size would overflow an int. | |
1077 layer->SetTexturePriorities(priority_calculator_); | |
1078 resource_manager_->PrioritizeTextures(); | |
1079 layer->SavePaintProperties(); | |
1080 layer->Update(queue_.get(), nullptr); | |
1081 } | |
1082 | |
1083 class TiledLayerPartialUpdateTest : public TiledLayerTest { | |
1084 public: | |
1085 TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; } | |
1086 }; | |
1087 | |
1088 TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) { | |
1089 // Create one 300 x 200 tiled layer with 3 x 2 tiles. | |
1090 gfx::Size content_bounds(300, 200); | |
1091 gfx::Rect content_rect(content_bounds); | |
1092 | |
1093 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr( | |
1094 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1095 layer->SetBounds(content_bounds); | |
1096 layer->SetPosition(gfx::PointF(0, 0)); | |
1097 layer->draw_properties().visible_content_rect = content_rect; | |
1098 layer->InvalidateContentRect(content_rect); | |
1099 | |
1100 layer_tree_host_->SetRootLayer(layer); | |
1101 layer_tree_host_->SetViewportSize(gfx::Size(300, 200)); | |
1102 | |
1103 // Full update of all 6 tiles. | |
1104 layer_tree_host_->UpdateLayers(queue_.get()); | |
1105 { | |
1106 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1107 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1108 EXPECT_EQ(6u, queue_->FullUploadSize()); | |
1109 EXPECT_EQ(0u, queue_->PartialUploadSize()); | |
1110 UpdateTextures(); | |
1111 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); | |
1112 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1113 layer->fake_layer_updater()->ClearUpdateCount(); | |
1114 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1115 } | |
1116 layer_tree_host_->CommitComplete(); | |
1117 | |
1118 // Full update of 3 tiles and partial update of 3 tiles. | |
1119 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150)); | |
1120 layer_tree_host_->UpdateLayers(queue_.get()); | |
1121 { | |
1122 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1123 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1124 EXPECT_EQ(3u, queue_->FullUploadSize()); | |
1125 EXPECT_EQ(3u, queue_->PartialUploadSize()); | |
1126 UpdateTextures(); | |
1127 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); | |
1128 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1129 layer->fake_layer_updater()->ClearUpdateCount(); | |
1130 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1131 } | |
1132 layer_tree_host_->CommitComplete(); | |
1133 | |
1134 // Partial update of 6 tiles. | |
1135 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); | |
1136 { | |
1137 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1138 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1139 layer_tree_host_->UpdateLayers(queue_.get()); | |
1140 EXPECT_EQ(2u, queue_->FullUploadSize()); | |
1141 EXPECT_EQ(4u, queue_->PartialUploadSize()); | |
1142 UpdateTextures(); | |
1143 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); | |
1144 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1145 layer->fake_layer_updater()->ClearUpdateCount(); | |
1146 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1147 } | |
1148 layer_tree_host_->CommitComplete(); | |
1149 | |
1150 // Checkerboard all tiles. | |
1151 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200)); | |
1152 { | |
1153 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1154 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1155 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1156 } | |
1157 layer_tree_host_->CommitComplete(); | |
1158 | |
1159 // Partial update of 6 checkerboard tiles. | |
1160 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); | |
1161 { | |
1162 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1163 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1164 layer_tree_host_->UpdateLayers(queue_.get()); | |
1165 EXPECT_EQ(6u, queue_->FullUploadSize()); | |
1166 EXPECT_EQ(0u, queue_->PartialUploadSize()); | |
1167 UpdateTextures(); | |
1168 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); | |
1169 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1170 layer->fake_layer_updater()->ClearUpdateCount(); | |
1171 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1172 } | |
1173 layer_tree_host_->CommitComplete(); | |
1174 | |
1175 // Partial update of 4 tiles. | |
1176 layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100)); | |
1177 { | |
1178 scoped_ptr<FakeTiledLayerImpl> layer_impl = | |
1179 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); | |
1180 layer_tree_host_->UpdateLayers(queue_.get()); | |
1181 EXPECT_EQ(0u, queue_->FullUploadSize()); | |
1182 EXPECT_EQ(4u, queue_->PartialUploadSize()); | |
1183 UpdateTextures(); | |
1184 EXPECT_EQ(4, layer->fake_layer_updater()->update_count()); | |
1185 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1186 layer->fake_layer_updater()->ClearUpdateCount(); | |
1187 LayerPushPropertiesTo(layer.get(), layer_impl.get()); | |
1188 } | |
1189 layer_tree_host_->CommitComplete(); | |
1190 | |
1191 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), | |
1192 resource_provider_.get()); | |
1193 layer_tree_host_->SetRootLayer(nullptr); | |
1194 } | |
1195 | |
1196 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) { | |
1197 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); | |
1198 | |
1199 scoped_refptr<FakeTiledLayer> layer = | |
1200 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1201 RenderSurfaceLayerList render_surface_layer_list; | |
1202 | |
1203 layer_tree_host_->root_layer()->AddChild(layer); | |
1204 | |
1205 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
1206 layer->SetBounds(gfx::Size(100, 200)); | |
1207 CalcDrawProps(&render_surface_layer_list); | |
1208 | |
1209 layer->SetTexturePriorities(priority_calculator_); | |
1210 resource_manager_->PrioritizeTextures(); | |
1211 layer->SavePaintProperties(); | |
1212 layer->Update(queue_.get(), nullptr); | |
1213 EXPECT_EQ(2, layer->fake_layer_updater()->update_count()); | |
1214 } | |
1215 | |
1216 TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { | |
1217 scoped_refptr<FakeTiledLayer> layer = | |
1218 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1219 RenderSurfaceLayerList render_surface_layer_list; | |
1220 TestOcclusionTracker occluded; | |
1221 occlusion_ = &occluded; | |
1222 | |
1223 layer_tree_host_->root_layer()->AddChild(layer); | |
1224 | |
1225 // The tile size is 100x100. | |
1226 | |
1227 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); | |
1228 layer->SetBounds(gfx::Size(600, 600)); | |
1229 CalcDrawProps(&render_surface_layer_list); | |
1230 | |
1231 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); | |
1232 layer->draw_properties().drawable_content_rect = | |
1233 gfx::Rect(layer->content_bounds()); | |
1234 layer->draw_properties().visible_content_rect = | |
1235 gfx::Rect(layer->content_bounds()); | |
1236 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1237 | |
1238 layer->SetTexturePriorities(priority_calculator_); | |
1239 resource_manager_->PrioritizeTextures(); | |
1240 layer->SavePaintProperties(); | |
1241 layer->Update(queue_.get(), &occluded); | |
1242 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); | |
1243 | |
1244 layer->fake_layer_updater()->ClearUpdateCount(); | |
1245 layer->SetTexturePriorities(priority_calculator_); | |
1246 resource_manager_->PrioritizeTextures(); | |
1247 | |
1248 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100))); | |
1249 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1250 layer->SavePaintProperties(); | |
1251 layer->Update(queue_.get(), &occluded); | |
1252 EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count()); | |
1253 | |
1254 layer->fake_layer_updater()->ClearUpdateCount(); | |
1255 layer->SetTexturePriorities(priority_calculator_); | |
1256 resource_manager_->PrioritizeTextures(); | |
1257 | |
1258 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100))); | |
1259 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1260 layer->SavePaintProperties(); | |
1261 layer->Update(queue_.get(), &occluded); | |
1262 EXPECT_EQ(36, layer->fake_layer_updater()->update_count()); | |
1263 } | |
1264 | |
1265 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { | |
1266 scoped_refptr<FakeTiledLayer> layer = | |
1267 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1268 RenderSurfaceLayerList render_surface_layer_list; | |
1269 TestOcclusionTracker occluded; | |
1270 occlusion_ = &occluded; | |
1271 | |
1272 layer_tree_host_->root_layer()->AddChild(layer); | |
1273 | |
1274 // The tile size is 100x100. | |
1275 | |
1276 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); | |
1277 layer->SetBounds(gfx::Size(600, 600)); | |
1278 CalcDrawProps(&render_surface_layer_list); | |
1279 | |
1280 // The partially occluded tiles (by the 150 occlusion height) are visible | |
1281 // beyond the occlusion, so not culled. | |
1282 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); | |
1283 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360); | |
1284 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360); | |
1285 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1286 | |
1287 layer->SetTexturePriorities(priority_calculator_); | |
1288 resource_manager_->PrioritizeTextures(); | |
1289 layer->SavePaintProperties(); | |
1290 layer->Update(queue_.get(), &occluded); | |
1291 EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count()); | |
1292 | |
1293 layer->fake_layer_updater()->ClearUpdateCount(); | |
1294 | |
1295 // Now the visible region stops at the edge of the occlusion so the partly | |
1296 // visible tiles become fully occluded. | |
1297 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); | |
1298 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350); | |
1299 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350); | |
1300 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1301 layer->SetTexturePriorities(priority_calculator_); | |
1302 resource_manager_->PrioritizeTextures(); | |
1303 layer->SavePaintProperties(); | |
1304 layer->Update(queue_.get(), &occluded); | |
1305 EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); | |
1306 | |
1307 layer->fake_layer_updater()->ClearUpdateCount(); | |
1308 | |
1309 // Now the visible region is even smaller than the occlusion, it should have | |
1310 // the same result. | |
1311 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); | |
1312 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340); | |
1313 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340); | |
1314 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1315 layer->SetTexturePriorities(priority_calculator_); | |
1316 resource_manager_->PrioritizeTextures(); | |
1317 layer->SavePaintProperties(); | |
1318 layer->Update(queue_.get(), &occluded); | |
1319 EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); | |
1320 } | |
1321 | |
1322 TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) { | |
1323 scoped_refptr<FakeTiledLayer> layer = | |
1324 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1325 RenderSurfaceLayerList render_surface_layer_list; | |
1326 TestOcclusionTracker occluded; | |
1327 occlusion_ = &occluded; | |
1328 | |
1329 layer_tree_host_->root_layer()->AddChild(layer); | |
1330 | |
1331 // The tile size is 100x100. | |
1332 | |
1333 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); | |
1334 layer->SetBounds(gfx::Size(600, 600)); | |
1335 CalcDrawProps(&render_surface_layer_list); | |
1336 | |
1337 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); | |
1338 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600); | |
1339 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600); | |
1340 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1341 layer->SetTexturePriorities(priority_calculator_); | |
1342 resource_manager_->PrioritizeTextures(); | |
1343 layer->SavePaintProperties(); | |
1344 layer->Update(queue_.get(), &occluded); | |
1345 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); | |
1346 UpdateTextures(); | |
1347 | |
1348 layer->fake_layer_updater()->ClearUpdateCount(); | |
1349 layer->SetTexturePriorities(priority_calculator_); | |
1350 resource_manager_->PrioritizeTextures(); | |
1351 layer->SavePaintProperties(); | |
1352 | |
1353 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted | |
1354 // now. | |
1355 layer->Update(queue_.get(), &occluded); | |
1356 EXPECT_EQ(3, layer->fake_layer_updater()->update_count()); | |
1357 } | |
1358 | |
1359 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) { | |
1360 scoped_refptr<FakeTiledLayer> layer = | |
1361 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); | |
1362 RenderSurfaceLayerList render_surface_layer_list; | |
1363 TestOcclusionTracker occluded; | |
1364 occlusion_ = &occluded; | |
1365 | |
1366 layer_tree_host_->root_layer()->AddChild(layer); | |
1367 | |
1368 // The tile size is 100x100. | |
1369 | |
1370 // This makes sure the painting works when the occluded region (in screen | |
1371 // space) is transformed differently than the layer. | |
1372 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); | |
1373 layer->SetBounds(gfx::Size(600, 600)); | |
1374 CalcDrawProps(&render_surface_layer_list); | |
1375 gfx::Transform screen_transform; | |
1376 screen_transform.Scale(0.5, 0.5); | |
1377 layer->draw_properties().screen_space_transform = screen_transform; | |
1378 layer->draw_properties().target_space_transform = screen_transform; | |
1379 | |
1380 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50))); | |
1381 layer->draw_properties().drawable_content_rect = | |
1382 gfx::Rect(layer->content_bounds()); | |
1383 layer->draw_properties().visible_content_rect = | |
1384 gfx::Rect(layer->content_bounds()); | |
1385 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1386 layer->SetTexturePriorities(priority_calculator_); | |
1387 resource_manager_->PrioritizeTextures(); | |
1388 layer->SavePaintProperties(); | |
1389 layer->Update(queue_.get(), &occluded); | |
1390 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); | |
1391 } | |
1392 | |
1393 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { | |
1394 scoped_refptr<FakeTiledLayer> layer = | |
1395 new FakeTiledLayer(resource_manager_.get()); | |
1396 RenderSurfaceLayerList render_surface_layer_list; | |
1397 TestOcclusionTracker occluded; | |
1398 occlusion_ = &occluded; | |
1399 | |
1400 scoped_refptr<FakeTiledLayer> scale_layer = | |
1401 new FakeTiledLayer(resource_manager_.get()); | |
1402 gfx::Transform scale_transform; | |
1403 scale_transform.Scale(2.0, 2.0); | |
1404 scale_layer->SetTransform(scale_transform); | |
1405 | |
1406 layer_tree_host_->root_layer()->AddChild(scale_layer); | |
1407 | |
1408 // The tile size is 100x100. | |
1409 | |
1410 // This makes sure the painting works when the content space is scaled to | |
1411 // a different layer space. | |
1412 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); | |
1413 layer->SetBounds(gfx::Size(300, 300)); | |
1414 scale_layer->AddChild(layer); | |
1415 CalcDrawProps(&render_surface_layer_list); | |
1416 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x()); | |
1417 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y()); | |
1418 EXPECT_EQ(gfx::Size(600, 600).ToString(), | |
1419 layer->content_bounds().ToString()); | |
1420 | |
1421 // No tiles are covered by the 300x50 occlusion. | |
1422 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50))); | |
1423 layer->draw_properties().drawable_content_rect = | |
1424 gfx::Rect(layer->bounds()); | |
1425 layer->draw_properties().visible_content_rect = | |
1426 gfx::Rect(layer->content_bounds()); | |
1427 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1428 layer->SetTexturePriorities(priority_calculator_); | |
1429 resource_manager_->PrioritizeTextures(); | |
1430 layer->SavePaintProperties(); | |
1431 layer->Update(queue_.get(), &occluded); | |
1432 int visible_tiles1 = 6 * 6; | |
1433 EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count()); | |
1434 | |
1435 layer->fake_layer_updater()->ClearUpdateCount(); | |
1436 | |
1437 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still. | |
1438 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); | |
1439 layer->draw_properties().drawable_content_rect = | |
1440 gfx::Rect(layer->bounds()); | |
1441 layer->draw_properties().visible_content_rect = | |
1442 gfx::Rect(layer->content_bounds()); | |
1443 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1444 layer->SetTexturePriorities(priority_calculator_); | |
1445 resource_manager_->PrioritizeTextures(); | |
1446 layer->SavePaintProperties(); | |
1447 layer->Update(queue_.get(), &occluded); | |
1448 int visible_tiles2 = 6 * 6 - 3; | |
1449 EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count()); | |
1450 | |
1451 layer->fake_layer_updater()->ClearUpdateCount(); | |
1452 | |
1453 // This makes sure content scaling and transforms work together. | |
1454 // When the tiles are scaled down by half, they are 50x50 each in the | |
1455 // screen. | |
1456 gfx::Transform screen_transform; | |
1457 screen_transform.Scale(0.5, 0.5); | |
1458 layer->draw_properties().screen_space_transform = screen_transform; | |
1459 layer->draw_properties().target_space_transform = screen_transform; | |
1460 | |
1461 // An occlusion of 150x100 will cover 3*2 = 6 tiles. | |
1462 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100))); | |
1463 | |
1464 gfx::Rect layer_bounds_rect(layer->bounds()); | |
1465 layer->draw_properties().drawable_content_rect = | |
1466 gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f); | |
1467 layer->draw_properties().visible_content_rect = | |
1468 gfx::Rect(layer->content_bounds()); | |
1469 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); | |
1470 layer->SetTexturePriorities(priority_calculator_); | |
1471 resource_manager_->PrioritizeTextures(); | |
1472 layer->SavePaintProperties(); | |
1473 layer->Update(queue_.get(), &occluded); | |
1474 int visible_tiles3 = 6 * 6 - 6; | |
1475 EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count()); | |
1476 } | |
1477 | |
1478 TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) { | |
1479 // Tile size is 100x100. | |
1480 gfx::Rect root_rect(0, 0, 300, 200); | |
1481 gfx::Rect child_rect(0, 0, 300, 100); | |
1482 gfx::Rect child2_rect(0, 100, 300, 100); | |
1483 | |
1484 scoped_refptr<FakeTiledLayer> root = make_scoped_refptr( | |
1485 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1486 scoped_refptr<Layer> surface = Layer::Create(); | |
1487 scoped_refptr<FakeTiledLayer> child = make_scoped_refptr( | |
1488 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1489 scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr( | |
1490 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); | |
1491 | |
1492 root->SetBounds(root_rect.size()); | |
1493 root->draw_properties().drawable_content_rect = root_rect; | |
1494 root->draw_properties().visible_content_rect = root_rect; | |
1495 root->AddChild(surface); | |
1496 | |
1497 surface->SetForceRenderSurface(true); | |
1498 surface->SetOpacity(0.5); | |
1499 surface->AddChild(child); | |
1500 surface->AddChild(child2); | |
1501 | |
1502 child->SetBounds(child_rect.size()); | |
1503 child->SetPosition(child_rect.origin()); | |
1504 child->draw_properties().visible_content_rect = child_rect; | |
1505 child->draw_properties().drawable_content_rect = root_rect; | |
1506 | |
1507 child2->SetBounds(child2_rect.size()); | |
1508 child2->SetPosition(child2_rect.origin()); | |
1509 child2->draw_properties().visible_content_rect = child2_rect; | |
1510 child2->draw_properties().drawable_content_rect = root_rect; | |
1511 | |
1512 layer_tree_host_->SetRootLayer(root); | |
1513 layer_tree_host_->SetViewportSize(root_rect.size()); | |
1514 | |
1515 // With a huge memory limit, all layers should update and push their textures. | |
1516 root->InvalidateContentRect(root_rect); | |
1517 child->InvalidateContentRect(child_rect); | |
1518 child2->InvalidateContentRect(child2_rect); | |
1519 layer_tree_host_->UpdateLayers(queue_.get()); | |
1520 { | |
1521 UpdateTextures(); | |
1522 EXPECT_EQ(6, root->fake_layer_updater()->update_count()); | |
1523 EXPECT_EQ(3, child->fake_layer_updater()->update_count()); | |
1524 EXPECT_EQ(3, child2->fake_layer_updater()->update_count()); | |
1525 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1526 | |
1527 root->fake_layer_updater()->ClearUpdateCount(); | |
1528 child->fake_layer_updater()->ClearUpdateCount(); | |
1529 child2->fake_layer_updater()->ClearUpdateCount(); | |
1530 | |
1531 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( | |
1532 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); | |
1533 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( | |
1534 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); | |
1535 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( | |
1536 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); | |
1537 LayerPushPropertiesTo(child2.get(), child2_impl.get()); | |
1538 LayerPushPropertiesTo(child.get(), child_impl.get()); | |
1539 LayerPushPropertiesTo(root.get(), root_impl.get()); | |
1540 | |
1541 for (unsigned i = 0; i < 3; ++i) { | |
1542 for (unsigned j = 0; j < 2; ++j) | |
1543 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); | |
1544 EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0)); | |
1545 EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0)); | |
1546 } | |
1547 } | |
1548 layer_tree_host_->CommitComplete(); | |
1549 | |
1550 // With a memory limit that includes only the root layer (3x2 tiles) and half | |
1551 // the surface that the child layers draw into, the child layers will not be | |
1552 // allocated. If the surface isn't accounted for, then one of the children | |
1553 // would fit within the memory limit. | |
1554 root->InvalidateContentRect(root_rect); | |
1555 child->InvalidateContentRect(child_rect); | |
1556 child2->InvalidateContentRect(child2_rect); | |
1557 | |
1558 size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4; | |
1559 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( | |
1560 memory_limit); | |
1561 layer_tree_host_->UpdateLayers(queue_.get()); | |
1562 { | |
1563 UpdateTextures(); | |
1564 EXPECT_EQ(6, root->fake_layer_updater()->update_count()); | |
1565 EXPECT_EQ(0, child->fake_layer_updater()->update_count()); | |
1566 EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); | |
1567 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1568 | |
1569 root->fake_layer_updater()->ClearUpdateCount(); | |
1570 child->fake_layer_updater()->ClearUpdateCount(); | |
1571 child2->fake_layer_updater()->ClearUpdateCount(); | |
1572 | |
1573 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( | |
1574 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); | |
1575 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( | |
1576 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); | |
1577 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( | |
1578 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); | |
1579 LayerPushPropertiesTo(child2.get(), child2_impl.get()); | |
1580 LayerPushPropertiesTo(child.get(), child_impl.get()); | |
1581 LayerPushPropertiesTo(root.get(), root_impl.get()); | |
1582 | |
1583 for (unsigned i = 0; i < 3; ++i) { | |
1584 for (unsigned j = 0; j < 2; ++j) | |
1585 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); | |
1586 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); | |
1587 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); | |
1588 } | |
1589 } | |
1590 layer_tree_host_->CommitComplete(); | |
1591 | |
1592 // With a memory limit that includes only half the root layer, no contents | |
1593 // will be allocated. If render surface memory wasn't accounted for, there is | |
1594 // enough space for one of the children layers, but they draw into a surface | |
1595 // that can't be allocated. | |
1596 root->InvalidateContentRect(root_rect); | |
1597 child->InvalidateContentRect(child_rect); | |
1598 child2->InvalidateContentRect(child2_rect); | |
1599 | |
1600 memory_limit = (3 * 1) * (100 * 100) * 4; | |
1601 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( | |
1602 memory_limit); | |
1603 layer_tree_host_->UpdateLayers(queue_.get()); | |
1604 { | |
1605 UpdateTextures(); | |
1606 EXPECT_EQ(0, root->fake_layer_updater()->update_count()); | |
1607 EXPECT_EQ(0, child->fake_layer_updater()->update_count()); | |
1608 EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); | |
1609 EXPECT_FALSE(queue_->HasMoreUpdates()); | |
1610 | |
1611 root->fake_layer_updater()->ClearUpdateCount(); | |
1612 child->fake_layer_updater()->ClearUpdateCount(); | |
1613 child2->fake_layer_updater()->ClearUpdateCount(); | |
1614 | |
1615 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( | |
1616 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); | |
1617 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( | |
1618 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); | |
1619 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( | |
1620 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); | |
1621 LayerPushPropertiesTo(child2.get(), child2_impl.get()); | |
1622 LayerPushPropertiesTo(child.get(), child_impl.get()); | |
1623 LayerPushPropertiesTo(root.get(), root_impl.get()); | |
1624 | |
1625 for (unsigned i = 0; i < 3; ++i) { | |
1626 for (unsigned j = 0; j < 2; ++j) | |
1627 EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j)); | |
1628 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); | |
1629 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); | |
1630 } | |
1631 } | |
1632 layer_tree_host_->CommitComplete(); | |
1633 | |
1634 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), | |
1635 resource_provider_.get()); | |
1636 layer_tree_host_->SetRootLayer(nullptr); | |
1637 } | |
1638 | |
1639 class TrackingLayerPainter : public LayerPainter { | |
1640 public: | |
1641 static scoped_ptr<TrackingLayerPainter> Create() { | |
1642 return make_scoped_ptr(new TrackingLayerPainter()); | |
1643 } | |
1644 | |
1645 void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) override { | |
1646 painted_rect_ = content_rect; | |
1647 } | |
1648 | |
1649 gfx::Rect PaintedRect() const { return painted_rect_; } | |
1650 void ResetPaintedRect() { painted_rect_ = gfx::Rect(); } | |
1651 | |
1652 private: | |
1653 gfx::Rect painted_rect_; | |
1654 }; | |
1655 | |
1656 class UpdateTrackingTiledLayer : public FakeTiledLayer { | |
1657 public: | |
1658 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager) | |
1659 : FakeTiledLayer(manager) { | |
1660 scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create()); | |
1661 tracking_layer_painter_ = painter.get(); | |
1662 layer_updater_ = BitmapContentLayerUpdater::Create(painter.Pass(), 0); | |
1663 } | |
1664 | |
1665 TrackingLayerPainter* tracking_layer_painter() const { | |
1666 return tracking_layer_painter_; | |
1667 } | |
1668 | |
1669 private: | |
1670 LayerUpdater* Updater() const override { return layer_updater_.get(); } | |
1671 ~UpdateTrackingTiledLayer() override {} | |
1672 | |
1673 TrackingLayerPainter* tracking_layer_painter_; | |
1674 scoped_refptr<BitmapContentLayerUpdater> layer_updater_; | |
1675 }; | |
1676 | |
1677 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) { | |
1678 scoped_refptr<UpdateTrackingTiledLayer> layer = | |
1679 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); | |
1680 | |
1681 layer_tree_host_->root_layer()->AddChild(layer); | |
1682 | |
1683 gfx::Rect layer_rect(0, 0, 30, 31); | |
1684 layer->SetPosition(layer_rect.origin()); | |
1685 layer->SetBounds(layer_rect.size()); | |
1686 layer->UpdateContentsScale(1.5f); | |
1687 | |
1688 gfx::Rect content_rect(0, 0, 45, 47); | |
1689 EXPECT_EQ(content_rect.size(), layer->content_bounds()); | |
1690 layer->draw_properties().visible_content_rect = content_rect; | |
1691 layer->draw_properties().drawable_content_rect = content_rect; | |
1692 | |
1693 layer->SetTexturePriorities(priority_calculator_); | |
1694 resource_manager_->PrioritizeTextures(); | |
1695 layer->SavePaintProperties(); | |
1696 | |
1697 // Update the whole tile. | |
1698 layer->Update(queue_.get(), nullptr); | |
1699 layer->tracking_layer_painter()->ResetPaintedRect(); | |
1700 | |
1701 EXPECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); | |
1702 UpdateTextures(); | |
1703 | |
1704 // Invalidate the entire layer in content space. When painting, the rect given | |
1705 // to webkit should match the layer's bounds. | |
1706 layer->InvalidateContentRect(content_rect); | |
1707 layer->Update(queue_.get(), nullptr); | |
1708 | |
1709 // Rounding leads to an extra pixel. | |
1710 gfx::Rect expanded_layer_rect(layer_rect); | |
1711 expanded_layer_rect.set_height(32); | |
1712 EXPECT_EQ(expanded_layer_rect, | |
1713 layer->tracking_layer_painter()->PaintedRect()); | |
1714 } | |
1715 | |
1716 TEST_F(TiledLayerTest, | |
1717 NonIntegerContentsScaleIsNotDistortedDuringInvalidation) { | |
1718 scoped_refptr<UpdateTrackingTiledLayer> layer = | |
1719 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); | |
1720 | |
1721 layer_tree_host_->root_layer()->AddChild(layer); | |
1722 | |
1723 gfx::Rect layer_rect(0, 0, 30, 31); | |
1724 layer->SetPosition(layer_rect.origin()); | |
1725 layer->SetBounds(layer_rect.size()); | |
1726 layer->UpdateContentsScale(1.3f); | |
1727 | |
1728 gfx::Rect content_rect(layer->content_bounds()); | |
1729 layer->draw_properties().visible_content_rect = content_rect; | |
1730 layer->draw_properties().drawable_content_rect = content_rect; | |
1731 | |
1732 layer->SetTexturePriorities(priority_calculator_); | |
1733 resource_manager_->PrioritizeTextures(); | |
1734 layer->SavePaintProperties(); | |
1735 | |
1736 // Update the whole tile. | |
1737 layer->Update(queue_.get(), nullptr); | |
1738 layer->tracking_layer_painter()->ResetPaintedRect(); | |
1739 | |
1740 EXPECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); | |
1741 UpdateTextures(); | |
1742 | |
1743 // Invalidate the entire layer in layer space. When painting, the rect given | |
1744 // to webkit should match the layer's bounds. | |
1745 layer->SetNeedsDisplayRect(layer_rect); | |
1746 layer->Update(queue_.get(), nullptr); | |
1747 | |
1748 // Rounding leads to an extra pixel. | |
1749 gfx::Rect expanded_layer_rect(layer_rect); | |
1750 expanded_layer_rect.set_height(32); | |
1751 EXPECT_EQ(expanded_layer_rect, | |
1752 layer->tracking_layer_painter()->PaintedRect()); | |
1753 } | |
1754 | |
1755 } // namespace | |
1756 } // namespace cc | |
OLD | NEW |