diff options
Diffstat (limited to 'cc/resources')
-rw-r--r-- | cc/resources/resource_format.cc | 19 | ||||
-rw-r--r-- | cc/resources/resource_format.h | 2 | ||||
-rw-r--r-- | cc/resources/resource_pool.cc | 5 | ||||
-rw-r--r-- | cc/resources/resource_pool.h | 5 | ||||
-rw-r--r-- | cc/resources/resource_pool_unittest.cc | 13 | ||||
-rw-r--r-- | cc/resources/resource_provider.cc | 156 | ||||
-rw-r--r-- | cc/resources/resource_provider.h | 18 | ||||
-rw-r--r-- | cc/resources/resource_provider_unittest.cc | 134 |
8 files changed, 293 insertions, 59 deletions
diff --git a/cc/resources/resource_format.cc b/cc/resources/resource_format.cc index c62ae93..ce9fe7d 100644 --- a/cc/resources/resource_format.cc +++ b/cc/resources/resource_format.cc @@ -87,23 +87,4 @@ GLenum GLInternalFormat(ResourceFormat format) { return GLDataFormat(format); } -gfx::BufferFormat BufferFormat(ResourceFormat format) { - switch (format) { - case RGBA_8888: - return gfx::BufferFormat::RGBA_8888; - case BGRA_8888: - return gfx::BufferFormat::BGRA_8888; - case RGBA_4444: - return gfx::BufferFormat::RGBA_4444; - case ALPHA_8: - case LUMINANCE_8: - case RGB_565: - case ETC1: - case RED_8: - break; - } - NOTREACHED(); - return gfx::BufferFormat::RGBA_8888; -} - } // namespace cc diff --git a/cc/resources/resource_format.h b/cc/resources/resource_format.h index 79b815f..d910bb0 100644 --- a/cc/resources/resource_format.h +++ b/cc/resources/resource_format.h @@ -8,7 +8,6 @@ #include "base/logging.h" #include "cc/base/cc_export.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/gfx/gpu_memory_buffer.h" // TODO(prashant.n): Including third_party/khronos/GLES2/gl2.h causes // redefinition errors as macros/functions defined in it conflict with @@ -36,7 +35,6 @@ CC_EXPORT int BitsPerPixel(ResourceFormat format); CC_EXPORT GLenum GLDataType(ResourceFormat format); CC_EXPORT GLenum GLDataFormat(ResourceFormat format); CC_EXPORT GLenum GLInternalFormat(ResourceFormat format); -CC_EXPORT gfx::BufferFormat BufferFormat(ResourceFormat format); } // namespace cc diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index e0e5af3..cdcaa4d 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc @@ -191,12 +191,15 @@ void ResourcePool::DeleteResource(ScopedResource* resource) { delete resource; } -void ResourcePool::CheckBusyResources() { +void ResourcePool::CheckBusyResources(bool wait_if_needed) { ResourceList::iterator it = busy_resources_.begin(); while (it != busy_resources_.end()) { ScopedResource* resource = it->resource; + if (wait_if_needed) + resource_provider_->WaitReadLockIfNeeded(resource->id()); + if (resource_provider_->CanLockForWrite(resource->id())) { DidFinishUsingResource(resource, it->content_id); it = busy_resources_.erase(it); diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index e87e217..e577826 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h @@ -41,7 +41,10 @@ class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider { size_t max_resource_count); void ReduceResourceUsage(); - void CheckBusyResources(); + // This might block if |wait_if_needed| is true and one of the currently + // busy resources has a read lock fence that needs to be waited upon before + // it can be locked for write again. + void CheckBusyResources(bool wait_if_needed); size_t total_memory_usage_bytes() const { return memory_usage_bytes_; } size_t acquired_memory_usage_bytes() const { diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc index f280f49..035b19e 100644 --- a/cc/resources/resource_pool_unittest.cc +++ b/cc/resources/resource_pool_unittest.cc @@ -71,7 +71,8 @@ TEST_F(ResourcePoolTest, AccountingSingleResource) { EXPECT_EQ(1u, resource_pool_->total_resource_count()); EXPECT_EQ(1u, resource_pool_->busy_resource_count()); - resource_pool_->CheckBusyResources(); + bool wait_if_needed = false; + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(resource_bytes, resource_pool_->total_memory_usage_bytes()); EXPECT_EQ(0u, resource_pool_->acquired_memory_usage_bytes()); EXPECT_EQ(1u, resource_pool_->total_resource_count()); @@ -95,25 +96,26 @@ TEST_F(ResourcePoolTest, SimpleResourceReuse) { gfx::Size size(100, 100); ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; scoped_ptr<ScopedResource> resource = resource_pool_->AcquireResource(size, format); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(1u, resource_provider_->num_resources()); // Same size/format should re-use resource. resource = resource_pool_->AcquireResource(size, format); EXPECT_EQ(1u, resource_provider_->num_resources()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(1u, resource_provider_->num_resources()); // Different size/format should alloate new resource. resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8); EXPECT_EQ(2u, resource_provider_->num_resources()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(2u, resource_provider_->num_resources()); } @@ -125,6 +127,7 @@ TEST_F(ResourcePoolTest, LostResource) { gfx::Size size(100, 100); ResourceFormat format = RGBA_8888; + bool wait_if_needed = false; scoped_ptr<ScopedResource> resource = resource_pool_->AcquireResource(size, format); @@ -132,7 +135,7 @@ TEST_F(ResourcePoolTest, LostResource) { resource_provider_->LoseResourceForTesting(resource->id()); resource_pool_->ReleaseResource(resource.Pass(), 0u); - resource_pool_->CheckBusyResources(); + resource_pool_->CheckBusyResources(wait_if_needed); EXPECT_EQ(0u, resource_provider_->num_resources()); } diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 6129b26..be282b9 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc @@ -33,6 +33,7 @@ #include "third_party/skia/include/gpu/GrTextureProvider.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/trace_util.h" using gpu::gles2::GLES2Interface; @@ -117,6 +118,25 @@ GrPixelConfig ToGrPixelConfig(ResourceFormat format) { return kSkia8888_GrPixelConfig; } +gfx::BufferFormat ToGpuMemoryBufferFormat(ResourceFormat format) { + switch (format) { + case RGBA_8888: + return gfx::BufferFormat::RGBA_8888; + case BGRA_8888: + return gfx::BufferFormat::BGRA_8888; + case RGBA_4444: + return gfx::BufferFormat::RGBA_4444; + case ALPHA_8: + case LUMINANCE_8: + case RGB_565: + case ETC1: + case RED_8: + break; + } + NOTREACHED(); + return gfx::BufferFormat::RGBA_8888; +} + class ScopedSetActiveTexture { public: ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit) @@ -187,6 +207,46 @@ class BufferIdAllocator : public IdAllocator { DISALLOW_COPY_AND_ASSIGN(BufferIdAllocator); }; +// Query object based fence implementation used to detect completion of copy +// texture operations. Fence has passed when query result is available. +class CopyTextureFence : public ResourceProvider::Fence { + public: + CopyTextureFence(gpu::gles2::GLES2Interface* gl, unsigned query_id) + : gl_(gl), query_id_(query_id) {} + + // Overridden from ResourceProvider::Fence: + void Set() override {} + bool HasPassed() override { + unsigned available = 1; + gl_->GetQueryObjectuivEXT( + query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); + if (!available) + return false; + + ProcessResult(); + return true; + } + void Wait() override { + // ProcessResult() will wait for result to become available. + ProcessResult(); + } + + private: + ~CopyTextureFence() override {} + + void ProcessResult() { + unsigned time_elapsed_us = 0; + gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &time_elapsed_us); + UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.CopyTextureLatency", time_elapsed_us, + 0, 256000, 50); + } + + gpu::gles2::GLES2Interface* gl_; + unsigned query_id_; + + DISALLOW_COPY_AND_ASSIGN(CopyTextureFence); +}; + // Generates process-unique IDs to use for tracing a ResourceProvider's // resources. base::StaticAtomicSequenceNumber g_next_resource_provider_tracing_id; @@ -342,12 +402,13 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create( int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector<unsigned>& use_image_texture_targets) { scoped_ptr<ResourceProvider> resource_provider(new ResourceProvider( output_surface, shared_bitmap_manager, gpu_memory_buffer_manager, blocking_main_thread_task_runner, highp_threshold_min, use_rgba_4444_texture_format, id_allocation_chunk_size, - use_image_texture_targets)); + use_persistent_map_for_gpu_memory_buffers, use_image_texture_targets)); resource_provider->Initialize(); return resource_provider; } @@ -938,9 +999,13 @@ gfx::GpuMemoryBuffer* ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { if (gpu_memory_buffer_) return gpu_memory_buffer_; + gfx::BufferUsage usage = + resource_provider_->use_persistent_map_for_gpu_memory_buffers() + ? gfx::BufferUsage::PERSISTENT_MAP + : gfx::BufferUsage::MAP; scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( - size_, BufferFormat(format_), gfx::BufferUsage::MAP); + size_, ToGpuMemoryBufferFormat(format_), usage); gpu_memory_buffer_ = gpu_memory_buffer.release(); return gpu_memory_buffer_; } @@ -1032,6 +1097,7 @@ ResourceProvider::ResourceProvider( int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector<unsigned>& use_image_texture_targets) : output_surface_(output_surface), shared_bitmap_manager_(shared_bitmap_manager), @@ -1053,6 +1119,8 @@ ResourceProvider::ResourceProvider( use_rgba_4444_texture_format_(use_rgba_4444_texture_format), id_allocation_chunk_size_(id_allocation_chunk_size), use_sync_query_(false), + use_persistent_map_for_gpu_memory_buffers_( + use_persistent_map_for_gpu_memory_buffers), use_image_texture_targets_(use_image_texture_targets), tracing_id_(g_next_resource_provider_tracing_id.GetNext()) { DCHECK(output_surface_->HasClient()); @@ -1788,6 +1856,79 @@ void ResourceProvider::BindImageForSampling(Resource* resource) { resource->dirty_image = false; } +void ResourceProvider::CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect) { + TRACE_EVENT0("cc", "ResourceProvider::CopyResource"); + + Resource* source_resource = GetResource(source_id); + DCHECK(!source_resource->lock_for_read_count); + DCHECK(source_resource->origin == Resource::INTERNAL); + DCHECK_EQ(source_resource->exported_count, 0); + DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, source_resource->type); + LazyAllocate(source_resource); + + Resource* dest_resource = GetResource(dest_id); + DCHECK(!dest_resource->locked_for_write); + DCHECK(!dest_resource->lock_for_read_count); + DCHECK(dest_resource->origin == Resource::INTERNAL); + DCHECK_EQ(dest_resource->exported_count, 0); + DCHECK_EQ(RESOURCE_TYPE_GL_TEXTURE, dest_resource->type); + LazyAllocate(dest_resource); + + DCHECK_EQ(source_resource->type, dest_resource->type); + DCHECK_EQ(source_resource->format, dest_resource->format); + DCHECK(source_resource->size == dest_resource->size); + DCHECK(gfx::Rect(dest_resource->size).Contains(rect)); + + GLES2Interface* gl = ContextGL(); + DCHECK(gl); + if (source_resource->image_id && source_resource->dirty_image) { + gl->BindTexture(source_resource->target, source_resource->gl_id); + BindImageForSampling(source_resource); + } + if (use_sync_query_) { + if (!source_resource->gl_read_lock_query_id) + gl->GenQueriesEXT(1, &source_resource->gl_read_lock_query_id); +#if defined(OS_CHROMEOS) + // TODO(reveman): This avoids a performance problem on some ChromeOS + // devices. This needs to be removed to support native GpuMemoryBuffer + // implementations. crbug.com/436314 + gl->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, + source_resource->gl_read_lock_query_id); +#else + gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, + source_resource->gl_read_lock_query_id); +#endif + } + DCHECK(!dest_resource->image_id); + dest_resource->allocated = true; + gl->CopySubTextureCHROMIUM(dest_resource->target, source_resource->gl_id, + dest_resource->gl_id, rect.x(), rect.y(), rect.x(), + rect.y(), rect.width(), rect.height(), + false, false, false); + if (source_resource->gl_read_lock_query_id) { + // End query and create a read lock fence that will prevent access to +// source resource until CopySubTextureCHROMIUM command has completed. +#if defined(OS_CHROMEOS) + gl->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); +#else + gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); +#endif + source_resource->read_lock_fence = make_scoped_refptr( + new CopyTextureFence(gl, source_resource->gl_read_lock_query_id)); + } else { + // Create a SynchronousFence when CHROMIUM_sync_query extension is missing. + // Try to use one synchronous fence for as many CopyResource operations as + // possible as that reduce the number of times we have to synchronize with + // the GL. + if (!synchronous_fence_.get() || synchronous_fence_->has_synchronized()) + synchronous_fence_ = make_scoped_refptr(new SynchronousFence(gl)); + source_resource->read_lock_fence = synchronous_fence_; + source_resource->read_lock_fence->Set(); + } +} + void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { Resource* resource = GetResource(id); DCHECK_EQ(resource->exported_count, 0); @@ -1803,6 +1944,15 @@ void ResourceProvider::WaitSyncPointIfNeeded(ResourceId id) { resource->mailbox.set_sync_point(0); } +void ResourceProvider::WaitReadLockIfNeeded(ResourceId id) { + Resource* resource = GetResource(id); + DCHECK_EQ(resource->exported_count, 0); + if (!resource->read_lock_fence.get()) + return; + + resource->read_lock_fence->Wait(); +} + GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) { GLint active_unit = 0; gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit); @@ -1810,7 +1960,7 @@ GLint ResourceProvider::GetActiveTextureUnit(GLES2Interface* gl) { } GLenum ResourceProvider::GetImageTextureTarget(ResourceFormat format) { - gfx::BufferFormat buffer_format = BufferFormat(format); + gfx::BufferFormat buffer_format = ToGpuMemoryBufferFormat(format); DCHECK_GT(use_image_texture_targets_.size(), static_cast<size_t>(buffer_format)); return use_image_texture_targets_[static_cast<size_t>(buffer_format)]; diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 8b7ccd8..324df1b 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h @@ -35,7 +35,6 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/geometry/size.h" -#include "ui/gfx/gpu_memory_buffer.h" class GrContext; @@ -47,6 +46,7 @@ class GLES2Interface; } namespace gfx { +class GpuMemoryBuffer; class Rect; class Vector2d; } @@ -88,6 +88,7 @@ class CC_EXPORT ResourceProvider int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector<unsigned>& use_image_texture_targets); ~ResourceProvider() override; @@ -103,8 +104,8 @@ class CC_EXPORT ResourceProvider } ResourceFormat yuv_resource_format() const { return yuv_resource_format_; } bool use_sync_query() const { return use_sync_query_; } - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() { - return gpu_memory_buffer_manager_; + bool use_persistent_map_for_gpu_memory_buffers() const { + return use_persistent_map_for_gpu_memory_buffers_; } size_t num_resources() const { return resources_.size(); } @@ -426,8 +427,15 @@ class CC_EXPORT ResourceProvider // Indicates if we can currently lock this resource for write. bool CanLockForWrite(ResourceId id); + // Copy |rect| pixels from source to destination. + void CopyResource(ResourceId source_id, + ResourceId dest_id, + const gfx::Rect& rect); + void WaitSyncPointIfNeeded(ResourceId id); + void WaitReadLockIfNeeded(ResourceId id); + static GLint GetActiveTextureUnit(gpu::gles2::GLES2Interface* gl); OutputSurface* output_surface() { return output_surface_; } @@ -450,6 +458,7 @@ class CC_EXPORT ResourceProvider int highp_threshold_min, bool use_rgba_4444_texture_format, size_t id_allocation_chunk_size, + bool use_persistent_map_for_gpu_memory_buffers, const std::vector<unsigned>& use_image_texture_targets); void Initialize(); @@ -605,6 +614,9 @@ class CC_EXPORT ResourceProvider scoped_ptr<IdAllocator> buffer_id_allocator_; bool use_sync_query_; + bool use_persistent_map_for_gpu_memory_buffers_; + // Fence used for CopyResource if CHROMIUM_sync_query is not supported. + scoped_refptr<SynchronousFence> synchronous_fence_; std::vector<unsigned> use_image_texture_targets_; // A process-unique ID used for disambiguating memory dumps from different diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 7c65b73..4a02e82 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc @@ -422,11 +422,11 @@ class ResourceProviderTest resource_provider_ = ResourceProvider::Create( output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_); + false, 1, false, use_image_texture_targets_); child_resource_provider_ = ResourceProvider::Create( child_output_surface_.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_); + false, 1, false, use_image_texture_targets_); } ResourceProviderTest() : ResourceProviderTest(true) {} @@ -1378,7 +1378,7 @@ TEST_P(ResourceProviderTest, TransferGLToSoftware) { scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create( child_output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -1863,7 +1863,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr<ResourceProvider> child_resource_provider( ResourceProvider::Create(child_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); scoped_ptr<TextureStateTrackingContext> parent_context_owned( new TextureStateTrackingContext); @@ -1877,7 +1877,7 @@ class ResourceProviderTestTextureFilters : public ResourceProviderTest { scoped_ptr<ResourceProvider> parent_resource_provider( ResourceProvider::Create(parent_output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); ResourceFormat format = RGBA_8888; @@ -2509,7 +2509,7 @@ TEST_P(ResourceProviderTest, ScopedSampler) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2592,7 +2592,7 @@ TEST_P(ResourceProviderTest, ManagedResource) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2640,7 +2640,7 @@ TEST_P(ResourceProviderTest, TextureWrapMode) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2691,7 +2691,7 @@ TEST_P(ResourceProviderTest, TextureHint) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(1, 1); @@ -2757,7 +2757,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0, - false, 1, use_image_texture_targets_)); + false, 1, false, use_image_texture_targets_)); uint32 release_sync_point = 0; bool lost_resource = false; @@ -2806,7 +2806,8 @@ class ResourceProviderTestTextureMailboxGLFilters scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager, - main_thread_task_runner, 0, false, 1, use_image_texture_targets_)); + main_thread_task_runner, 0, false, 1, false, + use_image_texture_targets_)); unsigned texture_id = 1; uint32 sync_point = 30; @@ -2949,7 +2950,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 30; @@ -3019,7 +3020,7 @@ TEST_P(ResourceProviderTest, scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 30; @@ -3073,7 +3074,7 @@ TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); uint32 sync_point = 0; @@ -3194,7 +3195,7 @@ TEST_P(ResourceProviderTest, TextureAllocation) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3269,7 +3270,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3325,7 +3326,7 @@ TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); gfx::Size size(2, 2); @@ -3380,7 +3381,7 @@ TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3423,7 +3424,7 @@ TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3466,7 +3467,7 @@ TEST_P(ResourceProviderTest, PixelBufferLostContext) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id)); @@ -3507,7 +3508,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); id = resource_provider->CreateResource( @@ -3568,6 +3569,89 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { .RetiresOnSaturation(); } +TEST_P(ResourceProviderTest, CopyResource_GLTexture) { + if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) + return; + scoped_ptr<AllocationTrackingContext3D> context_owned( + new StrictMock<AllocationTrackingContext3D>); + AllocationTrackingContext3D* context = context_owned.get(); + context_owned->set_support_sync_query(true); + + FakeOutputSurfaceClient output_surface_client; + scoped_ptr<OutputSurface> output_surface( + FakeOutputSurface::Create3d(context_owned.Pass())); + ASSERT_TRUE(output_surface->BindToClient(&output_surface_client)); + + const int kWidth = 2; + const int kHeight = 2; + gfx::Size size(kWidth, kHeight); + ResourceFormat format = RGBA_8888; + ResourceId source_id = 0; + ResourceId dest_id = 0; + const unsigned kSourceTextureId = 123u; + const unsigned kDestTextureId = 321u; + const unsigned kImageId = 234u; + + scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( + output_surface.get(), shared_bitmap_manager_.get(), + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, + std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1, + GL_TEXTURE_2D))); + + source_id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kSourceTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA)) + .WillOnce(Return(kImageId)) + .RetiresOnSaturation(); + { + ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( + resource_provider.get(), source_id); + EXPECT_TRUE(lock.GetGpuMemoryBuffer()); + } + Mock::VerifyAndClearExpectations(context); + + dest_id = resource_provider->CreateResource( + size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format); + + EXPECT_CALL(*context, NextTextureId()) + .WillOnce(Return(kDestTextureId)) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId)) + .Times(2) + .RetiresOnSaturation(); + EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId)) + .Times(1) + .RetiresOnSaturation(); + resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size)); + Mock::VerifyAndClearExpectations(context); + + EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, RetireTextureId(kSourceTextureId)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*context, RetireTextureId(kDestTextureId)) + .Times(1) + .RetiresOnSaturation(); + resource_provider->DeleteResource(source_id); + resource_provider->DeleteResource(dest_id); +} + TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) return; @@ -3585,7 +3669,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) { gfx::Size size(4, 4); scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); int texture_id = 123; @@ -3617,7 +3701,7 @@ TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) { gfx::Size size(4, 4); scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager_.get(), - gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, + gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false, use_image_texture_targets_)); int texture_id = 123; uint8_t pixels[8]; @@ -3674,7 +3758,7 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { size_t kTextureAllocationChunkSize = 1; scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - kTextureAllocationChunkSize, + kTextureAllocationChunkSize, false, ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource( @@ -3691,7 +3775,7 @@ TEST(ResourceProviderTest, TextureAllocationChunkSize) { size_t kTextureAllocationChunkSize = 8; scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create( output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false, - kTextureAllocationChunkSize, + kTextureAllocationChunkSize, false, ResourceProviderTest::use_image_texture_targets())); ResourceId id = resource_provider->CreateResource( |