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"
9 #include "base/callback.h"
10 #include "cc/layers/texture_layer_client.h"
11 #include "cc/layers/texture_layer_impl.h"
12 #include "cc/test/fake_impl_proxy.h"
13 #include "cc/test/fake_layer_tree_host_client.h"
14 #include "cc/test/fake_layer_tree_host_impl.h"
15 #include "cc/test/layer_test_common.h"
16 #include "cc/test/layer_tree_test.h"
17 #include "cc/trees/layer_tree_host.h"
18 #include "cc/trees/layer_tree_impl.h"
19 #include "cc/trees/single_thread_proxy.h"
20 #include "gpu/GLES2/gl2extchromium.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using ::testing::Mock
;
26 using ::testing::AtLeast
;
27 using ::testing::AnyNumber
;
32 class MockLayerTreeHost
: public LayerTreeHost
{
34 explicit MockLayerTreeHost(LayerTreeHostClient
* client
)
35 : LayerTreeHost(client
, LayerTreeSettings()) {
39 MOCK_METHOD0(AcquireLayerTextures
, void());
40 MOCK_METHOD0(SetNeedsCommit
, void());
41 MOCK_METHOD1(StartRateLimiter
, void(WebKit::WebGraphicsContext3D
* context
));
42 MOCK_METHOD1(StopRateLimiter
, void(WebKit::WebGraphicsContext3D
* context
));
45 class TextureLayerTest
: public testing::Test
{
49 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)),
50 host_impl_(&proxy_
) {}
53 virtual void SetUp() {
54 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
57 virtual void TearDown() {
58 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
59 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AnyNumber());
60 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
62 layer_tree_host_
->SetRootLayer(NULL
);
63 layer_tree_host_
.reset();
66 scoped_ptr
<MockLayerTreeHost
> layer_tree_host_
;
68 FakeLayerTreeHostClient fake_client_
;
69 FakeLayerTreeHostImpl host_impl_
;
72 TEST_F(TextureLayerTest
, SyncImplWhenChangingTextureId
) {
73 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::Create(NULL
);
74 ASSERT_TRUE(test_layer
.get());
76 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AnyNumber());
77 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
78 layer_tree_host_
->SetRootLayer(test_layer
);
79 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
80 EXPECT_EQ(test_layer
->layer_tree_host(), layer_tree_host_
.get());
82 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
83 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
84 test_layer
->SetTextureId(1);
85 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
87 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AtLeast(1));
88 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
89 test_layer
->SetTextureId(2);
90 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
92 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AtLeast(1));
93 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
94 test_layer
->SetTextureId(0);
95 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
98 TEST_F(TextureLayerTest
, SyncImplWhenDrawing
) {
99 gfx::RectF
dirty_rect(0.f
, 0.f
, 1.f
, 1.f
);
101 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::Create(NULL
);
102 ASSERT_TRUE(test_layer
.get());
103 scoped_ptr
<TextureLayerImpl
> impl_layer
;
104 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
105 ASSERT_TRUE(impl_layer
);
107 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AnyNumber());
108 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
109 layer_tree_host_
->SetRootLayer(test_layer
);
110 test_layer
->SetTextureId(1);
111 test_layer
->SetIsDrawable(true);
112 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
113 EXPECT_EQ(test_layer
->layer_tree_host(), layer_tree_host_
.get());
115 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(1);
116 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(0);
117 test_layer
->WillModifyTexture();
118 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
120 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
121 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
122 test_layer
->SetNeedsDisplayRect(dirty_rect
);
123 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
125 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
126 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(1);
127 test_layer
->PushPropertiesTo(impl_layer
.get()); // fake commit
128 test_layer
->SetIsDrawable(false);
129 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
131 // Verify that non-drawable layers don't signal the compositor,
132 // except for the first draw after last commit, which must acquire
134 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(1);
135 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(0);
136 test_layer
->WillModifyTexture();
137 test_layer
->SetNeedsDisplayRect(dirty_rect
);
138 test_layer
->PushPropertiesTo(impl_layer
.get()); // fake commit
139 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
141 // Second draw with layer in non-drawable state: no texture
143 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
144 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(0);
145 test_layer
->WillModifyTexture();
146 test_layer
->SetNeedsDisplayRect(dirty_rect
);
147 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
150 TEST_F(TextureLayerTest
, SyncImplWhenRemovingFromTree
) {
151 scoped_refptr
<Layer
> root_layer
= Layer::Create();
152 ASSERT_TRUE(root_layer
.get());
153 scoped_refptr
<Layer
> child_layer
= Layer::Create();
154 ASSERT_TRUE(child_layer
.get());
155 root_layer
->AddChild(child_layer
);
156 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::Create(NULL
);
157 ASSERT_TRUE(test_layer
.get());
158 test_layer
->SetTextureId(0);
159 child_layer
->AddChild(test_layer
);
161 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AnyNumber());
162 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
163 layer_tree_host_
->SetRootLayer(root_layer
);
164 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
166 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
167 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
168 test_layer
->RemoveFromParent();
169 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
171 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
172 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
173 child_layer
->AddChild(test_layer
);
174 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
176 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
177 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
178 test_layer
->SetTextureId(1);
179 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
181 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AtLeast(1));
182 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
183 test_layer
->RemoveFromParent();
184 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
187 TEST_F(TextureLayerTest
, CheckPropertyChangeCausesCorrectBehavior
) {
188 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::Create(NULL
);
189 layer_tree_host_
->SetRootLayer(test_layer
);
191 // Test properties that should call SetNeedsCommit. All properties need to
192 // be set to new values in order for SetNeedsCommit to be called.
193 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetFlipped(false));
194 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetUV(
195 gfx::PointF(0.25f
, 0.25f
), gfx::PointF(0.75f
, 0.75f
)));
196 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetVertexOpacity(
197 0.5f
, 0.5f
, 0.5f
, 0.5f
));
198 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetPremultipliedAlpha(false));
199 EXPECT_SET_NEEDS_COMMIT(1, test_layer
->SetTextureId(1));
201 // Calling SetTextureId can call AcquireLayerTextures.
202 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(AnyNumber());
205 class FakeTextureLayerClient
: public TextureLayerClient
{
207 FakeTextureLayerClient() : context_(TestWebGraphicsContext3D::Create()) {}
209 virtual unsigned PrepareTexture() OVERRIDE
{
213 virtual WebKit::WebGraphicsContext3D
* Context3d() OVERRIDE
{
214 return context_
.get();
217 virtual bool PrepareTextureMailbox(TextureMailbox
* mailbox
,
218 bool use_shared_memory
) OVERRIDE
{
219 *mailbox
= TextureMailbox();
224 scoped_ptr
<TestWebGraphicsContext3D
> context_
;
225 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient
);
228 TEST_F(TextureLayerTest
, RateLimiter
) {
229 FakeTextureLayerClient client
;
230 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(
232 test_layer
->SetIsDrawable(true);
233 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
234 layer_tree_host_
->SetRootLayer(test_layer
);
236 // Don't rate limit until we invalidate.
237 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter(_
)).Times(0);
238 test_layer
->SetRateLimitContext(true);
239 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
241 // Do rate limit after we invalidate.
242 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter(client
.Context3d()));
243 test_layer
->SetNeedsDisplay();
244 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
246 // Stop rate limiter when we don't want it any more.
247 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter(client
.Context3d()));
248 test_layer
->SetRateLimitContext(false);
249 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
251 // Or we clear the client.
252 test_layer
->SetRateLimitContext(true);
253 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter(client
.Context3d()));
254 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
255 test_layer
->ClearClient();
256 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
258 // Reset to a layer with a client, that started the rate limiter.
259 test_layer
= TextureLayer::CreateForMailbox(
261 test_layer
->SetIsDrawable(true);
262 test_layer
->SetRateLimitContext(true);
263 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
264 layer_tree_host_
->SetRootLayer(test_layer
);
265 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter(_
)).Times(0);
266 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
267 EXPECT_CALL(*layer_tree_host_
, StartRateLimiter(client
.Context3d()));
268 test_layer
->SetNeedsDisplay();
269 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
271 // Stop rate limiter when we're removed from the tree.
272 EXPECT_CALL(*layer_tree_host_
, StopRateLimiter(client
.Context3d()));
273 layer_tree_host_
->SetRootLayer(NULL
);
274 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
277 class MockMailboxCallback
{
279 MOCK_METHOD3(Release
, void(const std::string
& mailbox
,
281 bool lost_resource
));
282 MOCK_METHOD3(Release2
, void(base::SharedMemory
* shared_memory
,
284 bool lost_resource
));
287 struct CommonMailboxObjects
{
288 CommonMailboxObjects()
289 : mailbox_name1_(64, '1'),
290 mailbox_name2_(64, '2'),
293 shared_memory_(new base::SharedMemory
) {
294 release_mailbox1_
= base::Bind(&MockMailboxCallback::Release
,
295 base::Unretained(&mock_callback_
),
297 release_mailbox2_
= base::Bind(&MockMailboxCallback::Release
,
298 base::Unretained(&mock_callback_
),
301 m1
.SetName(reinterpret_cast<const int8
*>(mailbox_name1_
.data()));
302 mailbox1_
= TextureMailbox(m1
, release_mailbox1_
, sync_point1_
);
304 m2
.SetName(reinterpret_cast<const int8
*>(mailbox_name2_
.data()));
305 mailbox2_
= TextureMailbox(m2
, release_mailbox2_
, sync_point2_
);
307 gfx::Size
size(128, 128);
308 EXPECT_TRUE(shared_memory_
->CreateAndMapAnonymous(4 * size
.GetArea()));
309 release_mailbox3_
= base::Bind(&MockMailboxCallback::Release2
,
310 base::Unretained(&mock_callback_
),
311 shared_memory_
.get());
312 mailbox3_
= TextureMailbox(shared_memory_
.get(), size
, release_mailbox3_
);
315 std::string mailbox_name1_
;
316 std::string mailbox_name2_
;
317 MockMailboxCallback mock_callback_
;
318 TextureMailbox::ReleaseCallback release_mailbox1_
;
319 TextureMailbox::ReleaseCallback release_mailbox2_
;
320 TextureMailbox::ReleaseCallback release_mailbox3_
;
321 TextureMailbox mailbox1_
;
322 TextureMailbox mailbox2_
;
323 TextureMailbox mailbox3_
;
324 unsigned sync_point1_
;
325 unsigned sync_point2_
;
326 scoped_ptr
<base::SharedMemory
> shared_memory_
;
329 class TextureLayerWithMailboxTest
: public TextureLayerTest
{
331 virtual void TearDown() {
332 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
333 EXPECT_CALL(test_data_
.mock_callback_
,
334 Release(test_data_
.mailbox_name1_
,
335 test_data_
.sync_point1_
,
337 TextureLayerTest::TearDown();
340 CommonMailboxObjects test_data_
;
343 TEST_F(TextureLayerWithMailboxTest
, ReplaceMailboxOnMainThreadBeforeCommit
) {
344 scoped_refptr
<TextureLayer
> test_layer
= TextureLayer::CreateForMailbox(NULL
);
345 ASSERT_TRUE(test_layer
.get());
347 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
348 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AnyNumber());
349 layer_tree_host_
->SetRootLayer(test_layer
);
350 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
352 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
353 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
354 test_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
355 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
357 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
358 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
359 EXPECT_CALL(test_data_
.mock_callback_
,
360 Release(test_data_
.mailbox_name1_
,
361 test_data_
.sync_point1_
,
364 test_layer
->SetTextureMailbox(test_data_
.mailbox2_
);
365 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
366 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
368 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
369 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
370 EXPECT_CALL(test_data_
.mock_callback_
,
371 Release(test_data_
.mailbox_name2_
,
372 test_data_
.sync_point2_
,
375 test_layer
->SetTextureMailbox(TextureMailbox());
376 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
377 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
379 test_layer
->SetTextureMailbox(test_data_
.mailbox3_
);
380 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
381 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
383 EXPECT_CALL(*layer_tree_host_
, AcquireLayerTextures()).Times(0);
384 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
385 EXPECT_CALL(test_data_
.mock_callback_
,
386 Release2(test_data_
.shared_memory_
.get(),
389 test_layer
->SetTextureMailbox(TextureMailbox());
390 Mock::VerifyAndClearExpectations(layer_tree_host_
.get());
391 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
394 EXPECT_CALL(*layer_tree_host_
, SetNeedsCommit()).Times(AtLeast(1));
395 test_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
398 class TextureLayerImplWithMailboxThreadedCallback
: public LayerTreeTest
{
400 TextureLayerImplWithMailboxThreadedCallback()
401 : callback_count_(0),
404 // Make sure callback is received on main and doesn't block the impl thread.
405 void ReleaseCallback(unsigned sync_point
, bool lost_resource
) {
406 EXPECT_EQ(true, proxy()->IsMainThread());
407 EXPECT_FALSE(lost_resource
);
411 void SetMailbox(char mailbox_char
) {
412 TextureMailbox
mailbox(
413 std::string(64, mailbox_char
),
415 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback
,
416 base::Unretained(this)));
417 layer_
->SetTextureMailbox(mailbox
);
420 virtual void BeginTest() OVERRIDE
{
421 gfx::Size
bounds(100, 100);
422 root_
= Layer::Create();
423 root_
->SetAnchorPoint(gfx::PointF());
424 root_
->SetBounds(bounds
);
426 layer_
= TextureLayer::CreateForMailbox(NULL
);
427 layer_
->SetIsDrawable(true);
428 layer_
->SetAnchorPoint(gfx::PointF());
429 layer_
->SetBounds(bounds
);
431 root_
->AddChild(layer_
);
432 layer_tree_host()->SetRootLayer(root_
);
433 layer_tree_host()->SetViewportSize(bounds
);
435 EXPECT_EQ(0, callback_count_
);
437 // Case #1: change mailbox before the commit. The old mailbox should be
438 // released immediately.
440 EXPECT_EQ(1, callback_count_
);
441 PostSetNeedsCommitToMainThread();
444 virtual void DidCommit() OVERRIDE
{
446 switch (commit_count_
) {
448 // Case #2: change mailbox after the commit (and draw), where the
449 // layer draws. The old mailbox should be released during the next
452 EXPECT_EQ(1, callback_count_
);
455 // Old mailbox was released, task was posted, but won't execute
456 // until this DidCommit returns.
457 // TODO(piman): fix this.
458 EXPECT_EQ(1, callback_count_
);
459 layer_tree_host()->SetNeedsCommit();
462 EXPECT_EQ(2, callback_count_
);
463 // Case #3: change mailbox when the layer doesn't draw. The old
464 // mailbox should be released during the next commit.
465 layer_
->SetBounds(gfx::Size());
469 // Old mailbox was released, task was posted, but won't execute
470 // until this DidCommit returns.
471 // TODO(piman): fix this.
472 EXPECT_EQ(2, callback_count_
);
473 layer_tree_host()->SetNeedsCommit();
476 EXPECT_EQ(3, callback_count_
);
477 // Case #4: release mailbox that was committed but never drawn. The
478 // old mailbox should be released during the next commit.
479 layer_
->SetTextureMailbox(TextureMailbox());
482 // Old mailbox was released, task was posted, but won't execute
483 // until this DidCommit returns.
484 // TODO(piman): fix this.
485 EXPECT_EQ(3, callback_count_
);
486 layer_tree_host()->SetNeedsCommit();
489 EXPECT_EQ(4, callback_count_
);
490 // Restore a mailbox for the next step.
494 // Case #5: remove layer from tree. Callback should *not* be called, the
495 // mailbox is returned to the main thread.
496 EXPECT_EQ(4, callback_count_
);
497 layer_
->RemoveFromParent();
500 // Mailbox was released to the main thread, task was posted, but won't
501 // execute until this DidCommit returns.
502 // TODO(piman): fix this.
503 EXPECT_EQ(4, callback_count_
);
504 layer_tree_host()->SetNeedsCommit();
507 EXPECT_EQ(4, callback_count_
);
508 // Resetting the mailbox will call the callback now.
509 layer_
->SetTextureMailbox(TextureMailbox());
510 EXPECT_EQ(5, callback_count_
);
519 virtual void AfterTest() OVERRIDE
{}
524 scoped_refptr
<Layer
> root_
;
525 scoped_refptr
<TextureLayer
> layer_
;
528 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
529 TextureLayerImplWithMailboxThreadedCallback
);
531 class TextureLayerImplWithMailboxTest
: public TextureLayerTest
{
533 TextureLayerImplWithMailboxTest()
535 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D
)) {}
537 virtual void SetUp() {
538 TextureLayerTest::SetUp();
539 layer_tree_host_
.reset(new MockLayerTreeHost(&fake_client_
));
540 EXPECT_TRUE(host_impl_
.InitializeRenderer(CreateFakeOutputSurface()));
543 bool WillDraw(TextureLayerImpl
* layer
, DrawMode mode
) {
544 bool will_draw
= layer
->WillDraw(
545 mode
, host_impl_
.active_tree()->resource_provider());
547 layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
551 CommonMailboxObjects test_data_
;
552 FakeLayerTreeHostClient fake_client_
;
555 // Test conditions for results of TextureLayerImpl::WillDraw under
556 // different configurations of different mailbox, texture_id, and draw_mode.
557 TEST_F(TextureLayerImplWithMailboxTest
, TestWillDraw
) {
558 EXPECT_CALL(test_data_
.mock_callback_
,
559 Release(test_data_
.mailbox_name1_
,
560 test_data_
.sync_point1_
,
563 EXPECT_CALL(test_data_
.mock_callback_
,
564 Release2(test_data_
.shared_memory_
.get(), 0, false))
568 scoped_ptr
<TextureLayerImpl
> impl_layer
=
569 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
570 impl_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
571 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
575 scoped_ptr
<TextureLayerImpl
> impl_layer
=
576 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
577 impl_layer
->SetTextureMailbox(TextureMailbox());
578 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
582 // Software resource.
583 scoped_ptr
<TextureLayerImpl
> impl_layer
=
584 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
585 impl_layer
->SetTextureMailbox(test_data_
.mailbox3_
);
586 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
590 scoped_ptr
<TextureLayerImpl
> impl_layer
=
591 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
593 host_impl_
.output_surface()->context3d()->createTexture();
594 impl_layer
->set_texture_id(texture
);
595 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
599 scoped_ptr
<TextureLayerImpl
> impl_layer
=
600 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
601 impl_layer
->set_texture_id(0);
602 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_HARDWARE
));
607 scoped_ptr
<TextureLayerImpl
> impl_layer
=
608 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
609 impl_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
610 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
614 scoped_ptr
<TextureLayerImpl
> impl_layer
=
615 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
616 impl_layer
->SetTextureMailbox(TextureMailbox());
617 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
621 // Software resource.
622 scoped_ptr
<TextureLayerImpl
> impl_layer
=
623 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
624 impl_layer
->SetTextureMailbox(test_data_
.mailbox3_
);
625 EXPECT_TRUE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
629 scoped_ptr
<TextureLayerImpl
> impl_layer
=
630 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
632 host_impl_
.output_surface()->context3d()->createTexture();
633 impl_layer
->set_texture_id(texture
);
634 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
638 scoped_ptr
<TextureLayerImpl
> impl_layer
=
639 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
640 impl_layer
->set_texture_id(0);
641 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_SOFTWARE
));
644 // Resourceless software mode.
646 scoped_ptr
<TextureLayerImpl
> impl_layer
=
647 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
648 impl_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
649 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
653 scoped_ptr
<TextureLayerImpl
> impl_layer
=
654 TextureLayerImpl::Create(host_impl_
.active_tree(), 1, false);
656 host_impl_
.output_surface()->context3d()->createTexture();
657 impl_layer
->set_texture_id(texture
);
658 EXPECT_FALSE(WillDraw(impl_layer
.get(), DRAW_MODE_RESOURCELESS_SOFTWARE
));
662 TEST_F(TextureLayerImplWithMailboxTest
, TestImplLayerCallbacks
) {
663 host_impl_
.CreatePendingTree();
664 scoped_ptr
<TextureLayerImpl
> pending_layer
;
665 pending_layer
= TextureLayerImpl::Create(host_impl_
.pending_tree(), 1, true);
666 ASSERT_TRUE(pending_layer
);
668 scoped_ptr
<LayerImpl
> active_layer(
669 pending_layer
->CreateLayerImpl(host_impl_
.active_tree()));
670 ASSERT_TRUE(active_layer
);
672 pending_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
674 // Test multiple commits without an activation.
675 EXPECT_CALL(test_data_
.mock_callback_
,
676 Release(test_data_
.mailbox_name1_
,
677 test_data_
.sync_point1_
,
680 pending_layer
->SetTextureMailbox(test_data_
.mailbox2_
);
681 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
683 // Test callback after activation.
684 pending_layer
->PushPropertiesTo(active_layer
.get());
685 active_layer
->DidBecomeActive();
687 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
688 pending_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
689 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
691 EXPECT_CALL(test_data_
.mock_callback_
,
692 Release(test_data_
.mailbox_name2_
, _
, false))
694 pending_layer
->PushPropertiesTo(active_layer
.get());
695 active_layer
->DidBecomeActive();
696 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
698 // Test resetting the mailbox.
699 EXPECT_CALL(test_data_
.mock_callback_
,
700 Release(test_data_
.mailbox_name1_
, _
, false))
702 pending_layer
->SetTextureMailbox(TextureMailbox());
703 pending_layer
->PushPropertiesTo(active_layer
.get());
704 active_layer
->DidBecomeActive();
705 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
708 EXPECT_CALL(test_data_
.mock_callback_
,
709 Release(test_data_
.mailbox_name1_
,
710 test_data_
.sync_point1_
,
713 pending_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
716 TEST_F(TextureLayerImplWithMailboxTest
,
717 TestDestructorCallbackOnCreatedResource
) {
718 scoped_ptr
<TextureLayerImpl
> impl_layer
;
719 impl_layer
= TextureLayerImpl::Create(host_impl_
.active_tree(), 1, true);
720 ASSERT_TRUE(impl_layer
);
722 EXPECT_CALL(test_data_
.mock_callback_
,
723 Release(test_data_
.mailbox_name1_
, _
, false))
725 impl_layer
->SetTextureMailbox(test_data_
.mailbox1_
);
726 impl_layer
->DidBecomeActive();
727 EXPECT_TRUE(impl_layer
->WillDraw(
728 DRAW_MODE_HARDWARE
, host_impl_
.active_tree()->resource_provider()));
729 impl_layer
->DidDraw(host_impl_
.active_tree()->resource_provider());
730 impl_layer
->SetTextureMailbox(TextureMailbox());
733 TEST_F(TextureLayerImplWithMailboxTest
, TestCallbackOnInUseResource
) {
734 ResourceProvider
* provider
= host_impl_
.active_tree()->resource_provider();
735 ResourceProvider::ResourceId id
=
736 provider
->CreateResourceFromTextureMailbox(test_data_
.mailbox1_
);
737 provider
->AllocateForTesting(id
);
739 // Transfer some resources to the parent.
740 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
741 resource_ids_to_transfer
.push_back(id
);
742 TransferableResourceArray list
;
743 provider
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
744 EXPECT_TRUE(provider
->InUseByConsumer(id
));
745 EXPECT_CALL(test_data_
.mock_callback_
, Release(_
, _
, _
)).Times(0);
746 provider
->DeleteResource(id
);
747 Mock::VerifyAndClearExpectations(&test_data_
.mock_callback_
);
748 EXPECT_CALL(test_data_
.mock_callback_
,
749 Release(test_data_
.mailbox_name1_
, _
, false))
751 provider
->ReceiveFromParent(list
);
754 // Check that ClearClient correctly clears the state so that the impl side
755 // doesn't try to use a texture that could have been destroyed.
756 class TextureLayerClientTest
757 : public LayerTreeTest
,
758 public TextureLayerClient
{
760 TextureLayerClientTest()
764 expected_used_textures_on_draw_(0),
765 expected_used_textures_on_commit_(0) {}
767 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() OVERRIDE
{
768 scoped_ptr
<TestWebGraphicsContext3D
> context(
769 TestWebGraphicsContext3D::Create());
770 context_
= context
.get();
771 texture_
= context
->createTexture();
772 return FakeOutputSurface::Create3d(
773 context
.PassAs
<WebKit::WebGraphicsContext3D
>()).PassAs
<OutputSurface
>();
776 virtual unsigned PrepareTexture() OVERRIDE
{
780 virtual WebKit::WebGraphicsContext3D
* Context3d() OVERRIDE
{
784 virtual bool PrepareTextureMailbox(
785 cc::TextureMailbox
* mailbox
, bool use_shared_memory
) OVERRIDE
{
789 virtual void SetupTree() OVERRIDE
{
790 scoped_refptr
<Layer
> root
= Layer::Create();
791 root
->SetBounds(gfx::Size(10, 10));
792 root
->SetAnchorPoint(gfx::PointF());
793 root
->SetIsDrawable(true);
795 texture_layer_
= TextureLayer::Create(this);
796 texture_layer_
->SetBounds(gfx::Size(10, 10));
797 texture_layer_
->SetAnchorPoint(gfx::PointF());
798 texture_layer_
->SetIsDrawable(true);
799 root
->AddChild(texture_layer_
);
801 layer_tree_host()->SetRootLayer(root
);
802 LayerTreeTest::SetupTree();
804 base::AutoLock
lock(lock_
);
805 expected_used_textures_on_commit_
= 1;
809 virtual void BeginTest() OVERRIDE
{
810 PostSetNeedsCommitToMainThread();
813 virtual void DidCommitAndDrawFrame() OVERRIDE
{
815 switch (commit_count_
) {
817 texture_layer_
->ClearClient();
818 texture_layer_
->SetNeedsDisplay();
820 base::AutoLock
lock(lock_
);
821 expected_used_textures_on_commit_
= 0;
834 virtual void BeginCommitOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
835 base::AutoLock
lock(lock_
);
836 expected_used_textures_on_draw_
= expected_used_textures_on_commit_
;
839 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
840 LayerTreeHostImpl::FrameData
* frame_data
,
841 bool result
) OVERRIDE
{
842 context_
->ResetUsedTextures();
846 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
,
847 bool result
) OVERRIDE
{
849 EXPECT_EQ(expected_used_textures_on_draw_
, context_
->NumUsedTextures());
852 virtual void AfterTest() OVERRIDE
{}
855 scoped_refptr
<TextureLayer
> texture_layer_
;
856 TestWebGraphicsContext3D
* context_
;
860 // Used only on thread.
861 unsigned expected_used_textures_on_draw_
;
863 // Used on either thread, protected by lock_.
865 unsigned expected_used_textures_on_commit_
;
868 // The TextureLayerClient does not use mailboxes, so can't use a delegating
870 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest
);
872 // Test recovering from a lost context.
873 class TextureLayerLostContextTest
874 : public LayerTreeTest
,
875 public TextureLayerClient
{
877 TextureLayerLostContextTest()
881 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() OVERRIDE
{
882 texture_context_
= TestWebGraphicsContext3D::Create();
883 texture_
= texture_context_
->createTexture();
884 scoped_ptr
<TestWebGraphicsContext3D
> context(
885 TestWebGraphicsContext3D::Create());
886 return FakeOutputSurface::Create3d(
887 context
.PassAs
<WebKit::WebGraphicsContext3D
>()).PassAs
<OutputSurface
>();
890 virtual unsigned PrepareTexture() OVERRIDE
{
891 if (draw_count_
== 0) {
892 texture_context_
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
893 GL_INNOCENT_CONTEXT_RESET_ARB
);
898 virtual WebKit::WebGraphicsContext3D
* Context3d() OVERRIDE
{
899 return texture_context_
.get();
902 virtual bool PrepareTextureMailbox(
903 cc::TextureMailbox
* mailbox
, bool use_shared_memory
) OVERRIDE
{
907 virtual void SetupTree() OVERRIDE
{
908 scoped_refptr
<Layer
> root
= Layer::Create();
909 root
->SetBounds(gfx::Size(10, 10));
910 root
->SetIsDrawable(true);
912 texture_layer_
= TextureLayer::Create(this);
913 texture_layer_
->SetBounds(gfx::Size(10, 10));
914 texture_layer_
->SetIsDrawable(true);
915 root
->AddChild(texture_layer_
);
917 layer_tree_host()->SetRootLayer(root
);
918 LayerTreeTest::SetupTree();
921 virtual void BeginTest() OVERRIDE
{
922 PostSetNeedsCommitToMainThread();
925 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
926 LayerTreeHostImpl::FrameData
* frame_data
,
927 bool result
) OVERRIDE
{
928 LayerImpl
* root
= host_impl
->RootLayer();
929 TextureLayerImpl
* texture_layer
=
930 static_cast<TextureLayerImpl
*>(root
->children()[0]);
931 if (++draw_count_
== 1)
932 EXPECT_EQ(0u, texture_layer
->texture_id());
934 EXPECT_EQ(texture_
, texture_layer
->texture_id());
938 virtual void DidCommitAndDrawFrame() OVERRIDE
{
942 virtual void AfterTest() OVERRIDE
{}
945 scoped_refptr
<TextureLayer
> texture_layer_
;
946 scoped_ptr
<TestWebGraphicsContext3D
> texture_context_
;
951 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest
);