Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / mailbox_manager_unittest.cc
blobdf1cd4eced635fa56d8509f84a16dbd0fc5bed75
1 // Copyright 2013 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 "gpu/command_buffer/service/mailbox_manager.h"
7 #include "gpu/command_buffer/service/feature_info.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mailbox_synchronizer.h"
10 #include "gpu/command_buffer/service/texture_manager.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gl/gl_context_stub.h"
13 #include "ui/gl/gl_mock.h"
14 #include "ui/gl/gl_surface_stub.h"
16 namespace gpu {
17 namespace gles2 {
19 using namespace ::testing;
21 class MailboxManagerTest : public GpuServiceTest {
22 public:
23 MailboxManagerTest() : initialized_synchronizer_(false) {}
24 virtual ~MailboxManagerTest() {}
26 protected:
27 virtual void SetUp() {
28 GpuServiceTest::SetUp();
29 feature_info_ = new FeatureInfo;
30 manager_ = new MailboxManager;
33 virtual void SetUpWithSynchronizer() {
34 GpuServiceTest::SetUp();
35 MailboxSynchronizer::Initialize();
36 initialized_synchronizer_ = true;
37 feature_info_ = new FeatureInfo;
38 manager_ = new MailboxManager;
41 virtual void TearDown() {
42 if (initialized_synchronizer_)
43 MailboxSynchronizer::Terminate();
44 GpuServiceTest::TearDown();
47 Texture* CreateTexture() {
48 return new Texture(1);
51 void SetTarget(Texture* texture, GLenum target, GLuint max_level) {
52 texture->SetTarget(NULL, target, max_level);
55 void SetLevelInfo(
56 Texture* texture,
57 GLenum target,
58 GLint level,
59 GLenum internal_format,
60 GLsizei width,
61 GLsizei height,
62 GLsizei depth,
63 GLint border,
64 GLenum format,
65 GLenum type,
66 bool cleared) {
67 texture->SetLevelInfo(NULL,
68 target,
69 level,
70 internal_format,
71 width,
72 height,
73 depth,
74 border,
75 format,
76 type,
77 cleared);
80 GLenum SetParameter(Texture* texture, GLenum pname, GLint param) {
81 return texture->SetParameteri(feature_info_.get(), pname, param);
84 void DestroyTexture(Texture* texture) {
85 delete texture;
88 scoped_refptr<MailboxManager> manager_;
90 private:
91 bool initialized_synchronizer_;
92 scoped_refptr<FeatureInfo> feature_info_;
94 DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest);
97 // Tests basic produce/consume behavior.
98 TEST_F(MailboxManagerTest, Basic) {
99 Texture* texture = CreateTexture();
101 Mailbox name = Mailbox::Generate();
102 manager_->ProduceTexture(0, name, texture);
103 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
105 // We can consume multiple times.
106 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name));
108 // Wrong target should fail the consume.
109 EXPECT_EQ(NULL, manager_->ConsumeTexture(1, name));
111 // Destroy should cleanup the mailbox.
112 DestroyTexture(texture);
113 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
116 // Tests behavior with multiple produce on the same texture.
117 TEST_F(MailboxManagerTest, ProduceMultipleMailbox) {
118 Texture* texture = CreateTexture();
120 Mailbox name1 = Mailbox::Generate();
122 manager_->ProduceTexture(0, name1, texture);
123 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
125 // Can produce a second time with the same mailbox.
126 manager_->ProduceTexture(0, name1, texture);
127 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
129 // Can produce again, with a different mailbox.
130 Mailbox name2 = Mailbox::Generate();
131 manager_->ProduceTexture(0, name2, texture);
133 // Still available under all mailboxes.
134 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1));
135 EXPECT_EQ(texture, manager_->ConsumeTexture(0, name2));
137 // Destroy should cleanup all mailboxes.
138 DestroyTexture(texture);
139 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
140 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
143 // Tests behavior with multiple produce on the same mailbox with different
144 // textures.
145 TEST_F(MailboxManagerTest, ProduceMultipleTexture) {
146 Texture* texture1 = CreateTexture();
147 Texture* texture2 = CreateTexture();
149 Mailbox name = Mailbox::Generate();
151 manager_->ProduceTexture(0, name, texture1);
152 EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name));
154 // Can produce a second time with the same mailbox, but different texture.
155 manager_->ProduceTexture(0, name, texture2);
156 EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
158 // Destroying the texture that's under no mailbox shouldn't have an effect.
159 DestroyTexture(texture1);
160 EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name));
162 // Destroying the texture that's bound should clean up.
163 DestroyTexture(texture2);
164 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name));
167 TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) {
168 Texture* texture1 = CreateTexture();
169 Texture* texture2 = CreateTexture();
170 Mailbox name1 = Mailbox::Generate();
171 Mailbox name2 = Mailbox::Generate();
173 // Put texture1 on name1 and name2.
174 manager_->ProduceTexture(0, name1, texture1);
175 manager_->ProduceTexture(0, name2, texture1);
176 EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
177 EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name2));
179 // Put texture2 on name2.
180 manager_->ProduceTexture(0, name2, texture2);
181 EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1));
182 EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
184 // Destroy texture1, shouldn't affect name2.
185 DestroyTexture(texture1);
186 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name1));
187 EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2));
189 DestroyTexture(texture2);
190 EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2));
193 const GLsizei kMaxTextureWidth = 64;
194 const GLsizei kMaxTextureHeight = 64;
195 const GLsizei kMaxTextureDepth = 1;
197 class MailboxManagerSyncTest : public MailboxManagerTest {
198 public:
199 MailboxManagerSyncTest() {}
200 virtual ~MailboxManagerSyncTest() {}
202 protected:
203 virtual void SetUp() {
204 MailboxManagerTest::SetUpWithSynchronizer();
205 manager2_ = new MailboxManager;
206 context_ = new gfx::GLContextStub();
207 surface_ = new gfx::GLSurfaceStub();
208 context_->MakeCurrent(surface_.get());
211 Texture* DefineTexture() {
212 Texture* texture = CreateTexture();
213 const GLsizei levels_needed = TextureManager::ComputeMipMapCount(
214 GL_TEXTURE_2D, kMaxTextureWidth, kMaxTextureHeight, kMaxTextureDepth);
215 SetTarget(texture, GL_TEXTURE_2D, levels_needed);
216 SetLevelInfo(texture,
217 GL_TEXTURE_2D,
219 GL_RGBA,
224 GL_RGBA,
225 GL_UNSIGNED_BYTE,
226 true);
227 SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
228 SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
229 return texture;
232 void SetupUpdateTexParamExpectations(GLuint texture_id,
233 GLenum min,
234 GLenum mag,
235 GLenum wrap_s,
236 GLenum wrap_t) {
237 DCHECK(texture_id);
238 const GLuint kCurrentTexture = 0;
239 EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_2D, _))
240 .WillOnce(SetArgPointee<1>(kCurrentTexture))
241 .RetiresOnSaturation();
242 EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, texture_id))
243 .Times(1)
244 .RetiresOnSaturation();
245 EXPECT_CALL(*gl_,
246 TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min))
247 .Times(1)
248 .RetiresOnSaturation();
249 EXPECT_CALL(*gl_,
250 TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag))
251 .Times(1)
252 .RetiresOnSaturation();
253 EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s))
254 .Times(1)
255 .RetiresOnSaturation();
256 EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t))
257 .Times(1)
258 .RetiresOnSaturation();
259 EXPECT_CALL(*gl_, Flush())
260 .Times(1)
261 .RetiresOnSaturation();
262 EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kCurrentTexture))
263 .Times(1)
264 .RetiresOnSaturation();
267 virtual void TearDown() {
268 context_->ReleaseCurrent(NULL);
269 MailboxManagerTest::TearDown();
272 scoped_refptr<MailboxManager> manager2_;
273 scoped_refptr<gfx::GLContext> context_;
274 scoped_refptr<gfx::GLSurface> surface_;
276 private:
277 DISALLOW_COPY_AND_ASSIGN(MailboxManagerSyncTest);
280 TEST_F(MailboxManagerSyncTest, ProduceDestroy) {
281 Texture* texture = DefineTexture();
282 Mailbox name = Mailbox::Generate();
284 InSequence sequence;
285 manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
286 EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
288 DestroyTexture(texture);
289 EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
290 EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
293 TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) {
294 InSequence sequence;
296 Texture* texture = DefineTexture();
297 Mailbox name = Mailbox::Generate();
299 manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
300 EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
302 // Synchronize
303 manager_->PushTextureUpdates();
304 manager2_->PullTextureUpdates();
306 DestroyTexture(texture);
307 EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
308 EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
311 // Duplicates a texture into a second manager instance, and then
312 // makes sure a redefinition becomes visible there too.
313 TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) {
314 const GLuint kNewTextureId = 1234;
315 InSequence sequence;
317 Texture* texture = DefineTexture();
318 Mailbox name = Mailbox::Generate();
320 manager_->ProduceTexture(GL_TEXTURE_2D, name, texture);
321 EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
323 // Synchronize
324 manager_->PushTextureUpdates();
325 manager2_->PullTextureUpdates();
327 EXPECT_CALL(*gl_, GenTextures(1, _))
328 .WillOnce(SetArgPointee<1>(kNewTextureId));
329 SetupUpdateTexParamExpectations(
330 kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
331 Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name);
332 EXPECT_FALSE(new_texture == NULL);
333 EXPECT_NE(texture, new_texture);
334 EXPECT_EQ(kNewTextureId, new_texture->service_id());
336 // Resize original texture
337 SetLevelInfo(texture,
338 GL_TEXTURE_2D,
340 GL_RGBA,
345 GL_RGBA,
346 GL_UNSIGNED_BYTE,
347 true);
348 // Should have been orphaned
349 EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL);
351 // Synchronize again
352 manager_->PushTextureUpdates();
353 SetupUpdateTexParamExpectations(
354 kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
355 manager2_->PullTextureUpdates();
356 GLsizei width, height;
357 new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
358 EXPECT_EQ(16, width);
359 EXPECT_EQ(32, height);
361 // Should have gotten a new attachment
362 EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) != NULL);
363 // Resize original texture again....
364 SetLevelInfo(texture,
365 GL_TEXTURE_2D,
367 GL_RGBA,
372 GL_RGBA,
373 GL_UNSIGNED_BYTE,
374 true);
375 // ...and immediately delete the texture which should save the changes.
376 SetupUpdateTexParamExpectations(
377 kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
378 DestroyTexture(texture);
380 // Should be still around since there is a ref from manager2
381 EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
383 // The last change to the texture should be visible without a sync point (i.e.
384 // push).
385 manager2_->PullTextureUpdates();
386 new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
387 EXPECT_EQ(64, width);
388 EXPECT_EQ(64, height);
390 DestroyTexture(new_texture);
391 EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
392 EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name));
395 // Makes sure changes are correctly published even when updates are
396 // pushed in both directions, i.e. makes sure we don't clobber a shared
397 // texture definition with an older version.
398 TEST_F(MailboxManagerSyncTest, ProduceConsumeBidirectional) {
399 const GLuint kNewTextureId1 = 1234;
400 const GLuint kNewTextureId2 = 4321;
402 Texture* texture1 = DefineTexture();
403 Mailbox name1 = Mailbox::Generate();
404 Texture* texture2 = DefineTexture();
405 Mailbox name2 = Mailbox::Generate();
406 Texture* new_texture1 = NULL;
407 Texture* new_texture2 = NULL;
409 manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture1);
410 manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2);
412 // Make visible.
413 manager_->PushTextureUpdates();
414 manager2_->PushTextureUpdates();
416 // Create textures in the other manager instances for texture1 and texture2,
417 // respectively to create a real sharing scenario. Otherwise, there would
418 // never be conflicting updates/pushes.
420 InSequence sequence;
421 EXPECT_CALL(*gl_, GenTextures(1, _))
422 .WillOnce(SetArgPointee<1>(kNewTextureId1));
423 SetupUpdateTexParamExpectations(
424 kNewTextureId1, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
425 new_texture1 = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1);
426 EXPECT_CALL(*gl_, GenTextures(1, _))
427 .WillOnce(SetArgPointee<1>(kNewTextureId2));
428 SetupUpdateTexParamExpectations(
429 kNewTextureId2, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
430 new_texture2 = manager_->ConsumeTexture(GL_TEXTURE_2D, name2);
432 EXPECT_EQ(kNewTextureId1, new_texture1->service_id());
433 EXPECT_EQ(kNewTextureId2, new_texture2->service_id());
435 // Make a change to texture1
436 DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture1->min_filter());
437 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
438 SetParameter(texture1, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
440 // Make sure this does not clobber it with the previous version we pushed.
441 manager_->PullTextureUpdates();
443 // Make a change to texture2
444 DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture2->mag_filter());
445 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR),
446 SetParameter(texture2, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
448 Mock::VerifyAndClearExpectations(gl_.get());
450 // Synchronize in both directions
451 manager_->PushTextureUpdates();
452 manager2_->PushTextureUpdates();
453 // manager1 should see the change to texture2 mag_filter being applied.
454 SetupUpdateTexParamExpectations(
455 new_texture2->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT);
456 manager_->PullTextureUpdates();
457 // manager2 should see the change to texture1 min_filter being applied.
458 SetupUpdateTexParamExpectations(
459 new_texture1->service_id(), GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT);
460 manager2_->PullTextureUpdates();
462 DestroyTexture(texture1);
463 DestroyTexture(texture2);
464 DestroyTexture(new_texture1);
465 DestroyTexture(new_texture2);
468 // TODO: different texture into same mailbox
470 // TODO: same texture, multiple mailboxes
472 // TODO: Produce incomplete texture
474 // TODO: Texture::level_infos_[][].size()
476 // TODO: unsupported targets and formats
478 } // namespace gles2
479 } // namespace gpu