Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc

Issue 12717013: Add reference-counting for mailbox textures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add optional 'pool' reference while textures are in mailbox Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.cc ('k') | gpu/command_buffer/service/mailbox_manager.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 42f0fc5f8a5b7391e7368cf89b6f3ae1d9659638..00edbbc360fa3ef6c7c439b00c0b1eed4f7d81fe 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -7279,111 +7279,299 @@ TEST_F(GLES2DecoderTest, GenMailboxCHROMIUM) {
sizeof(zero)));
}
-TEST_F(GLES2DecoderTest, ProduceAndConsumeTextureCHROMIUM) {
- GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
- group().mailbox_manager()->GenerateMailboxName(
- reinterpret_cast<MailboxName*>(mailbox));
+class TextureMailboxTest : public GLES2DecoderTestBase {
+ public:
+ TextureMailboxTest()
+ : GLES2DecoderTestBase() {
+ }
- memcpy(shared_memory_address_, mailbox, sizeof(mailbox));
+ virtual void SetUp() {
+ GLES2DecoderTestBase::SetUp();
- DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
- DoTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- 0, 0);
- DoTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- 0, 0);
- Texture* texture = group().texture_manager()->GetTexture(client_texture_id_);
- EXPECT_EQ(kServiceTextureId, texture->service_id());
+ // Register some extra texture ids.
+ RegisterTexture(kClientId1, kServiceId1);
+ RegisterTexture(kClientId2, kServiceId2);
+ RegisterTexture(kClientId3, kServiceId3);
+ }
- // Assigns and binds new service side texture ID.
- EXPECT_CALL(*gl_, GenTextures(1, _))
- .WillOnce(SetArgumentPointee<1>(kNewServiceId))
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId))
- .Times(1)
- .RetiresOnSaturation();
+ protected:
+ MailboxName ProduceTexture() {
+ // Assigns and binds new service side texture ID.
+ EXPECT_CALL(*gl_, GenTextures(1, _))
+ .WillOnce(SetArgumentPointee<1>(kNewServiceId)).RetiresOnSaturation();
+ EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kNewServiceId)).Times(1)
+ .RetiresOnSaturation();
- ProduceTextureCHROMIUM produce_cmd;
- produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset);
- EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd));
+ MailboxName mailbox;
+ group().mailbox_manager()->GenerateMailboxName(&mailbox);
+ memcpy(shared_memory_address_, &mailbox, sizeof(mailbox));
+ ProduceTextureCHROMIUM produce_cmd;
+ produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd));
+ return mailbox;
+ }
- // Texture is zero-by-zero.
- GLsizei width;
- GLsizei height;
- GLenum type;
- GLenum internal_format;
+ void ConsumeTexture(
+ const MailboxName& mailbox, GLuint old_texture, GLuint new_texture) {
+ // TextureManager::Restore will set TexParameters.
+ EXPECT_CALL(
+ *gl_,
+ TexParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR))
+ .Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR))
+ .Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT))
+ .Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*gl_,
+ TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT))
+ .Times(1).RetiresOnSaturation();
+#if 0
+ EXPECT_CALL(*gl_,
+ TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_NONE))
+ .Times(1).RetiresOnSaturation();
+#endif
+ // Assigns and binds original service size texture ID.
+ EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(old_texture))).Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, new_texture)).Times(1)
+ .RetiresOnSaturation();
- EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
- EXPECT_EQ(0, width);
- EXPECT_EQ(0, height);
- EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format));
- EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format);
- EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
+ memcpy(shared_memory_address_, &mailbox, sizeof(mailbox));
+ ConsumeTextureCHROMIUM consume_cmd;
+ consume_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ ::testing::Mock::VerifyAndClearExpectations(gl_.get());
+ }
- EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
- EXPECT_EQ(0, width);
- EXPECT_EQ(0, height);
- EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format));
- EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format);
- EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
+ void VerifyLevel(Texture* texture, GLint level, GLint width, GLint height,
+ GLenum type, GLenum format) {
+ GLint w, h;
+ EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, level, &w, &h));
+ EXPECT_EQ(w, width);
+ EXPECT_EQ(h, height);
+ GLenum t, f;
+ EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, level, &t, &f));
+ EXPECT_EQ(static_cast<GLenum>(type), t);
+ EXPECT_EQ(static_cast<GLenum>(format), f);
+ }
+
+ static const GLuint kClientId1;
+ static const GLuint kServiceId1;
+ static const GLuint kClientId2;
+ static const GLuint kServiceId2;
+ static const GLuint kClientId3;
+ static const GLuint kServiceId3;
+
+ private:
+ void RegisterTexture(GLuint client_id, GLuint service_id) {
+ EXPECT_CALL(*gl_, GenTextures(_, _))
+ .WillOnce(SetArgumentPointee<1>(service_id))
+ .RetiresOnSaturation();
+ GenHelper<GenTexturesImmediate>(client_id);
+ Texture* texture = group().texture_manager()->GetTexture(client_id);
+ EXPECT_EQ(service_id, texture->service_id());
+ }
+};
+
+const GLuint TextureMailboxTest::kClientId1 = 4100;
+const GLuint TextureMailboxTest::kServiceId1 = 4101;
+const GLuint TextureMailboxTest::kClientId2 = 4102;
+const GLuint TextureMailboxTest::kServiceId2 = 4103;
+const GLuint TextureMailboxTest::kClientId3 = 4104;
+const GLuint TextureMailboxTest::kServiceId3 = 4105;
+
+// Produces and consumes a texture back into the same client texture.
+TEST_F(TextureMailboxTest, ProduceAndConsumeToSameTexture) {
+ GLsizei level0_width = 3;
+ GLsizei level0_height = 1;
+ GLenum type = GL_UNSIGNED_BYTE;
+ GLenum format = GL_RGBA;
+
+ DoBindTexture(GL_TEXTURE_2D, kClientId1, kServiceId1);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, level0_width, level0_height,
+ 0, format, type, 0, 0);
+ Texture* texture = group().texture_manager()->GetTexture(kClientId1);
+ EXPECT_FALSE(texture->IsImmutable());
+
+ MailboxName mailbox = ProduceTexture();
+
+ VerifyLevel(texture, 0, 0, 0, type, format);
// Service ID has changed.
EXPECT_EQ(kNewServiceId, texture->service_id());
+ EXPECT_TRUE(texture->IsImmutable());
+
+ ConsumeTexture(mailbox, kNewServiceId, kServiceId1);
+
+ // Texture is restored to the previous state.
+ VerifyLevel(texture, 0, level0_width, level0_height, type, format);
+ EXPECT_EQ(kServiceId1, texture->service_id());
+ EXPECT_FALSE(texture->IsImmutable());
+
+ DoDeleteTexture(kClientId1, kServiceId1);
+
+ // The texture should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox) == NULL);
+}
+
+// Produces and consumes two textures between two clients.
+TEST_F(TextureMailboxTest, ProduceAndConsumeTextures) {
+ const GLsizei level0_width = 3;
+ const GLsizei level0_height = 1;
+ const GLsizei level1_width = 2;
+ const GLsizei level1_height = 4;
+ const GLenum type = GL_UNSIGNED_BYTE;
+ const GLenum format = GL_RGBA;
+
+ // Produce a texture with two levels.
+ DoBindTexture(GL_TEXTURE_2D, kClientId1, kServiceId1);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, level0_width, level0_height,
+ 0, format, type, 0, 0);
+ DoTexImage2D(GL_TEXTURE_2D, 1, format, level1_width, level1_height,
+ 0, format, type, 0, 0);
+ MailboxName mailbox1 = ProduceTexture();
+
+ // Produce a second 16x16 texture.
+ DoBindTexture(GL_TEXTURE_2D, kClientId2, kServiceId2);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, 16, 16,
+ 0, format, type, 0, 0);
+ MailboxName mailbox2 = ProduceTexture();
+
+ // Consume the first texture.
+ DoBindTexture(GL_TEXTURE_2D, kClientId3, kServiceId3);
+ ConsumeTexture(mailbox1, kServiceId3, kServiceId1);
+ Texture* texture = group().texture_manager()->GetTexture(kClientId3);
+ EXPECT_FALSE(texture->IsImmutable());
+
+ // The textures should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox1) == NULL);
+
+ // Delete the producer texture now and make sure it still gets cleaned up
+ // correctly from the consumer.
+ DoDeleteTexture(kClientId1, kNewServiceId);
- // Assigns and binds original service size texture ID.
- EXPECT_CALL(*gl_, DeleteTextures(1, _))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_2D, kServiceTextureId))
- .Times(1)
- .RetiresOnSaturation();
+ // Texture is redefined.
+ VerifyLevel(texture, 0, level0_width, level0_height, type, format);
+ VerifyLevel(texture, 1, level1_width, level1_height, type, format);
+
+ // Service ID is unchanged.
+ EXPECT_EQ(kServiceId1, texture->service_id());
+
+ // Consume the second texture, which deletes the previous shared texture.
+ ConsumeTexture(mailbox2, kServiceId1, kServiceId2);
+ VerifyLevel(texture, 0, 16, 16, type, format);
+ VerifyLevel(texture, 1, 0, 0, 0, 0);
+
+ // The textures should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox2) == NULL);
+
+ // Delete the empty producer-side texture.
+ DoDeleteTexture(kClientId2, kNewServiceId);
+
+ // Deleting the consumer-side texure (most recent mailbox texture).
+ DoDeleteTexture(kClientId3, kServiceId2);
+}
+
+// Produces and consumes a texture back and forth between two clients.
+TEST_F(TextureMailboxTest, PingPongTexture) {
+ const GLsizei width = 2;
+ const GLsizei height = 4;
+ const GLenum type = GL_UNSIGNED_BYTE;
+ const GLenum format = GL_RGBA;
+
+ // Produce a texture from client1.
+ DoBindTexture(GL_TEXTURE_2D, kClientId1, kServiceId1);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, width, height,
+ 0, format, type, 0, 0);
+ MailboxName mailbox1 = ProduceTexture();
+
+ // Consume the texture from client2.
+ DoBindTexture(GL_TEXTURE_2D, kClientId2, kServiceId2);
+ ConsumeTexture(mailbox1, kServiceId2, kServiceId1);
+
+ // The textures should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox1) == NULL);
+
+ // Produce it into a new mailbox.
+ MailboxName mailbox2 = ProduceTexture();
+ Texture* texture = group().texture_manager()->GetTexture(kClientId2);
+ EXPECT_TRUE(texture->IsImmutable());
+
+ // Consume the texture back from client1.
+ DoBindTexture(GL_TEXTURE_2D, kClientId1, kNewServiceId);
+ ConsumeTexture(mailbox2, kNewServiceId, kServiceId1);
+ texture = group().texture_manager()->GetTexture(kClientId1);
+ EXPECT_FALSE(texture->IsImmutable());
+ VerifyLevel(texture, 0, width, height, type, format);
+
+ // The textures should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox2) == NULL);
+
+ // Delete kClientId2 first to also release the reference to kServiceId1.
+ DoDeleteTexture(kClientId2, kNewServiceId);
+ DoDeleteTexture(kClientId1, kServiceId1);
+}
+
+// Produces a texture but deletes it before it gets consumed from the mailbox.
+TEST_F(TextureMailboxTest, ProduceAndDeleteTexture) {
+ GLsizei width = 3;
+ GLsizei height = 1;
+ GLenum type = GL_UNSIGNED_BYTE;
+ GLenum format = GL_RGBA;
- // TextureManager::Restore will set TexParameters.
- EXPECT_CALL(*gl_, TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*gl_, TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT))
- .Times(1)
- .RetiresOnSaturation();
- #if 0
- EXPECT_CALL(*gl_, TexParameteri(
- GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_NONE))
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, width, height,
+ 0, format, type, 0, 0);
+
+ MailboxName mailbox = ProduceTexture();
+
+ // Both texures should get deleted (the empty producer texture and
+ // the one in the mailbox).
+ EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(kNewServiceId)))
.Times(1)
.RetiresOnSaturation();
- #endif
+ DoDeleteTexture(client_texture_id_, kServiceTextureId);
- ConsumeTextureCHROMIUM consume_cmd;
- consume_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset);
- EXPECT_EQ(error::kNoError, ExecuteCmd(consume_cmd));
+ // The texture should have been removed from the mailbox.
+ EXPECT_TRUE(group().mailbox_manager()->
+ ConsumeTexture(GL_TEXTURE_2D, mailbox) == NULL);
+}
- // Texture is redefined.
- EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height));
- EXPECT_EQ(3, width);
- EXPECT_EQ(1, height);
- EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 0, &type, &internal_format));
- EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format);
- EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
+// Test that trying to produce an immutable texture repeatedly fails.
+TEST_F(TextureMailboxTest, ProduceTextureTwiceFails) {
+ GLsizei width = 3;
+ GLsizei height = 1;
+ GLenum type = GL_UNSIGNED_BYTE;
+ GLenum format = GL_RGBA;
- EXPECT_TRUE(texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height));
- EXPECT_EQ(2, width);
- EXPECT_EQ(4, height);
- EXPECT_TRUE(texture->GetLevelType(GL_TEXTURE_2D, 1, &type, &internal_format));
- EXPECT_EQ(static_cast<GLenum>(GL_RGBA), internal_format);
- EXPECT_EQ(static_cast<GLenum>(GL_UNSIGNED_BYTE), type);
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ DoTexImage2D(GL_TEXTURE_2D, 0, format, width, height,
+ 0, format, type, 0, 0);
- // Service ID is restored.
- EXPECT_EQ(kServiceTextureId, texture->service_id());
-}
+ MailboxName mailbox = ProduceTexture();
+
+ EXPECT_EQ(memcmp(shared_memory_address_, &mailbox, sizeof(mailbox)), 0);
+ ProduceTextureCHROMIUM produce_cmd;
+ produce_cmd.Init(GL_TEXTURE_2D, kSharedMemoryId, kSharedMemoryOffset);
+ EXPECT_EQ(error::kNoError, ExecuteCmd(produce_cmd));
+ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
+ // Both texures should get deleted (the empty producer texture and
+ // the one in the mailbox).
+ EXPECT_CALL(*gl_, DeleteTextures(1, Pointee(kNewServiceId)))
+ .Times(1)
+ .RetiresOnSaturation();
+ DoDeleteTexture(client_texture_id_, kServiceTextureId);
+}
TEST_F(GLES2DecoderTest, CanChangeSurface) {
scoped_refptr<GLSurfaceMock> other_surface(new GLSurfaceMock);
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.cc ('k') | gpu/command_buffer/service/mailbox_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698