Index: gpu/command_buffer/service/mailbox_manager_unittest.cc |
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc |
index f7a4155179868cd46f06f11477d88e5d813529cb..8eb3e267d178794153f9fdc5a23f93cc30f7bb94 100644 |
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc |
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc |
@@ -4,20 +4,64 @@ |
#include "gpu/command_buffer/service/mailbox_manager.h" |
+#include "gpu/command_buffer/service/feature_info.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_mock.h" |
namespace gpu { |
namespace gles2 { |
+using namespace ::testing; |
+ |
class MailboxManagerTest : public testing::Test { |
public: |
- MailboxManagerTest() : manager_(new MailboxManager()) {} |
+ MailboxManagerTest() {} |
virtual ~MailboxManagerTest() {} |
protected: |
+ virtual void SetUp() { |
+ testing::Test::SetUp(); |
+ feature_info_ = new FeatureInfo; |
+ manager_ = new MailboxManager; |
+ } |
+ |
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->SetParameter(feature_info_, pname, param); |
} |
void DestroyTexture(Texture* texture) { |
@@ -27,6 +71,8 @@ class MailboxManagerTest : public testing::Test { |
scoped_refptr<MailboxManager> manager_; |
private: |
+ scoped_refptr<FeatureInfo> feature_info_; |
+ |
DISALLOW_COPY_AND_ASSIGN(MailboxManagerTest); |
}; |
@@ -126,5 +172,296 @@ 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() { |
+ MailboxSynchronizer::Initialize(); |
+ MailboxManagerTest::SetUp(); |
+ manager2_ = new MailboxManager; |
+ gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); |
+ ::gfx::MockGLInterface::SetGLInterface(gl_.get()); |
+ } |
+ |
+ 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() { |
+ MailboxManagerTest::TearDown(); |
+ MailboxSynchronizer::Terminate(); |
+ ::gfx::MockGLInterface::SetGLInterface(NULL); |
+ gl_.reset(); |
+ } |
+ |
+ scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; |
+ scoped_refptr<MailboxManager> manager2_; |
+ |
+ 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 |
+ EXPECT_CALL(*gl_, Flush()).Times(1); |
+ 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 |
+ EXPECT_CALL(*gl_, Flush()).Times(1); |
+ 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 |
+ EXPECT_CALL(*gl_, Flush()).Times(1); |
+ 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. |
+ EXPECT_CALL(*gl_, Flush()).Times(2); |
+ 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 |
+ EXPECT_CALL(*gl_, Flush()).Times(2); |
+ 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 |