Commit 2b6d4cba authored by reveman's avatar reveman Committed by Commit bot

cc: Move GpuMemoryBuffer allocation to worker threads.

Allocation of GpuMemoryBuffers requires a round-trip to the browser
process and by moving this to worker threads it is no longer on
the critical path on the compositor.

The LockForWrite mechanism in the ResourceProvider has been
adjusted to properly support worker thread allocation of
resources.

BUG=418553

Review URL: https://codereview.chromium.org/645943002

Cr-Commit-Position: refs/heads/master@{#301433}
parent 7b08e286
...@@ -55,7 +55,7 @@ class RasterBufferImpl : public RasterBuffer { ...@@ -55,7 +55,7 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& rect, const gfx::Rect& rect,
float scale, float scale,
RenderingStatsInstrumentation* stats) override { RenderingStatsInstrumentation* stats) override {
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_->gpu_memory_buffer(); gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_->GetGpuMemoryBuffer();
if (!gpu_memory_buffer) if (!gpu_memory_buffer)
return; return;
......
...@@ -922,11 +922,9 @@ void ResourceProvider::UnlockForRead(ResourceId id) { ...@@ -922,11 +922,9 @@ void ResourceProvider::UnlockForRead(ResourceId id) {
} }
} }
const ResourceProvider::Resource* ResourceProvider::LockForWrite( ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
ResourceId id) {
Resource* resource = GetResource(id); Resource* resource = GetResource(id);
DCHECK(CanLockForWrite(id)); DCHECK(CanLockForWrite(id));
LazyAllocate(resource);
resource->locked_for_write = true; resource->locked_for_write = true;
return resource; return resource;
...@@ -939,74 +937,10 @@ bool ResourceProvider::CanLockForWrite(ResourceId id) { ...@@ -939,74 +937,10 @@ bool ResourceProvider::CanLockForWrite(ResourceId id) {
!resource->lost && ReadLockFenceHasPassed(resource); !resource->lost && ReadLockFenceHasPassed(resource);
} }
void ResourceProvider::UnlockForWrite(ResourceId id) { void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(resource->origin == Resource::Internal);
resource->locked_for_write = false;
}
const ResourceProvider::Resource*
ResourceProvider::LockForWriteToGpuMemoryBuffer(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK_EQ(GLTexture, resource->type);
DCHECK(CanLockForWrite(id));
if (!resource->gpu_memory_buffer) {
scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
resource->size,
ToGpuMemoryBufferFormat(resource->format),
gfx::GpuMemoryBuffer::MAP);
resource->gpu_memory_buffer = gpu_memory_buffer.release();
resource->allocated = true;
}
resource->locked_for_write = true;
return resource;
}
void ResourceProvider::UnlockForWriteToGpuMemoryBuffer(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write);
DCHECK_EQ(resource->exported_count, 0);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(GLTexture, resource->type);
if (!resource->image_id) {
GLES2Interface* gl = ContextGL();
DCHECK(gl);
resource->image_id =
gl->CreateImageCHROMIUM(resource->gpu_memory_buffer->AsClientBuffer(),
resource->size.width(),
resource->size.height(),
GL_RGBA);
}
resource->locked_for_write = false;
resource->dirty_image = true;
// GpuMemoryBuffer provides direct access to the memory used by the GPU.
// Read lock fences are required to ensure that we're not trying to map a
// buffer that is currently in-use by the GPU.
resource->read_lock_fences_enabled = true;
}
void ResourceProvider::LockForWriteToSkSurface(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK_EQ(GLTexture, resource->type);
DCHECK(CanLockForWrite(id));
resource->locked_for_write = true;
}
void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK(resource->locked_for_write); DCHECK(resource->locked_for_write);
DCHECK_EQ(resource->exported_count, 0); DCHECK_EQ(resource->exported_count, 0);
DCHECK(resource->origin == Resource::Internal); DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(GLTexture, resource->type);
resource->locked_for_write = false; resource->locked_for_write = false;
} }
...@@ -1049,13 +983,14 @@ ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( ...@@ -1049,13 +983,14 @@ ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
ResourceProvider* resource_provider, ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id) ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider), : resource_provider_(resource_provider),
resource_id_(resource_id), resource_(resource_provider->LockForWrite(resource_id)) {
texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) { resource_provider_->LazyAllocate(resource_);
texture_id_ = resource_->gl_id;
DCHECK(texture_id_); DCHECK(texture_id_);
} }
ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
resource_provider_->UnlockForWrite(resource_id_); resource_provider_->UnlockForWrite(resource_);
} }
void ResourceProvider::PopulateSkBitmapWithResource( void ResourceProvider::PopulateSkBitmapWithResource(
...@@ -1084,76 +1019,111 @@ ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( ...@@ -1084,76 +1019,111 @@ ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
ResourceProvider* resource_provider, ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id) ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider), : resource_provider_(resource_provider),
resource_id_(resource_id) { resource_(resource_provider->LockForWrite(resource_id)) {
ResourceProvider::PopulateSkBitmapWithResource( ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
&sk_bitmap_, resource_provider->LockForWrite(resource_id));
DCHECK(valid()); DCHECK(valid());
sk_canvas_.reset(new SkCanvas(sk_bitmap_)); sk_canvas_.reset(new SkCanvas(sk_bitmap_));
} }
ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
resource_provider_->UnlockForWrite(resource_id_); resource_provider_->UnlockForWrite(resource_);
} }
ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id) ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider), : resource_provider_(resource_provider),
resource_id_(resource_id), resource_(resource_provider->LockForWrite(resource_id)),
gpu_memory_buffer_( gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
resource_provider->LockForWriteToGpuMemoryBuffer(resource_id) gpu_memory_buffer_(nullptr),
->gpu_memory_buffer) { size_(resource_->size),
format_(resource_->format) {
DCHECK_EQ(GLTexture, resource_->type);
std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
} }
ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
~ScopedWriteLockGpuMemoryBuffer() { ~ScopedWriteLockGpuMemoryBuffer() {
resource_provider_->UnlockForWriteToGpuMemoryBuffer(resource_id_); resource_provider_->UnlockForWrite(resource_);
if (!gpu_memory_buffer_)
return;
if (!resource_->image_id) {
GLES2Interface* gl = resource_provider_->ContextGL();
DCHECK(gl);
resource_->image_id =
gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
size_.width(),
size_.height(),
GL_RGBA);
}
std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_);
resource_->allocated = true;
resource_->dirty_image = true;
// GpuMemoryBuffer provides direct access to the memory used by the GPU.
// Read lock fences are required to ensure that we're not trying to map a
// buffer that is currently in-use by the GPU.
resource_->read_lock_fences_enabled = true;
}
gfx::GpuMemoryBuffer*
ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() {
if (!gpu_memory_buffer_) {
scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP);
gpu_memory_buffer_ = gpu_memory_buffer.release();
}
return gpu_memory_buffer_;
} }
ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr(
ResourceProvider* resource_provider, ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id) ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider), resource_id_(resource_id) { : resource_provider_(resource_provider),
resource_provider->LockForWriteToSkSurface(resource_id); resource_(resource_provider->LockForWrite(resource_id)) {
} }
ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() { ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
resource_provider_->UnlockForWriteToSkSurface(resource_id_); resource_provider_->UnlockForWrite(resource_);
} }
SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface( SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
bool use_distance_field_text) { bool use_distance_field_text) {
Resource* resource = resource_provider_->GetResource(resource_id_); DCHECK(resource_->locked_for_write);
DCHECK(resource->locked_for_write);
// If the surface doesn't exist, or doesn't have the correct dff setting, // If the surface doesn't exist, or doesn't have the correct dff setting,
// recreate the surface within the resource. // recreate the surface within the resource.
if (!resource->sk_surface || if (!resource_->sk_surface ||
use_distance_field_text != use_distance_field_text !=
resource->sk_surface->props().isUseDistanceFieldFonts()) { resource_->sk_surface->props().isUseDistanceFieldFonts()) {
class GrContext* gr_context = resource_provider_->GrContext(); class GrContext* gr_context = resource_provider_->GrContext();
// TODO(alokp): Implement TestContextProvider::GrContext(). // TODO(alokp): Implement TestContextProvider::GrContext().
if (!gr_context) if (!gr_context)
return nullptr; return nullptr;
resource_provider_->LazyAllocate(resource); resource_provider_->LazyAllocate(resource_);
GrBackendTextureDesc desc; GrBackendTextureDesc desc;
desc.fFlags = kRenderTarget_GrBackendTextureFlag; desc.fFlags = kRenderTarget_GrBackendTextureFlag;
desc.fWidth = resource->size.width(); desc.fWidth = resource_->size.width();
desc.fHeight = resource->size.height(); desc.fHeight = resource_->size.height();
desc.fConfig = ToGrPixelConfig(resource->format); desc.fConfig = ToGrPixelConfig(resource_->format);
desc.fOrigin = kTopLeft_GrSurfaceOrigin; desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fTextureHandle = resource->gl_id; desc.fTextureHandle = resource_->gl_id;
skia::RefPtr<GrTexture> gr_texture = skia::RefPtr<GrTexture> gr_texture =
skia::AdoptRef(gr_context->wrapBackendTexture(desc)); skia::AdoptRef(gr_context->wrapBackendTexture(desc));
SkSurface::TextRenderMode text_render_mode = SkSurface::TextRenderMode text_render_mode =
use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode
: SkSurface::kStandard_TextRenderMode; : SkSurface::kStandard_TextRenderMode;
resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( resource_->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
gr_texture->asRenderTarget(), text_render_mode)); gr_texture->asRenderTarget(), text_render_mode));
} }
return resource->sk_surface.get(); return resource_->sk_surface.get();
} }
ResourceProvider::ResourceProvider( ResourceProvider::ResourceProvider(
...@@ -1907,7 +1877,7 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) { ...@@ -1907,7 +1877,7 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
} }
resource->pending_set_pixels = false; resource->pending_set_pixels = false;
UnlockForWrite(id); UnlockForWrite(resource);
// Async set pixels commands are not necessarily processed in-sequence with // Async set pixels commands are not necessarily processed in-sequence with
// drawing commands. Read lock fences are required to ensure that async // drawing commands. Read lock fences are required to ensure that async
......
...@@ -58,6 +58,9 @@ class TextureUploader; ...@@ -58,6 +58,9 @@ class TextureUploader;
// This class is not thread-safe and can only be called from the thread it was // This class is not thread-safe and can only be called from the thread it was
// created on (in practice, the impl thread). // created on (in practice, the impl thread).
class CC_EXPORT ResourceProvider { class CC_EXPORT ResourceProvider {
private:
struct Resource;
public: public:
typedef unsigned ResourceId; typedef unsigned ResourceId;
typedef std::vector<ResourceId> ResourceIdArray; typedef std::vector<ResourceId> ResourceIdArray;
...@@ -258,7 +261,7 @@ class CC_EXPORT ResourceProvider { ...@@ -258,7 +261,7 @@ class CC_EXPORT ResourceProvider {
private: private:
ResourceProvider* resource_provider_; ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_; ResourceProvider::Resource* resource_;
unsigned texture_id_; unsigned texture_id_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL); DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
...@@ -298,7 +301,7 @@ class CC_EXPORT ResourceProvider { ...@@ -298,7 +301,7 @@ class CC_EXPORT ResourceProvider {
private: private:
ResourceProvider* resource_provider_; ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_; ResourceProvider::Resource* resource_;
SkBitmap sk_bitmap_; SkBitmap sk_bitmap_;
scoped_ptr<SkCanvas> sk_canvas_; scoped_ptr<SkCanvas> sk_canvas_;
...@@ -311,12 +314,15 @@ class CC_EXPORT ResourceProvider { ...@@ -311,12 +314,15 @@ class CC_EXPORT ResourceProvider {
ResourceProvider::ResourceId resource_id); ResourceProvider::ResourceId resource_id);
~ScopedWriteLockGpuMemoryBuffer(); ~ScopedWriteLockGpuMemoryBuffer();
gfx::GpuMemoryBuffer* gpu_memory_buffer() { return gpu_memory_buffer_; } gfx::GpuMemoryBuffer* GetGpuMemoryBuffer();
private: private:
ResourceProvider* resource_provider_; ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_; ResourceProvider::Resource* resource_;
GpuMemoryBufferManager* gpu_memory_buffer_manager_;
gfx::GpuMemoryBuffer* gpu_memory_buffer_; gfx::GpuMemoryBuffer* gpu_memory_buffer_;
gfx::Size size_;
ResourceFormat format_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer); DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer);
}; };
...@@ -331,7 +337,7 @@ class CC_EXPORT ResourceProvider { ...@@ -331,7 +337,7 @@ class CC_EXPORT ResourceProvider {
private: private:
ResourceProvider* resource_provider_; ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_; ResourceProvider::Resource* resource_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr); DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr);
}; };
...@@ -493,12 +499,8 @@ class CC_EXPORT ResourceProvider { ...@@ -493,12 +499,8 @@ class CC_EXPORT ResourceProvider {
Resource* GetResource(ResourceId id); Resource* GetResource(ResourceId id);
const Resource* LockForRead(ResourceId id); const Resource* LockForRead(ResourceId id);
void UnlockForRead(ResourceId id); void UnlockForRead(ResourceId id);
const Resource* LockForWrite(ResourceId id); Resource* LockForWrite(ResourceId id);
void UnlockForWrite(ResourceId id); void UnlockForWrite(Resource* resource);
const Resource* LockForWriteToGpuMemoryBuffer(ResourceId id);
void UnlockForWriteToGpuMemoryBuffer(ResourceId id);
void LockForWriteToSkSurface(ResourceId id);
void UnlockForWriteToSkSurface(ResourceId id);
static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap, static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
const Resource* resource); const Resource* resource);
......
...@@ -637,7 +637,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) { ...@@ -637,7 +637,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
{ {
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
child_resource_provider_.get(), id3); child_resource_provider_.get(), id3);
EXPECT_TRUE(!!lock.gpu_memory_buffer()); EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
} }
GLuint external_texture_id = child_context_->createExternalTexture(); GLuint external_texture_id = child_context_->createExternalTexture();
...@@ -3318,7 +3318,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { ...@@ -3318,7 +3318,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
{ {
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), id); resource_provider.get(), id);
EXPECT_TRUE(!!lock.gpu_memory_buffer()); EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
} }
EXPECT_CALL(*context, NextTextureId()) EXPECT_CALL(*context, NextTextureId())
...@@ -3339,7 +3339,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) { ...@@ -3339,7 +3339,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
{ {
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), id); resource_provider.get(), id);
EXPECT_TRUE(!!lock.gpu_memory_buffer()); EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
} }
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1) EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
...@@ -3405,7 +3405,7 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) { ...@@ -3405,7 +3405,7 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
{ {
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock( ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), source_id); resource_provider.get(), source_id);
EXPECT_TRUE(!!lock.gpu_memory_buffer()); EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
} }
Mock::VerifyAndClearExpectations(context); Mock::VerifyAndClearExpectations(context);
......
...@@ -28,7 +28,7 @@ class RasterBufferImpl : public RasterBuffer { ...@@ -28,7 +28,7 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& rect, const gfx::Rect& rect,
float scale, float scale,
RenderingStatsInstrumentation* stats) override { RenderingStatsInstrumentation* stats) override {
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.gpu_memory_buffer(); gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.GetGpuMemoryBuffer();
if (!gpu_memory_buffer) if (!gpu_memory_buffer)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment