Adding a logging class to cast.
[chromium-blink-merge.git] / cc / layers / texture_layer_unittest.cc
blobbdb1358ae60f24d2d988844b5ea685348cb280c7
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 <algorithm>
8 #include <string>
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/debug/test_web_graphics_context_3d.h"
16 #include "cc/layers/solid_color_layer.h"
17 #include "cc/layers/texture_layer_client.h"
18 #include "cc/layers/texture_layer_impl.h"
19 #include "cc/output/compositor_frame_ack.h"
20 #include "cc/output/context_provider.h"
21 #include "cc/resources/returned_resource.h"
22 #include "cc/test/fake_impl_proxy.h"
23 #include "cc/test/fake_layer_tree_host_client.h"
24 #include "cc/test/fake_layer_tree_host_impl.h"
25 #include "cc/test/fake_output_surface.h"
26 #include "cc/test/layer_test_common.h"
27 #include "cc/test/layer_tree_test.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;
37 using ::testing::_;
38 using ::testing::AtLeast;
39 using ::testing::AnyNumber;
41 namespace cc {
42 namespace {
44 class MockLayerTreeHost : public LayerTreeHost {
45 public:
46 explicit MockLayerTreeHost(LayerTreeHostClient* client)
47 : LayerTreeHost(client, LayerTreeSettings()) {
48 Initialize(NULL);
51 MOCK_METHOD0(AcquireLayerTextures, void());
52 MOCK_METHOD0(SetNeedsCommit, void());
53 MOCK_METHOD0(SetNeedsUpdateLayers, void());
54 MOCK_METHOD1(StartRateLimiter, void(WebKit::WebGraphicsContext3D* context));
55 MOCK_METHOD1(StopRateLimiter, void(WebKit::WebGraphicsContext3D* context));
58 class TextureLayerTest : public testing::Test {
59 public:
60 TextureLayerTest()
61 : fake_client_(
62 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)),
63 host_impl_(&proxy_) {}
65 protected:
66 virtual void SetUp() {
67 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
70 virtual void TearDown() {
71 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
72 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
73 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
75 layer_tree_host_->SetRootLayer(NULL);
76 layer_tree_host_.reset();
79 scoped_ptr<MockLayerTreeHost> layer_tree_host_;
80 FakeImplProxy proxy_;
81 FakeLayerTreeHostClient fake_client_;
82 FakeLayerTreeHostImpl host_impl_;
85 TEST_F(TextureLayerTest, SyncImplWhenChangingTextureId) {
86 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
87 ASSERT_TRUE(test_layer.get());
89 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
90 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
91 layer_tree_host_->SetRootLayer(test_layer);
92 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
93 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
95 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
96 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
97 test_layer->SetTextureId(1);
98 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
100 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
101 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
102 test_layer->SetTextureId(2);
103 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
105 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
106 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
107 test_layer->SetTextureId(0);
108 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
111 TEST_F(TextureLayerTest, SyncImplWhenDrawing) {
112 gfx::RectF dirty_rect(0.f, 0.f, 1.f, 1.f);
114 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
115 ASSERT_TRUE(test_layer.get());
116 scoped_ptr<TextureLayerImpl> impl_layer;
117 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
118 ASSERT_TRUE(impl_layer);
120 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
121 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
122 layer_tree_host_->SetRootLayer(test_layer);
123 test_layer->SetTextureId(1);
124 test_layer->SetIsDrawable(true);
125 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
126 EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get());
128 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
129 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
130 test_layer->WillModifyTexture();
131 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
133 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
134 EXPECT_CALL(*layer_tree_host_, SetNeedsUpdateLayers()).Times(1);
135 test_layer->SetNeedsDisplayRect(dirty_rect);
136 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
138 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
139 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
140 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
141 test_layer->SetIsDrawable(false);
142 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
144 // Verify that non-drawable layers don't signal the compositor,
145 // except for the first draw after last commit, which must acquire
146 // the texture.
147 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(1);
148 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
149 test_layer->WillModifyTexture();
150 test_layer->SetNeedsDisplayRect(dirty_rect);
151 test_layer->PushPropertiesTo(impl_layer.get()); // fake commit
152 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
154 // Second draw with layer in non-drawable state: no texture
155 // acquisition.
156 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
157 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(0);
158 test_layer->WillModifyTexture();
159 test_layer->SetNeedsDisplayRect(dirty_rect);
160 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
163 TEST_F(TextureLayerTest, SyncImplWhenRemovingFromTree) {
164 scoped_refptr<Layer> root_layer = Layer::Create();
165 ASSERT_TRUE(root_layer.get());
166 scoped_refptr<Layer> child_layer = Layer::Create();
167 ASSERT_TRUE(child_layer.get());
168 root_layer->AddChild(child_layer);
169 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
170 ASSERT_TRUE(test_layer.get());
171 test_layer->SetTextureId(0);
172 child_layer->AddChild(test_layer);
174 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
175 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
176 layer_tree_host_->SetRootLayer(root_layer);
177 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
179 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
180 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
181 test_layer->RemoveFromParent();
182 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
184 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
185 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
186 child_layer->AddChild(test_layer);
187 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
189 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
190 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
191 test_layer->SetTextureId(1);
192 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
194 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AtLeast(1));
195 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
196 test_layer->RemoveFromParent();
197 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
200 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) {
201 scoped_refptr<TextureLayer> test_layer = TextureLayer::Create(NULL);
202 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer));
204 // Test properties that should call SetNeedsCommit. All properties need to
205 // be set to new values in order for SetNeedsCommit to be called.
206 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false));
207 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV(
208 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f)));
209 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity(
210 0.5f, 0.5f, 0.5f, 0.5f));
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false));
212 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true));
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetTextureId(1));
215 // Calling SetTextureId can call AcquireLayerTextures.
216 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(AnyNumber());
219 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) {
220 const gfx::Size layer_bounds(100, 100);
221 const gfx::Rect layer_rect(layer_bounds);
222 const Region layer_region(layer_rect);
224 scoped_refptr<TextureLayer> layer = TextureLayer::Create(NULL);
225 layer->SetBounds(layer_bounds);
226 layer->draw_properties().visible_content_rect = layer_rect;
227 layer->SetBlendBackgroundColor(true);
229 // Verify initial conditions.
230 EXPECT_FALSE(layer->contents_opaque());
231 EXPECT_EQ(0u, layer->background_color());
232 EXPECT_EQ(Region().ToString(),
233 layer->VisibleContentOpaqueRegion().ToString());
235 // Opaque background.
236 layer->SetBackgroundColor(SK_ColorWHITE);
237 EXPECT_EQ(layer_region.ToString(),
238 layer->VisibleContentOpaqueRegion().ToString());
240 // Transparent background.
241 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255));
242 EXPECT_EQ(Region().ToString(),
243 layer->VisibleContentOpaqueRegion().ToString());
246 class FakeTextureLayerClient : public TextureLayerClient {
247 public:
248 FakeTextureLayerClient() : context_(TestWebGraphicsContext3D::Create()) {}
250 virtual unsigned PrepareTexture() OVERRIDE {
251 return 0;
254 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
255 return context_.get();
258 virtual bool PrepareTextureMailbox(
259 TextureMailbox* mailbox,
260 scoped_ptr<SingleReleaseCallback>* release_callback,
261 bool use_shared_memory) OVERRIDE {
262 *mailbox = TextureMailbox();
263 *release_callback = scoped_ptr<SingleReleaseCallback>();
264 return true;
267 private:
268 scoped_ptr<TestWebGraphicsContext3D> context_;
269 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient);
272 TEST_F(TextureLayerTest, RateLimiter) {
273 FakeTextureLayerClient client;
274 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(
275 &client);
276 test_layer->SetIsDrawable(true);
277 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
278 layer_tree_host_->SetRootLayer(test_layer);
280 // Don't rate limit until we invalidate.
281 EXPECT_CALL(*layer_tree_host_, StartRateLimiter(_)).Times(0);
282 test_layer->SetRateLimitContext(true);
283 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
285 // Do rate limit after we invalidate.
286 EXPECT_CALL(*layer_tree_host_, StartRateLimiter(client.Context3d()));
287 test_layer->SetNeedsDisplay();
288 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
290 // Stop rate limiter when we don't want it any more.
291 EXPECT_CALL(*layer_tree_host_, StopRateLimiter(client.Context3d()));
292 test_layer->SetRateLimitContext(false);
293 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
295 // Or we clear the client.
296 test_layer->SetRateLimitContext(true);
297 EXPECT_CALL(*layer_tree_host_, StopRateLimiter(client.Context3d()));
298 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
299 test_layer->ClearClient();
300 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
302 // Reset to a layer with a client, that started the rate limiter.
303 test_layer = TextureLayer::CreateForMailbox(
304 &client);
305 test_layer->SetIsDrawable(true);
306 test_layer->SetRateLimitContext(true);
307 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
308 layer_tree_host_->SetRootLayer(test_layer);
309 EXPECT_CALL(*layer_tree_host_, StartRateLimiter(_)).Times(0);
310 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
311 EXPECT_CALL(*layer_tree_host_, StartRateLimiter(client.Context3d()));
312 test_layer->SetNeedsDisplay();
313 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
315 // Stop rate limiter when we're removed from the tree.
316 EXPECT_CALL(*layer_tree_host_, StopRateLimiter(client.Context3d()));
317 layer_tree_host_->SetRootLayer(NULL);
318 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
321 class MockMailboxCallback {
322 public:
323 MOCK_METHOD3(Release, void(const std::string& mailbox,
324 unsigned sync_point,
325 bool lost_resource));
326 MOCK_METHOD3(Release2, void(base::SharedMemory* shared_memory,
327 unsigned sync_point,
328 bool lost_resource));
331 struct CommonMailboxObjects {
332 CommonMailboxObjects()
333 : mailbox_name1_(64, '1'),
334 mailbox_name2_(64, '2'),
335 sync_point1_(1),
336 sync_point2_(2),
337 shared_memory_(new base::SharedMemory) {
338 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
339 base::Unretained(&mock_callback_),
340 mailbox_name1_);
341 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release,
342 base::Unretained(&mock_callback_),
343 mailbox_name2_);
344 gpu::Mailbox m1;
345 m1.SetName(reinterpret_cast<const int8*>(mailbox_name1_.data()));
346 mailbox1_ = TextureMailbox(m1, sync_point1_);
347 gpu::Mailbox m2;
348 m2.SetName(reinterpret_cast<const int8*>(mailbox_name2_.data()));
349 mailbox2_ = TextureMailbox(m2, sync_point2_);
351 gfx::Size size(128, 128);
352 EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
353 release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
354 base::Unretained(&mock_callback_),
355 shared_memory_.get());
356 mailbox3_ = TextureMailbox(shared_memory_.get(), size);
359 std::string mailbox_name1_;
360 std::string mailbox_name2_;
361 MockMailboxCallback mock_callback_;
362 ReleaseCallback release_mailbox1_;
363 ReleaseCallback release_mailbox2_;
364 ReleaseCallback release_mailbox3_;
365 TextureMailbox mailbox1_;
366 TextureMailbox mailbox2_;
367 TextureMailbox mailbox3_;
368 unsigned sync_point1_;
369 unsigned sync_point2_;
370 scoped_ptr<base::SharedMemory> shared_memory_;
373 class TestMailboxHolder : public TextureLayer::MailboxHolder {
374 public:
375 using TextureLayer::MailboxHolder::Create;
377 protected:
378 virtual ~TestMailboxHolder() {}
381 class TextureLayerWithMailboxTest : public TextureLayerTest {
382 protected:
383 virtual void TearDown() {
384 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
385 EXPECT_CALL(test_data_.mock_callback_,
386 Release(test_data_.mailbox_name1_,
387 test_data_.sync_point1_,
388 false)).Times(1);
389 TextureLayerTest::TearDown();
392 CommonMailboxObjects test_data_;
395 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
396 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
397 ASSERT_TRUE(test_layer.get());
399 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
400 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber());
401 layer_tree_host_->SetRootLayer(test_layer);
402 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
404 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
405 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
406 test_layer->SetTextureMailbox(
407 test_data_.mailbox1_,
408 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
409 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
411 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
412 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
413 EXPECT_CALL(test_data_.mock_callback_,
414 Release(test_data_.mailbox_name1_,
415 test_data_.sync_point1_,
416 false))
417 .Times(1);
418 test_layer->SetTextureMailbox(
419 test_data_.mailbox2_,
420 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
421 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
422 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
424 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
425 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
426 EXPECT_CALL(test_data_.mock_callback_,
427 Release(test_data_.mailbox_name2_,
428 test_data_.sync_point2_,
429 false))
430 .Times(1);
431 test_layer->SetTextureMailbox(TextureMailbox(),
432 scoped_ptr<SingleReleaseCallback>());
433 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
434 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
436 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
437 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
438 test_layer->SetTextureMailbox(
439 test_data_.mailbox3_,
440 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
441 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
442 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
444 EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
445 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
446 EXPECT_CALL(test_data_.mock_callback_,
447 Release2(test_data_.shared_memory_.get(),
448 0, false))
449 .Times(1);
450 test_layer->SetTextureMailbox(TextureMailbox(),
451 scoped_ptr<SingleReleaseCallback>());
452 Mock::VerifyAndClearExpectations(layer_tree_host_.get());
453 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
455 // Test destructor.
456 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
457 test_layer->SetTextureMailbox(
458 test_data_.mailbox1_,
459 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
462 class TextureLayerMailboxHolderTest : public TextureLayerTest {
463 public:
464 TextureLayerMailboxHolderTest()
465 : main_thread_("MAIN") {
466 main_thread_.Start();
469 void Wait(const base::Thread& thread) {
470 bool manual_reset = false;
471 bool initially_signaled = false;
472 base::WaitableEvent event(manual_reset, initially_signaled);
473 thread.message_loop()->PostTask(
474 FROM_HERE,
475 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)));
476 event.Wait();
479 void CreateMainRef() {
480 main_ref_ = TestMailboxHolder::Create(
481 test_data_.mailbox1_,
482 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass();
485 void ReleaseMainRef() {
486 main_ref_.reset();
489 void CreateImplRef(scoped_ptr<SingleReleaseCallback>* impl_ref) {
490 *impl_ref = main_ref_->holder()->GetCallbackForImplThread();
493 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture,
494 base::WaitableEvent* wait_for_capture,
495 base::WaitableEvent* stop_capture) {
496 begin_capture->Wait();
497 BlockingTaskRunner::CapturePostTasks capture;
498 wait_for_capture->Signal();
499 stop_capture->Wait();
502 protected:
503 scoped_ptr<TestMailboxHolder::MainThreadReference>
504 main_ref_;
505 base::Thread main_thread_;
506 CommonMailboxObjects test_data_;
509 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) {
510 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
511 ASSERT_TRUE(test_layer.get());
513 main_thread_.message_loop()->PostTask(
514 FROM_HERE,
515 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
516 base::Unretained(this)));
518 Wait(main_thread_);
520 // The texture layer is attached to compositor1, and passes a reference to its
521 // impl tree.
522 scoped_ptr<SingleReleaseCallback> compositor1;
523 main_thread_.message_loop()->PostTask(
524 FROM_HERE,
525 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
526 base::Unretained(this),
527 &compositor1));
529 // Then the texture layer is removed and attached to compositor2, and passes a
530 // reference to its impl tree.
531 scoped_ptr<SingleReleaseCallback> compositor2;
532 main_thread_.message_loop()->PostTask(
533 FROM_HERE,
534 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
535 base::Unretained(this),
536 &compositor2));
538 Wait(main_thread_);
539 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
541 // The compositors both destroy their impl trees before the main thread layer
542 // is destroyed.
543 compositor1->Run(100, false);
544 compositor2->Run(200, false);
546 Wait(main_thread_);
548 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
549 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
551 // The main thread ref is the last one, so the mailbox is released back to the
552 // embedder, with the last sync point provided by the impl trees.
553 EXPECT_CALL(test_data_.mock_callback_,
554 Release(test_data_.mailbox_name1_, 200, false)).Times(1);
556 main_thread_.message_loop()->PostTask(
557 FROM_HERE,
558 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
559 base::Unretained(this)));
560 Wait(main_thread_);
561 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
564 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) {
565 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
566 ASSERT_TRUE(test_layer.get());
568 main_thread_.message_loop()->PostTask(
569 FROM_HERE,
570 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
571 base::Unretained(this)));
573 Wait(main_thread_);
575 // The texture layer is attached to compositor1, and passes a reference to its
576 // impl tree.
577 scoped_ptr<SingleReleaseCallback> compositor1;
578 main_thread_.message_loop()->PostTask(
579 FROM_HERE,
580 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
581 base::Unretained(this),
582 &compositor1));
584 // Then the texture layer is removed and attached to compositor2, and passes a
585 // reference to its impl tree.
586 scoped_ptr<SingleReleaseCallback> compositor2;
587 main_thread_.message_loop()->PostTask(
588 FROM_HERE,
589 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
590 base::Unretained(this),
591 &compositor2));
593 Wait(main_thread_);
594 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
596 // One compositor destroys their impl tree.
597 compositor1->Run(100, false);
599 // Then the main thread reference is destroyed.
600 main_thread_.message_loop()->PostTask(
601 FROM_HERE,
602 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
603 base::Unretained(this)));
605 Wait(main_thread_);
607 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
608 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
610 // The second impl reference is destroyed last, causing the mailbox to be
611 // released back to the embedder with the last sync point from the impl tree.
612 EXPECT_CALL(test_data_.mock_callback_,
613 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
615 compositor2->Run(200, true);
616 Wait(main_thread_);
617 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
620 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) {
621 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
622 ASSERT_TRUE(test_layer.get());
624 main_thread_.message_loop()->PostTask(
625 FROM_HERE,
626 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
627 base::Unretained(this)));
629 Wait(main_thread_);
631 // The texture layer is attached to compositor1, and passes a reference to its
632 // impl tree.
633 scoped_ptr<SingleReleaseCallback> compositor1;
634 main_thread_.message_loop()->PostTask(
635 FROM_HERE,
636 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
637 base::Unretained(this),
638 &compositor1));
640 // Then the texture layer is removed and attached to compositor2, and passes a
641 // reference to its impl tree.
642 scoped_ptr<SingleReleaseCallback> compositor2;
643 main_thread_.message_loop()->PostTask(
644 FROM_HERE,
645 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
646 base::Unretained(this),
647 &compositor2));
649 Wait(main_thread_);
650 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
652 // The main thread reference is destroyed first.
653 main_thread_.message_loop()->PostTask(
654 FROM_HERE,
655 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
656 base::Unretained(this)));
658 // One compositor destroys their impl tree.
659 compositor2->Run(200, false);
661 Wait(main_thread_);
663 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
664 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
666 // The second impl reference is destroyed last, causing the mailbox to be
667 // released back to the embedder with the last sync point from the impl tree.
668 EXPECT_CALL(test_data_.mock_callback_,
669 Release(test_data_.mailbox_name1_, 100, true)).Times(1);
671 compositor1->Run(100, true);
672 Wait(main_thread_);
673 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
676 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) {
677 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox(NULL);
678 ASSERT_TRUE(test_layer.get());
680 main_thread_.message_loop()->PostTask(
681 FROM_HERE,
682 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef,
683 base::Unretained(this)));
685 Wait(main_thread_);
687 // The texture layer is attached to compositor1, and passes a reference to its
688 // impl tree.
689 scoped_ptr<SingleReleaseCallback> compositor1;
690 main_thread_.message_loop()->PostTask(
691 FROM_HERE,
692 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
693 base::Unretained(this),
694 &compositor1));
696 // Then the texture layer is removed and attached to compositor2, and passes a
697 // reference to its impl tree.
698 scoped_ptr<SingleReleaseCallback> compositor2;
699 main_thread_.message_loop()->PostTask(
700 FROM_HERE,
701 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef,
702 base::Unretained(this),
703 &compositor2));
705 Wait(main_thread_);
706 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
708 // The main thread reference is destroyed first.
709 main_thread_.message_loop()->PostTask(
710 FROM_HERE,
711 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef,
712 base::Unretained(this)));
714 EXPECT_CALL(test_data_.mock_callback_,
715 Release(test_data_.mailbox_name1_, 200, true)).Times(1);
717 bool manual_reset = false;
718 bool initially_signaled = false;
719 base::WaitableEvent begin_capture(manual_reset, initially_signaled);
720 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled);
721 base::WaitableEvent stop_capture(manual_reset, initially_signaled);
723 // Post a task to start capturing tasks on the main thread. This will block
724 // the main thread until we signal the |stop_capture| event.
725 main_thread_.message_loop()->PostTask(
726 FROM_HERE,
727 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait,
728 base::Unretained(this),
729 &begin_capture,
730 &wait_for_capture,
731 &stop_capture));
733 // Before the main thread capturing starts, one compositor destroys their
734 // impl reference. Since capturing did not start, this gets post-tasked to
735 // the main thread.
736 compositor1->Run(100, false);
738 // Start capturing on the main thread.
739 begin_capture.Signal();
740 wait_for_capture.Wait();
742 // Meanwhile, the second compositor released its impl reference, but this task
743 // gets shortcutted directly to the main thread. This means the reference is
744 // released before compositor1, whose reference will be released later when
745 // the post-task is serviced. But since it was destroyed _on the impl thread_
746 // last, its sync point values should be used.
747 compositor2->Run(200, true);
749 stop_capture.Signal();
750 Wait(main_thread_);
752 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
755 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest {
756 public:
757 TextureLayerImplWithMailboxThreadedCallback()
758 : callback_count_(0),
759 commit_count_(0) {}
761 // Make sure callback is received on main and doesn't block the impl thread.
762 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
763 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
764 EXPECT_FALSE(lost_resource);
765 ++callback_count_;
768 void SetMailbox(char mailbox_char) {
769 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
770 TextureMailbox mailbox(std::string(64, mailbox_char));
771 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
772 base::Bind(
773 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback,
774 base::Unretained(this)));
775 layer_->SetTextureMailbox(mailbox, callback.Pass());
778 virtual void BeginTest() OVERRIDE {
779 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
781 gfx::Size bounds(100, 100);
782 root_ = Layer::Create();
783 root_->SetAnchorPoint(gfx::PointF());
784 root_->SetBounds(bounds);
786 layer_ = TextureLayer::CreateForMailbox(NULL);
787 layer_->SetIsDrawable(true);
788 layer_->SetAnchorPoint(gfx::PointF());
789 layer_->SetBounds(bounds);
791 root_->AddChild(layer_);
792 layer_tree_host()->SetRootLayer(root_);
793 layer_tree_host()->SetViewportSize(bounds);
794 SetMailbox('1');
795 EXPECT_EQ(0, callback_count_);
797 // Case #1: change mailbox before the commit. The old mailbox should be
798 // released immediately.
799 SetMailbox('2');
800 EXPECT_EQ(1, callback_count_);
801 PostSetNeedsCommitToMainThread();
804 virtual void DidCommit() OVERRIDE {
805 ++commit_count_;
806 switch (commit_count_) {
807 case 1:
808 // Case #2: change mailbox after the commit (and draw), where the
809 // layer draws. The old mailbox should be released during the next
810 // commit.
811 SetMailbox('3');
812 EXPECT_EQ(1, callback_count_);
813 break;
814 case 2:
815 EXPECT_EQ(2, callback_count_);
816 // Case #3: change mailbox when the layer doesn't draw. The old
817 // mailbox should be released during the next commit.
818 layer_->SetBounds(gfx::Size());
819 SetMailbox('4');
820 break;
821 case 3:
822 EXPECT_EQ(3, callback_count_);
823 // Case #4: release mailbox that was committed but never drawn. The
824 // old mailbox should be released during the next commit.
825 layer_->SetTextureMailbox(TextureMailbox(),
826 scoped_ptr<SingleReleaseCallback>());
827 break;
828 case 4:
829 if (layer_tree_host()->settings().impl_side_painting) {
830 // With impl painting, the texture mailbox will still be on the impl
831 // thread when the commit finishes, because the layer is not drawble
832 // when it has no texture mailbox, and thus does not block the commit
833 // on activation. So, we wait for activation.
834 // TODO(danakj): fix this. crbug.com/277953
835 layer_tree_host()->SetNeedsCommit();
836 break;
837 } else {
838 ++commit_count_;
840 case 5:
841 EXPECT_EQ(4, callback_count_);
842 // Restore a mailbox for the next step.
843 SetMailbox('5');
844 break;
845 case 6:
846 // Case #5: remove layer from tree. Callback should *not* be called, the
847 // mailbox is returned to the main thread.
848 EXPECT_EQ(4, callback_count_);
849 layer_->RemoveFromParent();
850 break;
851 case 7:
852 if (layer_tree_host()->settings().impl_side_painting) {
853 // With impl painting, the texture mailbox will still be on the impl
854 // thread when the commit finishes, because the layer is not around to
855 // block the commit on activation anymore. So, we wait for activation.
856 // TODO(danakj): fix this. crbug.com/277953
857 layer_tree_host()->SetNeedsCommit();
858 break;
859 } else {
860 ++commit_count_;
862 case 8:
863 EXPECT_EQ(4, callback_count_);
864 // Resetting the mailbox will call the callback now.
865 layer_->SetTextureMailbox(TextureMailbox(),
866 scoped_ptr<SingleReleaseCallback>());
867 EXPECT_EQ(5, callback_count_);
868 EndTest();
869 break;
870 default:
871 NOTREACHED();
872 break;
876 virtual void AfterTest() OVERRIDE {}
878 private:
879 base::ThreadChecker main_thread_;
880 int callback_count_;
881 int commit_count_;
882 scoped_refptr<Layer> root_;
883 scoped_refptr<TextureLayer> layer_;
886 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
887 TextureLayerImplWithMailboxThreadedCallback);
890 class TextureLayerNoMailboxIsActivatedDuringCommit : public LayerTreeTest,
891 public TextureLayerClient {
892 protected:
893 TextureLayerNoMailboxIsActivatedDuringCommit()
894 : wait_thread_("WAIT"),
895 wait_event_(false, false),
896 context_(TestWebGraphicsContext3D::Create()) {
897 wait_thread_.Start();
900 virtual void BeginTest() OVERRIDE {
901 activate_count_ = 0;
903 gfx::Size bounds(100, 100);
904 root_ = Layer::Create();
905 root_->SetAnchorPoint(gfx::PointF());
906 root_->SetBounds(bounds);
908 layer_ = TextureLayer::Create(this);
909 layer_->SetIsDrawable(true);
910 layer_->SetAnchorPoint(gfx::PointF());
911 layer_->SetBounds(bounds);
913 root_->AddChild(layer_);
914 layer_tree_host()->SetRootLayer(root_);
915 layer_tree_host()->SetViewportSize(bounds);
917 PostSetNeedsCommitToMainThread();
920 // TextureLayerClient implementation.
921 virtual unsigned PrepareTexture() OVERRIDE {
922 context_->makeContextCurrent();
923 return context_->createTexture();
925 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
926 return context_.get();
928 virtual bool PrepareTextureMailbox(
929 TextureMailbox* mailbox,
930 scoped_ptr<SingleReleaseCallback>* release_callback,
931 bool use_shared_memory) OVERRIDE {
932 return false;
935 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
936 // Slow down activation so the main thread DidCommit() will run if
937 // not blocked.
938 wait_thread_.message_loop()->PostDelayedTask(
939 FROM_HERE,
940 base::Bind(&base::WaitableEvent::Signal,
941 base::Unretained(&wait_event_)),
942 base::TimeDelta::FromMilliseconds(10));
943 wait_event_.Wait();
945 base::AutoLock lock(activate_lock_);
946 ++activate_count_;
949 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
950 // The main thread is awake now, and will run DidCommit() immediately.
951 // Run DidActivate() afterwards by posting it now.
952 proxy()->MainThreadTaskRunner()->PostTask(
953 FROM_HERE,
954 base::Bind(&TextureLayerNoMailboxIsActivatedDuringCommit::DidActivate,
955 base::Unretained(this)));
958 void DidActivate() {
959 base::AutoLock lock(activate_lock_);
960 switch (activate_count_) {
961 case 1:
962 // The first texture has been activated. Invalidate the layer so it
963 // grabs a new texture id from the client.
964 layer_->SetNeedsDisplay();
965 // So this commit number should complete after the second activate.
966 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
967 break;
968 case 2:
969 // The second mailbox has been activated. Remove the layer from
970 // the tree to cause another commit/activation. The commit should
971 // finish *after* the layer is removed from the active tree.
972 layer_->RemoveFromParent();
973 // So this commit number should complete after the third activate.
974 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
975 break;
976 case 3:
977 EndTest();
978 break;
982 virtual void DidCommit() OVERRIDE {
983 switch (layer_tree_host()->source_frame_number()) {
984 case 2: {
985 // The activate for the 2nd texture should have happened before now.
986 base::AutoLock lock(activate_lock_);
987 EXPECT_EQ(2, activate_count_);
988 break;
990 case 3: {
991 // The activate to remove the layer should have happened before now.
992 base::AutoLock lock(activate_lock_);
993 EXPECT_EQ(3, activate_count_);
994 break;
1000 virtual void AfterTest() OVERRIDE {}
1002 base::Thread wait_thread_;
1003 base::WaitableEvent wait_event_;
1004 base::Lock activate_lock_;
1005 int activate_count_;
1006 int activate_commit_;
1007 scoped_refptr<Layer> root_;
1008 scoped_refptr<TextureLayer> layer_;
1009 scoped_ptr<TestWebGraphicsContext3D> context_;
1012 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1013 TextureLayerNoMailboxIsActivatedDuringCommit);
1015 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest {
1016 protected:
1017 TextureLayerMailboxIsActivatedDuringCommit()
1018 : wait_thread_("WAIT"),
1019 wait_event_(false, false) {
1020 wait_thread_.Start();
1023 static void ReleaseCallback(unsigned sync_point, bool lost_resource) {}
1025 void SetMailbox(char mailbox_char) {
1026 TextureMailbox mailbox(std::string(64, mailbox_char));
1027 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1028 base::Bind(
1029 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback));
1030 layer_->SetTextureMailbox(mailbox, callback.Pass());
1033 virtual void BeginTest() OVERRIDE {
1034 activate_count_ = 0;
1036 gfx::Size bounds(100, 100);
1037 root_ = Layer::Create();
1038 root_->SetAnchorPoint(gfx::PointF());
1039 root_->SetBounds(bounds);
1041 layer_ = TextureLayer::CreateForMailbox(NULL);
1042 layer_->SetIsDrawable(true);
1043 layer_->SetAnchorPoint(gfx::PointF());
1044 layer_->SetBounds(bounds);
1046 root_->AddChild(layer_);
1047 layer_tree_host()->SetRootLayer(root_);
1048 layer_tree_host()->SetViewportSize(bounds);
1049 SetMailbox('1');
1051 PostSetNeedsCommitToMainThread();
1054 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1055 // Slow down activation so the main thread DidCommit() will run if
1056 // not blocked.
1057 wait_thread_.message_loop()->PostDelayedTask(
1058 FROM_HERE,
1059 base::Bind(&base::WaitableEvent::Signal,
1060 base::Unretained(&wait_event_)),
1061 base::TimeDelta::FromMilliseconds(10));
1062 wait_event_.Wait();
1064 base::AutoLock lock(activate_lock_);
1065 ++activate_count_;
1068 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1069 // The main thread is awake now, and will run DidCommit() immediately.
1070 // Run DidActivate() afterwards by posting it now.
1071 proxy()->MainThreadTaskRunner()->PostTask(
1072 FROM_HERE,
1073 base::Bind(&TextureLayerMailboxIsActivatedDuringCommit::DidActivate,
1074 base::Unretained(this)));
1077 void DidActivate() {
1078 base::AutoLock lock(activate_lock_);
1079 switch (activate_count_) {
1080 case 1:
1081 // The first mailbox has been activated. Set a new mailbox, and
1082 // expect the next commit to finish *after* it is activated.
1083 SetMailbox('2');
1084 // So this commit number should complete after the second activate.
1085 EXPECT_EQ(1, layer_tree_host()->source_frame_number());
1086 break;
1087 case 2:
1088 // The second mailbox has been activated. Remove the layer from
1089 // the tree to cause another commit/activation. The commit should
1090 // finish *after* the layer is removed from the active tree.
1091 layer_->RemoveFromParent();
1092 // So this commit number should complete after the third activate.
1093 EXPECT_EQ(2, layer_tree_host()->source_frame_number());
1094 break;
1095 case 3:
1096 EndTest();
1097 break;
1101 virtual void DidCommit() OVERRIDE {
1102 switch (layer_tree_host()->source_frame_number()) {
1103 case 2: {
1104 // The activate for the 2nd mailbox should have happened before now.
1105 base::AutoLock lock(activate_lock_);
1106 EXPECT_EQ(2, activate_count_);
1107 break;
1109 case 3: {
1110 // The activate to remove the layer should have happened before now.
1111 base::AutoLock lock(activate_lock_);
1112 EXPECT_EQ(3, activate_count_);
1113 break;
1119 virtual void AfterTest() OVERRIDE {}
1121 base::Thread wait_thread_;
1122 base::WaitableEvent wait_event_;
1123 base::Lock activate_lock_;
1124 int activate_count_;
1125 scoped_refptr<Layer> root_;
1126 scoped_refptr<TextureLayer> layer_;
1129 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1130 TextureLayerMailboxIsActivatedDuringCommit);
1132 class TextureLayerImplWithMailboxTest : public TextureLayerTest {
1133 protected:
1134 TextureLayerImplWithMailboxTest()
1135 : fake_client_(
1136 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {}
1138 virtual void SetUp() {
1139 TextureLayerTest::SetUp();
1140 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_));
1141 EXPECT_TRUE(host_impl_.InitializeRenderer(CreateFakeOutputSurface()));
1144 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
1145 bool will_draw = layer->WillDraw(
1146 mode, host_impl_.active_tree()->resource_provider());
1147 if (will_draw)
1148 layer->DidDraw(host_impl_.active_tree()->resource_provider());
1149 return will_draw;
1152 CommonMailboxObjects test_data_;
1153 FakeLayerTreeHostClient fake_client_;
1156 // Test conditions for results of TextureLayerImpl::WillDraw under
1157 // different configurations of different mailbox, texture_id, and draw_mode.
1158 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) {
1159 EXPECT_CALL(test_data_.mock_callback_,
1160 Release(test_data_.mailbox_name1_,
1161 test_data_.sync_point1_,
1162 false))
1163 .Times(AnyNumber());
1164 EXPECT_CALL(test_data_.mock_callback_,
1165 Release2(test_data_.shared_memory_.get(), 0, false))
1166 .Times(AnyNumber());
1167 // Hardware mode.
1169 scoped_ptr<TextureLayerImpl> impl_layer =
1170 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1171 impl_layer->SetDrawsContent(true);
1172 impl_layer->SetTextureMailbox(
1173 test_data_.mailbox1_,
1174 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1175 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1179 scoped_ptr<TextureLayerImpl> impl_layer =
1180 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1181 impl_layer->SetDrawsContent(true);
1182 impl_layer->SetTextureMailbox(TextureMailbox(),
1183 scoped_ptr<SingleReleaseCallback>());
1184 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1188 // Software resource.
1189 scoped_ptr<TextureLayerImpl> impl_layer =
1190 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1191 impl_layer->SetDrawsContent(true);
1192 impl_layer->SetTextureMailbox(
1193 test_data_.mailbox3_,
1194 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1195 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1199 scoped_ptr<TextureLayerImpl> impl_layer =
1200 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1201 impl_layer->SetDrawsContent(true);
1202 ContextProvider* context_provider =
1203 host_impl_.output_surface()->context_provider();
1204 unsigned texture =
1205 context_provider->Context3d()->createTexture();
1206 impl_layer->set_texture_id(texture);
1207 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1211 scoped_ptr<TextureLayerImpl> impl_layer =
1212 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1213 impl_layer->SetDrawsContent(true);
1214 impl_layer->set_texture_id(0);
1215 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE));
1218 // Software mode.
1220 scoped_ptr<TextureLayerImpl> impl_layer =
1221 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1222 impl_layer->SetDrawsContent(true);
1223 impl_layer->SetTextureMailbox(
1224 test_data_.mailbox1_,
1225 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1226 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1230 scoped_ptr<TextureLayerImpl> impl_layer =
1231 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1232 impl_layer->SetDrawsContent(true);
1233 impl_layer->SetTextureMailbox(TextureMailbox(),
1234 scoped_ptr<SingleReleaseCallback>());
1235 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1239 // Software resource.
1240 scoped_ptr<TextureLayerImpl> impl_layer =
1241 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1242 impl_layer->SetDrawsContent(true);
1243 impl_layer->SetTextureMailbox(
1244 test_data_.mailbox3_,
1245 SingleReleaseCallback::Create(test_data_.release_mailbox3_));
1246 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1250 scoped_ptr<TextureLayerImpl> impl_layer =
1251 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1252 impl_layer->SetDrawsContent(true);
1253 ContextProvider* context_provider =
1254 host_impl_.output_surface()->context_provider();
1255 unsigned texture =
1256 context_provider->Context3d()->createTexture();
1257 impl_layer->set_texture_id(texture);
1258 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1262 scoped_ptr<TextureLayerImpl> impl_layer =
1263 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1264 impl_layer->SetDrawsContent(true);
1265 impl_layer->set_texture_id(0);
1266 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
1269 // Resourceless software mode.
1271 scoped_ptr<TextureLayerImpl> impl_layer =
1272 TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1273 impl_layer->SetDrawsContent(true);
1274 impl_layer->SetTextureMailbox(
1275 test_data_.mailbox1_,
1276 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1277 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1281 scoped_ptr<TextureLayerImpl> impl_layer =
1282 TextureLayerImpl::Create(host_impl_.active_tree(), 1, false);
1283 impl_layer->SetDrawsContent(true);
1284 ContextProvider* context_provider =
1285 host_impl_.output_surface()->context_provider();
1286 unsigned texture =
1287 context_provider->Context3d()->createTexture();
1288 impl_layer->set_texture_id(texture);
1289 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE));
1293 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) {
1294 host_impl_.CreatePendingTree();
1295 scoped_ptr<TextureLayerImpl> pending_layer;
1296 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1, true);
1297 ASSERT_TRUE(pending_layer);
1299 scoped_ptr<LayerImpl> active_layer(
1300 pending_layer->CreateLayerImpl(host_impl_.active_tree()));
1301 ASSERT_TRUE(active_layer);
1303 pending_layer->SetTextureMailbox(
1304 test_data_.mailbox1_,
1305 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1307 // Test multiple commits without an activation.
1308 EXPECT_CALL(test_data_.mock_callback_,
1309 Release(test_data_.mailbox_name1_,
1310 test_data_.sync_point1_,
1311 false))
1312 .Times(1);
1313 pending_layer->SetTextureMailbox(
1314 test_data_.mailbox2_,
1315 SingleReleaseCallback::Create(test_data_.release_mailbox2_));
1316 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1318 // Test callback after activation.
1319 pending_layer->PushPropertiesTo(active_layer.get());
1320 active_layer->DidBecomeActive();
1322 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1323 pending_layer->SetTextureMailbox(
1324 test_data_.mailbox1_,
1325 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1326 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1328 EXPECT_CALL(test_data_.mock_callback_,
1329 Release(test_data_.mailbox_name2_, _, false))
1330 .Times(1);
1331 pending_layer->PushPropertiesTo(active_layer.get());
1332 active_layer->DidBecomeActive();
1333 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1335 // Test resetting the mailbox.
1336 EXPECT_CALL(test_data_.mock_callback_,
1337 Release(test_data_.mailbox_name1_, _, false))
1338 .Times(1);
1339 pending_layer->SetTextureMailbox(TextureMailbox(),
1340 scoped_ptr<SingleReleaseCallback>());
1341 pending_layer->PushPropertiesTo(active_layer.get());
1342 active_layer->DidBecomeActive();
1343 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1345 // Test destructor.
1346 EXPECT_CALL(test_data_.mock_callback_,
1347 Release(test_data_.mailbox_name1_,
1348 test_data_.sync_point1_,
1349 false))
1350 .Times(1);
1351 pending_layer->SetTextureMailbox(
1352 test_data_.mailbox1_,
1353 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1356 TEST_F(TextureLayerImplWithMailboxTest,
1357 TestDestructorCallbackOnCreatedResource) {
1358 scoped_ptr<TextureLayerImpl> impl_layer;
1359 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1, true);
1360 ASSERT_TRUE(impl_layer);
1362 EXPECT_CALL(test_data_.mock_callback_,
1363 Release(test_data_.mailbox_name1_, _, false))
1364 .Times(1);
1365 impl_layer->SetTextureMailbox(
1366 test_data_.mailbox1_,
1367 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1368 impl_layer->SetDrawsContent(true);
1369 impl_layer->DidBecomeActive();
1370 EXPECT_TRUE(impl_layer->WillDraw(
1371 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider()));
1372 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider());
1373 impl_layer->SetTextureMailbox(TextureMailbox(),
1374 scoped_ptr<SingleReleaseCallback>());
1377 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) {
1378 ResourceProvider* provider = host_impl_.active_tree()->resource_provider();
1379 ResourceProvider::ResourceId id =
1380 provider->CreateResourceFromTextureMailbox(
1381 test_data_.mailbox1_,
1382 SingleReleaseCallback::Create(test_data_.release_mailbox1_));
1383 provider->AllocateForTesting(id);
1385 // Transfer some resources to the parent.
1386 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1387 resource_ids_to_transfer.push_back(id);
1388 TransferableResourceArray list;
1389 provider->PrepareSendToParent(resource_ids_to_transfer, &list);
1390 EXPECT_TRUE(provider->InUseByConsumer(id));
1391 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0);
1392 provider->DeleteResource(id);
1393 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
1394 EXPECT_CALL(test_data_.mock_callback_,
1395 Release(test_data_.mailbox_name1_, _, false))
1396 .Times(1);
1397 ReturnedResourceArray returned;
1398 TransferableResource::ReturnResources(list, &returned);
1399 provider->ReceiveReturnsFromParent(returned);
1402 // Check that ClearClient correctly clears the state so that the impl side
1403 // doesn't try to use a texture that could have been destroyed.
1404 class TextureLayerClientTest
1405 : public LayerTreeTest,
1406 public TextureLayerClient {
1407 public:
1408 TextureLayerClientTest()
1409 : context_(NULL),
1410 texture_(0),
1411 commit_count_(0),
1412 expected_used_textures_on_draw_(0),
1413 expected_used_textures_on_commit_(0) {}
1415 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1416 OVERRIDE {
1417 scoped_ptr<TestWebGraphicsContext3D> context(
1418 TestWebGraphicsContext3D::Create());
1419 context_ = context.get();
1420 texture_ = context->createTexture();
1421 return FakeOutputSurface::Create3d(context.Pass()).PassAs<OutputSurface>();
1424 virtual unsigned PrepareTexture() OVERRIDE {
1425 return texture_;
1428 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
1429 return context_;
1432 virtual bool PrepareTextureMailbox(
1433 TextureMailbox* mailbox,
1434 scoped_ptr<SingleReleaseCallback>* release_callback,
1435 bool use_shared_memory) OVERRIDE {
1436 return false;
1439 virtual void SetupTree() OVERRIDE {
1440 scoped_refptr<Layer> root = Layer::Create();
1441 root->SetBounds(gfx::Size(10, 10));
1442 root->SetAnchorPoint(gfx::PointF());
1443 root->SetIsDrawable(true);
1445 texture_layer_ = TextureLayer::Create(this);
1446 texture_layer_->SetBounds(gfx::Size(10, 10));
1447 texture_layer_->SetAnchorPoint(gfx::PointF());
1448 texture_layer_->SetIsDrawable(true);
1449 root->AddChild(texture_layer_);
1451 layer_tree_host()->SetRootLayer(root);
1452 LayerTreeTest::SetupTree();
1454 base::AutoLock lock(lock_);
1455 expected_used_textures_on_commit_ = 1;
1459 virtual void BeginTest() OVERRIDE {
1460 PostSetNeedsCommitToMainThread();
1463 virtual void DidCommitAndDrawFrame() OVERRIDE {
1464 ++commit_count_;
1465 switch (commit_count_) {
1466 case 1:
1467 texture_layer_->ClearClient();
1468 texture_layer_->SetNeedsDisplay();
1470 base::AutoLock lock(lock_);
1471 expected_used_textures_on_commit_ = 0;
1473 texture_ = 0;
1474 break;
1475 case 2:
1476 EndTest();
1477 break;
1478 default:
1479 NOTREACHED();
1480 break;
1484 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1485 base::AutoLock lock(lock_);
1486 expected_used_textures_on_draw_ = expected_used_textures_on_commit_;
1489 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1490 LayerTreeHostImpl::FrameData* frame_data,
1491 bool result) OVERRIDE {
1492 context_->ResetUsedTextures();
1493 return true;
1496 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1497 bool result) OVERRIDE {
1498 ASSERT_TRUE(result);
1499 EXPECT_EQ(expected_used_textures_on_draw_, context_->NumUsedTextures());
1502 virtual void AfterTest() OVERRIDE {}
1504 private:
1505 scoped_refptr<TextureLayer> texture_layer_;
1506 TestWebGraphicsContext3D* context_;
1507 unsigned texture_;
1508 int commit_count_;
1510 // Used only on thread.
1511 unsigned expected_used_textures_on_draw_;
1513 // Used on either thread, protected by lock_.
1514 base::Lock lock_;
1515 unsigned expected_used_textures_on_commit_;
1518 // The TextureLayerClient does not use mailboxes, so can't use a delegating
1519 // renderer.
1520 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerClientTest);
1523 // Checks that changing a texture in the client for a TextureLayer that's
1524 // invisible correctly works without drawing a deleted texture. See
1525 // crbug.com/266628
1526 class TextureLayerChangeInvisibleTest
1527 : public LayerTreeTest,
1528 public TextureLayerClient {
1529 public:
1530 TextureLayerChangeInvisibleTest()
1531 : client_context_(TestWebGraphicsContext3D::Create()),
1532 texture_(client_context_->createTexture()),
1533 texture_to_delete_on_next_commit_(0),
1534 prepare_called_(0),
1535 commit_count_(0),
1536 expected_texture_on_draw_(0) {}
1538 // TextureLayerClient implementation.
1539 virtual unsigned PrepareTexture() OVERRIDE {
1540 ++prepare_called_;
1541 return texture_;
1544 // TextureLayerClient implementation.
1545 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
1546 return client_context_.get();
1549 // TextureLayerClient implementation.
1550 virtual bool PrepareTextureMailbox(
1551 cc::TextureMailbox* mailbox,
1552 scoped_ptr<SingleReleaseCallback>* release_callback,
1553 bool use_shared_memory) OVERRIDE {
1554 return false;
1557 virtual void SetupTree() OVERRIDE {
1558 scoped_refptr<Layer> root = Layer::Create();
1559 root->SetBounds(gfx::Size(10, 10));
1560 root->SetAnchorPoint(gfx::PointF());
1561 root->SetIsDrawable(true);
1563 solid_layer_ = SolidColorLayer::Create();
1564 solid_layer_->SetBounds(gfx::Size(10, 10));
1565 solid_layer_->SetIsDrawable(true);
1566 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1567 root->AddChild(solid_layer_);
1569 parent_layer_ = Layer::Create();
1570 parent_layer_->SetBounds(gfx::Size(10, 10));
1571 parent_layer_->SetIsDrawable(true);
1572 root->AddChild(parent_layer_);
1574 texture_layer_ = TextureLayer::Create(this);
1575 texture_layer_->SetBounds(gfx::Size(10, 10));
1576 texture_layer_->SetAnchorPoint(gfx::PointF());
1577 texture_layer_->SetIsDrawable(true);
1578 parent_layer_->AddChild(texture_layer_);
1580 layer_tree_host()->SetRootLayer(root);
1581 LayerTreeTest::SetupTree();
1584 virtual void BeginTest() OVERRIDE {
1585 PostSetNeedsCommitToMainThread();
1588 virtual void DidCommitAndDrawFrame() OVERRIDE {
1589 ++commit_count_;
1590 switch (commit_count_) {
1591 case 1:
1592 // We should have updated the layer, committing the texture.
1593 EXPECT_EQ(1, prepare_called_);
1594 // Make layer invisible.
1595 parent_layer_->SetOpacity(0.f);
1596 break;
1597 case 2: {
1598 // Layer shouldn't have been updated.
1599 EXPECT_EQ(1, prepare_called_);
1600 // Change the texture.
1601 texture_to_delete_on_next_commit_ = texture_;
1602 texture_ = client_context_->createTexture();
1603 texture_layer_->SetNeedsDisplay();
1604 // Force a change to make sure we draw a frame.
1605 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1606 break;
1608 case 3:
1609 EXPECT_EQ(1, prepare_called_);
1610 client_context_->deleteTexture(texture_to_delete_on_next_commit_);
1611 texture_to_delete_on_next_commit_ = 0;
1612 // Make layer visible again.
1613 parent_layer_->SetOpacity(1.f);
1614 break;
1615 case 4: {
1616 // Layer should have been updated.
1617 EXPECT_EQ(2, prepare_called_);
1618 texture_layer_->ClearClient();
1619 client_context_->deleteTexture(texture_);
1620 texture_ = 0;
1621 break;
1623 case 5:
1624 EndTest();
1625 break;
1626 default:
1627 NOTREACHED();
1628 break;
1632 virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1633 ASSERT_TRUE(proxy()->IsMainThreadBlocked());
1634 // This is the only texture that can be drawn this frame.
1635 expected_texture_on_draw_ = texture_;
1638 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1639 LayerTreeHostImpl::FrameData* frame_data,
1640 bool result) OVERRIDE {
1641 ContextForImplThread(host_impl)->ResetUsedTextures();
1642 return true;
1645 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1646 bool result) OVERRIDE {
1647 ASSERT_TRUE(result);
1648 TestWebGraphicsContext3D* context = ContextForImplThread(host_impl);
1649 int used_textures = context->NumUsedTextures();
1650 switch (host_impl->active_tree()->source_frame_number()) {
1651 case 0:
1652 EXPECT_EQ(1, used_textures);
1653 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1654 break;
1655 case 1:
1656 case 2:
1657 EXPECT_EQ(0, used_textures);
1658 break;
1659 case 3:
1660 EXPECT_EQ(1, used_textures);
1661 EXPECT_TRUE(context->UsedTexture(expected_texture_on_draw_));
1662 break;
1663 default:
1664 break;
1668 virtual void AfterTest() OVERRIDE {}
1670 private:
1671 TestWebGraphicsContext3D* ContextForImplThread(LayerTreeHostImpl* host_impl) {
1672 return static_cast<TestWebGraphicsContext3D*>(
1673 host_impl->output_surface()->context_provider()->Context3d());
1676 scoped_refptr<SolidColorLayer> solid_layer_;
1677 scoped_refptr<Layer> parent_layer_;
1678 scoped_refptr<TextureLayer> texture_layer_;
1679 scoped_ptr<TestWebGraphicsContext3D> client_context_;
1681 // Used on the main thread, and on the impl thread while the main thread is
1682 // blocked.
1683 unsigned texture_;
1685 // Used on the main thread.
1686 unsigned texture_to_delete_on_next_commit_;
1687 int prepare_called_;
1688 int commit_count_;
1690 // Used on the compositor thread.
1691 unsigned expected_texture_on_draw_;
1694 // The TextureLayerChangeInvisibleTest does not use mailboxes, so can't use a
1695 // delegating renderer.
1696 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerChangeInvisibleTest);
1698 // Checks that changing a mailbox in the client for a TextureLayer that's
1699 // invisible correctly works and uses the new mailbox as soon as the layer
1700 // becomes visible (and returns the old one).
1701 class TextureLayerChangeInvisibleMailboxTest
1702 : public LayerTreeTest,
1703 public TextureLayerClient {
1704 public:
1705 TextureLayerChangeInvisibleMailboxTest()
1706 : mailbox_changed_(true),
1707 mailbox_returned_(0),
1708 prepare_called_(0),
1709 commit_count_(0) {
1710 mailbox_ = MakeMailbox('1');
1713 // TextureLayerClient implementation.
1714 virtual unsigned PrepareTexture() OVERRIDE {
1715 NOTREACHED();
1716 return 0;
1719 // TextureLayerClient implementation.
1720 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
1721 NOTREACHED();
1722 return NULL;
1725 // TextureLayerClient implementation.
1726 virtual bool PrepareTextureMailbox(
1727 cc::TextureMailbox* mailbox,
1728 scoped_ptr<SingleReleaseCallback>* release_callback,
1729 bool use_shared_memory) OVERRIDE {
1730 ++prepare_called_;
1731 if (!mailbox_changed_)
1732 return false;
1733 *mailbox = mailbox_;
1734 *release_callback = SingleReleaseCallback::Create(
1735 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased,
1736 base::Unretained(this)));
1737 return true;
1740 TextureMailbox MakeMailbox(char name) {
1741 return TextureMailbox(std::string(64, name));
1744 void MailboxReleased(unsigned sync_point, bool lost_resource) {
1745 ++mailbox_returned_;
1748 virtual void SetupTree() OVERRIDE {
1749 scoped_refptr<Layer> root = Layer::Create();
1750 root->SetBounds(gfx::Size(10, 10));
1751 root->SetAnchorPoint(gfx::PointF());
1752 root->SetIsDrawable(true);
1754 solid_layer_ = SolidColorLayer::Create();
1755 solid_layer_->SetBounds(gfx::Size(10, 10));
1756 solid_layer_->SetIsDrawable(true);
1757 solid_layer_->SetBackgroundColor(SK_ColorWHITE);
1758 root->AddChild(solid_layer_);
1760 parent_layer_ = Layer::Create();
1761 parent_layer_->SetBounds(gfx::Size(10, 10));
1762 parent_layer_->SetIsDrawable(true);
1763 root->AddChild(parent_layer_);
1765 texture_layer_ = TextureLayer::CreateForMailbox(this);
1766 texture_layer_->SetBounds(gfx::Size(10, 10));
1767 texture_layer_->SetAnchorPoint(gfx::PointF());
1768 texture_layer_->SetIsDrawable(true);
1769 parent_layer_->AddChild(texture_layer_);
1771 layer_tree_host()->SetRootLayer(root);
1772 LayerTreeTest::SetupTree();
1775 virtual void BeginTest() OVERRIDE {
1776 PostSetNeedsCommitToMainThread();
1779 virtual void DidCommitAndDrawFrame() OVERRIDE {
1780 ++commit_count_;
1781 switch (commit_count_) {
1782 case 1:
1783 // We should have updated the layer, committing the texture.
1784 EXPECT_EQ(1, prepare_called_);
1785 // Make layer invisible.
1786 parent_layer_->SetOpacity(0.f);
1787 break;
1788 case 2:
1789 // Layer shouldn't have been updated.
1790 EXPECT_EQ(1, prepare_called_);
1791 // Change the texture.
1792 mailbox_ = MakeMailbox('2');
1793 mailbox_changed_ = true;
1794 texture_layer_->SetNeedsDisplay();
1795 // Force a change to make sure we draw a frame.
1796 solid_layer_->SetBackgroundColor(SK_ColorGRAY);
1797 break;
1798 case 3:
1799 // Layer shouldn't have been updated.
1800 EXPECT_EQ(1, prepare_called_);
1801 // So the old mailbox isn't returned yet.
1802 EXPECT_EQ(0, mailbox_returned_);
1803 // Make layer visible again.
1804 parent_layer_->SetOpacity(1.f);
1805 break;
1806 case 4:
1807 // Layer should have been updated.
1808 EXPECT_EQ(2, prepare_called_);
1809 // So the old mailbox should have been returned already.
1810 EXPECT_EQ(1, mailbox_returned_);
1811 texture_layer_->ClearClient();
1812 break;
1813 case 5:
1814 EXPECT_EQ(2, mailbox_returned_);
1815 EndTest();
1816 break;
1817 default:
1818 NOTREACHED();
1819 break;
1823 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1824 bool result) OVERRIDE {
1825 ASSERT_TRUE(result);
1826 DelegatedFrameData* delegated_frame_data =
1827 output_surface()->last_sent_frame().delegated_frame_data.get();
1828 if (!delegated_frame_data)
1829 return;
1831 // Return all resources immediately.
1832 TransferableResourceArray resources_to_return =
1833 output_surface()->resources_held_by_parent();
1835 CompositorFrameAck ack;
1836 for (size_t i = 0; i < resources_to_return.size(); ++i)
1837 output_surface()->ReturnResource(resources_to_return[i].id, &ack);
1838 host_impl->ReclaimResources(&ack);
1839 host_impl->OnSwapBuffersComplete();
1842 virtual void AfterTest() OVERRIDE {}
1844 private:
1845 scoped_refptr<SolidColorLayer> solid_layer_;
1846 scoped_refptr<Layer> parent_layer_;
1847 scoped_refptr<TextureLayer> texture_layer_;
1849 // Used on the main thread.
1850 bool mailbox_changed_;
1851 TextureMailbox mailbox_;
1852 int mailbox_returned_;
1853 int prepare_called_;
1854 int commit_count_;
1857 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest);
1859 // Test recovering from a lost context.
1860 class TextureLayerLostContextTest
1861 : public LayerTreeTest,
1862 public TextureLayerClient {
1863 public:
1864 TextureLayerLostContextTest()
1865 : texture_(0),
1866 draw_count_(0) {}
1868 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
1869 OVERRIDE {
1870 texture_context_ = TestWebGraphicsContext3D::Create();
1871 texture_ = texture_context_->createTexture();
1872 return CreateFakeOutputSurface();
1875 virtual unsigned PrepareTexture() OVERRIDE {
1876 if (draw_count_ == 0) {
1877 texture_context_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
1878 GL_INNOCENT_CONTEXT_RESET_ARB);
1880 return texture_;
1883 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
1884 return texture_context_.get();
1887 virtual bool PrepareTextureMailbox(
1888 TextureMailbox* mailbox,
1889 scoped_ptr<SingleReleaseCallback>* release_callback,
1890 bool use_shared_memory) OVERRIDE {
1891 return false;
1894 virtual void SetupTree() OVERRIDE {
1895 scoped_refptr<Layer> root = Layer::Create();
1896 root->SetBounds(gfx::Size(10, 10));
1897 root->SetIsDrawable(true);
1899 texture_layer_ = TextureLayer::Create(this);
1900 texture_layer_->SetBounds(gfx::Size(10, 10));
1901 texture_layer_->SetIsDrawable(true);
1902 root->AddChild(texture_layer_);
1904 layer_tree_host()->SetRootLayer(root);
1905 LayerTreeTest::SetupTree();
1908 virtual void BeginTest() OVERRIDE {
1909 PostSetNeedsCommitToMainThread();
1912 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1913 LayerTreeHostImpl::FrameData* frame_data,
1914 bool result) OVERRIDE {
1915 LayerImpl* root = host_impl->RootLayer();
1916 TextureLayerImpl* texture_layer =
1917 static_cast<TextureLayerImpl*>(root->children()[0]);
1918 if (++draw_count_ == 1)
1919 EXPECT_EQ(0u, texture_layer->texture_id());
1920 else
1921 EXPECT_EQ(texture_, texture_layer->texture_id());
1922 return true;
1925 virtual void DidCommitAndDrawFrame() OVERRIDE {
1926 EndTest();
1929 virtual void AfterTest() OVERRIDE {}
1931 private:
1932 scoped_refptr<TextureLayer> texture_layer_;
1933 scoped_ptr<TestWebGraphicsContext3D> texture_context_;
1934 unsigned texture_;
1935 int draw_count_;
1938 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(TextureLayerLostContextTest);
1940 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest {
1941 public:
1942 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
1943 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1944 EXPECT_FALSE(lost_resource);
1945 ++callback_count_;
1946 EndTest();
1949 void SetMailbox(char mailbox_char) {
1950 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1951 TextureMailbox mailbox(std::string(64, mailbox_char));
1952 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
1953 base::Bind(
1954 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback,
1955 base::Unretained(this)));
1956 layer_->SetTextureMailbox(mailbox, callback.Pass());
1959 virtual void SetupTree() OVERRIDE {
1960 gfx::Size bounds(100, 100);
1961 root_ = Layer::Create();
1962 root_->SetAnchorPoint(gfx::PointF());
1963 root_->SetBounds(bounds);
1965 layer_ = TextureLayer::CreateForMailbox(NULL);
1966 layer_->SetIsDrawable(true);
1967 layer_->SetAnchorPoint(gfx::PointF());
1968 layer_->SetBounds(bounds);
1970 root_->AddChild(layer_);
1971 layer_tree_host()->SetRootLayer(root_);
1972 layer_tree_host()->SetViewportSize(bounds);
1975 virtual void BeginTest() OVERRIDE {
1976 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
1978 callback_count_ = 0;
1980 // Set the mailbox on the main thread.
1981 SetMailbox('1');
1982 EXPECT_EQ(0, callback_count_);
1984 PostSetNeedsCommitToMainThread();
1987 virtual void DidCommitAndDrawFrame() OVERRIDE {
1988 switch (layer_tree_host()->source_frame_number()) {
1989 case 1:
1990 // Delete the TextureLayer on the main thread while the mailbox is in
1991 // the impl tree.
1992 layer_->RemoveFromParent();
1993 layer_ = NULL;
1994 break;
1998 virtual void AfterTest() OVERRIDE {
1999 EXPECT_EQ(1, callback_count_);
2002 private:
2003 base::ThreadChecker main_thread_;
2004 int callback_count_;
2005 scoped_refptr<Layer> root_;
2006 scoped_refptr<TextureLayer> layer_;
2009 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2010 TextureLayerWithMailboxMainThreadDeleted);
2012 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest {
2013 public:
2014 void ReleaseCallback(unsigned sync_point, bool lost_resource) {
2015 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2016 EXPECT_FALSE(lost_resource);
2017 ++callback_count_;
2018 EndTest();
2021 void SetMailbox(char mailbox_char) {
2022 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2023 TextureMailbox mailbox(std::string(64, mailbox_char));
2024 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2025 base::Bind(
2026 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback,
2027 base::Unretained(this)));
2028 layer_->SetTextureMailbox(mailbox, callback.Pass());
2031 virtual void SetupTree() OVERRIDE {
2032 gfx::Size bounds(100, 100);
2033 root_ = Layer::Create();
2034 root_->SetAnchorPoint(gfx::PointF());
2035 root_->SetBounds(bounds);
2037 layer_ = TextureLayer::CreateForMailbox(NULL);
2038 layer_->SetIsDrawable(true);
2039 layer_->SetAnchorPoint(gfx::PointF());
2040 layer_->SetBounds(bounds);
2042 root_->AddChild(layer_);
2043 layer_tree_host()->SetRootLayer(root_);
2044 layer_tree_host()->SetViewportSize(bounds);
2047 virtual void BeginTest() OVERRIDE {
2048 EXPECT_EQ(true, main_thread_.CalledOnValidThread());
2050 callback_count_ = 0;
2052 // Set the mailbox on the main thread.
2053 SetMailbox('1');
2054 EXPECT_EQ(0, callback_count_);
2056 PostSetNeedsCommitToMainThread();
2059 virtual void DidCommitAndDrawFrame() OVERRIDE {
2060 switch (layer_tree_host()->source_frame_number()) {
2061 case 1:
2062 // Remove the TextureLayer on the main thread while the mailbox is in
2063 // the impl tree, but don't delete the TextureLayer until after the impl
2064 // tree side is deleted.
2065 layer_->RemoveFromParent();
2066 break;
2067 case 2:
2068 layer_ = NULL;
2069 break;
2073 virtual void AfterTest() OVERRIDE {
2074 EXPECT_EQ(1, callback_count_);
2077 private:
2078 base::ThreadChecker main_thread_;
2079 int callback_count_;
2080 scoped_refptr<Layer> root_;
2081 scoped_refptr<TextureLayer> layer_;
2084 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2085 TextureLayerWithMailboxImplThreadDeleted);
2087 } // namespace
2088 } // namespace cc