diff options
Diffstat (limited to 'chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc')
-rw-r--r-- | chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc | 401 |
1 files changed, 367 insertions, 34 deletions
diff --git a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc index 8864843571d..8e57faa96c0 100644 --- a/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc +++ b/chromium/gpu/command_buffer/service/mailbox_manager_unittest.cc @@ -4,20 +4,81 @@ #include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/feature_info.h" +#include "gpu/command_buffer/service/gpu_service_test.h" +#include "gpu/command_buffer/service/mailbox_synchronizer.h" #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_context_stub.h" +#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_surface_stub.h" namespace gpu { namespace gles2 { -class MailboxManagerTest : public testing::Test { +using namespace ::testing; + +class MailboxManagerTest : public GpuServiceTest { public: - MailboxManagerTest() : manager_(new MailboxManager()) {} + MailboxManagerTest() : initialized_synchronizer_(false) {} virtual ~MailboxManagerTest() {} protected: + virtual void SetUp() { + GpuServiceTest::SetUp(); + feature_info_ = new FeatureInfo; + manager_ = new MailboxManager; + } + + virtual void SetUpWithSynchronizer() { + GpuServiceTest::SetUp(); + MailboxSynchronizer::Initialize(); + initialized_synchronizer_ = true; + feature_info_ = new FeatureInfo; + manager_ = new MailboxManager; + } + + virtual void TearDown() { + if (initialized_synchronizer_) + MailboxSynchronizer::Terminate(); + GpuServiceTest::TearDown(); + } + Texture* CreateTexture() { - return new Texture(0); + return new Texture(1); + } + + void SetTarget(Texture* texture, GLenum target, GLuint max_level) { + texture->SetTarget(NULL, target, max_level); + } + + void SetLevelInfo( + Texture* texture, + GLenum target, + GLint level, + GLenum internal_format, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + bool cleared) { + texture->SetLevelInfo(NULL, + target, + level, + internal_format, + width, + height, + depth, + border, + format, + type, + cleared); + } + + GLenum SetParameter(Texture* texture, GLenum pname, GLint param) { + return texture->SetParameteri(feature_info_, pname, param); } void DestroyTexture(Texture* texture) { @@ -27,6 +88,9 @@ class MailboxManagerTest : public testing::Test { scoped_refptr<MailboxManager> manager_; private: + bool initialized_synchronizer_; + scoped_refptr<FeatureInfo> feature_info_; + DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest); }; @@ -34,9 +98,8 @@ class MailboxManagerTest : public testing::Test { TEST_F(MailboxManagerTest, Basic) { Texture* texture = CreateTexture(); - MailboxName name; - manager_->GenerateMailboxName(&name); - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture)); + Mailbox name = Mailbox::Generate(); + manager_->ProduceTexture(0, name, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name)); // We can consume multiple times. @@ -50,34 +113,22 @@ TEST_F(MailboxManagerTest, Basic) { EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name)); } -// Should fail to produce or consume with an invalid mailbox. -TEST_F(MailboxManagerTest, InvalidName) { - Texture* texture = CreateTexture(); - MailboxName name; - memset(&name, 0, sizeof(name)); - EXPECT_FALSE(manager_->ProduceTexture(0, name, texture)); - EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name)); - DestroyTexture(texture); -} - // Tests behavior with multiple produce on the same texture. TEST_F(MailboxManagerTest, ProduceMultipleMailbox) { Texture* texture = CreateTexture(); - MailboxName name1; - manager_->GenerateMailboxName(&name1); + Mailbox name1 = Mailbox::Generate(); - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture)); + manager_->ProduceTexture(0, name1, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); // Can produce a second time with the same mailbox. - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture)); + manager_->ProduceTexture(0, name1, texture); EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); // Can produce again, with a different mailbox. - MailboxName name2; - manager_->GenerateMailboxName(&name2); - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture)); + Mailbox name2 = Mailbox::Generate(); + manager_->ProduceTexture(0, name2, texture); // Still available under all mailboxes. EXPECT_EQ(texture, manager_->ConsumeTexture(0, name1)); @@ -95,14 +146,13 @@ TEST_F(MailboxManagerTest, ProduceMultipleTexture) { Texture* texture1 = CreateTexture(); Texture* texture2 = CreateTexture(); - MailboxName name; - manager_->GenerateMailboxName(&name); + Mailbox name = Mailbox::Generate(); - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture1)); + manager_->ProduceTexture(0, name, texture1); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name)); // Can produce a second time with the same mailbox, but different texture. - EXPECT_TRUE(manager_->ProduceTexture(0, name, texture2)); + manager_->ProduceTexture(0, name, texture2); EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name)); // Destroying the texture that's under no mailbox shouldn't have an effect. @@ -117,19 +167,17 @@ TEST_F(MailboxManagerTest, ProduceMultipleTexture) { TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) { Texture* texture1 = CreateTexture(); Texture* texture2 = CreateTexture(); - MailboxName name1; - manager_->GenerateMailboxName(&name1); - MailboxName name2; - manager_->GenerateMailboxName(&name2); + Mailbox name1 = Mailbox::Generate(); + Mailbox name2 = Mailbox::Generate(); // Put texture1 on name1 and name2. - EXPECT_TRUE(manager_->ProduceTexture(0, name1, texture1)); - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture1)); + manager_->ProduceTexture(0, name1, texture1); + manager_->ProduceTexture(0, name2, texture1); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1)); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name2)); // Put texture2 on name2. - EXPECT_TRUE(manager_->ProduceTexture(0, name2, texture2)); + manager_->ProduceTexture(0, name2, texture2); EXPECT_EQ(texture1, manager_->ConsumeTexture(0, name1)); EXPECT_EQ(texture2, manager_->ConsumeTexture(0, name2)); @@ -142,5 +190,290 @@ TEST_F(MailboxManagerTest, ProduceMultipleTextureMailbox) { EXPECT_EQ(NULL, manager_->ConsumeTexture(0, name2)); } +const GLsizei kMaxTextureWidth = 64; +const GLsizei kMaxTextureHeight = 64; +const GLsizei kMaxTextureDepth = 1; + +class MailboxManagerSyncTest : public MailboxManagerTest { + public: + MailboxManagerSyncTest() {} + virtual ~MailboxManagerSyncTest() {} + + protected: + virtual void SetUp() { + MailboxManagerTest::SetUpWithSynchronizer(); + manager2_ = new MailboxManager; + context_ = new gfx::GLContextStub(); + surface_ = new gfx::GLSurfaceStub(); + context_->MakeCurrent(surface_); + } + + Texture* DefineTexture() { + Texture* texture = CreateTexture(); + const GLsizei levels_needed = TextureManager::ComputeMipMapCount( + GL_TEXTURE_2D, kMaxTextureWidth, kMaxTextureHeight, kMaxTextureDepth); + SetTarget(texture, GL_TEXTURE_2D, levels_needed); + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 1, + 1, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + SetParameter(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + SetParameter(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + return texture; + } + + void SetupUpdateTexParamExpectations(GLuint texture_id, + GLenum min, + GLenum mag, + GLenum wrap_s, + GLenum wrap_t) { + DCHECK(texture_id); + const GLuint kCurrentTexture = 0; + EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) + .WillOnce(SetArgPointee<1>(kCurrentTexture)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, texture_id)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, + TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Flush()) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kCurrentTexture)) + .Times(1) + .RetiresOnSaturation(); + } + + virtual void TearDown() { + context_->ReleaseCurrent(NULL); + MailboxManagerTest::TearDown(); + } + + scoped_refptr<MailboxManager> manager2_; + scoped_refptr<gfx::GLContext> context_; + scoped_refptr<gfx::GLSurface> surface_; + + private: + DISALLOW_COPY_AND_ASSIGN(MailboxManagerSyncTest); +}; + +TEST_F(MailboxManagerSyncTest, ProduceDestroy) { + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + InSequence sequence; + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + DestroyTexture(texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +TEST_F(MailboxManagerSyncTest, ProduceSyncDestroy) { + InSequence sequence; + + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // Synchronize + manager_->PushTextureUpdates(); + manager2_->PullTextureUpdates(); + + DestroyTexture(texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +// Duplicates a texture into a second manager instance, and then +// makes sure a redefinition becomes visible there too. +TEST_F(MailboxManagerSyncTest, ProduceConsumeResize) { + const GLuint kNewTextureId = 1234; + InSequence sequence; + + Texture* texture = DefineTexture(); + Mailbox name = Mailbox::Generate(); + + manager_->ProduceTexture(GL_TEXTURE_2D, name, texture); + EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // Synchronize + manager_->PushTextureUpdates(); + manager2_->PullTextureUpdates(); + + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId)); + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + Texture* new_texture = manager2_->ConsumeTexture(GL_TEXTURE_2D, name); + EXPECT_FALSE(new_texture == NULL); + EXPECT_NE(texture, new_texture); + EXPECT_EQ(kNewTextureId, new_texture->service_id()); + + // Resize original texture + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 16, + 32, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + // Should have been orphaned + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL); + + // Synchronize again + manager_->PushTextureUpdates(); + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + manager2_->PullTextureUpdates(); + GLsizei width, height; + new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height); + EXPECT_EQ(16, width); + EXPECT_EQ(32, height); + + // Should have gotten a new attachment + EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) != NULL); + // Resize original texture again.... + SetLevelInfo(texture, + GL_TEXTURE_2D, + 0, + GL_RGBA, + 64, + 64, + 1, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + true); + // ...and immediately delete the texture which should save the changes. + SetupUpdateTexParamExpectations( + kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + DestroyTexture(texture); + + // Should be still around since there is a ref from manager2 + EXPECT_EQ(new_texture, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); + + // The last change to the texture should be visible without a sync point (i.e. + // push). + manager2_->PullTextureUpdates(); + new_texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height); + EXPECT_EQ(64, width); + EXPECT_EQ(64, height); + + DestroyTexture(new_texture); + EXPECT_EQ(NULL, manager_->ConsumeTexture(GL_TEXTURE_2D, name)); + EXPECT_EQ(NULL, manager2_->ConsumeTexture(GL_TEXTURE_2D, name)); +} + +// Makes sure changes are correctly published even when updates are +// pushed in both directions, i.e. makes sure we don't clobber a shared +// texture definition with an older version. +TEST_F(MailboxManagerSyncTest, ProduceConsumeBidirectional) { + const GLuint kNewTextureId1 = 1234; + const GLuint kNewTextureId2 = 4321; + + Texture* texture1 = DefineTexture(); + Mailbox name1 = Mailbox::Generate(); + Texture* texture2 = DefineTexture(); + Mailbox name2 = Mailbox::Generate(); + Texture* new_texture1 = NULL; + Texture* new_texture2 = NULL; + + manager_->ProduceTexture(GL_TEXTURE_2D, name1, texture1); + manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2); + + // Make visible. + manager_->PushTextureUpdates(); + manager2_->PushTextureUpdates(); + + // Create textures in the other manager instances for texture1 and texture2, + // respectively to create a real sharing scenario. Otherwise, there would + // never be conflicting updates/pushes. + { + InSequence sequence; + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId1)); + SetupUpdateTexParamExpectations( + kNewTextureId1, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + new_texture1 = manager2_->ConsumeTexture(GL_TEXTURE_2D, name1); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgPointee<1>(kNewTextureId2)); + SetupUpdateTexParamExpectations( + kNewTextureId2, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT); + new_texture2 = manager_->ConsumeTexture(GL_TEXTURE_2D, name2); + } + EXPECT_EQ(kNewTextureId1, new_texture1->service_id()); + EXPECT_EQ(kNewTextureId2, new_texture2->service_id()); + + // Make a change to texture1 + DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture1->min_filter()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), + SetParameter(texture1, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + + // Make sure this does not clobber it with the previous version we pushed. + manager_->PullTextureUpdates(); + + // Make a change to texture2 + DCHECK_EQ(static_cast<GLuint>(GL_LINEAR), texture2->mag_filter()); + EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), + SetParameter(texture2, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + + Mock::VerifyAndClearExpectations(gl_.get()); + + // Synchronize in both directions + manager_->PushTextureUpdates(); + manager2_->PushTextureUpdates(); + // manager1 should see the change to texture2 mag_filter being applied. + SetupUpdateTexParamExpectations( + new_texture2->service_id(), GL_LINEAR, GL_NEAREST, GL_REPEAT, GL_REPEAT); + manager_->PullTextureUpdates(); + // manager2 should see the change to texture1 min_filter being applied. + SetupUpdateTexParamExpectations( + new_texture1->service_id(), GL_NEAREST, GL_LINEAR, GL_REPEAT, GL_REPEAT); + manager2_->PullTextureUpdates(); + + DestroyTexture(texture1); + DestroyTexture(texture2); + DestroyTexture(new_texture1); + DestroyTexture(new_texture2); +} + +// TODO: different texture into same mailbox + +// TODO: same texture, multiple mailboxes + +// TODO: Produce incomplete texture + +// TODO: Texture::level_infos_[][].size() + +// TODO: unsupported targets and formats + } // namespace gles2 } // namespace gpu |