1 // Copyright 2012 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/texture_layer.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "cc/layers/solid_color_layer.h"
16 #include "cc/layers/texture_layer_client.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/output/compositor_frame_ack.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/resources/returned_resource.h"
21 #include "cc/test/fake_impl_proxy.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_layer_tree_host_impl.h"
24 #include "cc/test/fake_output_surface.h"
25 #include "cc/test/layer_test_common.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_web_graphics_context_3d.h"
28 #include "cc/trees/blocking_task_runner.h"
29 #include "cc/trees/layer_tree_host.h"
30 #include "cc/trees/layer_tree_impl.h"
31 #include "cc/trees/single_thread_proxy.h"
32 #include "gpu/GLES2/gl2extchromium.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 using ::testing::Mock;
38 using ::testing::AtLeast;
39 using ::testing::AnyNumber;
44 gpu::Mailbox MailboxFromChar(char value) {
46 memset(mailbox.name, value, sizeof(mailbox.name));
50 class MockLayerTreeHost : public LayerTreeHost {
52 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client)
53 : LayerTreeHost(client, NULL, LayerTreeSettings()) {
54 InitializeSingleThreaded(client);
57 MOCK_METHOD0(AcquireLayerTextures, void());
58 MOCK_METHOD0(SetNeedsCommit, void());
59 MOCK_METHOD0(SetNeedsUpdateLayers, void());
60 MOCK_METHOD0(StartRateLimiter, void());
61 MOCK_METHOD0(StopRateLimiter, void());
64 class TextureLayerTest : public testing::Test {
68 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
69 host_impl_(&proxy_, &shared_bitmap_manager_) {}
72 virtual void SetUp() {
73 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
76 virtual void TearDown() {
77 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
78 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
79 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
81 layer_tree_host_->SetRootLayer(NULL);
82 layer_tree_host_.reset();
85 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
87 FakeLayerTreeHostClient fake_client_;
88 TestSharedBitmapManager shared_bitmap_manager_;
89 FakeLayerTreeHostImpl host_impl_;
92 TEST_F(TextureLayerTest, SyncImplWhenChangingTextureId) {
93 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
94 ASSERT_TRUE(test_layer.get());
96 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
97 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
98 layer_tree_host_->SetRootLayer(test_layer);
99 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
100 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
102 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
103 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
104 test_layer->SetTextureId(1);
105 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
107 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
108 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
109 test_layer->SetTextureId(2);
110 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
112 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
113 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
114 test_layer->SetTextureId(0);
115 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
118 TEST_F(TextureLayerTest, SyncImplWhenDrawing) {
119 gfx::RectF dirty_rect(0.f, 0.f, 1.f, 1.f);
121 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
122 ASSERT_TRUE(test_layer.get());
123 scoped_ptr<TextureLayerImpl> impl_layer;
124 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
125 ASSERT_TRUE(impl_layer);
127 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
128 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
129 layer_tree_host_->SetRootLayer(test_layer);
130 test_layer->SetTextureId(1);
131 test_layer->SetIsDrawable(true);
132 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
133 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
135 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
136 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
137 test_layer->WillModifyTexture();
138 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
140 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
141 EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(1);
142 test_layer->SetNeedsDisplayRect(dirty_rect);
143 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
145 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
146 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
147 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
148 test_layer->SetIsDrawable(false);
149 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
151 // Verify that non-drawable layers don't signal the compositor,
152 // except for the first draw after last commit, which must acquire
154 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
155 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
156 test_layer->WillModifyTexture();
157 test_layer->SetNeedsDisplayRect(dirty_rect);
158 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
159 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
161 // Second draw with layer in non-drawable state: no texture
163 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
164 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
165 test_layer->WillModifyTexture();
166 test_layer->SetNeedsDisplayRect(dirty_rect);
167 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
170 TEST_F(TextureLayerTest, SyncImplWhenRemovingFromTree) {
171 scoped_refptr<Layer> root_layer = Layer::Create();
172 ASSERT_TRUE(root_layer.get());
173 scoped_refptr<Layer> child_layer = Layer::Create();
174 ASSERT_TRUE(child_layer.get());
175 root_layer->AddChild(child_layer);
176 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
177 ASSERT_TRUE(test_layer.get());
178 test_layer->SetTextureId(0);
179 child_layer->AddChild(test_layer);
181 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
182 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
183 layer_tree_host_->SetRootLayer(root_layer);
184 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
186 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
187 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
188 test_layer->RemoveFromParent();
189 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
191 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
192 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
193 child_layer->AddChild(test_layer);
194 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
196 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
197 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
198 test_layer->SetTextureId(1);
199 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
201 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
202 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
203 test_layer->RemoveFromParent();
204 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
207 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
208 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
209 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
211 // Test properties that should call SetNeedsCommit. All properties need to
212 // be set to new values in order for SetNeedsCommit to be called.
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
214 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
215 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
216 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
217 0.5f, 0.5f, 0.5f, 0.5f));
218 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
219 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
220 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTextureId(1));
222 // Calling SetTextureId can call AcquireLayerTextures.
223 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
226 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
227 const gfx::Size layer_bounds(100, 100);
228 const gfx::Rect layer_rect(layer_bounds);
229 const Region layer_region(layer_rect);
231 scoped_refptr<TextureLayer> layer = TextureLayer::Create(NULL);
232 layer->SetBounds(layer_bounds);
233 layer->draw_properties().visible_content_rect = layer_rect;
234 layer->SetBlendBackgroundColor(true);
236 // Verify initial conditions.
237 EXPECT_FALSE(layer->contents_opaque());
238 EXPECT_EQ(0u, layer->background_color());
239 EXPECT_EQ(Region().ToString(),
240 layer->VisibleContentOpaqueRegion().ToString());
242 // Opaque background.
243 layer->SetBackgroundColor(SK_ColorWHITE);
244 EXPECT_EQ(layer_region.ToString(),
245 layer->VisibleContentOpaqueRegion().ToString());
247 // Transparent background.
248 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
249 EXPECT_EQ(Region().ToString(),
250 layer->VisibleContentOpaqueRegion().ToString());
253 class FakeTextureLayerClient : public TextureLayerClient {
255 FakeTextureLayerClient() {}
257 virtual unsigned PrepareTexture() OVERRIDE {
261 virtual bool PrepareTextureMailbox(
262 TextureMailbox* mailbox,
263 scoped_ptr<SingleReleaseCallback>* release_callback,
264 bool use_shared_memory) OVERRIDE {
265 *mailbox = TextureMailbox();
266 *release_callback = scoped_ptr<SingleReleaseCallback>();
271 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
274 TEST_F(TextureLayerTest, RateLimiter) {
275 FakeTextureLayerClient client;
276 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
278 test_layer->SetIsDrawable(true);
279 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
280 layer_tree_host_->SetRootLayer(test_layer);
282 // Don't rate limit until we invalidate.
283 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
284 test_layer->SetRateLimitContext(true);
285 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
287 // Do rate limit after we invalidate.
288 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
289 test_layer->SetNeedsDisplay();
290 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
292 // Stop rate limiter when we don't want it any more.
293 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
294 test_layer->SetRateLimitContext(false);
295 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
297 // Or we clear the client.
298 test_layer->SetRateLimitContext(true);
299 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
300 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
301 test_layer->ClearClient();
302 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
304 // Reset to a layer with a client, that started the rate limiter.
305 test_layer = TextureLayer::CreateForMailbox(
307 test_layer->SetIsDrawable(true);
308 test_layer->SetRateLimitContext(true);
309 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
310 layer_tree_host_->SetRootLayer(test_layer);
311 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0);
312 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
313 EXPECT_CALL(*layer_tree_host_, StartRateLimiter());
314 test_layer->SetNeedsDisplay();
315 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
317 // Stop rate limiter when we're removed from the tree.
318 EXPECT_CALL(*layer_tree_host_, StopRateLimiter());
319 layer_tree_host_->SetRootLayer(NULL);
320 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
323 class MockMailboxCallback {
325 MOCK_METHOD3(Release,
326 void(const gpu::Mailbox& mailbox,
328 bool lost_resource));
329 MOCK_METHOD3(Release2,
330 void(base::SharedMemory* shared_memory,
332 bool lost_resource));
335 struct CommonMailboxObjects {
336 CommonMailboxObjects()
337 : mailbox_name1_(MailboxFromChar('1')),
338 mailbox_name2_(MailboxFromChar('2')),
341 shared_memory_(new base::SharedMemory) {
342 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
343 base::Unretained(&mock_callback_),
345 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
346 base::Unretained(&mock_callback_),
348 const uint32 arbitrary_target1 = 1;
349 const uint32 arbitrary_target2 = 2;
350 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_);
351 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_);
352 gfx::Size size(128, 128);
353 EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
354 release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
355 base::Unretained(&mock_callback_),
356 shared_memory_.get());
357 mailbox3_ = TextureMailbox(shared_memory_.get(), size);
360 gpu::Mailbox mailbox_name1_;
361 gpu::Mailbox mailbox_name2_;
362 MockMailboxCallback mock_callback_;
363 ReleaseCallback release_mailbox1_;
364 ReleaseCallback release_mailbox2_;
365 ReleaseCallback release_mailbox3_;
366 TextureMailbox mailbox1_;
367 TextureMailbox mailbox2_;
368 TextureMailbox mailbox3_;
371 scoped_ptr<base::SharedMemory> shared_memory_;
374 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder {
376 using TextureLayer::TextureMailboxHolder::Create;
379 virtual ~TestMailboxHolder() {}
382 class TextureLayerWithMailboxTest : public TextureLayerTest {
384 virtual void TearDown() {
385 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
386 EXPECT_CALL(test_data_.mock_callback_,
387 Release(test_data_.mailbox_name1_,
388 test_data_.sync_point1_,
390 TextureLayerTest::TearDown();
393 CommonMailboxObjects test_data_;
396 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
397 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
398 ASSERT_TRUE(test_layer.get());
400 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
401 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
402 layer_tree_host_->SetRootLayer(test_layer);
403 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
405 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
406 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
407 test_layer->SetTextureMailbox(
408 test_data_.mailbox1_,
409 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
410 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
412 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
413 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
414 EXPECT_CALL(test_data_.mock_callback_,
415 Release(test_data_.mailbox_name1_,
416 test_data_.sync_point1_,
419 test_layer->SetTextureMailbox(
420 test_data_.mailbox2_,
421 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
422 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
423 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
425 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
426 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
427 EXPECT_CALL(test_data_.mock_callback_,
428 Release(test_data_.mailbox_name2_,
429 test_data_.sync_point2_,
432 test_layer->SetTextureMailbox(TextureMailbox(),
433 scoped_ptr<SingleReleaseCallback>());
434 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
435 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
437 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
438 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
439 test_layer->SetTextureMailbox(
440 test_data_.mailbox3_,
441 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
442 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
443 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
445 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
446 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
447 EXPECT_CALL(test_data_.mock_callback_,
448 Release2(test_data_.shared_memory_.get(),
451 test_layer->SetTextureMailbox(TextureMailbox(),
452 scoped_ptr<SingleReleaseCallback>());
453 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
454 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
457 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
458 test_layer->SetTextureMailbox(
459 test_data_.mailbox1_,
460 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
463 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) {
464 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
465 ASSERT_TRUE(test_layer.get());
467 // These use the same gpu::Mailbox, but different sync points.
468 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1);
469 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2);
471 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
472 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
473 layer_tree_host_->SetRootLayer(test_layer);
474 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
476 // Set the mailbox the first time. It should cause a commit.
477 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
478 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
479 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1);
480 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
482 // Set the mailbox again with a new sync point, as the backing texture has
483 // been updated. It should cause a new commit.
484 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
485 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
486 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2);
487 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
490 class TextureLayerMailboxHolderTest : public TextureLayerTest {
492 TextureLayerMailboxHolderTest()
493 : main_thread_("MAIN") {
494 main_thread_.Start();
497 void Wait(const base::Thread& thread) {
498 bool manual_reset = false;
499 bool initially_signaled = false;
500 base::WaitableEvent event(manual_reset, initially_signaled);
501 thread.message_loop()->PostTask(
503 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
507 void CreateMainRef() {
508 main_ref_ = TestMailboxHolder::Create(
509 test_data_.mailbox1_,
510 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
513 void ReleaseMainRef() {
517 void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
518 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
521 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
522 base::WaitableEvent* wait_for_capture,
523 base::WaitableEvent* stop_capture) {
524 begin_capture->Wait();
525 BlockingTaskRunner::CapturePostTasks capture;
526 wait_for_capture->Signal();
527 stop_capture->Wait();
531 scoped_ptr<TestMailboxHolder::MainThreadReference>
533 base::Thread main_thread_;
534 CommonMailboxObjects test_data_;
537 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
538 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
539 ASSERT_TRUE(test_layer.get());
541 main_thread_.message_loop()->PostTask(
543 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
544 base::Unretained(this)));
548 // The texture layer is attached to compositor1, and passes a reference to its
550 scoped_ptr<SingleReleaseCallback> compositor1;
551 main_thread_.message_loop()->PostTask(
553 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
554 base::Unretained(this),
557 // Then the texture layer is removed and attached to compositor2, and passes a
558 // reference to its impl tree.
559 scoped_ptr<SingleReleaseCallback> compositor2;
560 main_thread_.message_loop()->PostTask(
562 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
563 base::Unretained(this),
567 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
569 // The compositors both destroy their impl trees before the main thread layer
571 compositor1->Run(100, false);
572 compositor2->Run(200, false);
576 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
577 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
579 // The main thread ref is the last one, so the mailbox is released back to the
580 // embedder, with the last sync point provided by the impl trees.
581 EXPECT_CALL(test_data_.mock_callback_,
582 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
584 main_thread_.message_loop()->PostTask(
586 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
587 base::Unretained(this)));
589 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
592 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
593 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
594 ASSERT_TRUE(test_layer.get());
596 main_thread_.message_loop()->PostTask(
598 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
599 base::Unretained(this)));
603 // The texture layer is attached to compositor1, and passes a reference to its
605 scoped_ptr<SingleReleaseCallback> compositor1;
606 main_thread_.message_loop()->PostTask(
608 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
609 base::Unretained(this),
612 // Then the texture layer is removed and attached to compositor2, and passes a
613 // reference to its impl tree.
614 scoped_ptr<SingleReleaseCallback> compositor2;
615 main_thread_.message_loop()->PostTask(
617 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
618 base::Unretained(this),
622 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
624 // One compositor destroys their impl tree.
625 compositor1->Run(100, false);
627 // Then the main thread reference is destroyed.
628 main_thread_.message_loop()->PostTask(
630 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
631 base::Unretained(this)));
635 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
636 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
638 // The second impl reference is destroyed last, causing the mailbox to be
639 // released back to the embedder with the last sync point from the impl tree.
640 EXPECT_CALL(test_data_.mock_callback_,
641 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
643 compositor2->Run(200, true);
645 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
648 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
649 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
650 ASSERT_TRUE(test_layer.get());
652 main_thread_.message_loop()->PostTask(
654 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
655 base::Unretained(this)));
659 // The texture layer is attached to compositor1, and passes a reference to its
661 scoped_ptr<SingleReleaseCallback> compositor1;
662 main_thread_.message_loop()->PostTask(
664 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
665 base::Unretained(this),
668 // Then the texture layer is removed and attached to compositor2, and passes a
669 // reference to its impl tree.
670 scoped_ptr<SingleReleaseCallback> compositor2;
671 main_thread_.message_loop()->PostTask(
673 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
674 base::Unretained(this),
678 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
680 // The main thread reference is destroyed first.
681 main_thread_.message_loop()->PostTask(
683 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
684 base::Unretained(this)));
686 // One compositor destroys their impl tree.
687 compositor2->Run(200, false);
691 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
692 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
694 // The second impl reference is destroyed last, causing the mailbox to be
695 // released back to the embedder with the last sync point from the impl tree.
696 EXPECT_CALL(test_data_.mock_callback_,
697 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
699 compositor1->Run(100, true);
701 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
704 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
705 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
706 ASSERT_TRUE(test_layer.get());
708 main_thread_.message_loop()->PostTask(
710 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
711 base::Unretained(this)));
715 // The texture layer is attached to compositor1, and passes a reference to its
717 scoped_ptr<SingleReleaseCallback> compositor1;
718 main_thread_.message_loop()->PostTask(
720 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
721 base::Unretained(this),
724 // Then the texture layer is removed and attached to compositor2, and passes a
725 // reference to its impl tree.
726 scoped_ptr<SingleReleaseCallback> compositor2;
727 main_thread_.message_loop()->PostTask(
729 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
730 base::Unretained(this),
734 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
736 // The main thread reference is destroyed first.
737 main_thread_.message_loop()->PostTask(
739 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
740 base::Unretained(this)));
742 EXPECT_CALL(test_data_.mock_callback_,
743 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
745 bool manual_reset = false;
746 bool initially_signaled = false;
747 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
748 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
749 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
751 // Post a task to start capturing tasks on the main thread. This will block
752 // the main thread until we signal the |stop_capture| event.
753 main_thread_.message_loop()->PostTask(
755 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
756 base::Unretained(this),
761 // Before the main thread capturing starts, one compositor destroys their
762 // impl reference. Since capturing did not start, this gets post-tasked to
764 compositor1->Run(100, false);
766 // Start capturing on the main thread.
767 begin_capture.Signal();
768 wait_for_capture.Wait();
770 // Meanwhile, the second compositor released its impl reference, but this task
771 // gets shortcutted directly to the main thread. This means the reference is
772 // released before compositor1, whose reference will be released later when
773 // the post-task is serviced. But since it was destroyed _on the impl thread_
774 // last, its sync point values should be used.
775 compositor2->Run(200, true);
777 stop_capture.Signal();
780 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
783 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
785 TextureLayerImplWithMailboxThreadedCallback()
786 : callback_count_(0),
789 // Make sure callback is received on main and doesn't block the impl thread.
790 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
791 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
792 EXPECT_FALSE(lost_resource);
796 void SetMailbox(char mailbox_char) {
797 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
798 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
800 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
801 base::Unretained(this)));
802 layer_->SetTextureMailbox(
803 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
807 virtual void BeginTest() OVERRIDE {
808 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
810 gfx::Size bounds(100, 100);
811 root_ = Layer::Create();
812 root_->SetAnchorPoint(gfx::PointF());
813 root_->SetBounds(bounds);
815 layer_ = TextureLayer::CreateForMailbox(NULL);
816 layer_->SetIsDrawable(true);
817 layer_->SetAnchorPoint(gfx::PointF());
818 layer_->SetBounds(bounds);
820 root_->AddChild(layer_);
821 layer_tree_host()->SetRootLayer(root_);
822 layer_tree_host()->SetViewportSize(bounds);
824 EXPECT_EQ(0, callback_count_);
826 // Case #1: change mailbox before the commit. The old mailbox should be
827 // released immediately.
829 EXPECT_EQ(1, callback_count_);
830 PostSetNeedsCommitToMainThread();
833 virtual void DidCommit() OVERRIDE {
835 switch (commit_count_) {
837 // Case #2: change mailbox after the commit (and draw), where the
838 // layer draws. The old mailbox should be released during the next
841 EXPECT_EQ(1, callback_count_);
844 EXPECT_EQ(2, callback_count_);
845 // Case #3: change mailbox when the layer doesn't draw. The old
846 // mailbox should be released during the next commit.
847 layer_->SetBounds(gfx::Size());
851 EXPECT_EQ(3, callback_count_);
852 // Case #4: release mailbox that was committed but never drawn. The
853 // old mailbox should be released during the next commit.
854 layer_->SetTextureMailbox(TextureMailbox(),
855 scoped_ptr<SingleReleaseCallback>());
858 if (layer_tree_host()->settings().impl_side_painting) {
859 // With impl painting, the texture mailbox will still be on the impl
860 // thread when the commit finishes, because the layer is not drawble
861 // when it has no texture mailbox, and thus does not block the commit
862 // on activation. So, we wait for activation.
863 // TODO(danakj): fix this. crbug.com/277953
864 layer_tree_host()->SetNeedsCommit();
870 EXPECT_EQ(4, callback_count_);
871 // Restore a mailbox for the next step.
875 // Case #5: remove layer from tree. Callback should *not* be called, the
876 // mailbox is returned to the main thread.
877 EXPECT_EQ(4, callback_count_);
878 layer_->RemoveFromParent();
881 if (layer_tree_host()->settings().impl_side_painting) {
882 // With impl painting, the texture mailbox will still be on the impl
883 // thread when the commit finishes, because the layer is not around to
884 // block the commit on activation anymore. So, we wait for activation.
885 // TODO(danakj): fix this. crbug.com/277953
886 layer_tree_host()->SetNeedsCommit();
892 EXPECT_EQ(4, callback_count_);
893 // Resetting the mailbox will call the callback now.
894 layer_->SetTextureMailbox(TextureMailbox(),
895 scoped_ptr<SingleReleaseCallback>());
896 EXPECT_EQ(5, callback_count_);
905 virtual void AfterTest() OVERRIDE {}
908 base::ThreadChecker main_thread_;
911 scoped_refptr<Layer> root_;
912 scoped_refptr<TextureLayer> layer_;
915 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
916 TextureLayerImplWithMailboxThreadedCallback);
919 class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
920 public TextureLayerClient {
922 TextureLayerNoMailboxIsActivatedDuringCommit()
923 : texture_(0u), activate_count_(0) {}
925 virtual void BeginTest() OVERRIDE {
926 gfx::Size bounds(100, 100);
927 root_ = Layer::Create();
928 root_->SetAnchorPoint(gfx::PointF());
929 root_->SetBounds(bounds);
931 layer_ = TextureLayer::Create(this);
932 layer_->SetIsDrawable(true);
933 layer_->SetAnchorPoint(gfx::PointF());
934 layer_->SetBounds(bounds);
936 root_->AddChild(layer_);
937 layer_tree_host()->SetRootLayer(root_);
938 layer_tree_host()->SetViewportSize(bounds);
940 PostSetNeedsCommitToMainThread();
943 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
945 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
946 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
947 return FakeOutputSurface::Create3d(provider);
950 // TextureLayerClient implementation.
951 virtual unsigned PrepareTexture() OVERRIDE {
954 virtual bool PrepareTextureMailbox(
955 TextureMailbox* mailbox,
956 scoped_ptr<SingleReleaseCallback>* release_callback,
957 bool use_shared_memory) OVERRIDE {
961 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
965 virtual void DidCommit() OVERRIDE {
966 switch (layer_tree_host()->source_frame_number()) {
968 // The first texture has been activated. Invalidate the layer so it
969 // grabs a new texture id from the client.
970 layer_->SetNeedsDisplay();
973 // The second mailbox has been activated. Remove the layer from
974 // the tree to cause another commit/activation. The commit should
975 // finish *after* the layer is removed from the active tree.
976 layer_->RemoveFromParent();
984 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
985 switch (host_impl->active_tree()->source_frame_number()) {
987 // The activate for the 2nd texture should have happened before now.
988 EXPECT_EQ(2, activate_count_);
992 // The activate to remove the layer should have happened before now.
993 EXPECT_EQ(3, activate_count_);
999 virtual void AfterTest() OVERRIDE {}
1002 int activate_count_;
1003 scoped_refptr<Layer> root_;
1004 scoped_refptr<TextureLayer> layer_;
1007 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1008 TextureLayerNoMailboxIsActivatedDuringCommit);
1010 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
1012 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {}
1014 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {}
1016 void SetMailbox(char mailbox_char) {
1017 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1019 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
1020 layer_->SetTextureMailbox(
1021 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
1025 virtual void BeginTest() OVERRIDE {
1026 gfx::Size bounds(100, 100);
1027 root_ = Layer::Create();
1028 root_->SetAnchorPoint(gfx::PointF());
1029 root_->SetBounds(bounds);
1031 layer_ = TextureLayer::CreateForMailbox(NULL);
1032 layer_->SetIsDrawable(true);
1033 layer_->SetAnchorPoint(gfx::PointF());
1034 layer_->SetBounds(bounds);
1036 root_->AddChild(layer_);
1037 layer_tree_host()->SetRootLayer(root_);
1038 layer_tree_host()->SetViewportSize(bounds);
1041 PostSetNeedsCommitToMainThread();
1044 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1048 virtual void DidCommit() OVERRIDE {
1049 switch (layer_tree_host()->source_frame_number()) {
1051 // The first mailbox has been activated. Set a new mailbox, and
1052 // expect the next commit to finish *after* it is activated.
1056 // The second mailbox has been activated. Remove the layer from
1057 // the tree to cause another commit/activation. The commit should
1058 // finish *after* the layer is removed from the active tree.
1059 layer_->RemoveFromParent();
1067 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1068 switch (host_impl->active_tree()->source_frame_number()) {
1070 // The activate for the 2nd mailbox should have happened before now.
1071 EXPECT_EQ(2, activate_count_);
1075 // The activate to remove the layer should have happened before now.
1076 EXPECT_EQ(3, activate_count_);
1083 virtual void AfterTest() OVERRIDE {}
1085 int activate_count_;
1086 scoped_refptr<Layer> root_;
1087 scoped_refptr<TextureLayer> layer_;
1090 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1091 TextureLayerMailboxIsActivatedDuringCommit);
1093 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
1095 TextureLayerImplWithMailboxTest()
1097 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
1099 virtual void SetUp() {
1100 TextureLayerTest::SetUp();
1101 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
1102 EXPECT_TRUE(host_impl_.InitializeRenderer(
1103 FakeOutputSurface::Create3d().PassAs<OutputSurface>()));
1106 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
1107 bool will_draw = layer->WillDraw(
1108 mode, host_impl_.active_tree()->resource_provider());
1110 layer->DidDraw(host_impl_.active_tree()->resource_provider());
1114 CommonMailboxObjects test_data_;
1115 FakeLayerTreeHostClient fake_client_;
1118 // Test conditions for results of TextureLayerImpl::WillDraw under
1119 // different configurations of different mailbox, texture_id, and draw_mode.
1120 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
1121 EXPECT_CALL(test_data_.mock_callback_,
1122 Release(test_data_.mailbox_name1_,
1123 test_data_.sync_point1_,
1125 .Times(AnyNumber());
1126 EXPECT_CALL(test_data_.mock_callback_,
1127 Release2(test_data_.shared_memory_.get(), 0, false))
1128 .Times(AnyNumber());
1131 scoped_ptr<TextureLayerImpl> impl_layer =
1132 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1133 impl_layer->SetDrawsContent(true);
1134 impl_layer->SetTextureMailbox(
1135 test_data_.mailbox1_,
1136 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1137 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1141 scoped_ptr<TextureLayerImpl> impl_layer =
1142 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1143 impl_layer->SetDrawsContent(true);
1144 impl_layer->SetTextureMailbox(TextureMailbox(),
1145 scoped_ptr<SingleReleaseCallback>());
1146 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1150 // Software resource.
1151 scoped_ptr<TextureLayerImpl> impl_layer =
1152 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1153 impl_layer->SetDrawsContent(true);
1154 impl_layer->SetTextureMailbox(
1155 test_data_.mailbox3_,
1156 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1157 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1161 scoped_ptr<TextureLayerImpl> impl_layer =
1162 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1163 impl_layer->SetDrawsContent(true);
1164 ContextProvider* context_provider =
1165 host_impl_.output_surface()->context_provider();
1167 context_provider->ContextGL()->GenTextures(1, &texture);
1168 impl_layer->SetTextureId(texture);
1169 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1173 scoped_ptr<TextureLayerImpl> impl_layer =
1174 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1175 impl_layer->SetDrawsContent(true);
1176 impl_layer->SetTextureId(0);
1177 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1182 scoped_ptr<TextureLayerImpl> impl_layer =
1183 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1184 impl_layer->SetDrawsContent(true);
1185 impl_layer->SetTextureMailbox(
1186 test_data_.mailbox1_,
1187 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1188 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1192 scoped_ptr<TextureLayerImpl> impl_layer =
1193 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1194 impl_layer->SetDrawsContent(true);
1195 impl_layer->SetTextureMailbox(TextureMailbox(),
1196 scoped_ptr<SingleReleaseCallback>());
1197 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1201 // Software resource.
1202 scoped_ptr<TextureLayerImpl> impl_layer =
1203 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1204 impl_layer->SetDrawsContent(true);
1205 impl_layer->SetTextureMailbox(
1206 test_data_.mailbox3_,
1207 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1208 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1212 scoped_ptr<TextureLayerImpl> impl_layer =
1213 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1214 impl_layer->SetDrawsContent(true);
1215 ContextProvider* context_provider =
1216 host_impl_.output_surface()->context_provider();
1218 context_provider->ContextGL()->GenTextures(1, &texture);
1219 impl_layer->SetTextureId(texture);
1220 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1224 scoped_ptr<TextureLayerImpl> impl_layer =
1225 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1226 impl_layer->SetDrawsContent(true);
1227 impl_layer->SetTextureId(0);
1228 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1231 // Resourceless software mode.
1233 scoped_ptr<TextureLayerImpl> impl_layer =
1234 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1235 impl_layer->SetDrawsContent(true);
1236 impl_layer->SetTextureMailbox(
1237 test_data_.mailbox1_,
1238 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1239 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1243 scoped_ptr<TextureLayerImpl> impl_layer =
1244 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1245 impl_layer->SetDrawsContent(true);
1246 ContextProvider* context_provider =
1247 host_impl_.output_surface()->context_provider();
1249 context_provider->ContextGL()->GenTextures(1, &texture);
1250 impl_layer->SetTextureId(texture);
1251 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1255 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1256 host_impl_.CreatePendingTree();
1257 scoped_ptr<TextureLayerImpl> pending_layer;
1258 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1, true);
1259 ASSERT_TRUE(pending_layer);
1261 scoped_ptr<LayerImpl> active_layer(
1262 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1263 ASSERT_TRUE(active_layer);
1265 pending_layer->SetTextureMailbox(
1266 test_data_.mailbox1_,
1267 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1269 // Test multiple commits without an activation.
1270 EXPECT_CALL(test_data_.mock_callback_,
1271 Release(test_data_.mailbox_name1_,
1272 test_data_.sync_point1_,
1275 pending_layer->SetTextureMailbox(
1276 test_data_.mailbox2_,
1277 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1278 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1280 // Test callback after activation.
1281 pending_layer->PushPropertiesTo(active_layer.get());
1282 active_layer->DidBecomeActive();
1284 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1285 pending_layer->SetTextureMailbox(
1286 test_data_.mailbox1_,
1287 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1288 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1290 EXPECT_CALL(test_data_.mock_callback_,
1291 Release(test_data_.mailbox_name2_, _, false))
1293 pending_layer->PushPropertiesTo(active_layer.get());
1294 active_layer->DidBecomeActive();
1295 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1297 // Test resetting the mailbox.
1298 EXPECT_CALL(test_data_.mock_callback_,
1299 Release(test_data_.mailbox_name1_, _, false))
1301 pending_layer->SetTextureMailbox(TextureMailbox(),
1302 scoped_ptr<SingleReleaseCallback>());
1303 pending_layer->PushPropertiesTo(active_layer.get());
1304 active_layer->DidBecomeActive();
1305 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1308 EXPECT_CALL(test_data_.mock_callback_,
1309 Release(test_data_.mailbox_name1_,
1310 test_data_.sync_point1_,
1313 pending_layer->SetTextureMailbox(
1314 test_data_.mailbox1_,
1315 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1318 TEST_F(TextureLayerImplWithMailboxTest,
1319 TestDestructorCallbackOnCreatedResource) {
1320 scoped_ptr<TextureLayerImpl> impl_layer;
1321 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1322 ASSERT_TRUE(impl_layer);
1324 EXPECT_CALL(test_data_.mock_callback_,
1325 Release(test_data_.mailbox_name1_, _, false))
1327 impl_layer->SetTextureMailbox(
1328 test_data_.mailbox1_,
1329 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1330 impl_layer->SetDrawsContent(true);
1331 impl_layer->DidBecomeActive();
1332 EXPECT_TRUE(impl_layer->WillDraw(
1333 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1334 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1335 impl_layer->SetTextureMailbox(TextureMailbox(),
1336 scoped_ptr<SingleReleaseCallback>());
1339 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1340 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1341 ResourceProvider::ResourceId id =
1342 provider->CreateResourceFromTextureMailbox(
1343 test_data_.mailbox1_,
1344 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1345 provider->AllocateForTesting(id);
1347 // Transfer some resources to the parent.
1348 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1349 resource_ids_to_transfer.push_back(id);
1350 TransferableResourceArray list;
1351 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1352 EXPECT_TRUE(provider->InUseByConsumer(id));
1353 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1354 provider->DeleteResource(id);
1355 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1356 EXPECT_CALL(test_data_.mock_callback_,
1357 Release(test_data_.mailbox_name1_, _, false))
1359 ReturnedResourceArray returned;
1360 TransferableResource::ReturnResources(list, &returned);
1361 provider->ReceiveReturnsFromParent(returned);
1364 // Check that ClearClient correctly clears the state so that the impl side
1365 // doesn't try to use a texture that could have been destroyed.
1366 class TextureLayerClientTest
1367 : public LayerTreeTest,
1368 public TextureLayerClient {
1370 TextureLayerClientTest()
1373 expected_used_textures_on_draw_(0),
1374 expected_used_textures_on_commit_(0) {}
1376 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
1378 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1379 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1380 return FakeOutputSurface::Create3d(provider);
1383 virtual unsigned PrepareTexture() OVERRIDE { return texture_; }
1385 virtual bool PrepareTextureMailbox(
1386 TextureMailbox* mailbox,
1387 scoped_ptr<SingleReleaseCallback>* release_callback,
1388 bool use_shared_memory) OVERRIDE {
1392 virtual void SetupTree() OVERRIDE {
1393 scoped_refptr<Layer> root = Layer::Create();
1394 root->SetBounds(gfx::Size(10, 10));
1395 root->SetAnchorPoint(gfx::PointF());
1396 root->SetIsDrawable(true);
1398 texture_layer_ = TextureLayer::Create(this);
1399 texture_layer_->SetBounds(gfx::Size(10, 10));
1400 texture_layer_->SetAnchorPoint(gfx::PointF());
1401 texture_layer_->SetIsDrawable(true);
1402 root->AddChild(texture_layer_);
1404 layer_tree_host()->SetRootLayer(root);
1405 LayerTreeTest::SetupTree();
1407 base::AutoLock lock(lock_);
1408 expected_used_textures_on_commit_ = 1;
1412 virtual void BeginTest() OVERRIDE {
1413 PostSetNeedsCommitToMainThread();
1416 virtual void DidCommitAndDrawFrame() OVERRIDE {
1418 switch (commit_count_) {
1420 texture_layer_->ClearClient();
1421 texture_layer_->SetNeedsDisplay();
1423 base::AutoLock lock(lock_);
1424 expected_used_textures_on_commit_ = 0;
1436 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1437 base::AutoLock lock(lock_);
1438 expected_used_textures_on_draw_ = expected_used_textures_on_commit_;
1441 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1442 LayerTreeHostImpl* host_impl,
1443 LayerTreeHostImpl::FrameData* frame_data,
1444 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1445 ContextForImplThread(host_impl)->ResetUsedTextures();
1446 return DrawSwapReadbackResult::DRAW_SUCCESS;
1449 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1450 bool result) OVERRIDE {
1451 ASSERT_TRUE(result);
1452 EXPECT_EQ(expected_used_textures_on_draw_,
1453 ContextForImplThread(host_impl)->NumUsedTextures());
1456 virtual void AfterTest() OVERRIDE {}
1459 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1460 return static_cast<TestContextProvider*>(
1461 host_impl->output_surface()->context_provider().get())->TestContext3d();
1464 scoped_refptr<TextureLayer> texture_layer_;
1468 // Used only on thread.
1469 unsigned expected_used_textures_on_draw_;
1471 // Used on either thread, protected by lock_.
1473 unsigned expected_used_textures_on_commit_;
1476 // The TextureLayerClient does not use mailboxes, so can't use a delegating
1478 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest);
1481 // Checks that changing a texture in the client for a TextureLayer that's
1482 // invisible correctly works without drawing a deleted texture. See
1484 class TextureLayerChangeInvisibleTest
1485 : public LayerTreeTest,
1486 public TextureLayerClient {
1488 TextureLayerChangeInvisibleTest()
1492 expected_texture_on_draw_(0) {}
1494 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
1496 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
1497 texture_ = provider->UnboundTestContext3d()->createExternalTexture();
1498 return FakeOutputSurface::Create3d(provider);
1501 // TextureLayerClient implementation.
1502 virtual unsigned PrepareTexture() OVERRIDE {
1506 virtual bool PrepareTextureMailbox(
1507 TextureMailbox* mailbox,
1508 scoped_ptr<SingleReleaseCallback>* release_callback,
1509 bool use_shared_memory) OVERRIDE {
1513 virtual void SetupTree() OVERRIDE {
1514 scoped_refptr<Layer> root = Layer::Create();
1515 root->SetBounds(gfx::Size(10, 10));
1516 root->SetAnchorPoint(gfx::PointF());
1517 root->SetIsDrawable(true);
1519 solid_layer_ = SolidColorLayer::Create();
1520 solid_layer_->SetBounds(gfx::Size(10, 10));
1521 solid_layer_->SetIsDrawable(true);
1522 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1523 root->AddChild(solid_layer_);
1525 parent_layer_ = Layer::Create();
1526 parent_layer_->SetBounds(gfx::Size(10, 10));
1527 parent_layer_->SetIsDrawable(true);
1528 root->AddChild(parent_layer_);
1530 texture_layer_ = TextureLayer::Create(this);
1531 texture_layer_->SetBounds(gfx::Size(10, 10));
1532 texture_layer_->SetAnchorPoint(gfx::PointF());
1533 texture_layer_->SetIsDrawable(true);
1534 parent_layer_->AddChild(texture_layer_);
1536 layer_tree_host()->SetRootLayer(root);
1537 LayerTreeTest::SetupTree();
1540 virtual void BeginTest() OVERRIDE {
1541 PostSetNeedsCommitToMainThread();
1544 virtual void DidCommitAndDrawFrame() OVERRIDE {
1546 switch (commit_count_) {
1548 // We should have updated the layer, committing the texture.
1549 EXPECT_EQ(1, prepare_called_);
1550 // Make layer invisible.
1551 parent_layer_->SetOpacity(0.f);
1554 // Layer shouldn't have been updated.
1555 EXPECT_EQ(1, prepare_called_);
1556 texture_layer_->SetNeedsDisplay();
1557 // Force a change to make sure we draw a frame.
1558 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1562 EXPECT_EQ(1, prepare_called_);
1563 // Make layer visible again.
1564 parent_layer_->SetOpacity(1.f);
1567 // Layer should have been updated.
1568 EXPECT_EQ(2, prepare_called_);
1569 texture_layer_->ClearClient();
1582 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1583 ASSERT_TRUE(proxy()->IsMainThreadBlocked());
1584 // This is the only texture that can be drawn this frame.
1585 expected_texture_on_draw_ = texture_;
1588 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1589 LayerTreeHostImpl* host_impl,
1590 LayerTreeHostImpl::FrameData* frame_data,
1591 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1592 ContextForImplThread(host_impl)->ResetUsedTextures();
1593 return DrawSwapReadbackResult::DRAW_SUCCESS;
1596 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1597 bool result) OVERRIDE {
1598 ASSERT_TRUE(result);
1599 TestWebGraphicsContext3D* context = ContextForImplThread(host_impl);
1600 int used_textures = context->NumUsedTextures();
1601 switch (host_impl->active_tree()->source_frame_number()) {
1603 EXPECT_EQ(1, used_textures);
1604 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1608 EXPECT_EQ(0, used_textures);
1611 EXPECT_EQ(1, used_textures);
1612 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1619 virtual void AfterTest() OVERRIDE {}
1622 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1623 return static_cast<TestContextProvider*>(
1624 host_impl->output_surface()->context_provider().get())->TestContext3d();
1627 scoped_refptr<SolidColorLayer> solid_layer_;
1628 scoped_refptr<Layer> parent_layer_;
1629 scoped_refptr<TextureLayer> texture_layer_;
1631 // Used on the main thread, and on the impl thread while the main thread is
1635 // Used on the main thread.
1636 int prepare_called_;
1639 // Used on the compositor thread.
1640 unsigned expected_texture_on_draw_;
1643 // The TextureLayerChangeInvisibleTest does not use mailboxes, so can't use a
1644 // delegating renderer.
1645 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest);
1647 // Checks that TextureLayer::Update does not cause an extra commit when setting
1648 // the texture mailbox.
1649 class TextureLayerNoExtraCommitForMailboxTest
1650 : public LayerTreeTest,
1651 public TextureLayerClient {
1653 // TextureLayerClient implementation.
1654 virtual unsigned PrepareTexture() OVERRIDE {
1658 virtual bool PrepareTextureMailbox(
1659 TextureMailbox* texture_mailbox,
1660 scoped_ptr<SingleReleaseCallback>* release_callback,
1661 bool use_shared_memory) OVERRIDE {
1662 if (layer_tree_host()->source_frame_number() == 1) {
1663 *texture_mailbox = TextureMailbox();
1667 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1668 *release_callback = SingleReleaseCallback::Create(
1669 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased,
1670 base::Unretained(this)));
1674 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1675 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1679 virtual void SetupTree() OVERRIDE {
1680 scoped_refptr<Layer> root = Layer::Create();
1681 root->SetBounds(gfx::Size(10, 10));
1682 root->SetAnchorPoint(gfx::PointF());
1683 root->SetIsDrawable(true);
1685 texture_layer_ = TextureLayer::CreateForMailbox(this);
1686 texture_layer_->SetBounds(gfx::Size(10, 10));
1687 texture_layer_->SetAnchorPoint(gfx::PointF());
1688 texture_layer_->SetIsDrawable(true);
1689 root->AddChild(texture_layer_);
1691 layer_tree_host()->SetRootLayer(root);
1692 LayerTreeTest::SetupTree();
1695 virtual void BeginTest() OVERRIDE {
1696 PostSetNeedsCommitToMainThread();
1699 virtual void DidCommitAndDrawFrame() OVERRIDE {
1700 switch (layer_tree_host()->source_frame_number()) {
1702 EXPECT_FALSE(proxy()->CommitPendingForTesting());
1703 // Invalidate the texture layer to clear the mailbox before
1705 texture_layer_->SetNeedsDisplay();
1715 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1716 bool result) OVERRIDE {
1717 ASSERT_TRUE(result);
1718 DelegatedFrameData* delegated_frame_data =
1719 output_surface()->last_sent_frame().delegated_frame_data.get();
1720 if (!delegated_frame_data)
1723 // Return all resources immediately.
1724 TransferableResourceArray resources_to_return =
1725 output_surface()->resources_held_by_parent();
1727 CompositorFrameAck ack;
1728 for (size_t i = 0; i < resources_to_return.size(); ++i)
1729 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1730 host_impl->ReclaimResources(&ack);
1731 host_impl->OnSwapBuffersComplete();
1734 virtual void AfterTest() OVERRIDE {}
1737 scoped_refptr<TextureLayer> texture_layer_;
1740 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest);
1742 // Checks that changing a mailbox in the client for a TextureLayer that's
1743 // invisible correctly works and uses the new mailbox as soon as the layer
1744 // becomes visible (and returns the old one).
1745 class TextureLayerChangeInvisibleMailboxTest
1746 : public LayerTreeTest,
1747 public TextureLayerClient {
1749 TextureLayerChangeInvisibleMailboxTest()
1750 : mailbox_changed_(true),
1751 mailbox_returned_(0),
1754 mailbox_ = MakeMailbox('1');
1757 // TextureLayerClient implementation.
1758 virtual unsigned PrepareTexture() OVERRIDE {
1763 virtual bool PrepareTextureMailbox(
1764 TextureMailbox* mailbox,
1765 scoped_ptr<SingleReleaseCallback>* release_callback,
1766 bool use_shared_memory) OVERRIDE {
1768 if (!mailbox_changed_)
1770 *mailbox = mailbox_;
1771 *release_callback = SingleReleaseCallback::Create(
1772 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1773 base::Unretained(this)));
1777 TextureMailbox MakeMailbox(char name) {
1778 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0);
1781 void MailboxReleased(uint32 sync_point, bool lost_resource) {
1782 ++mailbox_returned_;
1785 virtual void SetupTree() OVERRIDE {
1786 scoped_refptr<Layer> root = Layer::Create();
1787 root->SetBounds(gfx::Size(10, 10));
1788 root->SetAnchorPoint(gfx::PointF());
1789 root->SetIsDrawable(true);
1791 solid_layer_ = SolidColorLayer::Create();
1792 solid_layer_->SetBounds(gfx::Size(10, 10));
1793 solid_layer_->SetIsDrawable(true);
1794 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1795 root->AddChild(solid_layer_);
1797 parent_layer_ = Layer::Create();
1798 parent_layer_->SetBounds(gfx::Size(10, 10));
1799 parent_layer_->SetIsDrawable(true);
1800 root->AddChild(parent_layer_);
1802 texture_layer_ = TextureLayer::CreateForMailbox(this);
1803 texture_layer_->SetBounds(gfx::Size(10, 10));
1804 texture_layer_->SetAnchorPoint(gfx::PointF());
1805 texture_layer_->SetIsDrawable(true);
1806 parent_layer_->AddChild(texture_layer_);
1808 layer_tree_host()->SetRootLayer(root);
1809 LayerTreeTest::SetupTree();
1812 virtual void BeginTest() OVERRIDE {
1813 PostSetNeedsCommitToMainThread();
1816 virtual void DidCommitAndDrawFrame() OVERRIDE {
1818 switch (commit_count_) {
1820 // We should have updated the layer, committing the texture.
1821 EXPECT_EQ(1, prepare_called_);
1822 // Make layer invisible.
1823 parent_layer_->SetOpacity(0.f);
1826 // Layer shouldn't have been updated.
1827 EXPECT_EQ(1, prepare_called_);
1828 // Change the texture.
1829 mailbox_ = MakeMailbox('2');
1830 mailbox_changed_ = true;
1831 texture_layer_->SetNeedsDisplay();
1832 // Force a change to make sure we draw a frame.
1833 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1836 // Layer shouldn't have been updated.
1837 EXPECT_EQ(1, prepare_called_);
1838 // So the old mailbox isn't returned yet.
1839 EXPECT_EQ(0, mailbox_returned_);
1840 // Make layer visible again.
1841 parent_layer_->SetOpacity(1.f);
1844 // Layer should have been updated.
1845 EXPECT_EQ(2, prepare_called_);
1846 // So the old mailbox should have been returned already.
1847 EXPECT_EQ(1, mailbox_returned_);
1848 texture_layer_->ClearClient();
1851 EXPECT_EQ(2, mailbox_returned_);
1860 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1861 bool result) OVERRIDE {
1862 ASSERT_TRUE(result);
1863 DelegatedFrameData* delegated_frame_data =
1864 output_surface()->last_sent_frame().delegated_frame_data.get();
1865 if (!delegated_frame_data)
1868 // Return all resources immediately.
1869 TransferableResourceArray resources_to_return =
1870 output_surface()->resources_held_by_parent();
1872 CompositorFrameAck ack;
1873 for (size_t i = 0; i < resources_to_return.size(); ++i)
1874 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1875 host_impl->ReclaimResources(&ack);
1876 host_impl->OnSwapBuffersComplete();
1879 virtual void AfterTest() OVERRIDE {}
1882 scoped_refptr<SolidColorLayer> solid_layer_;
1883 scoped_refptr<Layer> parent_layer_;
1884 scoped_refptr<TextureLayer> texture_layer_;
1886 // Used on the main thread.
1887 bool mailbox_changed_;
1888 TextureMailbox mailbox_;
1889 int mailbox_returned_;
1890 int prepare_called_;
1894 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1896 // Test that TextureLayerImpl::ReleaseResources can be called which releases
1897 // the mailbox back to TextureLayerClient.
1898 class TextureLayerReleaseResourcesBase
1899 : public LayerTreeTest,
1900 public TextureLayerClient {
1902 // TextureLayerClient implementation.
1903 virtual unsigned PrepareTexture() OVERRIDE {
1907 virtual bool PrepareTextureMailbox(
1908 TextureMailbox* mailbox,
1909 scoped_ptr<SingleReleaseCallback>* release_callback,
1910 bool use_shared_memory) OVERRIDE {
1911 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0);
1912 *release_callback = SingleReleaseCallback::Create(
1913 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased,
1914 base::Unretained(this)));
1918 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1919 mailbox_released_ = true;
1922 virtual void SetupTree() OVERRIDE {
1923 LayerTreeTest::SetupTree();
1925 scoped_refptr<TextureLayer> texture_layer =
1926 TextureLayer::CreateForMailbox(this);
1927 texture_layer->SetBounds(gfx::Size(10, 10));
1928 texture_layer->SetAnchorPoint(gfx::PointF());
1929 texture_layer->SetIsDrawable(true);
1931 layer_tree_host()->root_layer()->AddChild(texture_layer);
1934 virtual void BeginTest() OVERRIDE {
1935 mailbox_released_ = false;
1936 PostSetNeedsCommitToMainThread();
1939 virtual void DidCommitAndDrawFrame() OVERRIDE {
1943 virtual void AfterTest() OVERRIDE {
1944 EXPECT_TRUE(mailbox_released_);
1948 bool mailbox_released_;
1951 class TextureLayerReleaseResourcesAfterCommit
1952 : public TextureLayerReleaseResourcesBase {
1954 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1955 LayerTreeImpl* tree = NULL;
1956 if (host_impl->settings().impl_side_painting)
1957 tree = host_impl->pending_tree();
1959 tree = host_impl->active_tree();
1960 tree->root_layer()->children()[0]->ReleaseResources();
1964 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit);
1966 class TextureLayerReleaseResourcesAfterActivate
1967 : public TextureLayerReleaseResourcesBase {
1969 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1970 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources();
1974 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate);
1976 // Test recovering from a lost context.
1977 class TextureLayerLostContextTest
1978 : public LayerTreeTest,
1979 public TextureLayerClient {
1981 TextureLayerLostContextTest()
1982 : context_lost_(false),
1985 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
1987 return FakeOutputSurface::Create3d();
1990 virtual unsigned PrepareTexture() OVERRIDE {
1991 if (draw_count_ == 0)
1992 context_lost_ = true;
1998 virtual bool PrepareTextureMailbox(
1999 TextureMailbox* mailbox,
2000 scoped_ptr<SingleReleaseCallback>* release_callback,
2001 bool use_shared_memory) OVERRIDE {
2005 virtual void SetupTree() OVERRIDE {
2006 scoped_refptr<Layer> root = Layer::Create();
2007 root->SetBounds(gfx::Size(10, 10));
2008 root->SetIsDrawable(true);
2010 texture_layer_ = TextureLayer::Create(this);
2011 texture_layer_->SetBounds(gfx::Size(10, 10));
2012 texture_layer_->SetIsDrawable(true);
2013 root->AddChild(texture_layer_);
2015 layer_tree_host()->SetRootLayer(root);
2016 LayerTreeTest::SetupTree();
2019 virtual void BeginTest() OVERRIDE {
2020 PostSetNeedsCommitToMainThread();
2023 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
2024 LayerTreeHostImpl* host_impl,
2025 LayerTreeHostImpl::FrameData* frame_data,
2026 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
2027 LayerImpl* root = host_impl->RootLayer();
2028 TextureLayerImpl* texture_layer =
2029 static_cast<TextureLayerImpl*>(root->children()[0]);
2030 if (++draw_count_ == 1)
2031 EXPECT_EQ(0u, texture_layer->texture_id());
2033 EXPECT_EQ(1u, texture_layer->texture_id());
2034 return DrawSwapReadbackResult::DRAW_SUCCESS;
2037 virtual void DidCommitAndDrawFrame() OVERRIDE {
2041 virtual void AfterTest() OVERRIDE {}
2044 scoped_refptr<TextureLayer> texture_layer_;
2049 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest);
2051 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
2053 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
2054 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2055 EXPECT_FALSE(lost_resource);
2060 void SetMailbox(char mailbox_char) {
2061 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2062 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2064 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
2065 base::Unretained(this)));
2066 layer_->SetTextureMailbox(
2067 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
2071 virtual void SetupTree() OVERRIDE {
2072 gfx::Size bounds(100, 100);
2073 root_ = Layer::Create();
2074 root_->SetAnchorPoint(gfx::PointF());
2075 root_->SetBounds(bounds);
2077 layer_ = TextureLayer::CreateForMailbox(NULL);
2078 layer_->SetIsDrawable(true);
2079 layer_->SetAnchorPoint(gfx::PointF());
2080 layer_->SetBounds(bounds);
2082 root_->AddChild(layer_);
2083 layer_tree_host()->SetRootLayer(root_);
2084 layer_tree_host()->SetViewportSize(bounds);
2087 virtual void BeginTest() OVERRIDE {
2088 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2090 callback_count_ = 0;
2092 // Set the mailbox on the main thread.
2094 EXPECT_EQ(0, callback_count_);
2096 PostSetNeedsCommitToMainThread();
2099 virtual void DidCommitAndDrawFrame() OVERRIDE {
2100 switch (layer_tree_host()->source_frame_number()) {
2102 // Delete the TextureLayer on the main thread while the mailbox is in
2104 layer_->RemoveFromParent();
2110 virtual void AfterTest() OVERRIDE {
2111 EXPECT_EQ(1, callback_count_);
2115 base::ThreadChecker main_thread_;
2116 int callback_count_;
2117 scoped_refptr<Layer> root_;
2118 scoped_refptr<TextureLayer> layer_;
2121 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2122 TextureLayerWithMailboxMainThreadDeleted);
2124 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
2126 void ReleaseCallback(uint32 sync_point, bool lost_resource) {
2127 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2128 EXPECT_FALSE(lost_resource);
2133 void SetMailbox(char mailbox_char) {
2134 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2135 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2137 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
2138 base::Unretained(this)));
2139 layer_->SetTextureMailbox(
2140 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0),
2144 virtual void SetupTree() OVERRIDE {
2145 gfx::Size bounds(100, 100);
2146 root_ = Layer::Create();
2147 root_->SetAnchorPoint(gfx::PointF());
2148 root_->SetBounds(bounds);
2150 layer_ = TextureLayer::CreateForMailbox(NULL);
2151 layer_->SetIsDrawable(true);
2152 layer_->SetAnchorPoint(gfx::PointF());
2153 layer_->SetBounds(bounds);
2155 root_->AddChild(layer_);
2156 layer_tree_host()->SetRootLayer(root_);
2157 layer_tree_host()->SetViewportSize(bounds);
2160 virtual void BeginTest() OVERRIDE {
2161 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2163 callback_count_ = 0;
2165 // Set the mailbox on the main thread.
2167 EXPECT_EQ(0, callback_count_);
2169 PostSetNeedsCommitToMainThread();
2172 virtual void DidCommitAndDrawFrame() OVERRIDE {
2173 switch (layer_tree_host()->source_frame_number()) {
2175 // Remove the TextureLayer on the main thread while the mailbox is in
2176 // the impl tree, but don't delete the TextureLayer until after the impl
2177 // tree side is deleted.
2178 layer_->RemoveFromParent();
2186 virtual void AfterTest() OVERRIDE {
2187 EXPECT_EQ(1, callback_count_);
2191 base::ThreadChecker main_thread_;
2192 int callback_count_;
2193 scoped_refptr<Layer> root_;
2194 scoped_refptr<TextureLayer> layer_;
2197 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2198 TextureLayerWithMailboxImplThreadDeleted);