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/output/copy_output_request.h"
6 #include "cc/output/copy_output_result.h"
7 #include "cc/test/fake_content_layer.h"
8 #include "cc/test/fake_content_layer_client.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/layer_tree_test.h"
11 #include "cc/trees/layer_tree_impl.h"
12 #include "gpu/GLES2/gl2extchromium.h"
17 // These tests only use direct rendering, as there is no output to copy for
18 // delegated renderers.
19 class LayerTreeHostCopyRequestTest
: public LayerTreeTest
{};
21 class LayerTreeHostCopyRequestTestMultipleRequests
22 : public LayerTreeHostCopyRequestTest
{
24 virtual void SetupTree() OVERRIDE
{
25 root
= FakeContentLayer::Create(&client_
);
26 root
->SetBounds(gfx::Size(20, 20));
28 child
= FakeContentLayer::Create(&client_
);
29 child
->SetBounds(gfx::Size(10, 10));
30 root
->AddChild(child
);
32 layer_tree_host()->SetRootLayer(root
);
33 LayerTreeHostCopyRequestTest::SetupTree();
36 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
38 virtual void DidCommitAndDrawFrame() OVERRIDE
{ WaitForCallback(); }
40 void WaitForCallback() {
41 base::MessageLoop::current()->PostTask(
43 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep
,
44 base::Unretained(this)));
48 int frame
= layer_tree_host()->source_frame_number();
51 child
->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
52 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
54 base::Unretained(this))));
55 EXPECT_EQ(0u, callbacks_
.size());
58 if (callbacks_
.size() < 1u) {
62 EXPECT_EQ(1u, callbacks_
.size());
63 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_
[0].ToString());
65 child
->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
66 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
68 base::Unretained(this))));
69 root
->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
70 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
72 base::Unretained(this))));
73 child
->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
74 base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
76 base::Unretained(this))));
77 EXPECT_EQ(1u, callbacks_
.size());
80 if (callbacks_
.size() < 4u) {
84 EXPECT_EQ(4u, callbacks_
.size());
85 // The child was copied to a bitmap and passed back twice.
86 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_
[1].ToString());
87 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_
[2].ToString());
88 // The root was copied to a bitmap and passed back also.
89 EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_
[3].ToString());
95 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
96 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
97 EXPECT_TRUE(result
->HasBitmap());
98 scoped_ptr
<SkBitmap
> bitmap
= result
->TakeBitmap().Pass();
99 EXPECT_EQ(result
->size().ToString(),
100 gfx::Size(bitmap
->width(), bitmap
->height()).ToString());
101 callbacks_
.push_back(result
->size());
104 virtual void AfterTest() OVERRIDE
{ EXPECT_EQ(4u, callbacks_
.size()); }
106 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface(bool fallback
)
108 scoped_ptr
<FakeOutputSurface
> output_surface
;
109 if (use_gl_renderer_
) {
110 output_surface
= FakeOutputSurface::Create3d().Pass();
112 output_surface
= FakeOutputSurface::CreateSoftware(
113 make_scoped_ptr(new SoftwareOutputDevice
)).Pass();
115 return output_surface
.PassAs
<OutputSurface
>();
118 bool use_gl_renderer_
;
119 std::vector
<gfx::Size
> callbacks_
;
120 FakeContentLayerClient client_
;
121 scoped_refptr
<FakeContentLayer
> root
;
122 scoped_refptr
<FakeContentLayer
> child
;
125 // Readback can't be done with a delegating renderer.
126 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests
,
127 GLRenderer_RunSingleThread
) {
128 use_gl_renderer_
= true;
129 RunTest(false, false, false);
132 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests
,
133 GLRenderer_RunMultiThread_MainThreadPainting
) {
134 use_gl_renderer_
= true;
135 RunTest(true, false, false);
138 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests
,
139 SoftwareRenderer_RunSingleThread
) {
140 use_gl_renderer_
= false;
141 RunTest(false, false, false);
144 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests
,
145 SoftwareRenderer_RunMultiThread_MainThreadPainting
) {
146 use_gl_renderer_
= false;
147 RunTest(true, false, false);
150 class LayerTreeHostCopyRequestTestLayerDestroyed
151 : public LayerTreeHostCopyRequestTest
{
153 virtual void SetupTree() OVERRIDE
{
154 root_
= FakeContentLayer::Create(&client_
);
155 root_
->SetBounds(gfx::Size(20, 20));
157 main_destroyed_
= FakeContentLayer::Create(&client_
);
158 main_destroyed_
->SetBounds(gfx::Size(15, 15));
159 root_
->AddChild(main_destroyed_
);
161 impl_destroyed_
= FakeContentLayer::Create(&client_
);
162 impl_destroyed_
->SetBounds(gfx::Size(10, 10));
163 root_
->AddChild(impl_destroyed_
);
165 layer_tree_host()->SetRootLayer(root_
);
166 LayerTreeHostCopyRequestTest::SetupTree();
169 virtual void BeginTest() OVERRIDE
{
171 PostSetNeedsCommitToMainThread();
174 virtual void DidCommit() OVERRIDE
{
175 int frame
= layer_tree_host()->source_frame_number();
178 main_destroyed_
->RequestCopyOfOutput(
179 CopyOutputRequest::CreateBitmapRequest(base::Bind(
180 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback
,
181 base::Unretained(this))));
182 impl_destroyed_
->RequestCopyOfOutput(
183 CopyOutputRequest::CreateBitmapRequest(base::Bind(
184 &LayerTreeHostCopyRequestTestLayerDestroyed::CopyOutputCallback
,
185 base::Unretained(this))));
186 EXPECT_EQ(0, callback_count_
);
188 // Destroy the main thread layer right away.
189 main_destroyed_
->RemoveFromParent();
190 main_destroyed_
= NULL
;
192 // Should callback with a NULL bitmap.
193 EXPECT_EQ(1, callback_count_
);
195 // Prevent drawing so we can't make a copy of the impl_destroyed layer.
196 layer_tree_host()->SetViewportSize(gfx::Size());
199 // Flush the message loops and make sure the callbacks run.
200 layer_tree_host()->SetNeedsCommit();
203 // No drawing means no readback yet.
204 EXPECT_EQ(1, callback_count_
);
206 // Destroy the impl thread layer.
207 impl_destroyed_
->RemoveFromParent();
208 impl_destroyed_
= NULL
;
210 // No callback yet because it's on the impl side.
211 EXPECT_EQ(1, callback_count_
);
214 // Flush the message loops and make sure the callbacks run.
215 layer_tree_host()->SetNeedsCommit();
218 // We should get another callback with a NULL bitmap.
219 EXPECT_EQ(2, callback_count_
);
225 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
226 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
227 EXPECT_TRUE(result
->IsEmpty());
231 virtual void AfterTest() OVERRIDE
{}
234 FakeContentLayerClient client_
;
235 scoped_refptr
<FakeContentLayer
> root_
;
236 scoped_refptr
<FakeContentLayer
> main_destroyed_
;
237 scoped_refptr
<FakeContentLayer
> impl_destroyed_
;
240 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed
);
242 class LayerTreeHostCopyRequestTestInHiddenSubtree
243 : public LayerTreeHostCopyRequestTest
{
245 virtual void SetupTree() OVERRIDE
{
246 root_
= FakeContentLayer::Create(&client_
);
247 root_
->SetBounds(gfx::Size(20, 20));
249 grand_parent_layer_
= FakeContentLayer::Create(&client_
);
250 grand_parent_layer_
->SetBounds(gfx::Size(15, 15));
251 root_
->AddChild(grand_parent_layer_
);
253 // parent_layer_ owns a render surface.
254 parent_layer_
= FakeContentLayer::Create(&client_
);
255 parent_layer_
->SetBounds(gfx::Size(15, 15));
256 parent_layer_
->SetForceRenderSurface(true);
257 grand_parent_layer_
->AddChild(parent_layer_
);
259 copy_layer_
= FakeContentLayer::Create(&client_
);
260 copy_layer_
->SetBounds(gfx::Size(10, 10));
261 parent_layer_
->AddChild(copy_layer_
);
263 layer_tree_host()->SetRootLayer(root_
);
264 LayerTreeHostCopyRequestTest::SetupTree();
267 void AddCopyRequest(Layer
* layer
) {
268 layer
->RequestCopyOfOutput(
269 CopyOutputRequest::CreateBitmapRequest(base::Bind(
270 &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback
,
271 base::Unretained(this))));
274 virtual void BeginTest() OVERRIDE
{
276 PostSetNeedsCommitToMainThread();
278 AddCopyRequest(copy_layer_
.get());
281 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
283 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
284 EXPECT_EQ(copy_layer_
->bounds().ToString(), result
->size().ToString())
286 switch (callback_count_
) {
288 // Hide the copy request layer.
289 grand_parent_layer_
->SetHideLayerAndSubtree(false);
290 parent_layer_
->SetHideLayerAndSubtree(false);
291 copy_layer_
->SetHideLayerAndSubtree(true);
292 AddCopyRequest(copy_layer_
.get());
295 // Hide the copy request layer's parent only.
296 grand_parent_layer_
->SetHideLayerAndSubtree(false);
297 parent_layer_
->SetHideLayerAndSubtree(true);
298 copy_layer_
->SetHideLayerAndSubtree(false);
299 AddCopyRequest(copy_layer_
.get());
302 // Hide the copy request layer's grand parent only.
303 grand_parent_layer_
->SetHideLayerAndSubtree(true);
304 parent_layer_
->SetHideLayerAndSubtree(false);
305 copy_layer_
->SetHideLayerAndSubtree(false);
306 AddCopyRequest(copy_layer_
.get());
309 // Hide the copy request layer's parent and grandparent.
310 grand_parent_layer_
->SetHideLayerAndSubtree(true);
311 parent_layer_
->SetHideLayerAndSubtree(true);
312 copy_layer_
->SetHideLayerAndSubtree(false);
313 AddCopyRequest(copy_layer_
.get());
316 // Hide the copy request layer as well as its parent and grandparent.
317 grand_parent_layer_
->SetHideLayerAndSubtree(true);
318 parent_layer_
->SetHideLayerAndSubtree(true);
319 copy_layer_
->SetHideLayerAndSubtree(true);
320 AddCopyRequest(copy_layer_
.get());
328 virtual void AfterTest() OVERRIDE
{}
331 FakeContentLayerClient client_
;
332 scoped_refptr
<FakeContentLayer
> root_
;
333 scoped_refptr
<FakeContentLayer
> grand_parent_layer_
;
334 scoped_refptr
<FakeContentLayer
> parent_layer_
;
335 scoped_refptr
<FakeContentLayer
> copy_layer_
;
338 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
339 LayerTreeHostCopyRequestTestInHiddenSubtree
);
341 class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
342 : public LayerTreeHostCopyRequestTest
{
344 virtual void SetupTree() OVERRIDE
{
345 root_
= FakeContentLayer::Create(&client_
);
346 root_
->SetBounds(gfx::Size(20, 20));
348 grand_parent_layer_
= FakeContentLayer::Create(&client_
);
349 grand_parent_layer_
->SetBounds(gfx::Size(15, 15));
350 grand_parent_layer_
->SetHideLayerAndSubtree(true);
351 root_
->AddChild(grand_parent_layer_
);
353 // parent_layer_ owns a render surface.
354 parent_layer_
= FakeContentLayer::Create(&client_
);
355 parent_layer_
->SetBounds(gfx::Size(15, 15));
356 parent_layer_
->SetForceRenderSurface(true);
357 grand_parent_layer_
->AddChild(parent_layer_
);
359 copy_layer_
= FakeContentLayer::Create(&client_
);
360 copy_layer_
->SetBounds(gfx::Size(10, 10));
361 parent_layer_
->AddChild(copy_layer_
);
363 layer_tree_host()->SetRootLayer(root_
);
364 LayerTreeHostCopyRequestTest::SetupTree();
367 virtual void BeginTest() OVERRIDE
{
369 PostSetNeedsCommitToMainThread();
371 copy_layer_
->RequestCopyOfOutput(
372 CopyOutputRequest::CreateBitmapRequest(base::Bind(
373 &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
375 base::Unretained(this))));
378 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
379 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
380 EXPECT_EQ(copy_layer_
->bounds().ToString(), result
->size().ToString());
384 virtual void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
385 Renderer
* renderer
= host_impl
->renderer();
387 LayerImpl
* root
= host_impl
->active_tree()->root_layer();
388 LayerImpl
* grand_parent
= root
->children()[0];
389 LayerImpl
* parent
= grand_parent
->children()[0];
390 LayerImpl
* copy_layer
= parent
->children()[0];
392 // |parent| owns a surface, but it was hidden and not part of the copy
393 // request so it should not allocate any resource.
394 EXPECT_FALSE(renderer
->HasAllocatedResourcesForTesting(
395 parent
->render_surface()->RenderPassId()));
397 // |copy_layer| should have been rendered to a texture since it was needed
398 // for a copy request.
399 EXPECT_TRUE(renderer
->HasAllocatedResourcesForTesting(
400 copy_layer
->render_surface()->RenderPassId()));
405 virtual void AfterTest() OVERRIDE
{ EXPECT_TRUE(did_draw_
); }
407 FakeContentLayerClient client_
;
409 scoped_refptr
<FakeContentLayer
> root_
;
410 scoped_refptr
<FakeContentLayer
> grand_parent_layer_
;
411 scoped_refptr
<FakeContentLayer
> parent_layer_
;
412 scoped_refptr
<FakeContentLayer
> copy_layer_
;
415 // No output to copy for delegated renderers.
416 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
417 LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
);
419 class LayerTreeHostCopyRequestTestClippedOut
420 : public LayerTreeHostCopyRequestTest
{
422 virtual void SetupTree() OVERRIDE
{
423 root_
= FakeContentLayer::Create(&client_
);
424 root_
->SetBounds(gfx::Size(20, 20));
426 parent_layer_
= FakeContentLayer::Create(&client_
);
427 parent_layer_
->SetBounds(gfx::Size(15, 15));
428 parent_layer_
->SetMasksToBounds(true);
429 root_
->AddChild(parent_layer_
);
431 copy_layer_
= FakeContentLayer::Create(&client_
);
432 copy_layer_
->SetPosition(gfx::Point(15, 15));
433 copy_layer_
->SetBounds(gfx::Size(10, 10));
434 parent_layer_
->AddChild(copy_layer_
);
436 layer_tree_host()->SetRootLayer(root_
);
437 LayerTreeHostCopyRequestTest::SetupTree();
440 virtual void BeginTest() OVERRIDE
{
441 PostSetNeedsCommitToMainThread();
443 copy_layer_
->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
444 base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback
,
445 base::Unretained(this))));
448 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
449 // We should still get a callback with no output if the copy requested layer
450 // was completely clipped away.
451 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
452 EXPECT_EQ(gfx::Size().ToString(), result
->size().ToString());
456 virtual void AfterTest() OVERRIDE
{}
458 FakeContentLayerClient client_
;
459 scoped_refptr
<FakeContentLayer
> root_
;
460 scoped_refptr
<FakeContentLayer
> parent_layer_
;
461 scoped_refptr
<FakeContentLayer
> copy_layer_
;
464 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
465 LayerTreeHostCopyRequestTestClippedOut
);
467 class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
468 : public LayerTreeHostCopyRequestTest
{
470 virtual void SetupTree() OVERRIDE
{
471 root_
= FakeContentLayer::Create(&client_
);
472 root_
->SetBounds(gfx::Size(20, 20));
474 copy_layer_
= FakeContentLayer::Create(&client_
);
475 copy_layer_
->SetBounds(gfx::Size(10, 10));
476 root_
->AddChild(copy_layer_
);
478 layer_tree_host()->SetRootLayer(root_
);
479 LayerTreeHostCopyRequestTest::SetupTree();
482 void AddCopyRequest(Layer
* layer
) {
483 layer
->RequestCopyOfOutput(
484 CopyOutputRequest::CreateBitmapRequest(base::Bind(
485 &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback
,
486 base::Unretained(this))));
489 virtual void BeginTest() OVERRIDE
{
490 saw_copy_request_
= false;
492 PostSetNeedsCommitToMainThread();
495 layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
497 AddCopyRequest(copy_layer_
.get());
500 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
501 if (impl
->active_tree()->source_frame_number() == 0) {
502 LayerImpl
* root
= impl
->active_tree()->root_layer();
503 EXPECT_TRUE(root
->children()[0]->HasCopyRequest());
504 saw_copy_request_
= true;
508 virtual void DidCommit() OVERRIDE
{
509 if (layer_tree_host()->source_frame_number() == 1) {
511 layer_tree_host()->SetViewportSize(gfx::Size(root_
->bounds()));
513 AddCopyRequest(copy_layer_
.get());
517 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
518 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
519 EXPECT_EQ(copy_layer_
->bounds().ToString(), result
->size().ToString());
522 if (callback_count_
== 2)
526 virtual void AfterTest() OVERRIDE
{ EXPECT_TRUE(saw_copy_request_
); }
528 bool saw_copy_request_
;
530 FakeContentLayerClient client_
;
531 scoped_refptr
<FakeContentLayer
> root_
;
532 scoped_refptr
<FakeContentLayer
> copy_layer_
;
535 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
536 LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
);
538 class LayerTreeHostCopyRequestTestLostOutputSurface
539 : public LayerTreeHostCopyRequestTest
{
541 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface(bool fallback
)
543 if (!first_context_provider_
.get()) {
544 first_context_provider_
= TestContextProvider::Create();
545 return FakeOutputSurface::Create3d(first_context_provider_
)
546 .PassAs
<OutputSurface
>();
549 EXPECT_FALSE(second_context_provider_
.get());
550 second_context_provider_
= TestContextProvider::Create();
551 return FakeOutputSurface::Create3d(second_context_provider_
)
552 .PassAs
<OutputSurface
>();
555 virtual void SetupTree() OVERRIDE
{
556 root_
= FakeContentLayer::Create(&client_
);
557 root_
->SetBounds(gfx::Size(20, 20));
559 copy_layer_
= FakeContentLayer::Create(&client_
);
560 copy_layer_
->SetBounds(gfx::Size(10, 10));
561 root_
->AddChild(copy_layer_
);
563 layer_tree_host()->SetRootLayer(root_
);
564 LayerTreeHostCopyRequestTest::SetupTree();
567 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
569 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
570 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
571 EXPECT_EQ(gfx::Size(10, 10).ToString(), result
->size().ToString());
572 EXPECT_TRUE(result
->HasTexture());
574 // Save the result for later.
575 EXPECT_FALSE(result_
);
576 result_
= result
.Pass();
578 // Post a commit to lose the output surface.
579 layer_tree_host()->SetNeedsCommit();
582 virtual void DidCommitAndDrawFrame() OVERRIDE
{
583 switch (layer_tree_host()->source_frame_number()) {
585 // The layers have been pushed to the impl side. The layer textures have
588 // Request a copy of the layer. This will use another texture.
589 copy_layer_
->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
590 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
592 base::Unretained(this))));
595 // With SingleThreadProxy it takes two commits to finally swap after a
598 // Now destroy the CopyOutputResult, releasing the texture inside back
599 // to the compositor.
600 EXPECT_TRUE(result_
);
603 // Check that it is released.
604 ImplThreadTaskRunner()->PostTask(
606 base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
608 base::Unretained(this),
609 num_textures_after_loss_
- 1));
614 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* impl
,
615 bool result
) OVERRIDE
{
616 switch (impl
->active_tree()->source_frame_number()) {
618 // The layers have been drawn, so their textures have been allocated.
619 EXPECT_FALSE(result_
);
620 num_textures_without_readback_
=
621 first_context_provider_
->TestContext3d()->NumTextures();
624 // We did a readback, so there will be a readback texture around now.
625 EXPECT_LT(num_textures_without_readback_
,
626 first_context_provider_
->TestContext3d()->NumTextures());
629 // The readback texture is collected.
630 EXPECT_TRUE(result_
);
632 // Lose the output surface.
633 first_context_provider_
->TestContext3d()->loseContextCHROMIUM(
634 GL_GUILTY_CONTEXT_RESET_ARB
, GL_INNOCENT_CONTEXT_RESET_ARB
);
637 // With SingleThreadProxy it takes two commits to finally swap after a
640 // The output surface has been recreated.
641 EXPECT_TRUE(second_context_provider_
.get());
643 num_textures_after_loss_
=
644 first_context_provider_
->TestContext3d()->NumTextures();
649 void CheckNumTextures(size_t expected_num_textures
) {
650 EXPECT_EQ(expected_num_textures
,
651 first_context_provider_
->TestContext3d()->NumTextures());
655 virtual void AfterTest() OVERRIDE
{}
657 scoped_refptr
<TestContextProvider
> first_context_provider_
;
658 scoped_refptr
<TestContextProvider
> second_context_provider_
;
659 size_t num_textures_without_readback_
;
660 size_t num_textures_after_loss_
;
661 FakeContentLayerClient client_
;
662 scoped_refptr
<FakeContentLayer
> root_
;
663 scoped_refptr
<FakeContentLayer
> copy_layer_
;
664 scoped_ptr
<CopyOutputResult
> result_
;
667 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
668 LayerTreeHostCopyRequestTestLostOutputSurface
);
670 class LayerTreeHostCopyRequestTestCountTextures
671 : public LayerTreeHostCopyRequestTest
{
673 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface(bool fallback
)
675 context_provider_
= TestContextProvider::Create();
676 return FakeOutputSurface::Create3d(context_provider_
)
677 .PassAs
<OutputSurface
>();
680 virtual void SetupTree() OVERRIDE
{
681 root_
= FakeContentLayer::Create(&client_
);
682 root_
->SetBounds(gfx::Size(20, 20));
684 copy_layer_
= FakeContentLayer::Create(&client_
);
685 copy_layer_
->SetBounds(gfx::Size(10, 10));
686 root_
->AddChild(copy_layer_
);
688 layer_tree_host()->SetRootLayer(root_
);
689 LayerTreeHostCopyRequestTest::SetupTree();
692 virtual void BeginTest() OVERRIDE
{
693 num_textures_without_readback_
= 0;
694 num_textures_with_readback_
= 0;
695 waited_sync_point_after_readback_
= 0;
696 PostSetNeedsCommitToMainThread();
699 virtual void RequestCopy(Layer
* layer
) = 0;
701 virtual void DidCommitAndDrawFrame() OVERRIDE
{
702 switch (layer_tree_host()->source_frame_number()) {
704 // The layers have been pushed to the impl side. The layer textures have
706 RequestCopy(copy_layer_
.get());
711 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* impl
,
712 bool result
) OVERRIDE
{
713 switch (impl
->active_tree()->source_frame_number()) {
715 // The layers have been drawn, so their textures have been allocated.
716 num_textures_without_readback_
=
717 context_provider_
->TestContext3d()->NumTextures();
720 // We did a readback, so there will be a readback texture around now.
721 num_textures_with_readback_
=
722 context_provider_
->TestContext3d()->NumTextures();
723 waited_sync_point_after_readback_
=
724 context_provider_
->TestContext3d()->last_waited_sync_point();
726 MainThreadTaskRunner()->PostTask(
728 base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest
,
729 base::Unretained(this)));
734 virtual void DoEndTest() { EndTest(); }
736 scoped_refptr
<TestContextProvider
> context_provider_
;
737 size_t num_textures_without_readback_
;
738 size_t num_textures_with_readback_
;
739 unsigned waited_sync_point_after_readback_
;
740 FakeContentLayerClient client_
;
741 scoped_refptr
<FakeContentLayer
> root_
;
742 scoped_refptr
<FakeContentLayer
> copy_layer_
;
745 class LayerTreeHostCopyRequestTestCreatesTexture
746 : public LayerTreeHostCopyRequestTestCountTextures
{
748 virtual void RequestCopy(Layer
* layer
) OVERRIDE
{
749 // Request a normal texture copy. This should create a new texture.
750 copy_layer_
->RequestCopyOfOutput(
751 CopyOutputRequest::CreateRequest(base::Bind(
752 &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback
,
753 base::Unretained(this))));
756 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
757 EXPECT_FALSE(result
->IsEmpty());
758 EXPECT_TRUE(result
->HasTexture());
760 TextureMailbox mailbox
;
761 scoped_ptr
<SingleReleaseCallback
> release
;
762 result
->TakeTexture(&mailbox
, &release
);
763 EXPECT_TRUE(release
);
765 release
->Run(0, false);
768 virtual void AfterTest() OVERRIDE
{
769 // No sync point was needed.
770 EXPECT_EQ(0u, waited_sync_point_after_readback_
);
771 // Except the copy to have made another texture.
772 EXPECT_EQ(num_textures_without_readback_
+ 1, num_textures_with_readback_
);
776 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
777 LayerTreeHostCopyRequestTestCreatesTexture
);
779 class LayerTreeHostCopyRequestTestProvideTexture
780 : public LayerTreeHostCopyRequestTestCountTextures
{
782 virtual void BeginTest() OVERRIDE
{
783 external_context_provider_
= TestContextProvider::Create();
784 EXPECT_TRUE(external_context_provider_
->BindToCurrentThread());
785 LayerTreeHostCopyRequestTestCountTextures::BeginTest();
788 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
789 EXPECT_FALSE(result
->IsEmpty());
790 EXPECT_TRUE(result
->HasTexture());
792 TextureMailbox mailbox
;
793 scoped_ptr
<SingleReleaseCallback
> release
;
794 result
->TakeTexture(&mailbox
, &release
);
795 EXPECT_FALSE(release
);
798 virtual void RequestCopy(Layer
* layer
) OVERRIDE
{
799 // Request a copy to a provided texture. This should not create a new
801 scoped_ptr
<CopyOutputRequest
> request
=
802 CopyOutputRequest::CreateRequest(base::Bind(
803 &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback
,
804 base::Unretained(this)));
806 gpu::gles2::GLES2Interface
* gl
= external_context_provider_
->ContextGL();
807 gpu::Mailbox mailbox
;
808 gl
->GenMailboxCHROMIUM(mailbox
.name
);
809 sync_point_
= gl
->InsertSyncPointCHROMIUM();
810 request
->SetTextureMailbox(TextureMailbox(mailbox
, sync_point_
));
811 EXPECT_TRUE(request
->has_texture_mailbox());
813 copy_layer_
->RequestCopyOfOutput(request
.Pass());
816 virtual void AfterTest() OVERRIDE
{
817 // Expect the compositor to have waited for the sync point in the provided
819 EXPECT_EQ(sync_point_
, waited_sync_point_after_readback_
);
820 // Except the copy to have *not* made another texture.
821 EXPECT_EQ(num_textures_without_readback_
, num_textures_with_readback_
);
824 scoped_refptr
<TestContextProvider
> external_context_provider_
;
825 unsigned sync_point_
;
828 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
829 LayerTreeHostCopyRequestTestProvideTexture
);
831 class LayerTreeHostCopyRequestTestDestroyBeforeCopy
832 : public LayerTreeHostCopyRequestTest
{
834 virtual void SetupTree() OVERRIDE
{
835 root_
= FakeContentLayer::Create(&client_
);
836 root_
->SetBounds(gfx::Size(20, 20));
838 copy_layer_
= FakeContentLayer::Create(&client_
);
839 copy_layer_
->SetBounds(gfx::Size(10, 10));
840 root_
->AddChild(copy_layer_
);
842 layer_tree_host()->SetRootLayer(root_
);
843 LayerTreeHostCopyRequestTest::SetupTree();
846 virtual void BeginTest() OVERRIDE
{
848 PostSetNeedsCommitToMainThread();
851 void CopyOutputCallback(scoped_ptr
<CopyOutputResult
> result
) {
852 EXPECT_TRUE(result
->IsEmpty());
856 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
857 MainThreadTaskRunner()->PostTask(
859 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate
,
860 base::Unretained(this)));
864 switch (layer_tree_host()->source_frame_number()) {
866 EXPECT_EQ(0, callback_count_
);
867 // Put a copy request on the layer, but then don't allow any
868 // drawing to take place.
869 scoped_ptr
<CopyOutputRequest
> request
=
870 CopyOutputRequest::CreateRequest(
871 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
873 base::Unretained(this)));
874 copy_layer_
->RequestCopyOfOutput(request
.Pass());
876 layer_tree_host()->SetViewportSize(gfx::Size());
880 EXPECT_EQ(0, callback_count_
);
881 // Remove the copy layer before we were able to draw.
882 copy_layer_
->RemoveFromParent();
885 EXPECT_EQ(1, callback_count_
);
886 // Allow us to draw now.
887 layer_tree_host()->SetViewportSize(
888 layer_tree_host()->root_layer()->bounds());
891 EXPECT_EQ(1, callback_count_
);
892 // We should not have crashed.
897 virtual void AfterTest() OVERRIDE
{}
900 FakeContentLayerClient client_
;
901 scoped_refptr
<FakeContentLayer
> root_
;
902 scoped_refptr
<FakeContentLayer
> copy_layer_
;
905 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
906 LayerTreeHostCopyRequestTestDestroyBeforeCopy
);