Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_host_unittest_copyrequest.cc
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.
4
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"
13
14 namespace cc {
15 namespace {
16
17 // These tests only use direct rendering, as there is no output to copy for
18 // delegated renderers.
19 class LayerTreeHostCopyRequestTest : public LayerTreeTest {};
20
21 class LayerTreeHostCopyRequestTestMultipleRequests
22     : public LayerTreeHostCopyRequestTest {
23  protected:
24   virtual void SetupTree() OVERRIDE {
25     root = FakeContentLayer::Create(&client_);
26     root->SetBounds(gfx::Size(20, 20));
27
28     child = FakeContentLayer::Create(&client_);
29     child->SetBounds(gfx::Size(10, 10));
30     root->AddChild(child);
31
32     layer_tree_host()->SetRootLayer(root);
33     LayerTreeHostCopyRequestTest::SetupTree();
34   }
35
36   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
37
38   virtual void DidCommitAndDrawFrame() OVERRIDE { WaitForCallback(); }
39
40   void WaitForCallback() {
41     base::MessageLoop::current()->PostTask(
42         FROM_HERE,
43         base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::NextStep,
44                    base::Unretained(this)));
45   }
46
47   void NextStep() {
48     int frame = layer_tree_host()->source_frame_number();
49     switch (frame) {
50       case 1:
51         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
52             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
53                             CopyOutputCallback,
54                        base::Unretained(this))));
55         EXPECT_EQ(0u, callbacks_.size());
56         break;
57       case 2:
58         if (callbacks_.size() < 1u) {
59           WaitForCallback();
60           return;
61         }
62         EXPECT_EQ(1u, callbacks_.size());
63         EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
64
65         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
66             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
67                             CopyOutputCallback,
68                        base::Unretained(this))));
69         root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
70             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
71                             CopyOutputCallback,
72                        base::Unretained(this))));
73         child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
74             base::Bind(&LayerTreeHostCopyRequestTestMultipleRequests::
75                             CopyOutputCallback,
76                        base::Unretained(this))));
77         EXPECT_EQ(1u, callbacks_.size());
78         break;
79       case 3:
80         if (callbacks_.size() < 4u) {
81           WaitForCallback();
82           return;
83         }
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());
90         EndTest();
91         break;
92     }
93   }
94
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());
102   }
103
104   virtual void AfterTest() OVERRIDE { EXPECT_EQ(4u, callbacks_.size()); }
105
106   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
107       OVERRIDE {
108     if (use_gl_renderer_)
109       return FakeOutputSurface::Create3d();
110     return FakeOutputSurface::CreateSoftware(
111         make_scoped_ptr(new SoftwareOutputDevice));
112   }
113
114   bool use_gl_renderer_;
115   std::vector<gfx::Size> callbacks_;
116   FakeContentLayerClient client_;
117   scoped_refptr<FakeContentLayer> root;
118   scoped_refptr<FakeContentLayer> child;
119 };
120
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, false);
126 }
127
128 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
129        GLRenderer_RunMultiThread_MainThreadPainting) {
130   use_gl_renderer_ = true;
131   RunTest(true, false, false);
132 }
133
134 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
135        SoftwareRenderer_RunSingleThread) {
136   use_gl_renderer_ = false;
137   RunTest(false, false, false);
138 }
139
140 TEST_F(LayerTreeHostCopyRequestTestMultipleRequests,
141        SoftwareRenderer_RunMultiThread_MainThreadPainting) {
142   use_gl_renderer_ = false;
143   RunTest(true, false, false);
144 }
145
146 class LayerTreeHostCopyRequestTestLayerDestroyed
147     : public LayerTreeHostCopyRequestTest {
148  protected:
149   virtual void SetupTree() OVERRIDE {
150     root_ = FakeContentLayer::Create(&client_);
151     root_->SetBounds(gfx::Size(20, 20));
152
153     main_destroyed_ = FakeContentLayer::Create(&client_);
154     main_destroyed_->SetBounds(gfx::Size(15, 15));
155     root_->AddChild(main_destroyed_);
156
157     impl_destroyed_ = FakeContentLayer::Create(&client_);
158     impl_destroyed_->SetBounds(gfx::Size(10, 10));
159     root_->AddChild(impl_destroyed_);
160
161     layer_tree_host()->SetRootLayer(root_);
162     LayerTreeHostCopyRequestTest::SetupTree();
163   }
164
165   virtual void BeginTest() OVERRIDE {
166     callback_count_ = 0;
167     PostSetNeedsCommitToMainThread();
168   }
169
170   virtual 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_);
183
184         // Destroy the main thread layer right away.
185         main_destroyed_->RemoveFromParent();
186         main_destroyed_ = NULL;
187
188         // Should callback with a NULL bitmap.
189         EXPECT_EQ(1, callback_count_);
190
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_);
201
202         // Destroy the impl thread layer.
203         impl_destroyed_->RemoveFromParent();
204         impl_destroyed_ = NULL;
205
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;
218     }
219   }
220
221   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
222     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
223     EXPECT_TRUE(result->IsEmpty());
224     ++callback_count_;
225   }
226
227   virtual void AfterTest() OVERRIDE {}
228
229   int callback_count_;
230   FakeContentLayerClient client_;
231   scoped_refptr<FakeContentLayer> root_;
232   scoped_refptr<FakeContentLayer> main_destroyed_;
233   scoped_refptr<FakeContentLayer> impl_destroyed_;
234 };
235
236 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostCopyRequestTestLayerDestroyed);
237
238 class LayerTreeHostCopyRequestTestInHiddenSubtree
239     : public LayerTreeHostCopyRequestTest {
240  protected:
241   virtual void SetupTree() OVERRIDE {
242     root_ = FakeContentLayer::Create(&client_);
243     root_->SetBounds(gfx::Size(20, 20));
244
245     grand_parent_layer_ = FakeContentLayer::Create(&client_);
246     grand_parent_layer_->SetBounds(gfx::Size(15, 15));
247     root_->AddChild(grand_parent_layer_);
248
249     // parent_layer_ owns a render surface.
250     parent_layer_ = FakeContentLayer::Create(&client_);
251     parent_layer_->SetBounds(gfx::Size(15, 15));
252     parent_layer_->SetForceRenderSurface(true);
253     grand_parent_layer_->AddChild(parent_layer_);
254
255     copy_layer_ = FakeContentLayer::Create(&client_);
256     copy_layer_->SetBounds(gfx::Size(10, 10));
257     parent_layer_->AddChild(copy_layer_);
258
259     layer_tree_host()->SetRootLayer(root_);
260     LayerTreeHostCopyRequestTest::SetupTree();
261   }
262
263   void AddCopyRequest(Layer* layer) {
264     layer->RequestCopyOfOutput(
265         CopyOutputRequest::CreateBitmapRequest(base::Bind(
266             &LayerTreeHostCopyRequestTestInHiddenSubtree::CopyOutputCallback,
267             base::Unretained(this))));
268   }
269
270   virtual void BeginTest() OVERRIDE {
271     callback_count_ = 0;
272     PostSetNeedsCommitToMainThread();
273
274     AddCopyRequest(copy_layer_.get());
275   }
276
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;
321     }
322   }
323
324   virtual void AfterTest() OVERRIDE {}
325
326   int callback_count_;
327   FakeContentLayerClient client_;
328   scoped_refptr<FakeContentLayer> root_;
329   scoped_refptr<FakeContentLayer> grand_parent_layer_;
330   scoped_refptr<FakeContentLayer> parent_layer_;
331   scoped_refptr<FakeContentLayer> copy_layer_;
332 };
333
334 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
335     LayerTreeHostCopyRequestTestInHiddenSubtree);
336
337 class LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest
338     : public LayerTreeHostCopyRequestTest {
339  protected:
340   virtual void SetupTree() OVERRIDE {
341     root_ = FakeContentLayer::Create(&client_);
342     root_->SetBounds(gfx::Size(20, 20));
343
344     grand_parent_layer_ = FakeContentLayer::Create(&client_);
345     grand_parent_layer_->SetBounds(gfx::Size(15, 15));
346     grand_parent_layer_->SetHideLayerAndSubtree(true);
347     root_->AddChild(grand_parent_layer_);
348
349     // parent_layer_ owns a render surface.
350     parent_layer_ = FakeContentLayer::Create(&client_);
351     parent_layer_->SetBounds(gfx::Size(15, 15));
352     parent_layer_->SetForceRenderSurface(true);
353     grand_parent_layer_->AddChild(parent_layer_);
354
355     copy_layer_ = FakeContentLayer::Create(&client_);
356     copy_layer_->SetBounds(gfx::Size(10, 10));
357     parent_layer_->AddChild(copy_layer_);
358
359     layer_tree_host()->SetRootLayer(root_);
360     LayerTreeHostCopyRequestTest::SetupTree();
361   }
362
363   virtual void BeginTest() OVERRIDE {
364     did_draw_ = false;
365     PostSetNeedsCommitToMainThread();
366
367     copy_layer_->RequestCopyOfOutput(
368         CopyOutputRequest::CreateBitmapRequest(base::Bind(
369             &LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest::
370                  CopyOutputCallback,
371             base::Unretained(this))));
372   }
373
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();
378   }
379
380   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
381     Renderer* renderer = host_impl->renderer();
382
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];
387
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()));
392
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()));
397
398     did_draw_ = true;
399   }
400
401   virtual void AfterTest() OVERRIDE { EXPECT_TRUE(did_draw_); }
402
403   FakeContentLayerClient client_;
404   bool did_draw_;
405   scoped_refptr<FakeContentLayer> root_;
406   scoped_refptr<FakeContentLayer> grand_parent_layer_;
407   scoped_refptr<FakeContentLayer> parent_layer_;
408   scoped_refptr<FakeContentLayer> copy_layer_;
409 };
410
411 // No output to copy for delegated renderers.
412 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
413     LayerTreeHostTestHiddenSurfaceNotAllocatedForSubtreeCopyRequest);
414
415 class LayerTreeHostCopyRequestTestClippedOut
416     : public LayerTreeHostCopyRequestTest {
417  protected:
418   virtual void SetupTree() OVERRIDE {
419     root_ = FakeContentLayer::Create(&client_);
420     root_->SetBounds(gfx::Size(20, 20));
421
422     parent_layer_ = FakeContentLayer::Create(&client_);
423     parent_layer_->SetBounds(gfx::Size(15, 15));
424     parent_layer_->SetMasksToBounds(true);
425     root_->AddChild(parent_layer_);
426
427     copy_layer_ = FakeContentLayer::Create(&client_);
428     copy_layer_->SetPosition(gfx::Point(15, 15));
429     copy_layer_->SetBounds(gfx::Size(10, 10));
430     parent_layer_->AddChild(copy_layer_);
431
432     layer_tree_host()->SetRootLayer(root_);
433     LayerTreeHostCopyRequestTest::SetupTree();
434   }
435
436   virtual void BeginTest() OVERRIDE {
437     PostSetNeedsCommitToMainThread();
438
439     copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
440         base::Bind(&LayerTreeHostCopyRequestTestClippedOut::CopyOutputCallback,
441                    base::Unretained(this))));
442   }
443
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();
450   }
451
452   virtual void AfterTest() OVERRIDE {}
453
454   FakeContentLayerClient client_;
455   scoped_refptr<FakeContentLayer> root_;
456   scoped_refptr<FakeContentLayer> parent_layer_;
457   scoped_refptr<FakeContentLayer> copy_layer_;
458 };
459
460 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
461     LayerTreeHostCopyRequestTestClippedOut);
462
463 class LayerTreeHostTestAsyncTwoReadbacksWithoutDraw
464     : public LayerTreeHostCopyRequestTest {
465  protected:
466   virtual void SetupTree() OVERRIDE {
467     root_ = FakeContentLayer::Create(&client_);
468     root_->SetBounds(gfx::Size(20, 20));
469
470     copy_layer_ = FakeContentLayer::Create(&client_);
471     copy_layer_->SetBounds(gfx::Size(10, 10));
472     root_->AddChild(copy_layer_);
473
474     layer_tree_host()->SetRootLayer(root_);
475     LayerTreeHostCopyRequestTest::SetupTree();
476   }
477
478   void AddCopyRequest(Layer* layer) {
479     layer->RequestCopyOfOutput(
480         CopyOutputRequest::CreateBitmapRequest(base::Bind(
481             &LayerTreeHostTestAsyncTwoReadbacksWithoutDraw::CopyOutputCallback,
482             base::Unretained(this))));
483   }
484
485   virtual void BeginTest() OVERRIDE {
486     saw_copy_request_ = false;
487     callback_count_ = 0;
488     PostSetNeedsCommitToMainThread();
489
490     // Prevent drawing.
491     layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
492
493     AddCopyRequest(copy_layer_.get());
494   }
495
496   virtual 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;
501     }
502   }
503
504   virtual void DidCommit() OVERRIDE {
505     if (layer_tree_host()->source_frame_number() == 1) {
506       // Allow drawing.
507       layer_tree_host()->SetViewportSize(gfx::Size(root_->bounds()));
508
509       AddCopyRequest(copy_layer_.get());
510     }
511   }
512
513   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
514     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
515     EXPECT_EQ(copy_layer_->bounds().ToString(), result->size().ToString());
516     ++callback_count_;
517
518     if (callback_count_ == 2)
519       EndTest();
520   }
521
522   virtual void AfterTest() OVERRIDE { EXPECT_TRUE(saw_copy_request_); }
523
524   bool saw_copy_request_;
525   int callback_count_;
526   FakeContentLayerClient client_;
527   scoped_refptr<FakeContentLayer> root_;
528   scoped_refptr<FakeContentLayer> copy_layer_;
529 };
530
531 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
532     LayerTreeHostTestAsyncTwoReadbacksWithoutDraw);
533
534 class LayerTreeHostCopyRequestTestLostOutputSurface
535     : public LayerTreeHostCopyRequestTest {
536  protected:
537   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
538       OVERRIDE {
539     if (!first_context_provider_.get()) {
540       first_context_provider_ = TestContextProvider::Create();
541       return FakeOutputSurface::Create3d(first_context_provider_);
542     }
543
544     EXPECT_FALSE(second_context_provider_.get());
545     second_context_provider_ = TestContextProvider::Create();
546     return FakeOutputSurface::Create3d(second_context_provider_);
547   }
548
549   virtual void SetupTree() OVERRIDE {
550     root_ = FakeContentLayer::Create(&client_);
551     root_->SetBounds(gfx::Size(20, 20));
552
553     copy_layer_ = FakeContentLayer::Create(&client_);
554     copy_layer_->SetBounds(gfx::Size(10, 10));
555     root_->AddChild(copy_layer_);
556
557     layer_tree_host()->SetRootLayer(root_);
558     LayerTreeHostCopyRequestTest::SetupTree();
559   }
560
561   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
562
563   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
564     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
565     EXPECT_EQ(gfx::Size(10, 10).ToString(), result->size().ToString());
566     EXPECT_TRUE(result->HasTexture());
567
568     // Save the result for later.
569     EXPECT_FALSE(result_);
570     result_ = result.Pass();
571
572     // Post a commit to lose the output surface.
573     layer_tree_host()->SetNeedsCommit();
574   }
575
576   virtual void DidCommitAndDrawFrame() OVERRIDE {
577     switch (layer_tree_host()->source_frame_number()) {
578       case 1:
579         // The layers have been pushed to the impl side. The layer textures have
580         // been allocated.
581
582         // Request a copy of the layer. This will use another texture.
583         copy_layer_->RequestCopyOfOutput(CopyOutputRequest::CreateRequest(
584             base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
585                             CopyOutputCallback,
586                        base::Unretained(this))));
587         break;
588       case 4:
589       // With SingleThreadProxy it takes two commits to finally swap after a
590       // context loss.
591       case 5:
592         // Now destroy the CopyOutputResult, releasing the texture inside back
593         // to the compositor.
594         EXPECT_TRUE(result_);
595         result_.reset();
596
597         // Check that it is released.
598         ImplThreadTaskRunner()->PostTask(
599             FROM_HERE,
600             base::Bind(&LayerTreeHostCopyRequestTestLostOutputSurface::
601                             CheckNumTextures,
602                        base::Unretained(this),
603                        num_textures_after_loss_ - 1));
604         break;
605     }
606   }
607
608   virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
609                                    bool result) OVERRIDE {
610     switch (impl->active_tree()->source_frame_number()) {
611       case 0:
612         // The layers have been drawn, so their textures have been allocated.
613         EXPECT_FALSE(result_);
614         num_textures_without_readback_ =
615             first_context_provider_->TestContext3d()->NumTextures();
616         break;
617       case 1:
618         // We did a readback, so there will be a readback texture around now.
619         EXPECT_LT(num_textures_without_readback_,
620                   first_context_provider_->TestContext3d()->NumTextures());
621         break;
622       case 2:
623         // The readback texture is collected.
624         EXPECT_TRUE(result_);
625
626         // Lose the output surface.
627         first_context_provider_->TestContext3d()->loseContextCHROMIUM(
628             GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB);
629         break;
630       case 3:
631       // With SingleThreadProxy it takes two commits to finally swap after a
632       // context loss.
633       case 4:
634         // The output surface has been recreated.
635         EXPECT_TRUE(second_context_provider_.get());
636
637         num_textures_after_loss_ =
638             first_context_provider_->TestContext3d()->NumTextures();
639         break;
640     }
641   }
642
643   void CheckNumTextures(size_t expected_num_textures) {
644     EXPECT_EQ(expected_num_textures,
645               first_context_provider_->TestContext3d()->NumTextures());
646     EndTest();
647   }
648
649   virtual void AfterTest() OVERRIDE {}
650
651   scoped_refptr<TestContextProvider> first_context_provider_;
652   scoped_refptr<TestContextProvider> second_context_provider_;
653   size_t num_textures_without_readback_;
654   size_t num_textures_after_loss_;
655   FakeContentLayerClient client_;
656   scoped_refptr<FakeContentLayer> root_;
657   scoped_refptr<FakeContentLayer> copy_layer_;
658   scoped_ptr<CopyOutputResult> result_;
659 };
660
661 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
662     LayerTreeHostCopyRequestTestLostOutputSurface);
663
664 class LayerTreeHostCopyRequestTestCountTextures
665     : public LayerTreeHostCopyRequestTest {
666  protected:
667   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
668       OVERRIDE {
669     context_provider_ = TestContextProvider::Create();
670     return FakeOutputSurface::Create3d(context_provider_);
671   }
672
673   virtual void SetupTree() OVERRIDE {
674     root_ = FakeContentLayer::Create(&client_);
675     root_->SetBounds(gfx::Size(20, 20));
676
677     copy_layer_ = FakeContentLayer::Create(&client_);
678     copy_layer_->SetBounds(gfx::Size(10, 10));
679     root_->AddChild(copy_layer_);
680
681     layer_tree_host()->SetRootLayer(root_);
682     LayerTreeHostCopyRequestTest::SetupTree();
683   }
684
685   virtual void BeginTest() OVERRIDE {
686     num_textures_without_readback_ = 0;
687     num_textures_with_readback_ = 0;
688     waited_sync_point_after_readback_ = 0;
689     PostSetNeedsCommitToMainThread();
690   }
691
692   virtual void RequestCopy(Layer* layer) = 0;
693
694   virtual void DidCommitAndDrawFrame() OVERRIDE {
695     switch (layer_tree_host()->source_frame_number()) {
696       case 1:
697         // The layers have been pushed to the impl side. The layer textures have
698         // been allocated.
699         RequestCopy(copy_layer_.get());
700         break;
701     }
702   }
703
704   virtual void SwapBuffersOnThread(LayerTreeHostImpl* impl,
705                                    bool result) OVERRIDE {
706     switch (impl->active_tree()->source_frame_number()) {
707       case 0:
708         // The layers have been drawn, so their textures have been allocated.
709         num_textures_without_readback_ =
710             context_provider_->TestContext3d()->NumTextures();
711         break;
712       case 1:
713         // We did a readback, so there will be a readback texture around now.
714         num_textures_with_readback_ =
715             context_provider_->TestContext3d()->NumTextures();
716         waited_sync_point_after_readback_ =
717             context_provider_->TestContext3d()->last_waited_sync_point();
718
719         MainThreadTaskRunner()->PostTask(
720             FROM_HERE,
721             base::Bind(&LayerTreeHostCopyRequestTestCountTextures::DoEndTest,
722                        base::Unretained(this)));
723         break;
724     }
725   }
726
727   virtual void DoEndTest() { EndTest(); }
728
729   scoped_refptr<TestContextProvider> context_provider_;
730   size_t num_textures_without_readback_;
731   size_t num_textures_with_readback_;
732   unsigned waited_sync_point_after_readback_;
733   FakeContentLayerClient client_;
734   scoped_refptr<FakeContentLayer> root_;
735   scoped_refptr<FakeContentLayer> copy_layer_;
736 };
737
738 class LayerTreeHostCopyRequestTestCreatesTexture
739     : public LayerTreeHostCopyRequestTestCountTextures {
740  protected:
741   virtual void RequestCopy(Layer* layer) OVERRIDE {
742     // Request a normal texture copy. This should create a new texture.
743     copy_layer_->RequestCopyOfOutput(
744         CopyOutputRequest::CreateRequest(base::Bind(
745             &LayerTreeHostCopyRequestTestCreatesTexture::CopyOutputCallback,
746             base::Unretained(this))));
747   }
748
749   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
750     EXPECT_FALSE(result->IsEmpty());
751     EXPECT_TRUE(result->HasTexture());
752
753     TextureMailbox mailbox;
754     scoped_ptr<SingleReleaseCallback> release;
755     result->TakeTexture(&mailbox, &release);
756     EXPECT_TRUE(release);
757
758     release->Run(0, false);
759   }
760
761   virtual void AfterTest() OVERRIDE {
762     // No sync point was needed.
763     EXPECT_EQ(0u, waited_sync_point_after_readback_);
764     // Except the copy to have made another texture.
765     EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_);
766   }
767 };
768
769 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
770     LayerTreeHostCopyRequestTestCreatesTexture);
771
772 class LayerTreeHostCopyRequestTestProvideTexture
773     : public LayerTreeHostCopyRequestTestCountTextures {
774  protected:
775   virtual void BeginTest() OVERRIDE {
776     external_context_provider_ = TestContextProvider::Create();
777     EXPECT_TRUE(external_context_provider_->BindToCurrentThread());
778     LayerTreeHostCopyRequestTestCountTextures::BeginTest();
779   }
780
781   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
782     EXPECT_FALSE(result->IsEmpty());
783     EXPECT_TRUE(result->HasTexture());
784
785     TextureMailbox mailbox;
786     scoped_ptr<SingleReleaseCallback> release;
787     result->TakeTexture(&mailbox, &release);
788     EXPECT_FALSE(release);
789   }
790
791   virtual void RequestCopy(Layer* layer) OVERRIDE {
792     // Request a copy to a provided texture. This should not create a new
793     // texture.
794     scoped_ptr<CopyOutputRequest> request =
795         CopyOutputRequest::CreateRequest(base::Bind(
796             &LayerTreeHostCopyRequestTestProvideTexture::CopyOutputCallback,
797             base::Unretained(this)));
798
799     gpu::gles2::GLES2Interface* gl = external_context_provider_->ContextGL();
800     gpu::Mailbox mailbox;
801     gl->GenMailboxCHROMIUM(mailbox.name);
802     sync_point_ = gl->InsertSyncPointCHROMIUM();
803     request->SetTextureMailbox(
804         TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point_));
805     EXPECT_TRUE(request->has_texture_mailbox());
806
807     copy_layer_->RequestCopyOfOutput(request.Pass());
808   }
809
810   virtual void AfterTest() OVERRIDE {
811     // Expect the compositor to have waited for the sync point in the provided
812     // TextureMailbox.
813     EXPECT_EQ(sync_point_, waited_sync_point_after_readback_);
814     // Except the copy to have *not* made another texture.
815     EXPECT_EQ(num_textures_without_readback_, num_textures_with_readback_);
816   }
817
818   scoped_refptr<TestContextProvider> external_context_provider_;
819   unsigned sync_point_;
820 };
821
822 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_NOIMPL_TEST_F(
823     LayerTreeHostCopyRequestTestProvideTexture);
824
825 class LayerTreeHostCopyRequestTestDestroyBeforeCopy
826     : public LayerTreeHostCopyRequestTest {
827  protected:
828   virtual void SetupTree() OVERRIDE {
829     root_ = FakeContentLayer::Create(&client_);
830     root_->SetBounds(gfx::Size(20, 20));
831
832     copy_layer_ = FakeContentLayer::Create(&client_);
833     copy_layer_->SetBounds(gfx::Size(10, 10));
834     root_->AddChild(copy_layer_);
835
836     layer_tree_host()->SetRootLayer(root_);
837     LayerTreeHostCopyRequestTest::SetupTree();
838   }
839
840   virtual void BeginTest() OVERRIDE {
841     callback_count_ = 0;
842     PostSetNeedsCommitToMainThread();
843   }
844
845   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
846     EXPECT_TRUE(result->IsEmpty());
847     ++callback_count_;
848   }
849
850   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
851     MainThreadTaskRunner()->PostTask(
852         FROM_HERE,
853         base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::DidActivate,
854                    base::Unretained(this)));
855   }
856
857   void DidActivate() {
858     switch (layer_tree_host()->source_frame_number()) {
859       case 1: {
860         EXPECT_EQ(0, callback_count_);
861         // Put a copy request on the layer, but then don't allow any
862         // drawing to take place.
863         scoped_ptr<CopyOutputRequest> request =
864             CopyOutputRequest::CreateRequest(
865                 base::Bind(&LayerTreeHostCopyRequestTestDestroyBeforeCopy::
866                                 CopyOutputCallback,
867                            base::Unretained(this)));
868         copy_layer_->RequestCopyOfOutput(request.Pass());
869
870         layer_tree_host()->SetViewportSize(gfx::Size());
871         break;
872       }
873       case 2:
874         EXPECT_EQ(0, callback_count_);
875         // Remove the copy layer before we were able to draw.
876         copy_layer_->RemoveFromParent();
877         break;
878       case 3:
879         EXPECT_EQ(1, callback_count_);
880         // Allow us to draw now.
881         layer_tree_host()->SetViewportSize(
882             layer_tree_host()->root_layer()->bounds());
883         break;
884       case 4:
885         EXPECT_EQ(1, callback_count_);
886         // We should not have crashed.
887         EndTest();
888     }
889   }
890
891   virtual void AfterTest() OVERRIDE {}
892
893   int callback_count_;
894   FakeContentLayerClient client_;
895   scoped_refptr<FakeContentLayer> root_;
896   scoped_refptr<FakeContentLayer> copy_layer_;
897 };
898
899 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
900     LayerTreeHostCopyRequestTestDestroyBeforeCopy);
901
902 class LayerTreeHostCopyRequestTestShutdownBeforeCopy
903     : public LayerTreeHostCopyRequestTest {
904  protected:
905   virtual void SetupTree() OVERRIDE {
906     root_ = FakeContentLayer::Create(&client_);
907     root_->SetBounds(gfx::Size(20, 20));
908
909     copy_layer_ = FakeContentLayer::Create(&client_);
910     copy_layer_->SetBounds(gfx::Size(10, 10));
911     root_->AddChild(copy_layer_);
912
913     layer_tree_host()->SetRootLayer(root_);
914     LayerTreeHostCopyRequestTest::SetupTree();
915   }
916
917   virtual void BeginTest() OVERRIDE {
918     callback_count_ = 0;
919     PostSetNeedsCommitToMainThread();
920   }
921
922   void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
923     EXPECT_TRUE(result->IsEmpty());
924     ++callback_count_;
925   }
926
927   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
928     MainThreadTaskRunner()->PostTask(
929         FROM_HERE,
930         base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::DidActivate,
931                    base::Unretained(this)));
932   }
933
934   void DidActivate() {
935     switch (layer_tree_host()->source_frame_number()) {
936       case 1: {
937         EXPECT_EQ(0, callback_count_);
938         // Put a copy request on the layer, but then don't allow any
939         // drawing to take place.
940         scoped_ptr<CopyOutputRequest> request =
941             CopyOutputRequest::CreateRequest(
942                 base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::
943                                 CopyOutputCallback,
944                            base::Unretained(this)));
945         copy_layer_->RequestCopyOfOutput(request.Pass());
946
947         layer_tree_host()->SetViewportSize(gfx::Size());
948         break;
949       }
950       case 2:
951         DestroyLayerTreeHost();
952         // End the test after the copy result has had a chance to get back to
953         // the main thread.
954         MainThreadTaskRunner()->PostTask(
955             FROM_HERE,
956             base::Bind(&LayerTreeHostCopyRequestTestShutdownBeforeCopy::EndTest,
957                        base::Unretained(this)));
958         break;
959     }
960   }
961
962   virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, callback_count_); }
963
964   int callback_count_;
965   FakeContentLayerClient client_;
966   scoped_refptr<FakeContentLayer> root_;
967   scoped_refptr<FakeContentLayer> copy_layer_;
968 };
969
970 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
971     LayerTreeHostCopyRequestTestShutdownBeforeCopy);
972
973 }  // namespace
974 }  // namespace cc