| 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);
|
|
|