Fix TextureLayer cleanup
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blobf50edda70f8d153fde141a6747a5df99bdd48953
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"
7 #include <string>
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;
25 using ::testing::_;
26 using ::testing::AtLeast;
27 using ::testing::AnyNumber;
29 namespace cc {
30 namespace {
32 class MockLayerTreeHost : public LayerTreeHost {
33 public:
34 explicit MockLayerTreeHost(LayerTreeHostClient* client)
35 : LayerTreeHost(client, LayerTreeSettings()) {
36 Initialize(NULL);
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 {
46 public:
47 TextureLayerTest()
48 : fake_client_(
49 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
50 host_impl_(&proxy_) {}
52 protected:
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_;
67 FakeImplProxy proxy_;
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
133 // the texture.
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
142 // acquisition.
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 {
206 public:
207 FakeTextureLayerClient() : context_(TestWebGraphicsContext3D::Create()) {}
209 virtual unsigned PrepareTexture() OVERRIDE {
210 return 0;
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();
220 return true;
223 private:
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(
231 &client);
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(
260 &client);
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 {
278 public:
279 MOCK_METHOD3(Release, void(const std::string& mailbox,
280 unsigned sync_point,
281 bool lost_resource));
282 MOCK_METHOD3(Release2, void(base::SharedMemory* shared_memory,
283 unsigned sync_point,
284 bool lost_resource));
287 struct CommonMailboxObjects {
288 CommonMailboxObjects()
289 : mailbox_name1_(64, '1'),
290 mailbox_name2_(64, '2'),
291 sync_point1_(1),
292 sync_point2_(2),
293 shared_memory_(new base::SharedMemory) {
294 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
295 base::Unretained(&mock_callback_),
296 mailbox_name1_);
297 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
298 base::Unretained(&mock_callback_),
299 mailbox_name2_);
300 gpu::Mailbox m1;
301 m1.SetName(reinterpret_cast<const int8*>(mailbox_name1_.data()));
302 mailbox1_ = TextureMailbox(m1, release_mailbox1_, sync_point1_);
303 gpu::Mailbox m2;
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 {
330 protected:
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_,
336 false)).Times(1);
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_,
362 false))
363 .Times(1);
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_,
373 false))
374 .Times(1);
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(),
387 0, false))
388 .Times(1);
389 test_layer->SetTextureMailbox(TextureMailbox());
390 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
391 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
393 // Test destructor.
394 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
395 test_layer->SetTextureMailbox(test_data_.mailbox1_);
398 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
399 public:
400 TextureLayerImplWithMailboxThreadedCallback()
401 : callback_count_(0),
402 commit_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);
408 ++callback_count_;
411 void SetMailbox(char mailbox_char) {
412 TextureMailbox mailbox(
413 std::string(64, mailbox_char),
414 base::Bind(
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);
434 SetMailbox('1');
435 EXPECT_EQ(0, callback_count_);
437 // Case #1: change mailbox before the commit. The old mailbox should be
438 // released immediately.
439 SetMailbox('2');
440 EXPECT_EQ(1, callback_count_);
441 PostSetNeedsCommitToMainThread();
444 virtual void DidCommit() OVERRIDE {
445 ++commit_count_;
446 switch (commit_count_) {
447 case 1:
448 // Case #2: change mailbox after the commit (and draw), where the
449 // layer draws. The old mailbox should be released during the next
450 // commit.
451 SetMailbox('3');
452 EXPECT_EQ(1, callback_count_);
453 break;
454 case 2:
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();
460 break;
461 case 3:
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());
466 SetMailbox('4');
467 break;
468 case 4:
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();
474 break;
475 case 5:
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());
480 break;
481 case 6:
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();
487 break;
488 case 7:
489 EXPECT_EQ(4, callback_count_);
490 // Restore a mailbox for the next step.
491 SetMailbox('5');
492 break;
493 case 8:
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();
498 break;
499 case 9:
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();
505 break;
506 case 10:
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_);
511 EndTest();
512 break;
513 default:
514 NOTREACHED();
515 break;
519 virtual void AfterTest() OVERRIDE {}
521 private:
522 int callback_count_;
523 int commit_count_;
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 {
532 protected:
533 TextureLayerImplWithMailboxTest()
534 : fake_client_(
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());
546 if (will_draw)
547 layer->DidDraw(host_impl_.active_tree()->resource_provider());
548 return will_draw;
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_,
561 false))
562 .Times(AnyNumber());
563 EXPECT_CALL(test_data_.mock_callback_,
564 Release2(test_data_.shared_memory_.get(), 0, false))
565 .Times(AnyNumber());
566 // Hardware mode.
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);
592 unsigned texture =
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));
605 // Software mode.
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);
631 unsigned texture =
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);
655 unsigned texture =
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_,
678 false))
679 .Times(1);
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))
693 .Times(1);
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))
701 .Times(1);
702 pending_layer->SetTextureMailbox(TextureMailbox());
703 pending_layer->PushPropertiesTo(active_layer.get());
704 active_layer->DidBecomeActive();
705 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
707 // Test destructor.
708 EXPECT_CALL(test_data_.mock_callback_,
709 Release(test_data_.mailbox_name1_,
710 test_data_.sync_point1_,
711 false))
712 .Times(1);
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))
724 .Times(1);
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))
750 .Times(1);
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 {
759 public:
760 TextureLayerClientTest()
761 : context_(NULL),
762 texture_(0),
763 commit_count_(0),
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 {
777 return texture_;
780 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
781 return context_;
784 virtual bool PrepareTextureMailbox(
785 cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE {
786 return false;
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 {
814 ++commit_count_;
815 switch (commit_count_) {
816 case 1:
817 texture_layer_->ClearClient();
818 texture_layer_->SetNeedsDisplay();
820 base::AutoLock lock(lock_);
821 expected_used_textures_on_commit_ = 0;
823 texture_ = 0;
824 break;
825 case 2:
826 EndTest();
827 break;
828 default:
829 NOTREACHED();
830 break;
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();
843 return true;
846 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
847 bool result) OVERRIDE {
848 ASSERT_TRUE(result);
849 EXPECT_EQ(expected_used_textures_on_draw_, context_->NumUsedTextures());
852 virtual void AfterTest() OVERRIDE {}
854 private:
855 scoped_refptr<TextureLayer> texture_layer_;
856 TestWebGraphicsContext3D* context_;
857 unsigned texture_;
858 int commit_count_;
860 // Used only on thread.
861 unsigned expected_used_textures_on_draw_;
863 // Used on either thread, protected by lock_.
864 base::Lock lock_;
865 unsigned expected_used_textures_on_commit_;
868 // The TextureLayerClient does not use mailboxes, so can't use a delegating
869 // renderer.
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 {
876 public:
877 TextureLayerLostContextTest()
878 : texture_(0),
879 draw_count_(0) {}
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);
895 return texture_;
898 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
899 return texture_context_.get();
902 virtual bool PrepareTextureMailbox(
903 cc::TextureMailbox* mailbox, bool use_shared_memory) OVERRIDE {
904 return false;
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());
933 else
934 EXPECT_EQ(texture_, texture_layer->texture_id());
935 return true;
938 virtual void DidCommitAndDrawFrame() OVERRIDE {
939 EndTest();
942 virtual void AfterTest() OVERRIDE {}
944 private:
945 scoped_refptr<TextureLayer> texture_layer_;
946 scoped_ptr<TestWebGraphicsContext3D> texture_context_;
947 unsigned texture_;
948 int draw_count_;
951 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest);
953 } // namespace
954 } // namespace cc