Commit 5128ada4 authored by danakj@chromium.org's avatar danakj@chromium.org

cc: Allow copy requests to provide a texture.

When many readbacks will be occuring in a row, we don't want to have
texture create/delete calls constantly churning through GPU memory.
In particular, this has been a severe performance bottleneck on some
intel drivers.

Instead provide a way for the copy request client to provide a texture
to the compositor that it will use, and then the texture can be reused
for as long as the client wishes.

In the case of tab capture, the client (in RenderWidgetHostViewAura)
wants to use the GLHelper to act on the given texture. Since the
GLHelper lives on the main thread, and the compositor draws on the
compositor thread, we provide the texture from the client through
the main thread CopyOutputRequest API rather than hooking directly
into the compositor thread.

I moved the async readback unit tests out to their own file as
there are now quite a few.

Tests:
LayerTreeHostCopyRequestTestCreatesTexture
LayerTreeHostCopyRequestTestProvideTexture

R=piman@chromium.org
BUG=312497

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238324 0039d316-1c4b-4281-b951-d872f2087c98
parent 69895387
...@@ -89,9 +89,10 @@ ...@@ -89,9 +89,10 @@
'trees/layer_tree_host_pixeltest_masks.cc', 'trees/layer_tree_host_pixeltest_masks.cc',
'trees/layer_tree_host_pixeltest_on_demand_raster.cc', 'trees/layer_tree_host_pixeltest_on_demand_raster.cc',
'trees/layer_tree_host_pixeltest_readback.cc', 'trees/layer_tree_host_pixeltest_readback.cc',
'trees/layer_tree_host_unittest_animation.cc',
'trees/layer_tree_host_unittest.cc', 'trees/layer_tree_host_unittest.cc',
'trees/layer_tree_host_unittest_animation.cc',
'trees/layer_tree_host_unittest_context.cc', 'trees/layer_tree_host_unittest_context.cc',
'trees/layer_tree_host_unittest_copyrequest.cc',
'trees/layer_tree_host_unittest_damage.cc', 'trees/layer_tree_host_unittest_damage.cc',
'trees/layer_tree_host_unittest_delegated.cc', 'trees/layer_tree_host_unittest_delegated.cc',
'trees/layer_tree_host_unittest_occlusion.cc', 'trees/layer_tree_host_unittest_occlusion.cc',
......
...@@ -14,6 +14,19 @@ ...@@ -14,6 +14,19 @@
namespace cc { namespace cc {
// static
scoped_ptr<CopyOutputRequest> CopyOutputRequest::CreateRelayRequest(
const CopyOutputRequest& original_request,
const CopyOutputRequestCallback& result_callback) {
scoped_ptr<CopyOutputRequest> relay = CreateRequest(result_callback);
relay->force_bitmap_result_ = original_request.force_bitmap_result_;
relay->has_area_ = original_request.has_area_;
relay->area_ = original_request.area_;
relay->has_texture_mailbox_ = original_request.has_texture_mailbox_;
relay->texture_mailbox_ = original_request.texture_mailbox_;
return relay.Pass();
}
CopyOutputRequest::CopyOutputRequest() {} CopyOutputRequest::CopyOutputRequest() {}
CopyOutputRequest::CopyOutputRequest( CopyOutputRequest::CopyOutputRequest(
...@@ -21,8 +34,8 @@ CopyOutputRequest::CopyOutputRequest( ...@@ -21,8 +34,8 @@ CopyOutputRequest::CopyOutputRequest(
const CopyOutputRequestCallback& result_callback) const CopyOutputRequestCallback& result_callback)
: force_bitmap_result_(force_bitmap_result), : force_bitmap_result_(force_bitmap_result),
has_area_(false), has_area_(false),
result_callback_(result_callback) { has_texture_mailbox_(false),
} result_callback_(result_callback) {}
CopyOutputRequest::~CopyOutputRequest() { CopyOutputRequest::~CopyOutputRequest() {
if (!result_callback_.is_null()) if (!result_callback_.is_null())
...@@ -50,4 +63,12 @@ void CopyOutputRequest::SendTextureResult( ...@@ -50,4 +63,12 @@ void CopyOutputRequest::SendTextureResult(
size, texture_mailbox, release_callback.Pass())); size, texture_mailbox, release_callback.Pass()));
} }
void CopyOutputRequest::SetTextureMailbox(
const TextureMailbox& texture_mailbox) {
DCHECK(!force_bitmap_result_);
DCHECK(texture_mailbox.IsTexture());
has_texture_mailbox_ = true;
texture_mailbox_ = texture_mailbox;
}
} // namespace cc } // namespace cc
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h" #include "cc/base/cc_export.h"
#include "cc/resources/texture_mailbox.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
class SkBitmap; class SkBitmap;
...@@ -15,7 +16,6 @@ class SkBitmap; ...@@ -15,7 +16,6 @@ class SkBitmap;
namespace cc { namespace cc {
class CopyOutputResult; class CopyOutputResult;
class SingleReleaseCallback; class SingleReleaseCallback;
class TextureMailbox;
class CC_EXPORT CopyOutputRequest { class CC_EXPORT CopyOutputRequest {
public: public:
...@@ -35,13 +35,7 @@ class CC_EXPORT CopyOutputRequest { ...@@ -35,13 +35,7 @@ class CC_EXPORT CopyOutputRequest {
} }
static scoped_ptr<CopyOutputRequest> CreateRelayRequest( static scoped_ptr<CopyOutputRequest> CreateRelayRequest(
const CopyOutputRequest& original_request, const CopyOutputRequest& original_request,
const CopyOutputRequestCallback& result_callback) { const CopyOutputRequestCallback& result_callback);
scoped_ptr<CopyOutputRequest> relay = CreateRequest(result_callback);
relay->force_bitmap_result_ = original_request.force_bitmap_result_;
relay->has_area_ = original_request.has_area_;
relay->area_ = original_request.area_;
return relay.Pass();
}
~CopyOutputRequest(); ~CopyOutputRequest();
...@@ -59,6 +53,13 @@ class CC_EXPORT CopyOutputRequest { ...@@ -59,6 +53,13 @@ class CC_EXPORT CopyOutputRequest {
bool has_area() const { return has_area_; } bool has_area() const { return has_area_; }
gfx::Rect area() const { return area_; } gfx::Rect area() const { return area_; }
// By default copy requests create a new TextureMailbox to return contents
// in. This allows a client to provide a TextureMailbox, and the compositor
// will place the result inside the TextureMailbox.
void SetTextureMailbox(const TextureMailbox& texture_mailbox);
bool has_texture_mailbox() const { return has_texture_mailbox_; }
const TextureMailbox& texture_mailbox() const { return texture_mailbox_; }
void SendEmptyResult(); void SendEmptyResult();
void SendBitmapResult(scoped_ptr<SkBitmap> bitmap); void SendBitmapResult(scoped_ptr<SkBitmap> bitmap);
void SendTextureResult(gfx::Size size, void SendTextureResult(gfx::Size size,
...@@ -69,12 +70,14 @@ class CC_EXPORT CopyOutputRequest { ...@@ -69,12 +70,14 @@ class CC_EXPORT CopyOutputRequest {
private: private:
CopyOutputRequest(); CopyOutputRequest();
explicit CopyOutputRequest(bool force_bitmap_result, CopyOutputRequest(bool force_bitmap_result,
const CopyOutputRequestCallback& result_callback); const CopyOutputRequestCallback& result_callback);
bool force_bitmap_result_; bool force_bitmap_result_;
bool has_area_; bool has_area_;
bool has_texture_mailbox_;
gfx::Rect area_; gfx::Rect area_;
TextureMailbox texture_mailbox_;
CopyOutputRequestCallback result_callback_; CopyOutputRequestCallback result_callback_;
}; };
......
...@@ -2338,36 +2338,62 @@ void GLRenderer::GetFramebufferPixelsAsync( ...@@ -2338,36 +2338,62 @@ void GLRenderer::GetFramebufferPixelsAsync(
gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect); gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect);
if (!request->force_bitmap_result()) { if (!request->force_bitmap_result()) {
bool own_mailbox = !request->has_texture_mailbox();
unsigned int texture_id = context_->createTexture(); unsigned int texture_id = context_->createTexture();
GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
GLC(context_, context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLC(context_, context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLC(context_, context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLC(context_, context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GetFramebufferTexture(texture_id, RGBA_8888, window_rect);
gpu::Mailbox mailbox; gpu::Mailbox mailbox;
unsigned sync_point = 0; if (own_mailbox) {
GLC(context_, context_->genMailboxCHROMIUM(mailbox.name)); GLC(context_, context_->genMailboxCHROMIUM(mailbox.name));
if (mailbox.IsZero()) { if (mailbox.IsZero()) {
context_->deleteTexture(texture_id); context_->deleteTexture(texture_id);
request->SendEmptyResult(); request->SendEmptyResult();
return; return;
}
} else {
mailbox = request->texture_mailbox().name();
DCHECK_EQ(static_cast<unsigned>(GL_TEXTURE_2D),
request->texture_mailbox().target());
DCHECK(!mailbox.IsZero());
unsigned incoming_sync_point = request->texture_mailbox().sync_point();
if (incoming_sync_point)
GLC(context_, context_->waitSyncPoint(incoming_sync_point));
} }
GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id)); GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
GLC(context_, context_->produceTextureCHROMIUM( if (own_mailbox) {
GL_TEXTURE_2D, mailbox.name)); GLC(context_,
context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLC(context_,
context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLC(context_,
context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLC(context_,
context_->texParameteri(
GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GLC(context_,
context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
} else {
GLC(context_,
context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
}
GetFramebufferTexture(texture_id, RGBA_8888, window_rect);
GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0)); GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
sync_point = context_->insertSyncPoint();
unsigned sync_point = context_->insertSyncPoint();
TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point); TextureMailbox texture_mailbox(mailbox, GL_TEXTURE_2D, sync_point);
scoped_ptr<SingleReleaseCallback> release_callback =
texture_mailbox_deleter_->GetReleaseCallback( scoped_ptr<SingleReleaseCallback> release_callback;
output_surface_->context_provider(), texture_id); if (own_mailbox) {
release_callback = texture_mailbox_deleter_->GetReleaseCallback(
output_surface_->context_provider(), texture_id);
} else {
context_->deleteTexture(texture_id);
}
request->SendTextureResult(window_rect.size(), request->SendTextureResult(window_rect.size(),
texture_mailbox, texture_mailbox,
release_callback.Pass()); release_callback.Pass());
......
...@@ -79,6 +79,8 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D() ...@@ -79,6 +79,8 @@ TestWebGraphicsContext3D::TestWebGraphicsContext3D()
scale_factor_(-1.f), scale_factor_(-1.f),
test_support_(NULL), test_support_(NULL),
last_update_type_(NoUpdate), last_update_type_(NoUpdate),
next_insert_sync_point_(1),
last_waited_sync_point_(0),
bound_buffer_(0), bound_buffer_(0),
peak_transfer_buffer_memory_used_bytes_(0), peak_transfer_buffer_memory_used_bytes_(0),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
...@@ -605,6 +607,15 @@ void TestWebGraphicsContext3D::unmapImageCHROMIUM( ...@@ -605,6 +607,15 @@ void TestWebGraphicsContext3D::unmapImageCHROMIUM(
DCHECK_GT(namespace_->images.count(image_id), 0u); DCHECK_GT(namespace_->images.count(image_id), 0u);
} }
unsigned TestWebGraphicsContext3D::insertSyncPoint() {
return next_insert_sync_point_++;
}
void TestWebGraphicsContext3D::waitSyncPoint(unsigned sync_point) {
if (sync_point)
last_waited_sync_point_ = sync_point;
}
size_t TestWebGraphicsContext3D::NumTextures() const { size_t TestWebGraphicsContext3D::NumTextures() const {
base::AutoLock lock(namespace_->lock); base::AutoLock lock(namespace_->lock);
return namespace_->textures.Size(); return namespace_->textures.Size();
......
...@@ -158,6 +158,11 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { ...@@ -158,6 +158,11 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
blink::WGC3Denum access); blink::WGC3Denum access);
virtual void unmapImageCHROMIUM(blink::WGC3Duint image_id); virtual void unmapImageCHROMIUM(blink::WGC3Duint image_id);
virtual unsigned insertSyncPoint() OVERRIDE;
virtual void waitSyncPoint(unsigned sync_point) OVERRIDE;
unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
const ContextProvider::Capabilities& test_capabilities() const { const ContextProvider::Capabilities& test_capabilities() const {
return test_capabilities_; return test_capabilities_;
} }
...@@ -352,6 +357,8 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D { ...@@ -352,6 +357,8 @@ class TestWebGraphicsContext3D : public FakeWebGraphicsContext3D {
TestContextSupport* test_support_; TestContextSupport* test_support_;
gfx::Rect update_rect_; gfx::Rect update_rect_;
UpdateType last_update_type_; UpdateType last_update_type_;
unsigned next_insert_sync_point_;
unsigned last_waited_sync_point_;
unsigned bound_buffer_; unsigned bound_buffer_;
TextureTargets texture_targets_; TextureTargets texture_targets_;
......
This diff is collapsed.
This diff is collapsed.
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