Add ICU message format support
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_copyrequest.cc
blobe29cb21333e45731d6c0b3b646278c8376618968
1 // Copyright 2013 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.
5 #include "cc/layers/layer_iterator.h"
6 #include "cc/output/copy_output_request.h"
7 #include "cc/output/copy_output_result.h"
8 #include "cc/test/fake_content_layer_client.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_picture_layer.h"
11 #include "cc/test/layer_tree_test.h"
12 #include "cc/trees/layer_tree_impl.h"
13 #include "gpu/GLES2/gl2extchromium.h"
15 namespace cc {
16 namespace {
18 // These tests only use direct rendering, as there is no output to copy for
19 // delegated renderers.
20 class LayerTreeHostCopyRequestTest : public LayerTreeTest {};
22 class LayerTreeHostCopyRequestTestMultipleRequests
23 : public LayerTreeHostCopyRequestTest {
24 protected:
25 void SetupTree() override {
26 root = FakePictureLayer::Create(layer_settings(), &client_);
27 root->SetBounds(gfx::Size(20, 20));
29 child = FakePictureLayer::Create(layer_settings(), &client_);
30 child->SetBounds(gfx::Size(10, 10));
31 root->AddChild(child);
33 layer_tree_host()->SetRootLayer(root);
34 LayerTreeHostCopyRequestTest::SetupTree();
37 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
39 void DidCommitAndDrawFrame() override { WaitForCallback(); }
41 void WaitForCallback() {
42 base::MessageLoop::current()->PostTask(
43 FROM_HERE,
44 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep,
45 base::Unretained(this)));
48 void NextStep() {
49 int frame = layer_tree_host()->source_frame_number();
50 switch (frame) {
51 case 1:
52 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
53 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
54 CopyOutputCallback,
55 base::Unretained(this))));
56 EXPECT_EQ(0u, callbacks_.size());
57 break;
58 case 2:
59 if (callbacks_.size() < 1u) {
60 WaitForCallback();
61 return;
63 EXPECT_EQ(1u, callbacks_.size());
64 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
66 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
67 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
68 CopyOutputCallback,
69 base::Unretained(this))));
70 root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
71 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
72 CopyOutputCallback,
73 base::Unretained(this))));
74 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
75 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
76 CopyOutputCallback,
77 base::Unretained(this))));
78 EXPECT_EQ(1u, callbacks_.size());
79 break;
80 case 3:
81 if (callbacks_.size() < 4u) {
82 WaitForCallback();
83 return;
85 EXPECT_EQ(4u, callbacks_.size());
86 // The child was copied to a bitmap and passed back twice.
87 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString());
88 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString());
89 // The root was copied to a bitmap and passed back also.
90 EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString());
91 EndTest();
92 break;
96 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
97 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
98 EXPECT_TRUE(result->HasBitmap());
99 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass();
100 EXPECT_EQ(result->size().ToString(),
101 gfx::Size(bitmap->width(), bitmap->height()).ToString());
102 callbacks_.push_back(result->size());
105 void AfterTest() override { EXPECT_EQ(4u, callbacks_.size()); }
107 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
108 if (use_gl_renderer_)
109 return FakeOutputSurface::Create3d();
110 return FakeOutputSurface::CreateSoftware(
111 make_scoped_ptr(new SoftwareOutputDevice));
114 bool use_gl_renderer_;
115 std::vector<gfx::Size> callbacks_;
116 FakeContentLayerClient client_;
117 scoped_refptr<FakePictureLayer> root;
118 scoped_refptr<FakePictureLayer> child;
121 // Readback can't be done with a delegating renderer.
122 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
123 GLRenderer_RunSingleThread) {
124 use_gl_renderer_ = true;
125 RunTest(false, false);
128 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
129 GLRenderer_RunMultiThread) {
130 use_gl_renderer_ = true;
131 RunTest(true, false);
134 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
135 SoftwareRenderer_RunSingleThread) {
136 use_gl_renderer_ = false;
137 RunTest(false, false);
140 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
141 SoftwareRenderer_RunMultiThread) {
142 use_gl_renderer_ = false;
143 RunTest(true, false);
146 class LayerTreeHostCopyRequestTestLayerDestroyed
147 : public LayerTreeHostCopyRequestTest {
148 protected:
149 void SetupTree() override {
150 root_ = FakePictureLayer::Create(layer_settings(), &client_);
151 root_->SetBounds(gfx::Size(20, 20));
153 main_destroyed_ = FakePictureLayer::Create(layer_settings(), &client_);
154 main_destroyed_->SetBounds(gfx::Size(15, 15));
155 root_->AddChild(main_destroyed_);
157 impl_destroyed_ = FakePictureLayer::Create(layer_settings(), &client_);
158 impl_destroyed_->SetBounds(gfx::Size(10, 10));
159 root_->AddChild(impl_destroyed_);
161 layer_tree_host()->SetRootLayer(root_);
162 LayerTreeHostCopyRequestTest::SetupTree();
165 void BeginTest() override {
166 callback_count_ = 0;
167 PostSetNeedsCommitToMainThread();
170 void DidCommit() override {
171 int frame = layer_tree_host()->source_frame_number();
172 switch (frame) {
173 case 1:
174 main_destroyed_->RequestCopyOfOutput(
175 CopyOutputRequest::CreateBitmapRequest(base::Bind(
176 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
177 base::Unretained(this))));
178 impl_destroyed_->RequestCopyOfOutput(
179 CopyOutputRequest::CreateBitmapRequest(base::Bind(
180 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback,
181 base::Unretained(this))));
182 EXPECT_EQ(0, callback_count_);
184 // Destroy the main thread layer right away.
185 main_destroyed_->RemoveFromParent();
186 main_destroyed_ = NULL;
188 // Should callback with a NULL bitmap.
189 EXPECT_EQ(1, callback_count_);
191 // Prevent drawing so we can't make a copy of the impl_destroyed layer.
192 layer_tree_host()->SetViewportSize(gfx::Size());
193 break;
194 case 2:
195 // Flush the message loops and make sure the callbacks run.
196 layer_tree_host()->SetNeedsCommit();
197 break;
198 case 3:
199 // No drawing means no readback yet.
200 EXPECT_EQ(1, callback_count_);
202 // Destroy the impl thread layer.
203 impl_destroyed_->RemoveFromParent();
204 impl_destroyed_ = NULL;
206 // No callback yet because it's on the impl side.
207 EXPECT_EQ(1, callback_count_);
208 break;
209 case 4:
210 // Flush the message loops and make sure the callbacks run.
211 layer_tree_host()->SetNeedsCommit();
212 break;
213 case 5:
214 // We should get another callback with a NULL bitmap.
215 EXPECT_EQ(2, callback_count_);
216 EndTest();
217 break;
221 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
222 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
223 EXPECT_TRUE(result->IsEmpty());
224 ++callback_count_;
227 void AfterTest() override {}
229 int callback_count_;
230 FakeContentLayerClient client_;
231 scoped_refptr<FakePictureLayer> root_;
232 scoped_refptr<FakePictureLayer> main_destroyed_;
233 scoped_refptr<FakePictureLayer> impl_destroyed_;
236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed);
238 class LayerTreeHostCopyRequestTestInHiddenSubtree
239 : public LayerTreeHostCopyRequestTest {
240 protected:
241 void SetupTree() override {
242 root_ = FakePictureLayer::Create(layer_settings(), &client_);
243 root_->SetBounds(gfx::Size(20, 20));
245 grand_parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
246 grand_parent_layer_->SetBounds(gfx::Size(15, 15));
247 root_->AddChild(grand_parent_layer_);
249 // parent_layer_ owns a render surface.
250 parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
251 parent_layer_->SetBounds(gfx::Size(15, 15));
252 parent_layer_->SetForceRenderSurface(true);
253 grand_parent_layer_->AddChild(parent_layer_);
255 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
256 copy_layer_->SetBounds(gfx::Size(10, 10));
257 parent_layer_->AddChild(copy_layer_);
259 layer_tree_host()->SetRootLayer(root_);
260 LayerTreeHostCopyRequestTest::SetupTree();
263 void AddCopyRequest(Layer* layer) {
264 layer->RequestCopyOfOutput(
265 CopyOutputRequest::CreateBitmapRequest(base::Bind(
266 &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
267 base::Unretained(this))));
270 void BeginTest() override {
271 callback_count_ = 0;
272 PostSetNeedsCommitToMainThread();
274 AddCopyRequest(copy_layer_.get());
277 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
278 ++callback_count_;
279 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
280 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString())
281 << callback_count_;
282 switch (callback_count_) {
283 case 1:
284 // Hide the copy request layer.
285 grand_parent_layer_->SetHideLayerAndSubtree(false);
286 parent_layer_->SetHideLayerAndSubtree(false);
287 copy_layer_->SetHideLayerAndSubtree(true);
288 AddCopyRequest(copy_layer_.get());
289 break;
290 case 2:
291 // Hide the copy request layer's parent only.
292 grand_parent_layer_->SetHideLayerAndSubtree(false);
293 parent_layer_->SetHideLayerAndSubtree(true);
294 copy_layer_->SetHideLayerAndSubtree(false);
295 AddCopyRequest(copy_layer_.get());
296 break;
297 case 3:
298 // Hide the copy request layer's grand parent only.
299 grand_parent_layer_->SetHideLayerAndSubtree(true);
300 parent_layer_->SetHideLayerAndSubtree(false);
301 copy_layer_->SetHideLayerAndSubtree(false);
302 AddCopyRequest(copy_layer_.get());
303 break;
304 case 4:
305 // Hide the copy request layer's parent and grandparent.
306 grand_parent_layer_->SetHideLayerAndSubtree(true);
307 parent_layer_->SetHideLayerAndSubtree(true);
308 copy_layer_->SetHideLayerAndSubtree(false);
309 AddCopyRequest(copy_layer_.get());
310 break;
311 case 5:
312 // Hide the copy request layer as well as its parent and grandparent.
313 grand_parent_layer_->SetHideLayerAndSubtree(true);
314 parent_layer_->SetHideLayerAndSubtree(true);
315 copy_layer_->SetHideLayerAndSubtree(true);
316 AddCopyRequest(copy_layer_.get());
317 break;
318 case 6:
319 EndTest();
320 break;
324 void AfterTest() override {}
326 int callback_count_;
327 FakeContentLayerClient client_;
328 scoped_refptr<FakePictureLayer> root_;
329 scoped_refptr<FakePictureLayer> grand_parent_layer_;
330 scoped_refptr<FakePictureLayer> parent_layer_;
331 scoped_refptr<FakePictureLayer> copy_layer_;
334 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
335 LayerTreeHostCopyRequestTestInHiddenSubtree);
337 class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
338 : public LayerTreeHostCopyRequestTest {
339 protected:
340 void SetupTree() override {
341 root_ = FakePictureLayer::Create(layer_settings(), &client_);
342 root_->SetBounds(gfx::Size(20, 20));
344 grand_parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
345 grand_parent_layer_->SetBounds(gfx::Size(15, 15));
346 grand_parent_layer_->SetHideLayerAndSubtree(true);
347 root_->AddChild(grand_parent_layer_);
349 // parent_layer_ owns a render surface.
350 parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
351 parent_layer_->SetBounds(gfx::Size(15, 15));
352 parent_layer_->SetForceRenderSurface(true);
353 grand_parent_layer_->AddChild(parent_layer_);
355 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
356 copy_layer_->SetBounds(gfx::Size(10, 10));
357 parent_layer_->AddChild(copy_layer_);
359 layer_tree_host()->SetRootLayer(root_);
360 LayerTreeHostCopyRequestTest::SetupTree();
363 void BeginTest() override {
364 did_draw_ = false;
365 PostSetNeedsCommitToMainThread();
367 copy_layer_->RequestCopyOfOutput(
368 CopyOutputRequest::CreateBitmapRequest(base::Bind(
369 &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
370 CopyOutputCallback,
371 base::Unretained(this))));
374 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
375 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
376 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
377 EndTest();
380 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
381 Renderer* renderer = host_impl->renderer();
383 LayerImpl* root = host_impl->active_tree()->root_layer();
384 LayerImpl* grand_parent = root->children()[0];
385 LayerImpl* parent = grand_parent->children()[0];
386 LayerImpl* copy_layer = parent->children()[0];
388 // |parent| owns a surface, but it was hidden and not part of the copy
389 // request so it should not allocate any resource.
390 EXPECT_FALSE(renderer->HasAllocatedResourcesForTesting(
391 parent->render_surface()->GetRenderPassId()));
393 // |copy_layer| should have been rendered to a texture since it was needed
394 // for a copy request.
395 EXPECT_TRUE(renderer->HasAllocatedResourcesForTesting(
396 copy_layer->render_surface()->GetRenderPassId()));
398 did_draw_ = true;
401 void AfterTest() override { EXPECT_TRUE(did_draw_); }
403 FakeContentLayerClient client_;
404 bool did_draw_;
405 scoped_refptr<FakePictureLayer> root_;
406 scoped_refptr<FakePictureLayer> grand_parent_layer_;
407 scoped_refptr<FakePictureLayer> parent_layer_;
408 scoped_refptr<FakePictureLayer> copy_layer_;
411 // No output to copy for delegated renderers.
412 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
413 LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest);
415 class LayerTreeHostCopyRequestTestClippedOut
416 : public LayerTreeHostCopyRequestTest {
417 protected:
418 void SetupTree() override {
419 root_ = FakePictureLayer::Create(layer_settings(), &client_);
420 root_->SetBounds(gfx::Size(20, 20));
422 parent_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
423 parent_layer_->SetBounds(gfx::Size(15, 15));
424 parent_layer_->SetMasksToBounds(true);
425 root_->AddChild(parent_layer_);
427 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
428 copy_layer_->SetPosition(gfx::Point(15, 15));
429 copy_layer_->SetBounds(gfx::Size(10, 10));
430 parent_layer_->AddChild(copy_layer_);
432 layer_tree_host()->SetRootLayer(root_);
433 LayerTreeHostCopyRequestTest::SetupTree();
436 void BeginTest() override {
437 PostSetNeedsCommitToMainThread();
439 copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
440 base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
441 base::Unretained(this))));
444 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
445 // We should still get a callback with no output if the copy requested layer
446 // was completely clipped away.
447 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
448 EXPECT_EQ(gfx::Size().ToString(), result->size().ToString());
449 EndTest();
452 void AfterTest() override {}
454 FakeContentLayerClient client_;
455 scoped_refptr<FakePictureLayer> root_;
456 scoped_refptr<FakePictureLayer> parent_layer_;
457 scoped_refptr<FakePictureLayer> copy_layer_;
460 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
461 LayerTreeHostCopyRequestTestClippedOut);
463 class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
464 : public LayerTreeHostCopyRequestTest {
465 protected:
466 void SetupTree() override {
467 root_ = FakePictureLayer::Create(layer_settings(), &client_);
468 root_->SetBounds(gfx::Size(20, 20));
470 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
471 copy_layer_->SetBounds(gfx::Size(10, 10));
472 root_->AddChild(copy_layer_);
474 layer_tree_host()->SetRootLayer(root_);
475 LayerTreeHostCopyRequestTest::SetupTree();
478 void AddCopyRequest(Layer* layer) {
479 layer->RequestCopyOfOutput(
480 CopyOutputRequest::CreateBitmapRequest(base::Bind(
481 &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
482 base::Unretained(this))));
485 void BeginTest() override {
486 saw_copy_request_ = false;
487 callback_count_ = 0;
488 PostSetNeedsCommitToMainThread();
490 // Prevent drawing.
491 layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
493 AddCopyRequest(copy_layer_.get());
496 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
497 if (impl->active_tree()->source_frame_number() == 0) {
498 LayerImpl* root = impl->active_tree()->root_layer();
499 EXPECT_TRUE(root->children()[0]->HasCopyRequest());
500 saw_copy_request_ = true;
504 void DidCommit() override {
505 if (layer_tree_host()->source_frame_number() == 1) {
506 // Allow drawing.
507 layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds()));
509 AddCopyRequest(copy_layer_.get());
513 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
514 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
516 // The first frame can't be drawn.
517 switch (callback_count_) {
518 case 0:
519 EXPECT_TRUE(result->IsEmpty());
520 EXPECT_EQ(gfx::Size(), result->size());
521 break;
522 case 1:
523 EXPECT_FALSE(result->IsEmpty());
524 EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
525 EndTest();
526 break;
527 default:
528 NOTREACHED();
529 break;
532 ++callback_count_;
535 void AfterTest() override { EXPECT_TRUE(saw_copy_request_); }
537 bool saw_copy_request_;
538 int callback_count_;
539 FakeContentLayerClient client_;
540 scoped_refptr<FakePictureLayer> root_;
541 scoped_refptr<FakePictureLayer> copy_layer_;
544 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
545 LayerTreeHostTestAsyncTwoReadbacksWithoutDraw);
547 class LayerTreeHostCopyRequestTestLostOutputSurface
548 : public LayerTreeHostCopyRequestTest {
549 protected:
550 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
551 if (!first_context_provider_.get()) {
552 first_context_provider_ = TestContextProvider::Create();
553 return FakeOutputSurface::Create3d(first_context_provider_);
556 EXPECT_FALSE(second_context_provider_.get());
557 second_context_provider_ = TestContextProvider::Create();
558 return FakeOutputSurface::Create3d(second_context_provider_);
561 void SetupTree() override {
562 root_ = FakePictureLayer::Create(layer_settings(), &client_);
563 root_->SetBounds(gfx::Size(20, 20));
565 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
566 copy_layer_->SetBounds(gfx::Size(10, 10));
567 root_->AddChild(copy_layer_);
569 layer_tree_host()->SetRootLayer(root_);
570 LayerTreeHostCopyRequestTest::SetupTree();
573 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
575 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
576 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
577 EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
578 EXPECT_TRUE(result->HasTexture());
580 // Save the result for later.
581 EXPECT_FALSE(result_);
582 result_ = result.Pass();
584 // Post a commit to lose the output surface.
585 layer_tree_host()->SetNeedsCommit();
588 void DidCommitAndDrawFrame() override {
589 switch (layer_tree_host()->source_frame_number()) {
590 case 1:
591 // The layers have been pushed to the impl side. The layer textures have
592 // been allocated.
594 // Request a copy of the layer. This will use another texture.
595 copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
596 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
597 CopyOutputCallback,
598 base::Unretained(this))));
599 break;
600 case 4:
601 // With SingleThreadProxy it takes two commits to finally swap after a
602 // context loss.
603 case 5:
604 // Now destroy the CopyOutputResult, releasing the texture inside back
605 // to the compositor.
606 EXPECT_TRUE(result_);
607 result_ = nullptr;
609 // Check that it is released.
610 ImplThreadTaskRunner()->PostTask(
611 FROM_HERE,
612 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
613 CheckNumTextures,
614 base::Unretained(this),
615 num_textures_after_loss_ - 1));
616 break;
620 void SwapBuffersOnThread(LayerTreeHostImpl* impl, bool result) override {
621 switch (impl->active_tree()->source_frame_number()) {
622 case 0:
623 // The layers have been drawn, so their textures have been allocated.
624 EXPECT_FALSE(result_);
625 num_textures_without_readback_ =
626 first_context_provider_->TestContext3d()->NumTextures();
627 break;
628 case 1:
629 // We did a readback, so there will be a readback texture around now.
630 EXPECT_LT(num_textures_without_readback_,
631 first_context_provider_->TestContext3d()->NumTextures());
632 break;
633 case 2:
634 // The readback texture is collected.
635 EXPECT_TRUE(result_);
637 // Lose the output surface.
638 first_context_provider_->TestContext3d()->loseContextCHROMIUM(
639 GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
640 break;
641 case 3:
642 // With SingleThreadProxy it takes two commits to finally swap after a
643 // context loss.
644 case 4:
645 // The output surface has been recreated.
646 EXPECT_TRUE(second_context_provider_.get());
648 num_textures_after_loss_ =
649 first_context_provider_->TestContext3d()->NumTextures();
650 break;
654 void CheckNumTextures(size_t expected_num_textures) {
655 EXPECT_EQ(expected_num_textures,
656 first_context_provider_->TestContext3d()->NumTextures());
657 EndTest();
660 void AfterTest() override {}
662 scoped_refptr<TestContextProvider> first_context_provider_;
663 scoped_refptr<TestContextProvider> second_context_provider_;
664 size_t num_textures_without_readback_;
665 size_t num_textures_after_loss_;
666 FakeContentLayerClient client_;
667 scoped_refptr<FakePictureLayer> root_;
668 scoped_refptr<FakePictureLayer> copy_layer_;
669 scoped_ptr<CopyOutputResult> result_;
672 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
673 LayerTreeHostCopyRequestTestLostOutputSurface);
675 class LayerTreeHostCopyRequestTestCountTextures
676 : public LayerTreeHostCopyRequestTest {
677 protected:
678 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
679 context_provider_ = TestContextProvider::Create();
680 return FakeOutputSurface::Create3d(context_provider_);
683 void SetupTree() override {
684 client_.set_fill_with_nonsolid_color(true);
686 root_ = FakePictureLayer::Create(layer_settings(), &client_);
687 root_->SetBounds(gfx::Size(20, 20));
689 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
690 copy_layer_->SetBounds(gfx::Size(10, 10));
691 root_->AddChild(copy_layer_);
693 layer_tree_host()->SetRootLayer(root_);
694 LayerTreeHostCopyRequestTest::SetupTree();
697 void BeginTest() override {
698 num_textures_without_readback_ = 0;
699 num_textures_with_readback_ = 0;
700 waited_sync_point_after_readback_ = 0;
701 PostSetNeedsCommitToMainThread();
704 virtual void RequestCopy(Layer* layer) = 0;
706 void DidCommitAndDrawFrame() override {
707 switch (layer_tree_host()->source_frame_number()) {
708 case 1:
709 // The layers have been pushed to the impl side. The layer textures have
710 // been allocated.
711 RequestCopy(copy_layer_.get());
712 break;
716 void SwapBuffersOnThread(LayerTreeHostImpl* impl, bool result) override {
717 switch (impl->active_tree()->source_frame_number()) {
718 case 0:
719 // The layers have been drawn, so their textures have been allocated.
720 num_textures_without_readback_ =
721 context_provider_->TestContext3d()->NumTextures();
722 break;
723 case 1:
724 // We did a readback, so there will be a readback texture around now.
725 num_textures_with_readback_ =
726 context_provider_->TestContext3d()->NumTextures();
727 waited_sync_point_after_readback_ =
728 context_provider_->TestContext3d()->last_waited_sync_point();
730 MainThreadTaskRunner()->PostTask(
731 FROM_HERE,
732 base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest,
733 base::Unretained(this)));
734 break;
738 virtual void DoEndTest() { EndTest(); }
740 scoped_refptr<TestContextProvider> context_provider_;
741 size_t num_textures_without_readback_;
742 size_t num_textures_with_readback_;
743 unsigned waited_sync_point_after_readback_;
744 FakeContentLayerClient client_;
745 scoped_refptr<FakePictureLayer> root_;
746 scoped_refptr<FakePictureLayer> copy_layer_;
749 class LayerTreeHostCopyRequestTestCreatesTexture
750 : public LayerTreeHostCopyRequestTestCountTextures {
751 protected:
752 void RequestCopy(Layer* layer) override {
753 // Request a normal texture copy. This should create a new texture.
754 copy_layer_->RequestCopyOfOutput(
755 CopyOutputRequest::CreateRequest(base::Bind(
756 &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback,
757 base::Unretained(this))));
760 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
761 EXPECT_FALSE(result->IsEmpty());
762 EXPECT_TRUE(result->HasTexture());
764 TextureMailbox mailbox;
765 scoped_ptr<SingleReleaseCallback> release;
766 result->TakeTexture(&mailbox, &release);
767 EXPECT_TRUE(release);
769 release->Run(0, false);
772 void AfterTest() override {
773 // No sync point was needed.
774 EXPECT_EQ(0u, waited_sync_point_after_readback_);
775 // Except the copy to have made another texture.
776 EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_);
780 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
781 LayerTreeHostCopyRequestTestCreatesTexture);
783 class LayerTreeHostCopyRequestTestProvideTexture
784 : public LayerTreeHostCopyRequestTestCountTextures {
785 protected:
786 void BeginTest() override {
787 external_context_provider_ = TestContextProvider::Create();
788 EXPECT_TRUE(external_context_provider_->BindToCurrentThread());
789 LayerTreeHostCopyRequestTestCountTextures::BeginTest();
792 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
793 EXPECT_FALSE(result->IsEmpty());
794 EXPECT_TRUE(result->HasTexture());
796 TextureMailbox mailbox;
797 scoped_ptr<SingleReleaseCallback> release;
798 result->TakeTexture(&mailbox, &release);
799 EXPECT_FALSE(release);
802 void RequestCopy(Layer* layer) override {
803 // Request a copy to a provided texture. This should not create a new
804 // texture.
805 scoped_ptr<CopyOutputRequest> request =
806 CopyOutputRequest::CreateRequest(base::Bind(
807 &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback,
808 base::Unretained(this)));
810 gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL();
811 gpu::Mailbox mailbox;
812 gl->GenMailboxCHROMIUM(mailbox.name);
813 sync_point_ = gl->InsertSyncPointCHROMIUM();
814 request->SetTextureMailbox(
815 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point_));
816 EXPECT_TRUE(request->has_texture_mailbox());
818 copy_layer_->RequestCopyOfOutput(request.Pass());
821 void AfterTest() override {
822 // Expect the compositor to have waited for the sync point in the provided
823 // TextureMailbox.
824 EXPECT_EQ(sync_point_, waited_sync_point_after_readback_);
825 // Except the copy to have *not* made another texture.
826 EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_);
829 scoped_refptr<TestContextProvider> external_context_provider_;
830 unsigned sync_point_;
833 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
834 LayerTreeHostCopyRequestTestProvideTexture);
836 class LayerTreeHostCopyRequestTestDestroyBeforeCopy
837 : public LayerTreeHostCopyRequestTest {
838 protected:
839 void SetupTree() override {
840 root_ = FakePictureLayer::Create(layer_settings(), &client_);
841 root_->SetBounds(gfx::Size(20, 20));
843 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
844 copy_layer_->SetBounds(gfx::Size(10, 10));
845 root_->AddChild(copy_layer_);
847 layer_tree_host()->SetRootLayer(root_);
848 LayerTreeHostCopyRequestTest::SetupTree();
851 void BeginTest() override {
852 callback_count_ = 0;
853 PostSetNeedsCommitToMainThread();
856 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
857 EXPECT_TRUE(result->IsEmpty());
858 ++callback_count_;
861 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
862 MainThreadTaskRunner()->PostTask(
863 FROM_HERE,
864 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate,
865 base::Unretained(this)));
868 void DidActivate() {
869 switch (layer_tree_host()->source_frame_number()) {
870 case 1: {
871 EXPECT_EQ(0, callback_count_);
872 // Put a copy request on the layer, but then don't allow any
873 // drawing to take place.
874 scoped_ptr<CopyOutputRequest> request =
875 CopyOutputRequest::CreateRequest(
876 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
877 CopyOutputCallback,
878 base::Unretained(this)));
879 copy_layer_->RequestCopyOfOutput(request.Pass());
881 layer_tree_host()->SetViewportSize(gfx::Size());
882 break;
884 case 2:
885 EXPECT_EQ(0, callback_count_);
886 // Remove the copy layer before we were able to draw.
887 copy_layer_->RemoveFromParent();
888 break;
889 case 3:
890 EXPECT_EQ(1, callback_count_);
891 // Allow us to draw now.
892 layer_tree_host()->SetViewportSize(
893 layer_tree_host()->root_layer()->bounds());
894 break;
895 case 4:
896 EXPECT_EQ(1, callback_count_);
897 // We should not have crashed.
898 EndTest();
902 void AfterTest() override {}
904 int callback_count_;
905 FakeContentLayerClient client_;
906 scoped_refptr<FakePictureLayer> root_;
907 scoped_refptr<FakePictureLayer> copy_layer_;
910 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
911 LayerTreeHostCopyRequestTestDestroyBeforeCopy);
913 class LayerTreeHostCopyRequestTestShutdownBeforeCopy
914 : public LayerTreeHostCopyRequestTest {
915 protected:
916 void SetupTree() override {
917 root_ = FakePictureLayer::Create(layer_settings(), &client_);
918 root_->SetBounds(gfx::Size(20, 20));
920 copy_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
921 copy_layer_->SetBounds(gfx::Size(10, 10));
922 root_->AddChild(copy_layer_);
924 layer_tree_host()->SetRootLayer(root_);
925 LayerTreeHostCopyRequestTest::SetupTree();
928 void BeginTest() override {
929 callback_count_ = 0;
930 PostSetNeedsCommitToMainThread();
933 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
934 EXPECT_TRUE(result->IsEmpty());
935 ++callback_count_;
938 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
939 MainThreadTaskRunner()->PostTask(
940 FROM_HERE,
941 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate,
942 base::Unretained(this)));
945 void DidActivate() {
946 switch (layer_tree_host()->source_frame_number()) {
947 case 1: {
948 EXPECT_EQ(0, callback_count_);
949 // Put a copy request on the layer, but then don't allow any
950 // drawing to take place.
951 scoped_ptr<CopyOutputRequest> request =
952 CopyOutputRequest::CreateRequest(
953 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
954 CopyOutputCallback,
955 base::Unretained(this)));
956 copy_layer_->RequestCopyOfOutput(request.Pass());
958 layer_tree_host()->SetViewportSize(gfx::Size());
959 break;
961 case 2:
962 DestroyLayerTreeHost();
963 // End the test after the copy result has had a chance to get back to
964 // the main thread.
965 MainThreadTaskRunner()->PostTask(
966 FROM_HERE,
967 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest,
968 base::Unretained(this)));
969 break;
973 void AfterTest() override { EXPECT_EQ(1, callback_count_); }
975 int callback_count_;
976 FakeContentLayerClient client_;
977 scoped_refptr<FakePictureLayer> root_;
978 scoped_refptr<FakePictureLayer> copy_layer_;
981 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
982 LayerTreeHostCopyRequestTestShutdownBeforeCopy);
984 class LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest
985 : public LayerTreeHostCopyRequestTest {
986 protected:
987 void SetupTree() override {
988 scoped_refptr<FakePictureLayer> root =
989 FakePictureLayer::Create(layer_settings(), &client_);
990 root->SetBounds(gfx::Size(20, 20));
992 child_ = FakePictureLayer::Create(layer_settings(), &client_);
993 child_->SetBounds(gfx::Size(10, 10));
994 root->AddChild(child_);
995 child_->SetHideLayerAndSubtree(true);
997 layer_tree_host()->SetRootLayer(root);
998 LayerTreeHostCopyRequestTest::SetupTree();
1001 void BeginTest() override {
1002 num_draws_ = 0;
1003 copy_happened_ = false;
1004 draw_happened_ = false;
1005 PostSetNeedsCommitToMainThread();
1008 void DidCommitAndDrawFrame() override {
1009 // Send a copy request after the first commit.
1010 if (layer_tree_host()->source_frame_number() == 1) {
1011 child_->RequestCopyOfOutput(
1012 CopyOutputRequest::CreateBitmapRequest(base::Bind(
1013 &LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest::
1014 CopyOutputCallback,
1015 base::Unretained(this))));
1019 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1020 LayerTreeHostImpl::FrameData* frame_data,
1021 DrawResult draw_result) override {
1022 LayerImpl* root = host_impl->active_tree()->root_layer();
1023 LayerImpl* child = root->children()[0];
1025 bool saw_root = false;
1026 bool saw_child = false;
1027 for (LayerIterator it =
1028 LayerIterator::Begin(frame_data->render_surface_layer_list);
1029 it != LayerIterator::End(frame_data->render_surface_layer_list);
1030 ++it) {
1031 if (it.represents_itself()) {
1032 if (*it == root)
1033 saw_root = true;
1034 else if (*it == child)
1035 saw_child = true;
1036 else
1037 NOTREACHED();
1041 ++num_draws_;
1042 // The first draw has no copy request. The 2nd draw has a copy request, the
1043 // 3rd should not again.
1044 switch (num_draws_) {
1045 case 1:
1046 // Only the root layer draws, the child is hidden.
1047 EXPECT_TRUE(saw_root);
1048 EXPECT_FALSE(saw_child);
1049 break;
1050 case 2:
1051 // Copy happening here, the child will draw.
1052 EXPECT_TRUE(saw_root);
1053 EXPECT_TRUE(saw_child);
1054 // Make another draw happen after doing the copy request.
1055 host_impl->SetNeedsRedrawRect(gfx::Rect(1, 1));
1056 break;
1057 case 3:
1058 // If LayerTreeHostImpl does the wrong thing, it will try to draw the
1059 // layer which had a copy request. But only the root should draw.
1060 EXPECT_TRUE(saw_root);
1061 EXPECT_FALSE(saw_child);
1063 // End the test! Don't race with copy request callbacks, so post the end
1064 // to the main thread.
1065 draw_happened_ = true;
1066 MainThreadTaskRunner()->PostTask(
1067 FROM_HERE,
1068 base::Bind(
1069 &LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest::
1070 TryEndTest,
1071 base::Unretained(this)));
1072 break;
1074 return draw_result;
1077 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
1078 EXPECT_FALSE(TestEnded());
1079 copy_happened_ = true;
1080 TryEndTest();
1083 void TryEndTest() {
1084 if (draw_happened_ && copy_happened_)
1085 EndTest();
1088 void AfterTest() override {}
1090 scoped_refptr<FakePictureLayer> child_;
1091 FakeContentLayerClient client_;
1092 int num_draws_;
1093 bool copy_happened_;
1094 bool draw_happened_;
1097 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1098 LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest);
1100 } // namespace
1101 } // namespace cc