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 {
const gfx::Rect& rect,
float scale,
RenderingStatsInstrumentation* stats) override {
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_->gpu_memory_buffer();
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_->GetGpuMemoryBuffer();
if (!gpu_memory_buffer)
return;
......
......@@ -922,11 +922,9 @@ void ResourceProvider::UnlockForRead(ResourceId id) {
}
}
const ResourceProvider::Resource* ResourceProvider::LockForWrite(
ResourceId id) {
ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK(CanLockForWrite(id));
LazyAllocate(resource);
resource->locked_for_write = true;
return resource;
......@@ -939,77 +937,13 @@ bool ResourceProvider::CanLockForWrite(ResourceId id) {
!resource->lost && ReadLockFenceHasPassed(resource);
}
void ResourceProvider::UnlockForWrite(ResourceId id) {
Resource* resource = GetResource(id);
void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) {
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_EQ(resource->exported_count, 0);
DCHECK(resource->origin == Resource::Internal);
DCHECK_EQ(GLTexture, resource->type);
resource->locked_for_write = false;
}
ResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
......@@ -1049,13 +983,14 @@ ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
resource_id_(resource_id),
texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) {
resource_(resource_provider->LockForWrite(resource_id)) {
resource_provider_->LazyAllocate(resource_);
texture_id_ = resource_->gl_id;
DCHECK(texture_id_);
}
ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() {
resource_provider_->UnlockForWrite(resource_id_);
resource_provider_->UnlockForWrite(resource_);
}
void ResourceProvider::PopulateSkBitmapWithResource(
......@@ -1084,76 +1019,111 @@ ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware(
ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
resource_id_(resource_id) {
ResourceProvider::PopulateSkBitmapWithResource(
&sk_bitmap_, resource_provider->LockForWrite(resource_id));
resource_(resource_provider->LockForWrite(resource_id)) {
ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_);
DCHECK(valid());
sk_canvas_.reset(new SkCanvas(sk_bitmap_));
}
ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() {
resource_provider_->UnlockForWrite(resource_id_);
resource_provider_->UnlockForWrite(resource_);
}
ResourceProvider::ScopedWriteLockGpuMemoryBuffer::
ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider),
resource_id_(resource_id),
gpu_memory_buffer_(
resource_provider->LockForWriteToGpuMemoryBuffer(resource_id)
->gpu_memory_buffer) {
resource_(resource_provider->LockForWrite(resource_id)),
gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_),
gpu_memory_buffer_(nullptr),
size_(resource_->size),
format_(resource_->format) {
DCHECK_EQ(GLTexture, resource_->type);
std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer);
}
ResourceProvider::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* resource_provider,
ResourceProvider::ResourceId resource_id)
: resource_provider_(resource_provider), resource_id_(resource_id) {
resource_provider->LockForWriteToSkSurface(resource_id);
: resource_provider_(resource_provider),
resource_(resource_provider->LockForWrite(resource_id)) {
}
ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() {
resource_provider_->UnlockForWriteToSkSurface(resource_id_);
resource_provider_->UnlockForWrite(resource_);
}
SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface(
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,
// recreate the surface within the resource.
if (!resource->sk_surface ||
if (!resource_->sk_surface ||
use_distance_field_text !=
resource->sk_surface->props().isUseDistanceFieldFonts()) {
resource_->sk_surface->props().isUseDistanceFieldFonts()) {
class GrContext* gr_context = resource_provider_->GrContext();
// TODO(alokp): Implement TestContextProvider::GrContext().
if (!gr_context)
return nullptr;
resource_provider_->LazyAllocate(resource);
resource_provider_->LazyAllocate(resource_);
GrBackendTextureDesc desc;
desc.fFlags = kRenderTarget_GrBackendTextureFlag;
desc.fWidth = resource->size.width();
desc.fHeight = resource->size.height();
desc.fConfig = ToGrPixelConfig(resource->format);
desc.fWidth = resource_->size.width();
desc.fHeight = resource_->size.height();
desc.fConfig = ToGrPixelConfig(resource_->format);
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fTextureHandle = resource->gl_id;
desc.fTextureHandle = resource_->gl_id;
skia::RefPtr<GrTexture> gr_texture =
skia::AdoptRef(gr_context->wrapBackendTexture(desc));
SkSurface::TextRenderMode text_render_mode =
use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode
: SkSurface::kStandard_TextRenderMode;
resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
resource_->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect(
gr_texture->asRenderTarget(), text_render_mode));
}
return resource->sk_surface.get();
return resource_->sk_surface.get();
}
ResourceProvider::ResourceProvider(
......@@ -1907,7 +1877,7 @@ bool ResourceProvider::DidSetPixelsComplete(ResourceId id) {
}
resource->pending_set_pixels = false;
UnlockForWrite(id);
UnlockForWrite(resource);
// Async set pixels commands are not necessarily processed in-sequence with
// drawing commands. Read lock fences are required to ensure that async
......
......@@ -58,6 +58,9 @@ class TextureUploader;
// This class is not thread-safe and can only be called from the thread it was
// created on (in practice, the impl thread).
class CC_EXPORT ResourceProvider {
private:
struct Resource;
public:
typedef unsigned ResourceId;
typedef std::vector<ResourceId> ResourceIdArray;
......@@ -258,7 +261,7 @@ class CC_EXPORT ResourceProvider {
private:
ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_;
ResourceProvider::Resource* resource_;
unsigned texture_id_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGL);
......@@ -298,7 +301,7 @@ class CC_EXPORT ResourceProvider {
private:
ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_;
ResourceProvider::Resource* resource_;
SkBitmap sk_bitmap_;
scoped_ptr<SkCanvas> sk_canvas_;
......@@ -311,12 +314,15 @@ class CC_EXPORT ResourceProvider {
ResourceProvider::ResourceId resource_id);
~ScopedWriteLockGpuMemoryBuffer();
gfx::GpuMemoryBuffer* gpu_memory_buffer() { return gpu_memory_buffer_; }
gfx::GpuMemoryBuffer* GetGpuMemoryBuffer();
private:
ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_;
ResourceProvider::Resource* resource_;
GpuMemoryBufferManager* gpu_memory_buffer_manager_;
gfx::GpuMemoryBuffer* gpu_memory_buffer_;
gfx::Size size_;
ResourceFormat format_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGpuMemoryBuffer);
};
......@@ -331,7 +337,7 @@ class CC_EXPORT ResourceProvider {
private:
ResourceProvider* resource_provider_;
ResourceProvider::ResourceId resource_id_;
ResourceProvider::Resource* resource_;
DISALLOW_COPY_AND_ASSIGN(ScopedWriteLockGr);
};
......@@ -493,12 +499,8 @@ class CC_EXPORT ResourceProvider {
Resource* GetResource(ResourceId id);
const Resource* LockForRead(ResourceId id);
void UnlockForRead(ResourceId id);
const Resource* LockForWrite(ResourceId id);
void UnlockForWrite(ResourceId id);
const Resource* LockForWriteToGpuMemoryBuffer(ResourceId id);
void UnlockForWriteToGpuMemoryBuffer(ResourceId id);
void LockForWriteToSkSurface(ResourceId id);
void UnlockForWriteToSkSurface(ResourceId id);
Resource* LockForWrite(ResourceId id);
void UnlockForWrite(Resource* resource);
static void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
const Resource* resource);
......
......@@ -637,7 +637,7 @@ TEST_P(ResourceProviderTest, TransferGLResources) {
{
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
child_resource_provider_.get(), id3);
EXPECT_TRUE(!!lock.gpu_memory_buffer());
EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
}
GLuint external_texture_id = child_context_->createExternalTexture();
......@@ -3318,7 +3318,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
{
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), id);
EXPECT_TRUE(!!lock.gpu_memory_buffer());
EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
}
EXPECT_CALL(*context, NextTextureId())
......@@ -3339,7 +3339,7 @@ TEST_P(ResourceProviderTest, Image_GLTexture) {
{
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), id);
EXPECT_TRUE(!!lock.gpu_memory_buffer());
EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
}
EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
......@@ -3405,7 +3405,7 @@ TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
{
ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
resource_provider.get(), source_id);
EXPECT_TRUE(!!lock.gpu_memory_buffer());
EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
}
Mock::VerifyAndClearExpectations(context);
......
......@@ -28,7 +28,7 @@ class RasterBufferImpl : public RasterBuffer {
const gfx::Rect& rect,
float scale,
RenderingStatsInstrumentation* stats) override {
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.gpu_memory_buffer();
gfx::GpuMemoryBuffer* gpu_memory_buffer = lock_.GetGpuMemoryBuffer();
if (!gpu_memory_buffer)
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