Chromium Code Reviews| Index: cc/resources/resource_provider_unittest.cc |
| diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc |
| index b804afbb7ba4e2f71030e6234e48735847e6c761..78e0c5ee5f21d93fe63abf4a683b18a85670fbdf 100644 |
| --- a/cc/resources/resource_provider_unittest.cc |
| +++ b/cc/resources/resource_provider_unittest.cc |
| @@ -36,10 +36,13 @@ |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/gpu_memory_buffer.h" |
| +using testing::InSequence; |
| using testing::Mock; |
| using testing::NiceMock; |
| +using testing::Pointee; |
| using testing::Return; |
| using testing::StrictMock; |
| +using testing::TypedEq; |
| using testing::_; |
| namespace cc { |
| @@ -624,9 +627,9 @@ TEST_P(ResourceProviderTest, TransferGLResources) { |
| uint8_t data2[4] = { 5, 5, 5, 5 }; |
| child_resource_provider_->CopyToResource(id2, data2, size); |
| - ResourceId id3 = child_resource_provider_->CreateResource( |
| + ResourceId id3 = child_resource_provider_->CreateGpuMemoryBufferResource( |
| size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, |
| - gfx::ColorSpace()); |
| + gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); |
| { |
| ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( |
| child_resource_provider_.get(), id3); |
| @@ -999,9 +1002,9 @@ TEST_P(ResourceProviderTestNoSyncToken, TransferGLResources) { |
| uint8_t data1[4] = {1, 2, 3, 4}; |
| child_resource_provider_->CopyToResource(id1, data1, size); |
| - ResourceId id2 = child_resource_provider_->CreateResource( |
| + ResourceId id2 = child_resource_provider_->CreateGpuMemoryBufferResource( |
| size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, |
| - gfx::ColorSpace()); |
| + gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); |
| { |
| // Ensure locking the memory buffer doesn't create an unnecessary sync |
| // point. |
| @@ -3384,11 +3387,10 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncTokenIfNeeded_NoSyncToken) { |
| } |
| } |
| -class AllocationTrackingContext3D : public TestWebGraphicsContext3D { |
| +class AllocationTrackingContext3D : public TextureStateTrackingContext { |
| public: |
| MOCK_METHOD0(NextTextureId, GLuint()); |
| MOCK_METHOD1(RetireTextureId, void(GLuint id)); |
| - MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture)); |
| MOCK_METHOD5(texStorage2DEXT, |
| void(GLenum target, |
| GLint levels, |
| @@ -3454,7 +3456,7 @@ class AllocationTrackingContext3D : public TestWebGraphicsContext3D { |
| // We're mocking bindTexture, so we override |
| // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the |
| // currently bound texture. |
| - virtual void texParameteri(GLenum target, GLenum pname, GLint param) {} |
| + void texParameteri(GLenum target, GLenum pname, GLint param) override {} |
| }; |
| TEST_P(ResourceProviderTest, TextureAllocation) { |
| @@ -3634,9 +3636,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { |
| const int kWidth = 2; |
| const int kHeight = 2; |
| - gfx::Size size(kWidth, kHeight); |
| - ResourceFormat format = RGBA_8888; |
| - ResourceId id = 0; |
| + const ResourceFormat format = RGBA_8888; |
| const unsigned kTextureId = 123u; |
| const unsigned kImageId = 234u; |
| @@ -3648,34 +3648,28 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { |
| kEnableColorCorrectRendering, |
| DefaultBufferToTextureTargetMapForTesting())); |
| - id = resource_provider->CreateResource( |
| - size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format, |
| - gfx::ColorSpace()); |
| + ResourceId id = resource_provider->CreateGpuMemoryBufferResource( |
| + gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_IMMUTABLE, |
| + format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); |
| + |
| + InSequence sequence; |
| - EXPECT_CALL(*context, NextTextureId()) |
| - .WillOnce(Return(kTextureId)) |
| - .RetiresOnSaturation(); |
| - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) |
| - .Times(3) |
| - .RetiresOnSaturation(); |
| + // Image is created in the lock's dtor. |
| + EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); |
| EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) |
| - .WillOnce(Return(kImageId)) |
| - .RetiresOnSaturation(); |
| + .WillOnce(Return(kImageId)); |
| { |
| ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( |
| resource_provider.get(), id); |
| EXPECT_TRUE(lock.GetGpuMemoryBuffer()); |
| } |
| - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| - EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| { |
| - ResourceProvider::ScopedSamplerGL lock_gl( |
| - resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2); |
| + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); |
| + ResourceProvider::ScopedSamplerGL lock_gl(resource_provider.get(), id, |
| + GL_TEXTURE_2D, GL_LINEAR); |
| EXPECT_EQ(kTextureId, lock_gl.texture_id()); |
| } |
| @@ -3685,26 +3679,18 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { |
| EXPECT_TRUE(lock.GetGpuMemoryBuffer()); |
| } |
| - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1) |
| - .RetiresOnSaturation(); |
| - EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| - EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| - EXPECT_CALL(*context, RetireTextureId(kTextureId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| + // Upload to GPU again since image is dirty after the write lock. |
| { |
| - ResourceProvider::ScopedSamplerGL lock_gl( |
| - resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2); |
| + EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); |
| + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); |
| + ResourceProvider::ScopedSamplerGL lock_gl(resource_provider.get(), id, |
| + GL_TEXTURE_2D, GL_LINEAR); |
| EXPECT_EQ(kTextureId, lock_gl.texture_id()); |
| } |
| - EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) |
| - .Times(1) |
| - .RetiresOnSaturation(); |
| + EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)); |
| + EXPECT_CALL(*context, RetireTextureId(kTextureId)); |
| } |
| TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { |
| @@ -3732,7 +3718,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { |
| size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1, gfx::ColorSpace()); |
| EXPECT_NE(0u, id); |
| EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); |
| - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1); |
| resource_provider->AllocateForTesting(id); |
| EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1); |
| @@ -3765,7 +3751,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { |
| size, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1, gfx::ColorSpace()); |
| EXPECT_NE(0u, id); |
| EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id)); |
| - EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2); |
| EXPECT_CALL(*context, |
| compressedTexImage2D( |
| _, 0, _, size.width(), size.height(), _, _, _)).Times(1); |
| @@ -3874,5 +3860,261 @@ TEST_P(ResourceProviderTest, GetSyncTokenForResources) { |
| EXPECT_EQ(last_token.release_count(), 10u); |
| } |
| +TEST_P(ResourceProviderTest, ScopedWriteLockGL) { |
| + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) |
| + return; |
| + std::unique_ptr<AllocationTrackingContext3D> context_owned( |
| + new StrictMock<AllocationTrackingContext3D>); |
| + AllocationTrackingContext3D* context = context_owned.get(); |
| + auto context_provider = TestContextProvider::Create(std::move(context_owned)); |
| + context_provider->BindToCurrentThread(); |
| + |
| + const int kWidth = 2; |
| + const int kHeight = 2; |
| + const ResourceFormat format = RGBA_8888; |
| + const unsigned kTextureId = 123u; |
| + |
| + std::unique_ptr<ResourceProvider> resource_provider( |
| + base::MakeUnique<ResourceProvider>( |
| + context_provider.get(), shared_bitmap_manager_.get(), |
| + gpu_memory_buffer_manager_.get(), nullptr, 1, |
| + kDelegatedSyncPointsRequired, kUseGpuMemoryBufferResources, |
| + kEnableColorCorrectRendering, |
| + DefaultBufferToTextureTargetMapForTesting())); |
| + |
| + ResourceId id = resource_provider->CreateResource( |
| + gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_IMMUTABLE, |
| + format, gfx::ColorSpace()); |
| + |
| + InSequence sequence; |
| + |
| + // First use will allocate lazily on creation of lock. |
| + { |
| + EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2); |
| + EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), |
| + kWidth, kHeight, 0, GLDataFormat(format), |
| + GLDataType(format), nullptr)); |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, |
| + false); |
|
piman
2017/06/09 22:14:20
nit: you may want to add Mock::VerifyAndClearExpec
|
| + } |
| + |
| + // Subsequent uses will not allocate. |
| + { |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, |
| + false); |
| + } |
| + |
| + EXPECT_CALL(*context, RetireTextureId(kTextureId)); |
| + resource_provider->DeleteResource(id); |
| +} |
| + |
| +TEST_P(ResourceProviderTest, ScopedWriteLockGL_GpuMemoryBuffer) { |
| + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) |
| + return; |
| + std::unique_ptr<AllocationTrackingContext3D> context_owned( |
| + new StrictMock<AllocationTrackingContext3D>); |
| + AllocationTrackingContext3D* context = context_owned.get(); |
| + auto context_provider = TestContextProvider::Create(std::move(context_owned)); |
| + context_provider->BindToCurrentThread(); |
| + |
| + const int kWidth = 2; |
| + const int kHeight = 2; |
| + const ResourceFormat format = RGBA_8888; |
| + const unsigned kTextureId = 123u; |
| + const unsigned kImageId = 234u; |
| + |
| + std::unique_ptr<ResourceProvider> resource_provider( |
| + base::MakeUnique<ResourceProvider>( |
| + context_provider.get(), shared_bitmap_manager_.get(), |
| + gpu_memory_buffer_manager_.get(), nullptr, 1, |
| + kDelegatedSyncPointsRequired, kUseGpuMemoryBufferResources, |
| + kEnableColorCorrectRendering, |
| + DefaultBufferToTextureTargetMapForTesting())); |
| + |
| + ResourceId id = resource_provider->CreateGpuMemoryBufferResource( |
| + gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_IMMUTABLE, |
| + format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); |
| + |
| + InSequence sequence; |
| + |
| + // First use will allocate lazily on creation of lock. |
| + { |
| + EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); |
| + EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, |
| + GLInternalFormat(format))) |
| + .WillOnce(Return(kImageId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); |
| + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, |
| + false); |
| + } |
| + |
| + // Subsequent uses will not allocate. |
| + { |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, |
| + false); |
| + } |
| + |
| + EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)); |
| + EXPECT_CALL(*context, RetireTextureId(kTextureId)); |
| + resource_provider->DeleteResource(id); |
| +} |
| + |
| +TEST_P(ResourceProviderTest, ScopedWriteLockGL_AsyncWorkerContext) { |
| + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) |
| + return; |
| + std::unique_ptr<AllocationTrackingContext3D> context_owned( |
| + new StrictMock<AllocationTrackingContext3D>); |
| + AllocationTrackingContext3D* context = context_owned.get(); |
| + auto context_provider = TestContextProvider::Create(std::move(context_owned)); |
| + context_provider->BindToCurrentThread(); |
| + |
| + const int kWidth = 2; |
| + const int kHeight = 2; |
| + const ResourceFormat format = RGBA_8888; |
| + const unsigned kTextureId = 123u; |
| + const unsigned kWorkerTextureId = 234u; |
| + |
| + std::unique_ptr<ResourceProvider> resource_provider( |
| + base::MakeUnique<ResourceProvider>( |
| + context_provider.get(), shared_bitmap_manager_.get(), |
| + gpu_memory_buffer_manager_.get(), nullptr, 1, |
| + kDelegatedSyncPointsRequired, kUseGpuMemoryBufferResources, |
| + kEnableColorCorrectRendering, |
| + DefaultBufferToTextureTargetMapForTesting())); |
| + |
| + ResourceId id = resource_provider->CreateResource( |
| + gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_IMMUTABLE, |
| + format, gfx::ColorSpace()); |
| + |
| + gpu::SyncToken sync_token; |
| + context->genSyncToken(context->insertFenceSync(), sync_token.GetData()); |
| + |
| + InSequence sequence; |
| + |
| + // First use will create mailbox when lock is created and allocate lazily in |
| + // ConsumeTexture. |
| + { |
| + EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); |
| + EXPECT_CALL(*context, |
| + produceTextureDirectCHROMIUM(kTextureId, GL_TEXTURE_2D, _)); |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, true); |
| + |
| + EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _)) |
| + .WillOnce(Return(kWorkerTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kWorkerTextureId)); |
| + EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GLInternalFormat(format), |
| + kWidth, kHeight, 0, GLDataFormat(format), |
| + GLDataType(format), nullptr)); |
| + EXPECT_EQ(kWorkerTextureId, |
| + lock.ConsumeTexture(context_provider->ContextGL())); |
| + |
| + EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); |
| + context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); |
| + } |
| + |
| + // Subsequent uses will not create mailbox or allocate. |
| + { |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, true); |
| + |
| + EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _)) |
| + .WillOnce(Return(kWorkerTextureId)); |
| + EXPECT_EQ(kWorkerTextureId, |
| + lock.ConsumeTexture(context_provider->ContextGL())); |
| + |
| + lock.set_sync_token(sync_token); |
| + |
| + EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); |
| + context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); |
| + } |
| + |
| + // Wait for worker context sync token before deleting texture. |
| + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); |
| + EXPECT_CALL(*context, RetireTextureId(kTextureId)); |
| + resource_provider->DeleteResource(id); |
| +} |
| + |
| +TEST_P(ResourceProviderTest, |
| + ScopedWriteLockGL_GpuMemoryBuffer_AsyncWorkerContext) { |
| + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) |
| + return; |
| + std::unique_ptr<AllocationTrackingContext3D> context_owned( |
| + new StrictMock<AllocationTrackingContext3D>); |
| + AllocationTrackingContext3D* context = context_owned.get(); |
| + auto context_provider = TestContextProvider::Create(std::move(context_owned)); |
| + context_provider->BindToCurrentThread(); |
| + |
| + const int kWidth = 2; |
| + const int kHeight = 2; |
| + const ResourceFormat format = RGBA_8888; |
| + const unsigned kTextureId = 123u; |
| + const unsigned kWorkerTextureId = 234u; |
| + const unsigned kImageId = 345u; |
| + |
| + std::unique_ptr<ResourceProvider> resource_provider( |
| + base::MakeUnique<ResourceProvider>( |
| + context_provider.get(), shared_bitmap_manager_.get(), |
| + gpu_memory_buffer_manager_.get(), nullptr, 1, |
| + kDelegatedSyncPointsRequired, kUseGpuMemoryBufferResources, |
| + kEnableColorCorrectRendering, |
| + DefaultBufferToTextureTargetMapForTesting())); |
| + |
| + ResourceId id = resource_provider->CreateGpuMemoryBufferResource( |
| + gfx::Size(kWidth, kHeight), ResourceProvider::TEXTURE_HINT_IMMUTABLE, |
| + format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, gfx::ColorSpace()); |
| + |
| + gpu::SyncToken sync_token; |
| + context->genSyncToken(context->insertFenceSync(), sync_token.GetData()); |
| + |
| + InSequence sequence; |
| + |
| + // First use will create mailbox when lock is created and allocate lazily in |
| + // ConsumeTexture. |
| + { |
| + EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(kTextureId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)); |
| + EXPECT_CALL(*context, |
| + produceTextureDirectCHROMIUM(kTextureId, GL_TEXTURE_2D, _)); |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, true); |
| + |
| + EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _)) |
| + .WillOnce(Return(kWorkerTextureId)); |
| + EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, |
| + GLInternalFormat(format))) |
| + .WillOnce(Return(kImageId)); |
| + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kWorkerTextureId)); |
| + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)); |
| + EXPECT_EQ(kWorkerTextureId, |
| + lock.ConsumeTexture(context_provider->ContextGL())); |
| + |
| + EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); |
| + context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); |
| + } |
| + |
| + // Subsequent uses will not create mailbox or allocate. |
| + { |
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider.get(), id, true); |
| + |
| + EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _)) |
| + .WillOnce(Return(kWorkerTextureId)); |
| + EXPECT_EQ(kWorkerTextureId, |
| + lock.ConsumeTexture(context_provider->ContextGL())); |
| + |
| + lock.set_sync_token(sync_token); |
| + |
| + EXPECT_CALL(*context, RetireTextureId(kWorkerTextureId)); |
| + context_provider->ContextGL()->DeleteTextures(1, &kWorkerTextureId); |
| + } |
| + |
| + // Wait for worker context sync token before deleting texture. |
| + EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))); |
| + EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)); |
| + EXPECT_CALL(*context, RetireTextureId(kTextureId)); |
| + resource_provider->DeleteResource(id); |
| +} |
| + |
| } // namespace |
| } // namespace cc |