OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "cc/layers/texture_layer.h" | |
6 | |
7 #include <algorithm> | |
8 #include <string> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/callback.h" | |
12 #include "base/synchronization/waitable_event.h" | |
13 #include "base/threading/thread.h" | |
14 #include "base/time/time.h" | |
15 #include "cc/layers/solid_color_layer.h" | |
16 #include "cc/layers/texture_layer_client.h" | |
17 #include "cc/layers/texture_layer_impl.h" | |
18 #include "cc/output/compositor_frame_ack.h" | |
19 #include "cc/output/context_provider.h" | |
20 #include "cc/resources/returned_resource.h" | |
21 #include "cc/test/fake_impl_proxy.h" | |
22 #include "cc/test/fake_layer_tree_host_client.h" | |
23 #include "cc/test/fake_layer_tree_host_impl.h" | |
24 #include "cc/test/fake_output_surface.h" | |
25 #include "cc/test/layer_test_common.h" | |
26 #include "cc/test/layer_tree_test.h" | |
27 #include "cc/test/test_task_graph_runner.h" | |
28 #include "cc/test/test_web_graphics_context_3d.h" | |
29 #include "cc/trees/blocking_task_runner.h" | |
30 #include "cc/trees/layer_tree_host.h" | |
31 #include "cc/trees/layer_tree_impl.h" | |
32 #include "cc/trees/single_thread_proxy.h" | |
33 #include "gpu/GLES2/gl2extchromium.h" | |
34 #include "testing/gmock/include/gmock/gmock.h" | |
35 #include "testing/gtest/include/gtest/gtest.h" | |
36 | |
37 using ::testing::Mock; | |
38 using ::testing::_; | |
39 using ::testing::AtLeast; | |
40 using ::testing::AnyNumber; | |
41 using ::testing::InvokeWithoutArgs; | |
42 | |
43 namespace cc { | |
44 namespace { | |
45 | |
46 gpu::Mailbox MailboxFromChar(char value) { | |
47 gpu::Mailbox mailbox; | |
48 memset(mailbox.name, value, sizeof(mailbox.name)); | |
49 return mailbox; | |
50 } | |
51 | |
52 class MockLayerTreeHost : public LayerTreeHost { | |
53 public: | |
54 explicit MockLayerTreeHost(FakeLayerTreeHostClient* client) | |
55 : LayerTreeHost(client, nullptr, nullptr, nullptr, LayerTreeSettings()) { | |
56 InitializeSingleThreaded(client, | |
57 base::MessageLoopProxy::current(), | |
58 nullptr); | |
59 } | |
60 | |
61 MOCK_METHOD0(SetNeedsCommit, void()); | |
62 MOCK_METHOD0(SetNeedsUpdateLayers, void()); | |
63 MOCK_METHOD0(StartRateLimiter, void()); | |
64 MOCK_METHOD0(StopRateLimiter, void()); | |
65 }; | |
66 | |
67 class FakeTextureLayerClient : public TextureLayerClient { | |
68 public: | |
69 FakeTextureLayerClient() : mailbox_changed_(true) {} | |
70 | |
71 bool PrepareTextureMailbox( | |
72 TextureMailbox* mailbox, | |
73 scoped_ptr<SingleReleaseCallback>* release_callback, | |
74 bool use_shared_memory) override { | |
75 if (!mailbox_changed_) | |
76 return false; | |
77 | |
78 *mailbox = mailbox_; | |
79 *release_callback = release_callback_.Pass(); | |
80 mailbox_changed_ = false; | |
81 return true; | |
82 } | |
83 | |
84 void set_mailbox(const TextureMailbox& mailbox, | |
85 scoped_ptr<SingleReleaseCallback> release_callback) { | |
86 mailbox_ = mailbox; | |
87 release_callback_ = release_callback.Pass(); | |
88 mailbox_changed_ = true; | |
89 } | |
90 | |
91 private: | |
92 TextureMailbox mailbox_; | |
93 scoped_ptr<SingleReleaseCallback> release_callback_; | |
94 bool mailbox_changed_; | |
95 DISALLOW_COPY_AND_ASSIGN(FakeTextureLayerClient); | |
96 }; | |
97 | |
98 class MockMailboxCallback { | |
99 public: | |
100 MOCK_METHOD3(Release, | |
101 void(const gpu::Mailbox& mailbox, | |
102 uint32 sync_point, | |
103 bool lost_resource)); | |
104 MOCK_METHOD3(Release2, | |
105 void(SharedBitmap* shared_bitmap, | |
106 uint32 sync_point, | |
107 bool lost_resource)); | |
108 MOCK_METHOD4(ReleaseImpl, | |
109 void(const gpu::Mailbox& mailbox, | |
110 uint32 sync_point, | |
111 bool lost_resource, | |
112 BlockingTaskRunner* main_thread_task_runner)); | |
113 MOCK_METHOD4(ReleaseImpl2, | |
114 void(SharedBitmap* shared_bitmap, | |
115 uint32 sync_point, | |
116 bool lost_resource, | |
117 BlockingTaskRunner* main_thread_task_runner)); | |
118 }; | |
119 | |
120 struct CommonMailboxObjects { | |
121 explicit CommonMailboxObjects(SharedBitmapManager* manager) | |
122 : mailbox_name1_(MailboxFromChar('1')), | |
123 mailbox_name2_(MailboxFromChar('2')), | |
124 sync_point1_(1), | |
125 sync_point2_(2) { | |
126 release_mailbox1_ = base::Bind(&MockMailboxCallback::Release, | |
127 base::Unretained(&mock_callback_), | |
128 mailbox_name1_); | |
129 release_mailbox2_ = base::Bind(&MockMailboxCallback::Release, | |
130 base::Unretained(&mock_callback_), | |
131 mailbox_name2_); | |
132 release_mailbox1_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl, | |
133 base::Unretained(&mock_callback_), | |
134 mailbox_name1_); | |
135 release_mailbox2_impl_ = base::Bind(&MockMailboxCallback::ReleaseImpl, | |
136 base::Unretained(&mock_callback_), | |
137 mailbox_name2_); | |
138 const uint32 arbitrary_target1 = GL_TEXTURE_2D; | |
139 const uint32 arbitrary_target2 = GL_TEXTURE_EXTERNAL_OES; | |
140 mailbox1_ = TextureMailbox(mailbox_name1_, arbitrary_target1, sync_point1_); | |
141 mailbox2_ = TextureMailbox(mailbox_name2_, arbitrary_target2, sync_point2_); | |
142 gfx::Size size(128, 128); | |
143 shared_bitmap_ = manager->AllocateSharedBitmap(size); | |
144 DCHECK(shared_bitmap_); | |
145 release_mailbox3_ = | |
146 base::Bind(&MockMailboxCallback::Release2, | |
147 base::Unretained(&mock_callback_), shared_bitmap_.get()); | |
148 release_mailbox3_impl_ = | |
149 base::Bind(&MockMailboxCallback::ReleaseImpl2, | |
150 base::Unretained(&mock_callback_), shared_bitmap_.get()); | |
151 mailbox3_ = TextureMailbox(shared_bitmap_.get(), size); | |
152 } | |
153 | |
154 gpu::Mailbox mailbox_name1_; | |
155 gpu::Mailbox mailbox_name2_; | |
156 MockMailboxCallback mock_callback_; | |
157 ReleaseCallback release_mailbox1_; | |
158 ReleaseCallback release_mailbox2_; | |
159 ReleaseCallback release_mailbox3_; | |
160 ReleaseCallbackImpl release_mailbox1_impl_; | |
161 ReleaseCallbackImpl release_mailbox2_impl_; | |
162 ReleaseCallbackImpl release_mailbox3_impl_; | |
163 TextureMailbox mailbox1_; | |
164 TextureMailbox mailbox2_; | |
165 TextureMailbox mailbox3_; | |
166 uint32 sync_point1_; | |
167 uint32 sync_point2_; | |
168 scoped_ptr<SharedBitmap> shared_bitmap_; | |
169 }; | |
170 | |
171 class TextureLayerTest : public testing::Test { | |
172 public: | |
173 TextureLayerTest() | |
174 : fake_client_( | |
175 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)), | |
176 host_impl_(&proxy_, &shared_bitmap_manager_, &task_graph_runner_), | |
177 test_data_(&shared_bitmap_manager_) {} | |
178 | |
179 protected: | |
180 void SetUp() override { | |
181 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_)); | |
182 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
183 layer_tree_host_->SetViewportSize(gfx::Size(10, 10)); | |
184 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
185 } | |
186 | |
187 void TearDown() override { | |
188 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
189 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
190 | |
191 layer_tree_host_->SetRootLayer(nullptr); | |
192 layer_tree_host_ = nullptr; | |
193 } | |
194 | |
195 scoped_ptr<MockLayerTreeHost> layer_tree_host_; | |
196 FakeImplProxy proxy_; | |
197 FakeLayerTreeHostClient fake_client_; | |
198 TestSharedBitmapManager shared_bitmap_manager_; | |
199 TestTaskGraphRunner task_graph_runner_; | |
200 FakeLayerTreeHostImpl host_impl_; | |
201 CommonMailboxObjects test_data_; | |
202 }; | |
203 | |
204 TEST_F(TextureLayerTest, CheckPropertyChangeCausesCorrectBehavior) { | |
205 scoped_refptr<TextureLayer> test_layer = | |
206 TextureLayer::CreateForMailbox(nullptr); | |
207 EXPECT_SET_NEEDS_COMMIT(1, layer_tree_host_->SetRootLayer(test_layer)); | |
208 | |
209 // Test properties that should call SetNeedsCommit. All properties need to | |
210 // be set to new values in order for SetNeedsCommit to be called. | |
211 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetFlipped(false)); | |
212 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetNearestNeighbor(true)); | |
213 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetUV( | |
214 gfx::PointF(0.25f, 0.25f), gfx::PointF(0.75f, 0.75f))); | |
215 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetVertexOpacity( | |
216 0.5f, 0.5f, 0.5f, 0.5f)); | |
217 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetPremultipliedAlpha(false)); | |
218 EXPECT_SET_NEEDS_COMMIT(1, test_layer->SetBlendBackgroundColor(true)); | |
219 } | |
220 | |
221 TEST_F(TextureLayerTest, VisibleContentOpaqueRegion) { | |
222 const gfx::Size layer_bounds(100, 100); | |
223 const gfx::Rect layer_rect(layer_bounds); | |
224 const Region layer_region(layer_rect); | |
225 | |
226 scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(nullptr); | |
227 layer->SetBounds(layer_bounds); | |
228 layer->draw_properties().visible_content_rect = layer_rect; | |
229 layer->SetBlendBackgroundColor(true); | |
230 | |
231 // Verify initial conditions. | |
232 EXPECT_FALSE(layer->contents_opaque()); | |
233 EXPECT_EQ(0u, layer->background_color()); | |
234 EXPECT_EQ(Region().ToString(), | |
235 layer->VisibleContentOpaqueRegion().ToString()); | |
236 | |
237 // Opaque background. | |
238 layer->SetBackgroundColor(SK_ColorWHITE); | |
239 EXPECT_EQ(layer_region.ToString(), | |
240 layer->VisibleContentOpaqueRegion().ToString()); | |
241 | |
242 // Transparent background. | |
243 layer->SetBackgroundColor(SkColorSetARGB(100, 255, 255, 255)); | |
244 EXPECT_EQ(Region().ToString(), | |
245 layer->VisibleContentOpaqueRegion().ToString()); | |
246 } | |
247 | |
248 TEST_F(TextureLayerTest, RateLimiter) { | |
249 FakeTextureLayerClient client; | |
250 scoped_refptr<TextureLayer> test_layer = TextureLayer::CreateForMailbox( | |
251 &client); | |
252 test_layer->SetIsDrawable(true); | |
253 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
254 layer_tree_host_->SetRootLayer(test_layer); | |
255 | |
256 // Don't rate limit until we invalidate. | |
257 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0); | |
258 test_layer->SetRateLimitContext(true); | |
259 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
260 | |
261 // Do rate limit after we invalidate. | |
262 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()); | |
263 test_layer->SetNeedsDisplay(); | |
264 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
265 | |
266 // Stop rate limiter when we don't want it any more. | |
267 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); | |
268 test_layer->SetRateLimitContext(false); | |
269 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
270 | |
271 // Or we clear the client. | |
272 test_layer->SetRateLimitContext(true); | |
273 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); | |
274 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
275 test_layer->ClearClient(); | |
276 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
277 | |
278 // Reset to a layer with a client, that started the rate limiter. | |
279 test_layer = TextureLayer::CreateForMailbox( | |
280 &client); | |
281 test_layer->SetIsDrawable(true); | |
282 test_layer->SetRateLimitContext(true); | |
283 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
284 layer_tree_host_->SetRootLayer(test_layer); | |
285 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()).Times(0); | |
286 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
287 EXPECT_CALL(*layer_tree_host_, StartRateLimiter()); | |
288 test_layer->SetNeedsDisplay(); | |
289 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
290 | |
291 // Stop rate limiter when we're removed from the tree. | |
292 EXPECT_CALL(*layer_tree_host_, StopRateLimiter()); | |
293 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); | |
294 layer_tree_host_->SetRootLayer(nullptr); | |
295 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
296 } | |
297 | |
298 class TestMailboxHolder : public TextureLayer::TextureMailboxHolder { | |
299 public: | |
300 using TextureLayer::TextureMailboxHolder::Create; | |
301 | |
302 protected: | |
303 ~TestMailboxHolder() override {} | |
304 }; | |
305 | |
306 class TextureLayerWithMailboxTest : public TextureLayerTest { | |
307 protected: | |
308 void TearDown() override { | |
309 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
310 EXPECT_CALL(test_data_.mock_callback_, | |
311 Release(test_data_.mailbox_name1_, | |
312 test_data_.sync_point1_, | |
313 false)).Times(1); | |
314 TextureLayerTest::TearDown(); | |
315 } | |
316 }; | |
317 | |
318 TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) { | |
319 scoped_refptr<TextureLayer> test_layer = | |
320 TextureLayer::CreateForMailbox(nullptr); | |
321 ASSERT_TRUE(test_layer.get()); | |
322 | |
323 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
324 layer_tree_host_->SetRootLayer(test_layer); | |
325 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
326 | |
327 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
328 test_layer->SetTextureMailbox( | |
329 test_data_.mailbox1_, | |
330 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); | |
331 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
332 | |
333 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
334 EXPECT_CALL(test_data_.mock_callback_, | |
335 Release(test_data_.mailbox_name1_, | |
336 test_data_.sync_point1_, | |
337 false)) | |
338 .Times(1); | |
339 test_layer->SetTextureMailbox( | |
340 test_data_.mailbox2_, | |
341 SingleReleaseCallback::Create(test_data_.release_mailbox2_)); | |
342 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
343 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
344 | |
345 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
346 EXPECT_CALL(test_data_.mock_callback_, | |
347 Release(test_data_.mailbox_name2_, | |
348 test_data_.sync_point2_, | |
349 false)) | |
350 .Times(1); | |
351 test_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
352 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
353 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
354 | |
355 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
356 test_layer->SetTextureMailbox( | |
357 test_data_.mailbox3_, | |
358 SingleReleaseCallback::Create(test_data_.release_mailbox3_)); | |
359 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
360 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
361 | |
362 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
363 EXPECT_CALL(test_data_.mock_callback_, | |
364 Release2(test_data_.shared_bitmap_.get(), 0, false)).Times(1); | |
365 test_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
366 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
367 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
368 | |
369 // Test destructor. | |
370 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
371 test_layer->SetTextureMailbox( | |
372 test_data_.mailbox1_, | |
373 SingleReleaseCallback::Create(test_data_.release_mailbox1_)); | |
374 } | |
375 | |
376 TEST_F(TextureLayerTest, SetTextureMailboxWithoutReleaseCallback) { | |
377 scoped_refptr<TextureLayer> test_layer = | |
378 TextureLayer::CreateForMailbox(nullptr); | |
379 ASSERT_TRUE(test_layer.get()); | |
380 | |
381 // These use the same gpu::Mailbox, but different sync points. | |
382 TextureMailbox mailbox1(MailboxFromChar('a'), GL_TEXTURE_2D, 1); | |
383 TextureMailbox mailbox2(MailboxFromChar('a'), GL_TEXTURE_2D, 2); | |
384 | |
385 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AnyNumber()); | |
386 layer_tree_host_->SetRootLayer(test_layer); | |
387 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
388 | |
389 // Set the mailbox the first time. It should cause a commit. | |
390 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
391 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox1); | |
392 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
393 | |
394 // Set the mailbox again with a new sync point, as the backing texture has | |
395 // been updated. It should cause a new commit. | |
396 EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1)); | |
397 test_layer->SetTextureMailboxWithoutReleaseCallback(mailbox2); | |
398 Mock::VerifyAndClearExpectations(layer_tree_host_.get()); | |
399 } | |
400 | |
401 class TextureLayerMailboxHolderTest : public TextureLayerTest { | |
402 public: | |
403 TextureLayerMailboxHolderTest() | |
404 : main_thread_("MAIN") { | |
405 main_thread_.Start(); | |
406 main_thread_.message_loop()->PostTask( | |
407 FROM_HERE, | |
408 base::Bind(&TextureLayerMailboxHolderTest::InitializeOnMain, | |
409 base::Unretained(this))); | |
410 Wait(main_thread_); | |
411 } | |
412 | |
413 void Wait(const base::Thread& thread) { | |
414 bool manual_reset = false; | |
415 bool initially_signaled = false; | |
416 base::WaitableEvent event(manual_reset, initially_signaled); | |
417 thread.message_loop()->PostTask( | |
418 FROM_HERE, | |
419 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); | |
420 event.Wait(); | |
421 } | |
422 | |
423 void CreateMainRef() { | |
424 main_ref_ = TestMailboxHolder::Create( | |
425 test_data_.mailbox1_, | |
426 SingleReleaseCallback::Create(test_data_.release_mailbox1_)).Pass(); | |
427 } | |
428 | |
429 void ReleaseMainRef() { main_ref_ = nullptr; } | |
430 | |
431 void CreateImplRef(scoped_ptr<SingleReleaseCallbackImpl>* impl_ref) { | |
432 *impl_ref = main_ref_->holder()->GetCallbackForImplThread(); | |
433 } | |
434 | |
435 void CapturePostTasksAndWait(base::WaitableEvent* begin_capture, | |
436 base::WaitableEvent* wait_for_capture, | |
437 base::WaitableEvent* stop_capture) { | |
438 begin_capture->Wait(); | |
439 BlockingTaskRunner::CapturePostTasks capture( | |
440 main_thread_task_runner_.get()); | |
441 wait_for_capture->Signal(); | |
442 stop_capture->Wait(); | |
443 } | |
444 | |
445 protected: | |
446 void InitializeOnMain() { | |
447 main_thread_task_runner_ = | |
448 BlockingTaskRunner::Create(main_thread_.message_loop_proxy()); | |
449 } | |
450 | |
451 scoped_ptr<TestMailboxHolder::MainThreadReference> | |
452 main_ref_; | |
453 base::Thread main_thread_; | |
454 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_; | |
455 }; | |
456 | |
457 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_BothReleaseThenMain) { | |
458 scoped_refptr<TextureLayer> test_layer = | |
459 TextureLayer::CreateForMailbox(nullptr); | |
460 ASSERT_TRUE(test_layer.get()); | |
461 | |
462 main_thread_.message_loop()->PostTask( | |
463 FROM_HERE, | |
464 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, | |
465 base::Unretained(this))); | |
466 | |
467 Wait(main_thread_); | |
468 | |
469 // The texture layer is attached to compositor1, and passes a reference to its | |
470 // impl tree. | |
471 scoped_ptr<SingleReleaseCallbackImpl> compositor1; | |
472 main_thread_.message_loop()->PostTask( | |
473 FROM_HERE, | |
474 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
475 base::Unretained(this), | |
476 &compositor1)); | |
477 | |
478 // Then the texture layer is removed and attached to compositor2, and passes a | |
479 // reference to its impl tree. | |
480 scoped_ptr<SingleReleaseCallbackImpl> compositor2; | |
481 main_thread_.message_loop()->PostTask( | |
482 FROM_HERE, | |
483 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
484 base::Unretained(this), | |
485 &compositor2)); | |
486 | |
487 Wait(main_thread_); | |
488 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
489 | |
490 // The compositors both destroy their impl trees before the main thread layer | |
491 // is destroyed. | |
492 compositor1->Run(100, false, main_thread_task_runner_.get()); | |
493 compositor2->Run(200, false, main_thread_task_runner_.get()); | |
494 | |
495 Wait(main_thread_); | |
496 | |
497 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); | |
498 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
499 | |
500 // The main thread ref is the last one, so the mailbox is released back to the | |
501 // embedder, with the last sync point provided by the impl trees. | |
502 EXPECT_CALL(test_data_.mock_callback_, | |
503 Release(test_data_.mailbox_name1_, 200, false)).Times(1); | |
504 | |
505 main_thread_.message_loop()->PostTask( | |
506 FROM_HERE, | |
507 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, | |
508 base::Unretained(this))); | |
509 Wait(main_thread_); | |
510 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
511 } | |
512 | |
513 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleaseBetween) { | |
514 scoped_refptr<TextureLayer> test_layer = | |
515 TextureLayer::CreateForMailbox(nullptr); | |
516 ASSERT_TRUE(test_layer.get()); | |
517 | |
518 main_thread_.message_loop()->PostTask( | |
519 FROM_HERE, | |
520 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, | |
521 base::Unretained(this))); | |
522 | |
523 Wait(main_thread_); | |
524 | |
525 // The texture layer is attached to compositor1, and passes a reference to its | |
526 // impl tree. | |
527 scoped_ptr<SingleReleaseCallbackImpl> compositor1; | |
528 main_thread_.message_loop()->PostTask( | |
529 FROM_HERE, | |
530 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
531 base::Unretained(this), | |
532 &compositor1)); | |
533 | |
534 // Then the texture layer is removed and attached to compositor2, and passes a | |
535 // reference to its impl tree. | |
536 scoped_ptr<SingleReleaseCallbackImpl> compositor2; | |
537 main_thread_.message_loop()->PostTask( | |
538 FROM_HERE, | |
539 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
540 base::Unretained(this), | |
541 &compositor2)); | |
542 | |
543 Wait(main_thread_); | |
544 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
545 | |
546 // One compositor destroys their impl tree. | |
547 compositor1->Run(100, false, main_thread_task_runner_.get()); | |
548 | |
549 // Then the main thread reference is destroyed. | |
550 main_thread_.message_loop()->PostTask( | |
551 FROM_HERE, | |
552 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, | |
553 base::Unretained(this))); | |
554 | |
555 Wait(main_thread_); | |
556 | |
557 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); | |
558 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
559 | |
560 // The second impl reference is destroyed last, causing the mailbox to be | |
561 // released back to the embedder with the last sync point from the impl tree. | |
562 EXPECT_CALL(test_data_.mock_callback_, | |
563 Release(test_data_.mailbox_name1_, 200, true)).Times(1); | |
564 | |
565 compositor2->Run(200, true, main_thread_task_runner_.get()); | |
566 Wait(main_thread_); | |
567 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
568 } | |
569 | |
570 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_MainReleasedFirst) { | |
571 scoped_refptr<TextureLayer> test_layer = | |
572 TextureLayer::CreateForMailbox(nullptr); | |
573 ASSERT_TRUE(test_layer.get()); | |
574 | |
575 main_thread_.message_loop()->PostTask( | |
576 FROM_HERE, | |
577 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, | |
578 base::Unretained(this))); | |
579 | |
580 Wait(main_thread_); | |
581 | |
582 // The texture layer is attached to compositor1, and passes a reference to its | |
583 // impl tree. | |
584 scoped_ptr<SingleReleaseCallbackImpl> compositor1; | |
585 main_thread_.message_loop()->PostTask( | |
586 FROM_HERE, | |
587 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
588 base::Unretained(this), | |
589 &compositor1)); | |
590 | |
591 // Then the texture layer is removed and attached to compositor2, and passes a | |
592 // reference to its impl tree. | |
593 scoped_ptr<SingleReleaseCallbackImpl> compositor2; | |
594 main_thread_.message_loop()->PostTask( | |
595 FROM_HERE, | |
596 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
597 base::Unretained(this), | |
598 &compositor2)); | |
599 | |
600 Wait(main_thread_); | |
601 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
602 | |
603 // The main thread reference is destroyed first. | |
604 main_thread_.message_loop()->PostTask( | |
605 FROM_HERE, | |
606 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, | |
607 base::Unretained(this))); | |
608 | |
609 // One compositor destroys their impl tree. | |
610 compositor2->Run(200, false, main_thread_task_runner_.get()); | |
611 | |
612 Wait(main_thread_); | |
613 | |
614 EXPECT_CALL(test_data_.mock_callback_, Release(_, _, _)).Times(0); | |
615 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
616 | |
617 // The second impl reference is destroyed last, causing the mailbox to be | |
618 // released back to the embedder with the last sync point from the impl tree. | |
619 EXPECT_CALL(test_data_.mock_callback_, | |
620 Release(test_data_.mailbox_name1_, 100, true)).Times(1); | |
621 | |
622 compositor1->Run(100, true, main_thread_task_runner_.get()); | |
623 Wait(main_thread_); | |
624 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
625 } | |
626 | |
627 TEST_F(TextureLayerMailboxHolderTest, TwoCompositors_SecondImplRefShortcut) { | |
628 scoped_refptr<TextureLayer> test_layer = | |
629 TextureLayer::CreateForMailbox(nullptr); | |
630 ASSERT_TRUE(test_layer.get()); | |
631 | |
632 main_thread_.message_loop()->PostTask( | |
633 FROM_HERE, | |
634 base::Bind(&TextureLayerMailboxHolderTest::CreateMainRef, | |
635 base::Unretained(this))); | |
636 | |
637 Wait(main_thread_); | |
638 | |
639 // The texture layer is attached to compositor1, and passes a reference to its | |
640 // impl tree. | |
641 scoped_ptr<SingleReleaseCallbackImpl> compositor1; | |
642 main_thread_.message_loop()->PostTask( | |
643 FROM_HERE, | |
644 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
645 base::Unretained(this), | |
646 &compositor1)); | |
647 | |
648 // Then the texture layer is removed and attached to compositor2, and passes a | |
649 // reference to its impl tree. | |
650 scoped_ptr<SingleReleaseCallbackImpl> compositor2; | |
651 main_thread_.message_loop()->PostTask( | |
652 FROM_HERE, | |
653 base::Bind(&TextureLayerMailboxHolderTest::CreateImplRef, | |
654 base::Unretained(this), | |
655 &compositor2)); | |
656 | |
657 Wait(main_thread_); | |
658 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
659 | |
660 // The main thread reference is destroyed first. | |
661 main_thread_.message_loop()->PostTask( | |
662 FROM_HERE, | |
663 base::Bind(&TextureLayerMailboxHolderTest::ReleaseMainRef, | |
664 base::Unretained(this))); | |
665 | |
666 EXPECT_CALL(test_data_.mock_callback_, | |
667 Release(test_data_.mailbox_name1_, 200, true)).Times(1); | |
668 | |
669 bool manual_reset = false; | |
670 bool initially_signaled = false; | |
671 base::WaitableEvent begin_capture(manual_reset, initially_signaled); | |
672 base::WaitableEvent wait_for_capture(manual_reset, initially_signaled); | |
673 base::WaitableEvent stop_capture(manual_reset, initially_signaled); | |
674 | |
675 // Post a task to start capturing tasks on the main thread. This will block | |
676 // the main thread until we signal the |stop_capture| event. | |
677 main_thread_.message_loop()->PostTask( | |
678 FROM_HERE, | |
679 base::Bind(&TextureLayerMailboxHolderTest::CapturePostTasksAndWait, | |
680 base::Unretained(this), | |
681 &begin_capture, | |
682 &wait_for_capture, | |
683 &stop_capture)); | |
684 | |
685 // Before the main thread capturing starts, one compositor destroys their | |
686 // impl reference. Since capturing did not start, this gets post-tasked to | |
687 // the main thread. | |
688 compositor1->Run(100, false, main_thread_task_runner_.get()); | |
689 | |
690 // Start capturing on the main thread. | |
691 begin_capture.Signal(); | |
692 wait_for_capture.Wait(); | |
693 | |
694 // Meanwhile, the second compositor released its impl reference, but this task | |
695 // gets shortcutted directly to the main thread. This means the reference is | |
696 // released before compositor1, whose reference will be released later when | |
697 // the post-task is serviced. But since it was destroyed _on the impl thread_ | |
698 // last, its sync point values should be used. | |
699 compositor2->Run(200, true, main_thread_task_runner_.get()); | |
700 | |
701 stop_capture.Signal(); | |
702 Wait(main_thread_); | |
703 | |
704 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
705 } | |
706 | |
707 class TextureLayerImplWithMailboxThreadedCallback : public LayerTreeTest { | |
708 public: | |
709 TextureLayerImplWithMailboxThreadedCallback() | |
710 : callback_count_(0), | |
711 commit_count_(0) {} | |
712 | |
713 // Make sure callback is received on main and doesn't block the impl thread. | |
714 void ReleaseCallback(uint32 sync_point, bool lost_resource) { | |
715 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
716 EXPECT_FALSE(lost_resource); | |
717 ++callback_count_; | |
718 } | |
719 | |
720 void SetMailbox(char mailbox_char) { | |
721 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
722 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( | |
723 base::Bind( | |
724 &TextureLayerImplWithMailboxThreadedCallback::ReleaseCallback, | |
725 base::Unretained(this))); | |
726 layer_->SetTextureMailbox( | |
727 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), | |
728 callback.Pass()); | |
729 } | |
730 | |
731 void BeginTest() override { | |
732 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
733 | |
734 gfx::Size bounds(100, 100); | |
735 root_ = Layer::Create(); | |
736 root_->SetBounds(bounds); | |
737 | |
738 layer_ = TextureLayer::CreateForMailbox(nullptr); | |
739 layer_->SetIsDrawable(true); | |
740 layer_->SetBounds(bounds); | |
741 | |
742 root_->AddChild(layer_); | |
743 layer_tree_host()->SetRootLayer(root_); | |
744 layer_tree_host()->SetViewportSize(bounds); | |
745 SetMailbox('1'); | |
746 EXPECT_EQ(0, callback_count_); | |
747 | |
748 // Case #1: change mailbox before the commit. The old mailbox should be | |
749 // released immediately. | |
750 SetMailbox('2'); | |
751 EXPECT_EQ(1, callback_count_); | |
752 PostSetNeedsCommitToMainThread(); | |
753 } | |
754 | |
755 void DidCommit() override { | |
756 ++commit_count_; | |
757 switch (commit_count_) { | |
758 case 1: | |
759 // Case #2: change mailbox after the commit (and draw), where the | |
760 // layer draws. The old mailbox should be released during the next | |
761 // commit. | |
762 SetMailbox('3'); | |
763 EXPECT_EQ(1, callback_count_); | |
764 break; | |
765 case 2: | |
766 EXPECT_EQ(2, callback_count_); | |
767 // Case #3: change mailbox when the layer doesn't draw. The old | |
768 // mailbox should be released during the next commit. | |
769 layer_->SetBounds(gfx::Size()); | |
770 SetMailbox('4'); | |
771 break; | |
772 case 3: | |
773 EXPECT_EQ(3, callback_count_); | |
774 // Case #4: release mailbox that was committed but never drawn. The | |
775 // old mailbox should be released during the next commit. | |
776 layer_->SetTextureMailbox(TextureMailbox(), nullptr); | |
777 break; | |
778 case 4: | |
779 if (layer_tree_host()->settings().impl_side_painting) { | |
780 // With impl painting, the texture mailbox will still be on the impl | |
781 // thread when the commit finishes, because the layer is not drawble | |
782 // when it has no texture mailbox, and thus does not block the commit | |
783 // on activation. So, we wait for activation. | |
784 // TODO(danakj): fix this. crbug.com/277953 | |
785 layer_tree_host()->SetNeedsCommit(); | |
786 break; | |
787 } else { | |
788 ++commit_count_; | |
789 } | |
790 case 5: | |
791 EXPECT_EQ(4, callback_count_); | |
792 // Restore a mailbox for the next step. | |
793 SetMailbox('5'); | |
794 break; | |
795 case 6: | |
796 // Case #5: remove layer from tree. Callback should *not* be called, the | |
797 // mailbox is returned to the main thread. | |
798 EXPECT_EQ(4, callback_count_); | |
799 layer_->RemoveFromParent(); | |
800 break; | |
801 case 7: | |
802 if (layer_tree_host()->settings().impl_side_painting) { | |
803 // With impl painting, the texture mailbox will still be on the impl | |
804 // thread when the commit finishes, because the layer is not around to | |
805 // block the commit on activation anymore. So, we wait for activation. | |
806 // TODO(danakj): fix this. crbug.com/277953 | |
807 layer_tree_host()->SetNeedsCommit(); | |
808 break; | |
809 } else { | |
810 ++commit_count_; | |
811 } | |
812 case 8: | |
813 EXPECT_EQ(4, callback_count_); | |
814 // Resetting the mailbox will call the callback now. | |
815 layer_->SetTextureMailbox(TextureMailbox(), nullptr); | |
816 EXPECT_EQ(5, callback_count_); | |
817 EndTest(); | |
818 break; | |
819 default: | |
820 NOTREACHED(); | |
821 break; | |
822 } | |
823 } | |
824 | |
825 void AfterTest() override {} | |
826 | |
827 private: | |
828 base::ThreadChecker main_thread_; | |
829 int callback_count_; | |
830 int commit_count_; | |
831 scoped_refptr<Layer> root_; | |
832 scoped_refptr<TextureLayer> layer_; | |
833 }; | |
834 | |
835 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( | |
836 TextureLayerImplWithMailboxThreadedCallback); | |
837 | |
838 | |
839 class TextureLayerMailboxIsActivatedDuringCommit : public LayerTreeTest { | |
840 protected: | |
841 TextureLayerMailboxIsActivatedDuringCommit() : activate_count_(0) {} | |
842 | |
843 static void ReleaseCallback(uint32 sync_point, bool lost_resource) {} | |
844 | |
845 void SetMailbox(char mailbox_char) { | |
846 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( | |
847 base::Bind( | |
848 &TextureLayerMailboxIsActivatedDuringCommit::ReleaseCallback)); | |
849 layer_->SetTextureMailbox( | |
850 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), | |
851 callback.Pass()); | |
852 } | |
853 | |
854 void BeginTest() override { | |
855 gfx::Size bounds(100, 100); | |
856 root_ = Layer::Create(); | |
857 root_->SetBounds(bounds); | |
858 | |
859 layer_ = TextureLayer::CreateForMailbox(nullptr); | |
860 layer_->SetIsDrawable(true); | |
861 layer_->SetBounds(bounds); | |
862 | |
863 root_->AddChild(layer_); | |
864 layer_tree_host()->SetRootLayer(root_); | |
865 layer_tree_host()->SetViewportSize(bounds); | |
866 SetMailbox('1'); | |
867 | |
868 PostSetNeedsCommitToMainThread(); | |
869 } | |
870 | |
871 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override { | |
872 ++activate_count_; | |
873 } | |
874 | |
875 void DidCommit() override { | |
876 switch (layer_tree_host()->source_frame_number()) { | |
877 case 1: | |
878 // The first mailbox has been activated. Set a new mailbox, and | |
879 // expect the next commit to finish *after* it is activated. | |
880 SetMailbox('2'); | |
881 break; | |
882 case 2: | |
883 // The second mailbox has been activated. Remove the layer from | |
884 // the tree to cause another commit/activation. The commit should | |
885 // finish *after* the layer is removed from the active tree. | |
886 layer_->RemoveFromParent(); | |
887 break; | |
888 case 3: | |
889 EndTest(); | |
890 break; | |
891 } | |
892 } | |
893 | |
894 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { | |
895 switch (host_impl->active_tree()->source_frame_number()) { | |
896 case 0: { | |
897 // The activate for the 1st mailbox should have happened before now. | |
898 EXPECT_EQ(1, activate_count_); | |
899 break; | |
900 } | |
901 case 1: { | |
902 // The activate for the 2nd mailbox should have happened before now. | |
903 EXPECT_EQ(2, activate_count_); | |
904 break; | |
905 } | |
906 case 2: { | |
907 // The activate to remove the layer should have happened before now. | |
908 EXPECT_EQ(3, activate_count_); | |
909 break; | |
910 } | |
911 case 3: { | |
912 NOTREACHED(); | |
913 break; | |
914 } | |
915 } | |
916 } | |
917 | |
918 void AfterTest() override {} | |
919 | |
920 int activate_count_; | |
921 scoped_refptr<Layer> root_; | |
922 scoped_refptr<TextureLayer> layer_; | |
923 }; | |
924 | |
925 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( | |
926 TextureLayerMailboxIsActivatedDuringCommit); | |
927 | |
928 class TextureLayerImplWithMailboxTest : public TextureLayerTest { | |
929 protected: | |
930 TextureLayerImplWithMailboxTest() | |
931 : fake_client_( | |
932 FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D)) {} | |
933 | |
934 void SetUp() override { | |
935 TextureLayerTest::SetUp(); | |
936 layer_tree_host_.reset(new MockLayerTreeHost(&fake_client_)); | |
937 EXPECT_TRUE(host_impl_.InitializeRenderer(FakeOutputSurface::Create3d())); | |
938 } | |
939 | |
940 bool WillDraw(TextureLayerImpl* layer, DrawMode mode) { | |
941 bool will_draw = layer->WillDraw( | |
942 mode, host_impl_.active_tree()->resource_provider()); | |
943 if (will_draw) | |
944 layer->DidDraw(host_impl_.active_tree()->resource_provider()); | |
945 return will_draw; | |
946 } | |
947 | |
948 FakeLayerTreeHostClient fake_client_; | |
949 }; | |
950 | |
951 // Test conditions for results of TextureLayerImpl::WillDraw under | |
952 // different configurations of different mailbox, texture_id, and draw_mode. | |
953 TEST_F(TextureLayerImplWithMailboxTest, TestWillDraw) { | |
954 EXPECT_CALL( | |
955 test_data_.mock_callback_, | |
956 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) | |
957 .Times(AnyNumber()); | |
958 EXPECT_CALL(test_data_.mock_callback_, | |
959 ReleaseImpl2(test_data_.shared_bitmap_.get(), 0, false, _)) | |
960 .Times(AnyNumber()); | |
961 // Hardware mode. | |
962 { | |
963 scoped_ptr<TextureLayerImpl> impl_layer = | |
964 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
965 impl_layer->SetTextureMailbox( | |
966 test_data_.mailbox1_, | |
967 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
968 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); | |
969 } | |
970 | |
971 { | |
972 scoped_ptr<TextureLayerImpl> impl_layer = | |
973 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
974 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
975 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); | |
976 } | |
977 | |
978 { | |
979 // Software resource. | |
980 scoped_ptr<TextureLayerImpl> impl_layer = | |
981 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
982 impl_layer->SetTextureMailbox( | |
983 test_data_.mailbox3_, | |
984 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_)); | |
985 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_HARDWARE)); | |
986 } | |
987 | |
988 // Software mode. | |
989 { | |
990 scoped_ptr<TextureLayerImpl> impl_layer = | |
991 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
992 impl_layer->SetTextureMailbox( | |
993 test_data_.mailbox1_, | |
994 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
995 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); | |
996 } | |
997 | |
998 { | |
999 scoped_ptr<TextureLayerImpl> impl_layer = | |
1000 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
1001 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
1002 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); | |
1003 } | |
1004 | |
1005 { | |
1006 // Software resource. | |
1007 scoped_ptr<TextureLayerImpl> impl_layer = | |
1008 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
1009 impl_layer->SetTextureMailbox( | |
1010 test_data_.mailbox3_, | |
1011 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox3_impl_)); | |
1012 EXPECT_TRUE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE)); | |
1013 } | |
1014 | |
1015 // Resourceless software mode. | |
1016 { | |
1017 scoped_ptr<TextureLayerImpl> impl_layer = | |
1018 TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
1019 impl_layer->SetTextureMailbox( | |
1020 test_data_.mailbox1_, | |
1021 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1022 EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_RESOURCELESS_SOFTWARE)); | |
1023 } | |
1024 } | |
1025 | |
1026 TEST_F(TextureLayerImplWithMailboxTest, TestImplLayerCallbacks) { | |
1027 host_impl_.CreatePendingTree(); | |
1028 scoped_ptr<TextureLayerImpl> pending_layer; | |
1029 pending_layer = TextureLayerImpl::Create(host_impl_.pending_tree(), 1); | |
1030 ASSERT_TRUE(pending_layer); | |
1031 | |
1032 scoped_ptr<LayerImpl> active_layer( | |
1033 pending_layer->CreateLayerImpl(host_impl_.active_tree())); | |
1034 ASSERT_TRUE(active_layer); | |
1035 | |
1036 pending_layer->SetTextureMailbox( | |
1037 test_data_.mailbox1_, | |
1038 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1039 | |
1040 // Test multiple commits without an activation. | |
1041 EXPECT_CALL( | |
1042 test_data_.mock_callback_, | |
1043 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) | |
1044 .Times(1); | |
1045 pending_layer->SetTextureMailbox( | |
1046 test_data_.mailbox2_, | |
1047 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox2_impl_)); | |
1048 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
1049 | |
1050 // Test callback after activation. | |
1051 pending_layer->PushPropertiesTo(active_layer.get()); | |
1052 active_layer->DidBecomeActive(); | |
1053 | |
1054 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0); | |
1055 pending_layer->SetTextureMailbox( | |
1056 test_data_.mailbox1_, | |
1057 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1058 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
1059 | |
1060 EXPECT_CALL(test_data_.mock_callback_, | |
1061 ReleaseImpl(test_data_.mailbox_name2_, _, false, _)).Times(1); | |
1062 pending_layer->PushPropertiesTo(active_layer.get()); | |
1063 active_layer->DidBecomeActive(); | |
1064 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
1065 | |
1066 // Test resetting the mailbox. | |
1067 EXPECT_CALL(test_data_.mock_callback_, | |
1068 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1); | |
1069 pending_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
1070 pending_layer->PushPropertiesTo(active_layer.get()); | |
1071 active_layer->DidBecomeActive(); | |
1072 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
1073 | |
1074 // Test destructor. | |
1075 EXPECT_CALL( | |
1076 test_data_.mock_callback_, | |
1077 ReleaseImpl(test_data_.mailbox_name1_, test_data_.sync_point1_, false, _)) | |
1078 .Times(1); | |
1079 pending_layer->SetTextureMailbox( | |
1080 test_data_.mailbox1_, | |
1081 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1082 } | |
1083 | |
1084 TEST_F(TextureLayerImplWithMailboxTest, | |
1085 TestDestructorCallbackOnCreatedResource) { | |
1086 scoped_ptr<TextureLayerImpl> impl_layer; | |
1087 impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1); | |
1088 ASSERT_TRUE(impl_layer); | |
1089 | |
1090 EXPECT_CALL(test_data_.mock_callback_, | |
1091 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1); | |
1092 impl_layer->SetTextureMailbox( | |
1093 test_data_.mailbox1_, | |
1094 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1095 impl_layer->DidBecomeActive(); | |
1096 EXPECT_TRUE(impl_layer->WillDraw( | |
1097 DRAW_MODE_HARDWARE, host_impl_.active_tree()->resource_provider())); | |
1098 impl_layer->DidDraw(host_impl_.active_tree()->resource_provider()); | |
1099 impl_layer->SetTextureMailbox(TextureMailbox(), nullptr); | |
1100 } | |
1101 | |
1102 TEST_F(TextureLayerImplWithMailboxTest, TestCallbackOnInUseResource) { | |
1103 ResourceProvider* provider = host_impl_.active_tree()->resource_provider(); | |
1104 ResourceProvider::ResourceId id = provider->CreateResourceFromTextureMailbox( | |
1105 test_data_.mailbox1_, | |
1106 SingleReleaseCallbackImpl::Create(test_data_.release_mailbox1_impl_)); | |
1107 provider->AllocateForTesting(id); | |
1108 | |
1109 // Transfer some resources to the parent. | |
1110 ResourceProvider::ResourceIdArray resource_ids_to_transfer; | |
1111 resource_ids_to_transfer.push_back(id); | |
1112 TransferableResourceArray list; | |
1113 provider->PrepareSendToParent(resource_ids_to_transfer, &list); | |
1114 EXPECT_TRUE(provider->InUseByConsumer(id)); | |
1115 EXPECT_CALL(test_data_.mock_callback_, ReleaseImpl(_, _, _, _)).Times(0); | |
1116 provider->DeleteResource(id); | |
1117 Mock::VerifyAndClearExpectations(&test_data_.mock_callback_); | |
1118 EXPECT_CALL(test_data_.mock_callback_, | |
1119 ReleaseImpl(test_data_.mailbox_name1_, _, false, _)).Times(1); | |
1120 ReturnedResourceArray returned; | |
1121 TransferableResource::ReturnResources(list, &returned); | |
1122 provider->ReceiveReturnsFromParent(returned); | |
1123 } | |
1124 | |
1125 // Checks that TextureLayer::Update does not cause an extra commit when setting | |
1126 // the texture mailbox. | |
1127 class TextureLayerNoExtraCommitForMailboxTest | |
1128 : public LayerTreeTest, | |
1129 public TextureLayerClient { | |
1130 public: | |
1131 // TextureLayerClient implementation. | |
1132 bool PrepareTextureMailbox( | |
1133 TextureMailbox* texture_mailbox, | |
1134 scoped_ptr<SingleReleaseCallback>* release_callback, | |
1135 bool use_shared_memory) override { | |
1136 if (layer_tree_host()->source_frame_number() == 1) { | |
1137 // Once this has been committed, the mailbox will be released. | |
1138 *texture_mailbox = TextureMailbox(); | |
1139 return true; | |
1140 } | |
1141 | |
1142 *texture_mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); | |
1143 *release_callback = SingleReleaseCallback::Create( | |
1144 base::Bind(&TextureLayerNoExtraCommitForMailboxTest::MailboxReleased, | |
1145 base::Unretained(this))); | |
1146 return true; | |
1147 } | |
1148 | |
1149 void MailboxReleased(uint32 sync_point, bool lost_resource) { | |
1150 // Source frame number during callback is the same as the source frame | |
1151 // on which it was released. | |
1152 EXPECT_EQ(1, layer_tree_host()->source_frame_number()); | |
1153 EndTest(); | |
1154 } | |
1155 | |
1156 void SetupTree() override { | |
1157 scoped_refptr<Layer> root = Layer::Create(); | |
1158 root->SetBounds(gfx::Size(10, 10)); | |
1159 root->SetIsDrawable(true); | |
1160 | |
1161 texture_layer_ = TextureLayer::CreateForMailbox(this); | |
1162 texture_layer_->SetBounds(gfx::Size(10, 10)); | |
1163 texture_layer_->SetIsDrawable(true); | |
1164 root->AddChild(texture_layer_); | |
1165 | |
1166 layer_tree_host()->SetRootLayer(root); | |
1167 LayerTreeTest::SetupTree(); | |
1168 } | |
1169 | |
1170 void BeginTest() override { PostSetNeedsCommitToMainThread(); } | |
1171 | |
1172 void DidCommitAndDrawFrame() override { | |
1173 switch (layer_tree_host()->source_frame_number()) { | |
1174 case 1: | |
1175 EXPECT_FALSE(proxy()->MainFrameWillHappenForTesting()); | |
1176 // Invalidate the texture layer to clear the mailbox before | |
1177 // ending the test. | |
1178 texture_layer_->SetNeedsDisplay(); | |
1179 break; | |
1180 case 2: | |
1181 break; | |
1182 default: | |
1183 NOTREACHED(); | |
1184 break; | |
1185 } | |
1186 } | |
1187 | |
1188 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { | |
1189 ASSERT_TRUE(result); | |
1190 DelegatedFrameData* delegated_frame_data = | |
1191 output_surface()->last_sent_frame().delegated_frame_data.get(); | |
1192 if (!delegated_frame_data) | |
1193 return; | |
1194 | |
1195 // Return all resources immediately. | |
1196 TransferableResourceArray resources_to_return = | |
1197 output_surface()->resources_held_by_parent(); | |
1198 | |
1199 CompositorFrameAck ack; | |
1200 for (size_t i = 0; i < resources_to_return.size(); ++i) | |
1201 output_surface()->ReturnResource(resources_to_return[i].id, &ack); | |
1202 host_impl->ReclaimResources(&ack); | |
1203 } | |
1204 | |
1205 void AfterTest() override {} | |
1206 | |
1207 private: | |
1208 scoped_refptr<TextureLayer> texture_layer_; | |
1209 }; | |
1210 | |
1211 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerNoExtraCommitForMailboxTest); | |
1212 | |
1213 // Checks that changing a mailbox in the client for a TextureLayer that's | |
1214 // invisible correctly works and uses the new mailbox as soon as the layer | |
1215 // becomes visible (and returns the old one). | |
1216 class TextureLayerChangeInvisibleMailboxTest | |
1217 : public LayerTreeTest, | |
1218 public TextureLayerClient { | |
1219 public: | |
1220 TextureLayerChangeInvisibleMailboxTest() | |
1221 : mailbox_changed_(true), | |
1222 mailbox_returned_(0), | |
1223 prepare_called_(0), | |
1224 commit_count_(0) { | |
1225 mailbox_ = MakeMailbox('1'); | |
1226 } | |
1227 | |
1228 // TextureLayerClient implementation. | |
1229 bool PrepareTextureMailbox( | |
1230 TextureMailbox* mailbox, | |
1231 scoped_ptr<SingleReleaseCallback>* release_callback, | |
1232 bool use_shared_memory) override { | |
1233 ++prepare_called_; | |
1234 if (!mailbox_changed_) | |
1235 return false; | |
1236 *mailbox = mailbox_; | |
1237 *release_callback = SingleReleaseCallback::Create( | |
1238 base::Bind(&TextureLayerChangeInvisibleMailboxTest::MailboxReleased, | |
1239 base::Unretained(this))); | |
1240 return true; | |
1241 } | |
1242 | |
1243 TextureMailbox MakeMailbox(char name) { | |
1244 return TextureMailbox(MailboxFromChar(name), GL_TEXTURE_2D, 0); | |
1245 } | |
1246 | |
1247 void MailboxReleased(uint32 sync_point, bool lost_resource) { | |
1248 ++mailbox_returned_; | |
1249 } | |
1250 | |
1251 void SetupTree() override { | |
1252 scoped_refptr<Layer> root = Layer::Create(); | |
1253 root->SetBounds(gfx::Size(10, 10)); | |
1254 root->SetIsDrawable(true); | |
1255 | |
1256 solid_layer_ = SolidColorLayer::Create(); | |
1257 solid_layer_->SetBounds(gfx::Size(10, 10)); | |
1258 solid_layer_->SetIsDrawable(true); | |
1259 solid_layer_->SetBackgroundColor(SK_ColorWHITE); | |
1260 root->AddChild(solid_layer_); | |
1261 | |
1262 parent_layer_ = Layer::Create(); | |
1263 parent_layer_->SetBounds(gfx::Size(10, 10)); | |
1264 parent_layer_->SetIsDrawable(true); | |
1265 root->AddChild(parent_layer_); | |
1266 | |
1267 texture_layer_ = TextureLayer::CreateForMailbox(this); | |
1268 texture_layer_->SetBounds(gfx::Size(10, 10)); | |
1269 texture_layer_->SetIsDrawable(true); | |
1270 parent_layer_->AddChild(texture_layer_); | |
1271 | |
1272 layer_tree_host()->SetRootLayer(root); | |
1273 LayerTreeTest::SetupTree(); | |
1274 } | |
1275 | |
1276 void BeginTest() override { PostSetNeedsCommitToMainThread(); } | |
1277 | |
1278 void DidCommitAndDrawFrame() override { | |
1279 ++commit_count_; | |
1280 switch (commit_count_) { | |
1281 case 1: | |
1282 // We should have updated the layer, committing the texture. | |
1283 EXPECT_EQ(1, prepare_called_); | |
1284 // Make layer invisible. | |
1285 parent_layer_->SetOpacity(0.f); | |
1286 break; | |
1287 case 2: | |
1288 // Layer shouldn't have been updated. | |
1289 EXPECT_EQ(1, prepare_called_); | |
1290 // Change the texture. | |
1291 mailbox_ = MakeMailbox('2'); | |
1292 mailbox_changed_ = true; | |
1293 texture_layer_->SetNeedsDisplay(); | |
1294 // Force a change to make sure we draw a frame. | |
1295 solid_layer_->SetBackgroundColor(SK_ColorGRAY); | |
1296 break; | |
1297 case 3: | |
1298 // Layer shouldn't have been updated. | |
1299 EXPECT_EQ(1, prepare_called_); | |
1300 // So the old mailbox isn't returned yet. | |
1301 EXPECT_EQ(0, mailbox_returned_); | |
1302 // Make layer visible again. | |
1303 parent_layer_->SetOpacity(1.f); | |
1304 break; | |
1305 case 4: | |
1306 // Layer should have been updated. | |
1307 EXPECT_EQ(2, prepare_called_); | |
1308 // So the old mailbox should have been returned already. | |
1309 EXPECT_EQ(1, mailbox_returned_); | |
1310 texture_layer_->ClearClient(); | |
1311 break; | |
1312 case 5: | |
1313 EXPECT_EQ(2, mailbox_returned_); | |
1314 EndTest(); | |
1315 break; | |
1316 default: | |
1317 NOTREACHED(); | |
1318 break; | |
1319 } | |
1320 } | |
1321 | |
1322 void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { | |
1323 ASSERT_TRUE(result); | |
1324 DelegatedFrameData* delegated_frame_data = | |
1325 output_surface()->last_sent_frame().delegated_frame_data.get(); | |
1326 if (!delegated_frame_data) | |
1327 return; | |
1328 | |
1329 // Return all resources immediately. | |
1330 TransferableResourceArray resources_to_return = | |
1331 output_surface()->resources_held_by_parent(); | |
1332 | |
1333 CompositorFrameAck ack; | |
1334 for (size_t i = 0; i < resources_to_return.size(); ++i) | |
1335 output_surface()->ReturnResource(resources_to_return[i].id, &ack); | |
1336 host_impl->ReclaimResources(&ack); | |
1337 } | |
1338 | |
1339 void AfterTest() override {} | |
1340 | |
1341 private: | |
1342 scoped_refptr<SolidColorLayer> solid_layer_; | |
1343 scoped_refptr<Layer> parent_layer_; | |
1344 scoped_refptr<TextureLayer> texture_layer_; | |
1345 | |
1346 // Used on the main thread. | |
1347 bool mailbox_changed_; | |
1348 TextureMailbox mailbox_; | |
1349 int mailbox_returned_; | |
1350 int prepare_called_; | |
1351 int commit_count_; | |
1352 }; | |
1353 | |
1354 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerChangeInvisibleMailboxTest); | |
1355 | |
1356 // Test that TextureLayerImpl::ReleaseResources can be called which releases | |
1357 // the mailbox back to TextureLayerClient. | |
1358 class TextureLayerReleaseResourcesBase | |
1359 : public LayerTreeTest, | |
1360 public TextureLayerClient { | |
1361 public: | |
1362 // TextureLayerClient implementation. | |
1363 bool PrepareTextureMailbox( | |
1364 TextureMailbox* mailbox, | |
1365 scoped_ptr<SingleReleaseCallback>* release_callback, | |
1366 bool use_shared_memory) override { | |
1367 *mailbox = TextureMailbox(MailboxFromChar('1'), GL_TEXTURE_2D, 0); | |
1368 *release_callback = SingleReleaseCallback::Create( | |
1369 base::Bind(&TextureLayerReleaseResourcesBase::MailboxReleased, | |
1370 base::Unretained(this))); | |
1371 return true; | |
1372 } | |
1373 | |
1374 void MailboxReleased(unsigned sync_point, bool lost_resource) { | |
1375 mailbox_released_ = true; | |
1376 } | |
1377 | |
1378 void SetupTree() override { | |
1379 LayerTreeTest::SetupTree(); | |
1380 | |
1381 scoped_refptr<TextureLayer> texture_layer = | |
1382 TextureLayer::CreateForMailbox(this); | |
1383 texture_layer->SetBounds(gfx::Size(10, 10)); | |
1384 texture_layer->SetIsDrawable(true); | |
1385 | |
1386 layer_tree_host()->root_layer()->AddChild(texture_layer); | |
1387 } | |
1388 | |
1389 void BeginTest() override { | |
1390 mailbox_released_ = false; | |
1391 PostSetNeedsCommitToMainThread(); | |
1392 } | |
1393 | |
1394 void DidCommitAndDrawFrame() override { EndTest(); } | |
1395 | |
1396 void AfterTest() override { EXPECT_TRUE(mailbox_released_); } | |
1397 | |
1398 private: | |
1399 bool mailbox_released_; | |
1400 }; | |
1401 | |
1402 class TextureLayerReleaseResourcesAfterCommit | |
1403 : public TextureLayerReleaseResourcesBase { | |
1404 public: | |
1405 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { | |
1406 LayerTreeImpl* tree = nullptr; | |
1407 tree = host_impl->sync_tree(); | |
1408 tree->root_layer()->children()[0]->ReleaseResources(); | |
1409 } | |
1410 }; | |
1411 | |
1412 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterCommit); | |
1413 | |
1414 class TextureLayerReleaseResourcesAfterActivate | |
1415 : public TextureLayerReleaseResourcesBase { | |
1416 public: | |
1417 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override { | |
1418 host_impl->active_tree()->root_layer()->children()[0]->ReleaseResources(); | |
1419 } | |
1420 }; | |
1421 | |
1422 SINGLE_AND_MULTI_THREAD_TEST_F(TextureLayerReleaseResourcesAfterActivate); | |
1423 | |
1424 class TextureLayerWithMailboxMainThreadDeleted : public LayerTreeTest { | |
1425 public: | |
1426 void ReleaseCallback(uint32 sync_point, bool lost_resource) { | |
1427 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1428 EXPECT_FALSE(lost_resource); | |
1429 ++callback_count_; | |
1430 EndTest(); | |
1431 } | |
1432 | |
1433 void SetMailbox(char mailbox_char) { | |
1434 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1435 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( | |
1436 base::Bind( | |
1437 &TextureLayerWithMailboxMainThreadDeleted::ReleaseCallback, | |
1438 base::Unretained(this))); | |
1439 layer_->SetTextureMailbox( | |
1440 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), | |
1441 callback.Pass()); | |
1442 } | |
1443 | |
1444 void SetupTree() override { | |
1445 gfx::Size bounds(100, 100); | |
1446 root_ = Layer::Create(); | |
1447 root_->SetBounds(bounds); | |
1448 | |
1449 layer_ = TextureLayer::CreateForMailbox(nullptr); | |
1450 layer_->SetIsDrawable(true); | |
1451 layer_->SetBounds(bounds); | |
1452 | |
1453 root_->AddChild(layer_); | |
1454 layer_tree_host()->SetRootLayer(root_); | |
1455 layer_tree_host()->SetViewportSize(bounds); | |
1456 } | |
1457 | |
1458 void BeginTest() override { | |
1459 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1460 | |
1461 callback_count_ = 0; | |
1462 | |
1463 // Set the mailbox on the main thread. | |
1464 SetMailbox('1'); | |
1465 EXPECT_EQ(0, callback_count_); | |
1466 | |
1467 PostSetNeedsCommitToMainThread(); | |
1468 } | |
1469 | |
1470 void DidCommitAndDrawFrame() override { | |
1471 switch (layer_tree_host()->source_frame_number()) { | |
1472 case 1: | |
1473 // Delete the TextureLayer on the main thread while the mailbox is in | |
1474 // the impl tree. | |
1475 layer_->RemoveFromParent(); | |
1476 layer_ = nullptr; | |
1477 break; | |
1478 } | |
1479 } | |
1480 | |
1481 void AfterTest() override { EXPECT_EQ(1, callback_count_); } | |
1482 | |
1483 private: | |
1484 base::ThreadChecker main_thread_; | |
1485 int callback_count_; | |
1486 scoped_refptr<Layer> root_; | |
1487 scoped_refptr<TextureLayer> layer_; | |
1488 }; | |
1489 | |
1490 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( | |
1491 TextureLayerWithMailboxMainThreadDeleted); | |
1492 | |
1493 class TextureLayerWithMailboxImplThreadDeleted : public LayerTreeTest { | |
1494 public: | |
1495 void ReleaseCallback(uint32 sync_point, bool lost_resource) { | |
1496 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1497 EXPECT_FALSE(lost_resource); | |
1498 ++callback_count_; | |
1499 EndTest(); | |
1500 } | |
1501 | |
1502 void SetMailbox(char mailbox_char) { | |
1503 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1504 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create( | |
1505 base::Bind( | |
1506 &TextureLayerWithMailboxImplThreadDeleted::ReleaseCallback, | |
1507 base::Unretained(this))); | |
1508 layer_->SetTextureMailbox( | |
1509 TextureMailbox(MailboxFromChar(mailbox_char), GL_TEXTURE_2D, 0), | |
1510 callback.Pass()); | |
1511 } | |
1512 | |
1513 void SetupTree() override { | |
1514 gfx::Size bounds(100, 100); | |
1515 root_ = Layer::Create(); | |
1516 root_->SetBounds(bounds); | |
1517 | |
1518 layer_ = TextureLayer::CreateForMailbox(nullptr); | |
1519 layer_->SetIsDrawable(true); | |
1520 layer_->SetBounds(bounds); | |
1521 | |
1522 root_->AddChild(layer_); | |
1523 layer_tree_host()->SetRootLayer(root_); | |
1524 layer_tree_host()->SetViewportSize(bounds); | |
1525 } | |
1526 | |
1527 void BeginTest() override { | |
1528 EXPECT_EQ(true, main_thread_.CalledOnValidThread()); | |
1529 | |
1530 callback_count_ = 0; | |
1531 | |
1532 // Set the mailbox on the main thread. | |
1533 SetMailbox('1'); | |
1534 EXPECT_EQ(0, callback_count_); | |
1535 | |
1536 PostSetNeedsCommitToMainThread(); | |
1537 } | |
1538 | |
1539 void DidCommitAndDrawFrame() override { | |
1540 switch (layer_tree_host()->source_frame_number()) { | |
1541 case 1: | |
1542 // Remove the TextureLayer on the main thread while the mailbox is in | |
1543 // the impl tree, but don't delete the TextureLayer until after the impl | |
1544 // tree side is deleted. | |
1545 layer_->RemoveFromParent(); | |
1546 break; | |
1547 case 2: | |
1548 layer_ = nullptr; | |
1549 break; | |
1550 } | |
1551 } | |
1552 | |
1553 void AfterTest() override { EXPECT_EQ(1, callback_count_); } | |
1554 | |
1555 private: | |
1556 base::ThreadChecker main_thread_; | |
1557 int callback_count_; | |
1558 scoped_refptr<Layer> root_; | |
1559 scoped_refptr<TextureLayer> layer_; | |
1560 }; | |
1561 | |
1562 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F( | |
1563 TextureLayerWithMailboxImplThreadDeleted); | |
1564 | |
1565 } // namespace | |
1566 } // namespace cc | |
OLD | NEW |