summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-08 04:38:51 +0000
committerskaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-08 04:38:51 +0000
commit42f40a546f90a81727c05aea44ce299d97d7507b (patch)
tree3004f86f245e15cea8606868cdbdac2d0d1b0ac0
parent165e50b4b57c105da46d662273f1ce4a164b195d (diff)
downloadchromium_src-42f40a546f90a81727c05aea44ce299d97d7507b.zip
chromium_src-42f40a546f90a81727c05aea44ce299d97d7507b.tar.gz
chromium_src-42f40a546f90a81727c05aea44ce299d97d7507b.tar.bz2
[Aura] Added Support for rendering software compositor frames as cc::TextureLayers through cc::TextureMailbox.
BUG=161008 R=piman TBR=jschuh,ben Review URL: https://chromiumcodereview.appspot.com/15001027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205010 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--cc/DEPS1
-rw-r--r--cc/cc.gyp1
-rw-r--r--cc/layers/texture_layer.cc42
-rw-r--r--cc/layers/texture_layer.h1
-rw-r--r--cc/layers/texture_layer_impl.cc5
-rw-r--r--cc/layers/texture_layer_unittest.cc30
-rw-r--r--cc/output/compositor_frame_ack.cc3
-rw-r--r--cc/output/compositor_frame_ack.h3
-rw-r--r--cc/output/software_frame_data.cc4
-rw-r--r--cc/output/software_frame_data.h6
-rw-r--r--cc/output/software_output_device.cc5
-rw-r--r--cc/output/software_output_device.h4
-rw-r--r--cc/output/software_renderer.cc2
-rw-r--r--cc/resources/resource_provider.cc91
-rw-r--r--cc/resources/resource_provider_unittest.cc66
-rw-r--r--cc/resources/texture_mailbox.cc80
-rw-r--r--cc/resources/texture_mailbox.h27
-rw-r--r--content/browser/android/in_process/synchronous_compositor_output_surface.cc7
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc2
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc128
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h11
-rw-r--r--content/common/cc_messages.cc6
-rw-r--r--content/common/cc_messages.h3
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h1
-rw-r--r--content/common/gpu/gpu_messages.h1
-rw-r--r--content/common/gpu/image_transport_surface.h1
-rw-r--r--content/renderer/gpu/compositor_software_output_device.cc197
-rw-r--r--content/renderer/gpu/compositor_software_output_device.h61
-rw-r--r--gpu/command_buffer/common/mailbox.cc4
-rw-r--r--gpu/command_buffer/common/mailbox.h1
-rw-r--r--ui/aura/aura.gyp2
-rw-r--r--ui/aura/window.cc36
-rw-r--r--ui/aura/window.h3
-rw-r--r--ui/compositor/layer.cc48
-rw-r--r--ui/compositor/layer.h12
35 files changed, 612 insertions, 283 deletions
diff --git a/cc/DEPS b/cc/DEPS
index 26a233d..f55495f 100644
--- a/cc/DEPS
+++ b/cc/DEPS
@@ -9,7 +9,6 @@ include_rules = [
"+ui/base",
"+ui/gfx",
"+ui/gl",
- "+ui/surface",
# DO NOT ADD ANY NEW WEBKIT HEADERS TO THIS LIST.
# TODO(danakj): Drop dependencies on WebKit Platform API from cc.
"+third_party/WebKit/public/platform/WebAnimationDelegate.h",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 2425fd2..d08ade1 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -363,7 +363,6 @@
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/media/media.gyp:media',
'<(DEPTH)/ui/gl/gl.gyp:gl',
- '<(DEPTH)/ui/surface/surface.gyp:surface',
'<(DEPTH)/ui/ui.gyp:ui',
'<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
],
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
index 4266718..d099631 100644
--- a/cc/layers/texture_layer.cc
+++ b/cc/layers/texture_layer.cc
@@ -12,24 +12,28 @@
namespace cc {
-static void RunCallbackOnMainThread(
+namespace {
+
+void RunCallback(
const TextureMailbox::ReleaseCallback& callback,
unsigned sync_point,
bool lost_resource) {
callback.Run(sync_point, lost_resource);
}
-static void PostCallbackToMainThread(
- Thread* main_thread,
+void PostCallbackToThread(
+ Thread* thread,
const TextureMailbox::ReleaseCallback& callback,
unsigned sync_point,
bool lost_resource) {
- main_thread->PostTask(base::Bind(&RunCallbackOnMainThread,
- callback,
- sync_point,
- lost_resource));
+ if (!callback.is_null()) {
+ thread->PostTask(base::Bind(&RunCallback, callback,
+ sync_point, lost_resource));
+ }
}
+} // namespace
+
scoped_refptr<TextureLayer> TextureLayer::Create(TextureLayerClient* client) {
return scoped_refptr<TextureLayer>(new TextureLayer(client, false));
}
@@ -143,13 +147,13 @@ void TextureLayer::SetTextureId(unsigned id) {
void TextureLayer::SetTextureMailbox(const TextureMailbox& mailbox) {
DCHECK(uses_mailbox_);
- DCHECK(mailbox.IsEmpty() || !mailbox.Equals(texture_mailbox_));
+ if (own_mailbox_)
+ DCHECK(!mailbox.IsValid() || !mailbox.Equals(texture_mailbox_));
// If we never commited the mailbox, we need to release it here
if (own_mailbox_)
texture_mailbox_.RunReleaseCallback(texture_mailbox_.sync_point(), false);
texture_mailbox_ = mailbox;
own_mailbox_ = true;
-
SetNeedsCommit();
}
@@ -174,7 +178,7 @@ void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
}
bool TextureLayer::DrawsContent() const {
- return (client_ || texture_id_ || !texture_mailbox_.IsEmpty()) &&
+ return (client_ || texture_id_ || texture_mailbox_.IsValid()) &&
!context_lost_ && Layer::DrawsContent();
}
@@ -184,12 +188,16 @@ void TextureLayer::Update(ResourceUpdateQueue* queue,
if (client_) {
if (uses_mailbox_) {
TextureMailbox mailbox;
- if (client_->PrepareTextureMailbox(&mailbox))
+ if (client_->PrepareTextureMailbox(&mailbox)) {
+ if (mailbox.IsTexture())
+ DCHECK(client_->Context3d());
SetTextureMailbox(mailbox);
+ }
} else {
+ DCHECK(client_->Context3d());
texture_id_ = client_->PrepareTexture(queue);
}
- context_lost_ =
+ context_lost_ = client_->Context3d() &&
client_->Context3d()->getGraphicsResetStatusARB() != GL_NO_ERROR;
}
@@ -207,12 +215,10 @@ void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
texture_layer->set_premultiplied_alpha(premultiplied_alpha_);
if (uses_mailbox_ && own_mailbox_) {
Thread* main_thread = layer_tree_host()->proxy()->MainThread();
- TextureMailbox::ReleaseCallback callback;
- if (!texture_mailbox_.IsEmpty())
- callback = base::Bind(
- &PostCallbackToMainThread, main_thread, texture_mailbox_.callback());
- texture_layer->SetTextureMailbox(TextureMailbox(
- texture_mailbox_.name(), callback, texture_mailbox_.sync_point()));
+ TextureMailbox::ReleaseCallback callback = base::Bind(
+ &PostCallbackToThread, main_thread, texture_mailbox_.callback());
+ texture_layer->SetTextureMailbox(
+ texture_mailbox_.CopyWithNewCallback(callback));
own_mailbox_ = false;
} else {
texture_layer->set_texture_id(texture_id_);
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h
index cff2e3c..6de1ea49 100644
--- a/cc/layers/texture_layer.h
+++ b/cc/layers/texture_layer.h
@@ -62,6 +62,7 @@ class CC_EXPORT TextureLayer : public Layer {
void SetTextureId(unsigned texture_id);
// Code path for plugins which supply their own mailbox.
+ bool uses_mailbox() const { return uses_mailbox_; }
void SetTextureMailbox(const TextureMailbox& mailbox);
void WillModifyTexture();
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index 4406297..58b4508 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -34,7 +34,8 @@ TextureLayerImpl::~TextureLayerImpl() { FreeTextureMailbox(); }
void TextureLayerImpl::SetTextureMailbox(const TextureMailbox& mailbox) {
DCHECK(uses_mailbox_);
- DCHECK(mailbox.IsEmpty() || !mailbox.Equals(texture_mailbox_));
+ if (own_mailbox_)
+ DCHECK(!mailbox.IsValid() || !mailbox.Equals(texture_mailbox_));
FreeTextureMailbox();
texture_mailbox_ = mailbox;
own_mailbox_ = true;
@@ -146,7 +147,7 @@ void TextureLayerImpl::DidBecomeActive() {
return;
DCHECK(!external_texture_resource_);
ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
- if (!texture_mailbox_.IsEmpty()) {
+ if (texture_mailbox_.IsValid()) {
external_texture_resource_ =
resource_provider->CreateResourceFromTextureMailbox(texture_mailbox_);
}
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 505c1fc..65351da 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -205,6 +205,9 @@ class MockMailboxCallback {
MOCK_METHOD3(Release, void(const std::string& mailbox,
unsigned sync_point,
bool lost_resource));
+ MOCK_METHOD3(Release2, void(base::SharedMemory* shared_memory,
+ unsigned sync_point,
+ bool lost_resource));
};
struct CommonMailboxObjects {
@@ -212,7 +215,8 @@ struct CommonMailboxObjects {
: mailbox_name1_(64, '1'),
mailbox_name2_(64, '2'),
sync_point1_(1),
- sync_point2_(2) {
+ sync_point2_(2),
+ shared_memory_(new base::SharedMemory) {
release_mailbox1_ = base::Bind(&MockMailboxCallback::Release,
base::Unretained(&mock_callback_),
mailbox_name1_);
@@ -225,6 +229,13 @@ struct CommonMailboxObjects {
gpu::Mailbox m2;
m2.SetName(reinterpret_cast<const int8*>(mailbox_name2_.data()));
mailbox2_ = TextureMailbox(m2, release_mailbox2_, sync_point2_);
+
+ gfx::Size size(128, 128);
+ EXPECT_TRUE(shared_memory_->CreateAndMapAnonymous(4 * size.GetArea()));
+ release_mailbox3_ = base::Bind(&MockMailboxCallback::Release2,
+ base::Unretained(&mock_callback_),
+ shared_memory_.get());
+ mailbox3_ = TextureMailbox(shared_memory_.get(), size, release_mailbox3_);
}
std::string mailbox_name1_;
@@ -232,10 +243,13 @@ struct CommonMailboxObjects {
MockMailboxCallback mock_callback_;
TextureMailbox::ReleaseCallback release_mailbox1_;
TextureMailbox::ReleaseCallback release_mailbox2_;
+ TextureMailbox::ReleaseCallback release_mailbox3_;
TextureMailbox mailbox1_;
TextureMailbox mailbox2_;
+ TextureMailbox mailbox3_;
unsigned sync_point1_;
unsigned sync_point2_;
+ scoped_ptr<base::SharedMemory> shared_memory_;
};
class TextureLayerWithMailboxTest : public TextureLayerTest {
@@ -288,6 +302,20 @@ TEST_F(TextureLayerWithMailboxTest, ReplaceMailboxOnMainThreadBeforeCommit) {
Mock::VerifyAndClearExpectations(layer_tree_host_.get());
Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
+ test_layer->SetTextureMailbox(test_data_.mailbox3_);
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
+
+ EXPECT_CALL(*layer_tree_host_, AcquireLayerTextures()).Times(0);
+ EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
+ EXPECT_CALL(test_data_.mock_callback_,
+ Release2(test_data_.shared_memory_.get(),
+ 0, false))
+ .Times(1);
+ test_layer->SetTextureMailbox(TextureMailbox());
+ Mock::VerifyAndClearExpectations(layer_tree_host_.get());
+ Mock::VerifyAndClearExpectations(&test_data_.mock_callback_);
+
// Test destructor.
EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
test_layer->SetTextureMailbox(test_data_.mailbox1_);
diff --git a/cc/output/compositor_frame_ack.cc b/cc/output/compositor_frame_ack.cc
index a411b42..feb0bac 100644
--- a/cc/output/compositor_frame_ack.cc
+++ b/cc/output/compositor_frame_ack.cc
@@ -6,7 +6,8 @@
namespace cc {
-CompositorFrameAck::CompositorFrameAck() {}
+CompositorFrameAck::CompositorFrameAck()
+ : last_software_frame_id(0) {}
CompositorFrameAck::~CompositorFrameAck() {}
diff --git a/cc/output/compositor_frame_ack.h b/cc/output/compositor_frame_ack.h
index 5b4bb50..276ecf0 100644
--- a/cc/output/compositor_frame_ack.h
+++ b/cc/output/compositor_frame_ack.h
@@ -9,7 +9,6 @@
#include "cc/base/cc_export.h"
#include "cc/output/gl_frame_data.h"
#include "cc/resources/transferable_resource.h"
-#include "ui/surface/transport_dib.h"
namespace cc {
@@ -20,7 +19,7 @@ class CC_EXPORT CompositorFrameAck {
TransferableResourceArray resources;
scoped_ptr<GLFrameData> gl_frame_data;
- TransportDIB::Id last_dib_id;
+ unsigned last_software_frame_id;
private:
DISALLOW_COPY_AND_ASSIGN(CompositorFrameAck);
diff --git a/cc/output/software_frame_data.cc b/cc/output/software_frame_data.cc
index 20da28e..0b43032 100644
--- a/cc/output/software_frame_data.cc
+++ b/cc/output/software_frame_data.cc
@@ -6,7 +6,9 @@
namespace cc {
-SoftwareFrameData::SoftwareFrameData() {}
+SoftwareFrameData::SoftwareFrameData()
+ : id(0),
+ handle(base::SharedMemory::NULLHandle()) {}
SoftwareFrameData::~SoftwareFrameData() {}
diff --git a/cc/output/software_frame_data.h b/cc/output/software_frame_data.h
index c1e3dd7..b7fb44a 100644
--- a/cc/output/software_frame_data.h
+++ b/cc/output/software_frame_data.h
@@ -5,10 +5,9 @@
#ifndef CC_OUTPUT_SOFTWARE_FRAME_DATA_H_
#define CC_OUTPUT_SOFTWARE_FRAME_DATA_H_
-#include "base/basictypes.h"
+#include "base/memory/shared_memory.h"
#include "cc/base/cc_export.h"
#include "ui/gfx/rect.h"
-#include "ui/surface/transport_dib.h"
namespace cc {
@@ -17,9 +16,10 @@ class CC_EXPORT SoftwareFrameData {
SoftwareFrameData();
~SoftwareFrameData();
+ unsigned id;
gfx::Size size;
gfx::Rect damage_rect;
- TransportDIB::Id dib_id;
+ base::SharedMemoryHandle handle;
};
} // namespace cc
diff --git a/cc/output/software_output_device.cc b/cc/output/software_output_device.cc
index 719eeed..30817e0 100644
--- a/cc/output/software_output_device.cc
+++ b/cc/output/software_output_device.cc
@@ -35,9 +35,10 @@ SkCanvas* SoftwareOutputDevice::BeginPaint(gfx::Rect damage_rect) {
void SoftwareOutputDevice::EndPaint(SoftwareFrameData* frame_data) {
DCHECK(device_);
if (frame_data) {
+ frame_data->id = 0;
frame_data->size = viewport_size_;
frame_data->damage_rect = damage_rect_;
- frame_data->dib_id = TransportDIB::Id();
+ frame_data->handle = base::SharedMemory::NULLHandle();
}
}
@@ -53,7 +54,7 @@ void SoftwareOutputDevice::Scroll(
NOTIMPLEMENTED();
}
-void SoftwareOutputDevice::ReclaimDIB(const TransportDIB::Id& id) {
+void SoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
NOTIMPLEMENTED();
}
diff --git a/cc/output/software_output_device.h b/cc/output/software_output_device.h
index 9899629..fbada74 100644
--- a/cc/output/software_output_device.h
+++ b/cc/output/software_output_device.h
@@ -11,7 +11,6 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "ui/gfx/vector2d.h"
-#include "ui/surface/transport_dib.h"
class SkBitmap;
class SkDevice;
@@ -39,7 +38,7 @@ class CC_EXPORT SoftwareOutputDevice {
gfx::Rect clip_rect);
// TODO(skaslev) Remove this after UberCompositor lands.
- virtual void ReclaimDIB(const TransportDIB::Id& id);
+ virtual void ReclaimSoftwareFrame(unsigned id);
protected:
gfx::Size viewport_size_;
@@ -47,6 +46,7 @@ class CC_EXPORT SoftwareOutputDevice {
skia::RefPtr<SkDevice> device_;
skia::RefPtr<SkCanvas> canvas_;
+ private:
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDevice);
};
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index c53e0c7..9884666 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -113,7 +113,7 @@ void SoftwareRenderer::SwapBuffers(const ui::LatencyInfo& latency_info) {
void SoftwareRenderer::ReceiveCompositorFrameAck(
const CompositorFrameAck& ack) {
- output_device_->ReclaimDIB(ack.last_dib_id);
+ output_device_->ReclaimSoftwareFrame(ack.last_software_frame_id);
}
bool SoftwareRenderer::FlippedFramebuffer() const {
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index a2b6eec..68882c6 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -236,7 +236,7 @@ ResourceProvider::ResourceId ResourceProvider::CreateGLTexture(
ResourceProvider::ResourceId ResourceProvider::CreateBitmap(gfx::Size size) {
DCHECK(thread_checker_.CalledOnValidThread());
- uint8_t* pixels = new uint8_t[size.width() * size.height() * 4];
+ uint8_t* pixels = new uint8_t[4 * size.GetArea()];
ResourceId id = next_id_++;
Resource resource(pixels, size, GL_RGBA, GL_LINEAR);
@@ -276,12 +276,22 @@ ResourceProvider::ResourceId ResourceProvider::CreateResourceFromTextureMailbox(
DCHECK(thread_checker_.CalledOnValidThread());
// Just store the information. Mailbox will be consumed in LockForRead().
ResourceId id = next_id_++;
- unsigned texture_id = 0;
- Resource resource(texture_id, gfx::Size(), 0, GL_LINEAR);
+ DCHECK(mailbox.IsValid());
+ Resource& resource = resources_[id];
+ if (mailbox.IsTexture()) {
+ unsigned texture_id = 0;
+ resource = Resource(texture_id, gfx::Size(), 0, GL_LINEAR);
+ } else {
+ DCHECK(mailbox.IsSharedMemory());
+ base::SharedMemory* shared_memory = mailbox.shared_memory();
+ DCHECK(shared_memory->memory());
+ uint8_t* pixels = reinterpret_cast<uint8_t*>(shared_memory->memory());
+ resource = Resource(pixels, mailbox.shared_memory_size(),
+ GL_RGBA, GL_LINEAR);
+ }
resource.external = true;
resource.allocated = true;
resource.mailbox = mailbox;
- resources_[id] = resource;
return id;
}
@@ -332,20 +342,29 @@ void ResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
DCHECK(context3d);
GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id));
}
- if (!resource->mailbox.IsEmpty() && resource->external) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
- DCHECK(context3d);
+ if (resource->mailbox.IsValid() && resource->external) {
unsigned sync_point = resource->mailbox.sync_point();
- if (!lost_resource && resource->gl_id) {
- GLC(context3d, context3d->bindTexture(
- resource->mailbox.target(), resource->gl_id));
- GLC(context3d, context3d->produceTextureCHROMIUM(
- resource->mailbox.target(), resource->mailbox.data()));
+ if (resource->mailbox.IsTexture()) {
+ WebGraphicsContext3D* context3d = output_surface_->context3d();
+ DCHECK(context3d);
+ if (!lost_resource && resource->gl_id) {
+ GLC(context3d, context3d->bindTexture(
+ resource->mailbox.target(), resource->gl_id));
+ GLC(context3d, context3d->produceTextureCHROMIUM(
+ resource->mailbox.target(), resource->mailbox.data()));
+ }
+ if (resource->gl_id)
+ GLC(context3d, context3d->deleteTexture(resource->gl_id));
+ if (!lost_resource && resource->gl_id)
+ sync_point = context3d->insertSyncPoint();
+ } else {
+ DCHECK(resource->mailbox.IsSharedMemory());
+ base::SharedMemory* shared_memory = resource->mailbox.shared_memory();
+ if (resource->pixels && shared_memory) {
+ DCHECK(shared_memory->memory() == resource->pixels);
+ resource->pixels = NULL;
+ }
}
- if (resource->gl_id)
- GLC(context3d, context3d->deleteTexture(resource->gl_id));
- if (!lost_resource && resource->gl_id)
- sync_point = context3d->insertSyncPoint();
resource->mailbox.RunReleaseCallback(sync_point, lost_resource);
}
if (resource->pixels)
@@ -487,18 +506,21 @@ const ResourceProvider::Resource* ResourceProvider::LockForRead(ResourceId id) {
// Uninitialized! Call SetPixels or LockForWrite first.
DCHECK(resource->allocated);
- if (!resource->gl_id && resource->external && !resource->mailbox.IsEmpty()) {
- WebGraphicsContext3D* context3d = output_surface_->context3d();
- DCHECK(context3d);
- if (resource->mailbox.sync_point()) {
- GLC(context3d, context3d->waitSyncPoint(resource->mailbox.sync_point()));
- resource->mailbox.ResetSyncPoint();
+ if (resource->external) {
+ if (!resource->gl_id && resource->mailbox.IsTexture()) {
+ WebGraphicsContext3D* context3d = output_surface_->context3d();
+ DCHECK(context3d);
+ if (resource->mailbox.sync_point()) {
+ GLC(context3d,
+ context3d->waitSyncPoint(resource->mailbox.sync_point()));
+ resource->mailbox.ResetSyncPoint();
+ }
+ resource->gl_id = context3d->createTexture();
+ GLC(context3d, context3d->bindTexture(
+ resource->mailbox.target(), resource->gl_id));
+ GLC(context3d, context3d->consumeTextureCHROMIUM(
+ resource->mailbox.target(), resource->mailbox.data()));
}
- resource->gl_id = context3d->createTexture();
- GLC(context3d, context3d->bindTexture(
- resource->mailbox.target(), resource->gl_id));
- GLC(context3d, context3d->consumeTextureCHROMIUM(
- resource->mailbox.target(), resource->mailbox.data()));
}
resource->lock_for_read_count++;
@@ -840,7 +862,7 @@ void ResourceProvider::ReceiveFromParent(
DCHECK(resource->exported);
resource->exported = false;
resource->filter = it->filter;
- DCHECK(resource->mailbox.Equals(it->mailbox));
+ DCHECK(resource->mailbox.ContainsMailbox(it->mailbox));
if (resource->gl_id) {
if (it->sync_point)
GLC(context3d, context3d->waitSyncPoint(it->sync_point));
@@ -867,7 +889,7 @@ bool ResourceProvider::TransferResource(WebGraphicsContext3D* context,
Resource* source = &it->second;
DCHECK(!source->locked_for_write);
DCHECK(!source->lock_for_read_count);
- DCHECK(!source->external || (source->external && !source->mailbox.IsEmpty()));
+ DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
DCHECK(source->allocated);
if (source->exported)
return false;
@@ -876,7 +898,10 @@ bool ResourceProvider::TransferResource(WebGraphicsContext3D* context,
resource->filter = source->filter;
resource->size = source->size;
- if (source->mailbox.IsEmpty()) {
+ // TODO(skaslev) Implement this path for shared memory resources.
+ DCHECK(!source->mailbox.IsSharedMemory());
+
+ if (!source->mailbox.IsTexture()) {
GLC(context3d, context3d->genMailboxCHROMIUM(resource->mailbox.name));
source->mailbox.SetName(resource->mailbox);
} else {
@@ -913,7 +938,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
resource->gl_pixel_buffer_id);
context3d->bufferData(
GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM,
- resource->size.width() * resource->size.height() * 4,
+ 4 * resource->size.GetArea(),
NULL,
GL_DYNAMIC_DRAW);
context3d->bindBuffer(GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM, 0);
@@ -923,8 +948,7 @@ void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
if (resource->pixel_buffer)
return;
- resource->pixel_buffer = new uint8_t[
- resource->size.width() * resource->size.height() * 4];
+ resource->pixel_buffer = new uint8_t[4 * resource->size.GetArea()];
}
}
@@ -1049,6 +1073,7 @@ void ResourceProvider::SetPixelsFromBuffer(ResourceId id) {
}
if (resource->pixels) {
+ DCHECK(!resource->mailbox.IsValid());
DCHECK(resource->pixel_buffer);
DCHECK(resource->format == GL_RGBA);
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index c7cba3b..0ca3d02 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -874,6 +874,41 @@ TEST_P(ResourceProviderTest, Shutdown) {
EXPECT_FALSE(lost_resource);
}
+static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
+ gfx::Size size, uint32_t value) {
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
+ CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
+ uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
+ CHECK(pixels);
+ std::fill_n(pixels, size.GetArea(), value);
+ return shared_memory.Pass();
+}
+
+static void ReleaseSharedMemoryCallback(
+ bool* release_called,
+ unsigned sync_point, bool lost_resource) {
+ *release_called = true;
+}
+
+TEST_P(ResourceProviderTest, ShutdownSharedMemory) {
+ if (GetParam() != ResourceProvider::Bitmap)
+ return;
+
+ gfx::Size size(64, 64);
+ scoped_ptr<base::SharedMemory> shared_memory(
+ CreateAndFillSharedMemory(size, 0));
+
+ bool release_called = false;
+ TextureMailbox::ReleaseCallback callback =
+ base::Bind(ReleaseSharedMemoryCallback, &release_called);
+ resource_provider_->CreateResourceFromTextureMailbox(
+ TextureMailbox(shared_memory.get(), size, callback));
+
+ resource_provider_.reset();
+
+ EXPECT_TRUE(release_called);
+}
+
TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
// TextureMailbox callbacks only exist for GL textures for now.
if (GetParam() != ResourceProvider::GLTexture)
@@ -1072,6 +1107,37 @@ TEST_P(ResourceProviderTest, ManagedResource) {
static void EmptyReleaseCallback(unsigned sync_point, bool lost_resource) {}
+TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
+ if (GetParam() != ResourceProvider::Bitmap)
+ return;
+
+ gfx::Size size(64, 64);
+ const uint32_t kBadBeef = 0xbadbeef;
+ scoped_ptr<base::SharedMemory> shared_memory(
+ CreateAndFillSharedMemory(size, kBadBeef));
+
+ scoped_ptr<OutputSurface> output_surface(
+ FakeOutputSurface::CreateSoftware(make_scoped_ptr(
+ new SoftwareOutputDevice)));
+ scoped_ptr<ResourceProvider> resource_provider(
+ ResourceProvider::Create(output_surface.get(), 0));
+
+ TextureMailbox::ReleaseCallback callback = base::Bind(&EmptyReleaseCallback);
+ TextureMailbox mailbox(shared_memory.get(), size, callback);
+
+ ResourceProvider::ResourceId id =
+ resource_provider->CreateResourceFromTextureMailbox(mailbox);
+ EXPECT_NE(0u, id);
+
+ {
+ ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
+ const SkBitmap* sk_bitmap = lock.sk_bitmap();
+ EXPECT_EQ(sk_bitmap->width(), size.width());
+ EXPECT_EQ(sk_bitmap->height(), size.height());
+ EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
+ }
+}
+
TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
// Mailboxing is only supported for GL textures.
if (GetParam() != ResourceProvider::GLTexture)
diff --git a/cc/resources/texture_mailbox.cc b/cc/resources/texture_mailbox.cc
index 6900518..0d47874 100644
--- a/cc/resources/texture_mailbox.cc
+++ b/cc/resources/texture_mailbox.cc
@@ -11,16 +11,18 @@ namespace cc {
TextureMailbox::TextureMailbox()
: target_(GL_TEXTURE_2D),
- sync_point_(0) {
+ sync_point_(0),
+ shared_memory_(NULL) {
}
TextureMailbox::TextureMailbox(
const std::string& mailbox_name,
- const ReleaseCallback& mailbox_callback)
- : callback_(mailbox_callback),
+ const ReleaseCallback& callback)
+ : callback_(callback),
target_(GL_TEXTURE_2D),
- sync_point_(0) {
- DCHECK(mailbox_name.empty() == mailbox_callback.is_null());
+ sync_point_(0),
+ shared_memory_(NULL) {
+ DCHECK(mailbox_name.empty() == callback.is_null());
if (!mailbox_name.empty()) {
CHECK(mailbox_name.size() == sizeof(name_.name));
name_.SetName(reinterpret_cast<const int8*>(mailbox_name.data()));
@@ -29,50 +31,70 @@ TextureMailbox::TextureMailbox(
TextureMailbox::TextureMailbox(
const gpu::Mailbox& mailbox_name,
- const ReleaseCallback& mailbox_callback)
- : callback_(mailbox_callback),
+ const ReleaseCallback& callback)
+ : callback_(callback),
target_(GL_TEXTURE_2D),
- sync_point_(0) {
- DCHECK(mailbox_name.IsZero() == mailbox_callback.is_null());
+ sync_point_(0),
+ shared_memory_(NULL) {
+ DCHECK(mailbox_name.IsZero() == callback.is_null());
name_.SetName(mailbox_name.name);
}
TextureMailbox::TextureMailbox(
const gpu::Mailbox& mailbox_name,
- const ReleaseCallback& mailbox_callback,
+ const ReleaseCallback& callback,
unsigned sync_point)
- : callback_(mailbox_callback),
+ : callback_(callback),
target_(GL_TEXTURE_2D),
- sync_point_(sync_point) {
- DCHECK(mailbox_name.IsZero() == mailbox_callback.is_null());
+ sync_point_(sync_point),
+ shared_memory_(NULL) {
+ DCHECK(mailbox_name.IsZero() == callback.is_null());
name_.SetName(mailbox_name.name);
}
TextureMailbox::TextureMailbox(
const gpu::Mailbox& mailbox_name,
- const ReleaseCallback& mailbox_callback,
+ const ReleaseCallback& callback,
unsigned texture_target,
unsigned sync_point)
- : callback_(mailbox_callback),
+ : callback_(callback),
target_(texture_target),
- sync_point_(sync_point) {
- DCHECK(mailbox_name.IsZero() == mailbox_callback.is_null());
+ sync_point_(sync_point),
+ shared_memory_(NULL) {
+ DCHECK(mailbox_name.IsZero() == callback.is_null());
name_.SetName(mailbox_name.name);
}
-TextureMailbox::~TextureMailbox() {
+TextureMailbox::TextureMailbox(
+ base::SharedMemory* shared_memory,
+ gfx::Size size,
+ const ReleaseCallback& callback)
+ : callback_(callback),
+ target_(GL_TEXTURE_2D),
+ sync_point_(0),
+ shared_memory_(shared_memory),
+ shared_memory_size_(size) {
}
-bool TextureMailbox::Equals(const gpu::Mailbox& other) const {
- return !memcmp(data(), other.name, sizeof(name_.name));
+TextureMailbox::~TextureMailbox() {
}
bool TextureMailbox::Equals(const TextureMailbox& other) const {
- return Equals(other.name());
+ if (other.IsTexture())
+ return ContainsMailbox(other.name());
+ else if (other.IsSharedMemory())
+ return ContainsHandle(other.shared_memory_->handle());
+
+ DCHECK(!other.IsValid());
+ return !IsValid();
}
-bool TextureMailbox::IsEmpty() const {
- return name_.IsZero();
+bool TextureMailbox::ContainsMailbox(const gpu::Mailbox& other) const {
+ return IsTexture() && !memcmp(data(), other.name, sizeof(name_.name));
+}
+
+bool TextureMailbox::ContainsHandle(base::SharedMemoryHandle handle) const {
+ return shared_memory_ && shared_memory_->handle() == handle;
}
void TextureMailbox::RunReleaseCallback(unsigned sync_point,
@@ -82,7 +104,19 @@ void TextureMailbox::RunReleaseCallback(unsigned sync_point,
}
void TextureMailbox::SetName(const gpu::Mailbox& other) {
+ DCHECK(shared_memory_ == NULL);
name_.SetName(other.name);
}
+TextureMailbox TextureMailbox::CopyWithNewCallback(
+ const ReleaseCallback& callback) const {
+ TextureMailbox result(*this);
+ result.callback_ = callback;
+ return result;
+}
+
+size_t TextureMailbox::shared_memory_size_in_bytes() const {
+ return 4 * shared_memory_size_.GetArea();
+}
+
} // namespace cc
diff --git a/cc/resources/texture_mailbox.h b/cc/resources/texture_mailbox.h
index ff8c184..855287d 100644
--- a/cc/resources/texture_mailbox.h
+++ b/cc/resources/texture_mailbox.h
@@ -7,13 +7,16 @@
#include <string>
-#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/memory/shared_memory.h"
#include "cc/base/cc_export.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "ui/gfx/size.h"
namespace cc {
+// TODO(skaslev, danakj) Rename this class more apropriately since now it
+// can hold a shared memory resource as well as a texture mailbox.
class CC_EXPORT TextureMailbox {
public:
typedef base::Callback<void(unsigned sync_point,
@@ -30,14 +33,22 @@ class CC_EXPORT TextureMailbox {
const ReleaseCallback& callback,
unsigned texture_target,
unsigned sync_point);
+ TextureMailbox(base::SharedMemory* shared_memory,
+ gfx::Size size,
+ const ReleaseCallback& callback);
~TextureMailbox();
+ bool IsValid() const { return IsTexture() || IsSharedMemory(); }
+ bool IsTexture() const { return !name_.IsZero(); }
+ bool IsSharedMemory() const { return shared_memory_ != NULL; }
+
+ bool Equals(const TextureMailbox&) const;
+ bool ContainsMailbox(const gpu::Mailbox&) const;
+ bool ContainsHandle(base::SharedMemoryHandle handle) const;
+
const ReleaseCallback& callback() const { return callback_; }
const int8* data() const { return name_.name; }
- bool Equals(const gpu::Mailbox&) const;
- bool Equals(const TextureMailbox&) const;
- bool IsEmpty() const;
const gpu::Mailbox& name() const { return name_; }
void ResetSyncPoint() { sync_point_ = 0; }
void RunReleaseCallback(unsigned sync_point, bool lost_resource) const;
@@ -45,11 +56,19 @@ class CC_EXPORT TextureMailbox {
unsigned target() const { return target_; }
unsigned sync_point() const { return sync_point_; }
+ base::SharedMemory* shared_memory() const { return shared_memory_; }
+ gfx::Size shared_memory_size() const { return shared_memory_size_; }
+ size_t shared_memory_size_in_bytes() const;
+
+ TextureMailbox CopyWithNewCallback(const ReleaseCallback& callback) const;
+
private:
gpu::Mailbox name_;
ReleaseCallback callback_;
unsigned target_;
unsigned sync_point_;
+ base::SharedMemory* shared_memory_;
+ gfx::Size shared_memory_size_;
};
} // namespace cc
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index b0e2d0e..4000a2c 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -72,13 +72,6 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
virtual void CopyToBitmap(gfx::Rect rect, SkBitmap* output) OVERRIDE {
NOTIMPLEMENTED();
}
- virtual void Scroll(gfx::Vector2d delta,
- gfx::Rect clip_rect) OVERRIDE {
- NOTIMPLEMENTED();
- }
- virtual void ReclaimDIB(const TransportDIB::Id& id) OVERRIDE {
- NOTIMPLEMENTED();
- }
private:
SynchronousCompositorOutputSurface* surface_;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 49fcbd9..62fa6cb 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1715,7 +1715,7 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
} else if (frame->delegated_frame_data) {
ack.resources.swap(frame->delegated_frame_data->resource_list);
} else if (frame->software_frame_data) {
- ack.last_dib_id = frame->software_frame_data->dib_id;
+ ack.last_software_frame_id = frame->software_frame_data->id;
}
SendSwapCompositorFrameAck(routing_id_, process_->GetID(), ack);
}
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index a5daece..4c77599 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -13,6 +13,7 @@
#include "base/string_number_conversions.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
+#include "cc/resources/texture_mailbox.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/renderer_host/backing_store_aura.h"
@@ -344,6 +345,12 @@ void AcknowledgeBufferForGpu(
route_id, gpu_host_id, ack);
}
+void ReleaseMailbox(scoped_ptr<base::SharedMemory> shared_memory,
+ base::Callback<void()> callback,
+ unsigned sync_point, bool lost_resource) {
+ callback.Run();
+}
+
} // namespace
// We need to watch for mouse events outside a Web Popup or its parent
@@ -941,7 +948,9 @@ bool RenderWidgetHostViewAura::HasFocus() const {
}
bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
- return current_surface_ || current_dib_ || !!host_->GetBackingStore(false);
+ return current_surface_ ||
+ current_software_frame_.IsValid() ||
+ !!host_->GetBackingStore(false);
}
void RenderWidgetHostViewAura::Show() {
@@ -1285,6 +1294,7 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
}
bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
+ // TODO(skaslev): Implement this path for s/w compositing.
return current_surface_ != NULL && host_->is_accelerated_compositing_active();
}
@@ -1347,17 +1357,20 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
bool is_compositing_active = host_->is_accelerated_compositing_active();
if (is_compositing_active && current_surface_) {
- window_->SetExternalTexture(current_surface_.get());
+ window_->layer()->SetExternalTexture(current_surface_.get());
current_frame_size_ = ConvertSizeToDIP(
current_surface_->device_scale_factor(), current_surface_->size());
CheckResizeLock();
- } else if (is_compositing_active && current_dib_) {
- window_->SetExternalTexture(NULL);
- current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
- last_swapped_surface_size_);
+ } else if (is_compositing_active &&
+ current_software_frame_.IsSharedMemory()) {
+ window_->layer()->SetTextureMailbox(current_software_frame_,
+ last_swapped_surface_scale_factor_);
+ current_frame_size_ = ConvertSizeToDIP(
+ last_swapped_surface_scale_factor_,
+ current_software_frame_.shared_memory_size());
CheckResizeLock();
} else {
- window_->SetExternalTexture(NULL);
+ window_->layer()->SetExternalTexture(NULL);
resize_lock_.reset();
host_->WasResized();
}
@@ -1522,60 +1535,67 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
const ui::LatencyInfo& latency_info) {
const gfx::Size& frame_size = frame_data->size;
const gfx::Rect& damage_rect = frame_data->damage_rect;
- const TransportDIB::Id& dib_id = frame_data->dib_id;
- scoped_ptr<TransportDIB> dib(host_->GetProcess()->MapTransportDIB(dib_id));
+ gfx::Size frame_size_in_dip =
+ ConvertSizeToDIP(frame_device_scale_factor, frame_size);
+ if (ShouldSkipFrame(frame_size_in_dip)) {
+ SendSoftwareFrameAck(frame_data->id);
+ return;
+ }
- // Validate the received DIB.
- size_t expected_size = 4 * frame_size.GetArea();
- if (!dib || dib->size() < expected_size) {
+ base::SharedMemoryHandle handle = frame_data->handle;
+#ifdef OS_WIN
+ BOOL success = ::DuplicateHandle(
+ host_->GetProcess()->GetHandle(), frame_data->handle,
+ ::GetCurrentProcess(), &handle,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ if (!success) {
+ host_->GetProcess()->ReceivedBadMessage();
+ return;
+ }
+#endif
+ const size_t expected_size = 4 * frame_size.GetArea();
+ scoped_ptr<base::SharedMemory> shared_memory(
+ new base::SharedMemory(handle, false));
+ if (!shared_memory->Map(expected_size)) {
host_->GetProcess()->ReceivedBadMessage();
return;
}
if (last_swapped_surface_size_ != frame_size) {
DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
- << "Expected full damage rect";
+ << "Expected full damage rect";
}
-
- TransportDIB::Id last_dib_id = current_dib_id_;
- current_dib_.reset(dib.release());
- current_dib_id_ = dib_id;
last_swapped_surface_size_ = frame_size;
last_swapped_surface_scale_factor_ = frame_device_scale_factor;
- ui::Compositor* compositor = GetCompositor();
- if (!compositor) {
- SendSoftwareFrameAck(last_dib_id);
- return;
- }
-
- gfx::Size frame_size_in_dip =
- ConvertSizeToDIP(frame_device_scale_factor, frame_size);
- if (ShouldSkipFrame(frame_size_in_dip)) {
- can_lock_compositor_ = NO_PENDING_COMMIT;
- SendSoftwareFrameAck(last_dib_id);
- } else {
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
- AsWeakPtr(), last_dib_id));
- }
-
+ base::SharedMemory* shared_memory_raw_ptr = shared_memory.get();
+ cc::TextureMailbox::ReleaseCallback callback =
+ base::Bind(ReleaseMailbox, Passed(&shared_memory),
+ base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck,
+ AsWeakPtr(), frame_data->id));
+ current_software_frame_ =
+ cc::TextureMailbox(shared_memory_raw_ptr, frame_size, callback);
+ DCHECK(current_software_frame_.IsSharedMemory());
current_frame_size_ = frame_size_in_dip;
- CheckResizeLock();
+
released_front_lock_ = NULL;
- window_->SetExternalTexture(NULL);
+ CheckResizeLock();
+ window_->layer()->SetTextureMailbox(current_software_frame_,
+ frame_device_scale_factor);
window_->SchedulePaintInRect(
ConvertRectToDIP(frame_device_scale_factor, damage_rect));
- compositor->SetLatencyInfo(latency_info);
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor)
+ compositor->SetLatencyInfo(latency_info);
if (paint_observer_)
paint_observer_->OnUpdateCompositorContent();
}
void RenderWidgetHostViewAura::SendSoftwareFrameAck(
- const TransportDIB::Id& id) {
+ unsigned software_frame_id) {
cc::CompositorFrameAck ack;
- ack.last_dib_id = id;
+ ack.last_software_frame_id = software_frame_id;
RenderWidgetHostImpl::SendSwapCompositorFrameAck(
host_->GetRoutingID(), host_->GetProcess()->GetID(), ack);
}
@@ -2192,36 +2212,8 @@ void RenderWidgetHostViewAura::OnCaptureLost() {
}
void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
- bool is_compositing_active = host_->is_accelerated_compositing_active();
bool has_backing_store = !!host_->GetBackingStore(false);
- if (is_compositing_active && current_dib_) {
- const gfx::Size window_size = window_->bounds().size();
- const gfx::Size& frame_size = last_swapped_surface_size_;
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- frame_size.width(),
- frame_size.height());
- bitmap.setPixels(current_dib_->memory());
-
- SkCanvas* sk_canvas = canvas->sk_canvas();
- sk_canvas->drawBitmap(bitmap, 0, 0);
-
- if (frame_size != window_size) {
- SkRegion region;
- region.op(0, 0, window_size.width(), window_size.height(),
- SkRegion::kUnion_Op);
- region.op(0, 0, frame_size.width(), frame_size.height(),
- SkRegion::kDifference_Op);
- SkPaint paint;
- paint.setColor(SK_ColorWHITE);
- for (SkRegion::Iterator it(region); !it.done(); it.next())
- sk_canvas->drawIRect(it.rect(), paint);
- }
-
- if (paint_observer_)
- paint_observer_->OnPaintComplete();
- } else if (!is_compositing_active && has_backing_store) {
+ if (has_backing_store) {
paint_canvas_ = canvas;
BackingStoreAura* backing_store = static_cast<BackingStoreAura*>(
host_->GetBackingStore(true));
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 0ed95a0..58e5d08 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "cc/resources/texture_mailbox.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/image_transport_factory.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -484,7 +485,7 @@ class RenderWidgetHostViewAura
scoped_ptr<cc::SoftwareFrameData> frame_data,
float frame_device_scale_factor,
const ui::LatencyInfo& latency_info);
- void SendSoftwareFrameAck(const TransportDIB::Id& id);
+ void SendSoftwareFrameAck(unsigned software_frame_id);
BrowserAccessibilityManager* GetOrCreateBrowserAccessibilityManager();
@@ -562,12 +563,8 @@ class RenderWidgetHostViewAura
// The current frontbuffer texture.
scoped_refptr<ui::Texture> current_surface_;
- // The current frontbuffer DIB.
- scoped_ptr<TransportDIB> current_dib_;
-
- // The current DIB id as it was received from the renderer. Note that on
- // some platforms (e.g. Windows) this is different from current_dib_->id().
- TransportDIB::Id current_dib_id_;
+ // The current software frontbuffer.
+ cc::TextureMailbox current_software_frame_;
// The damage in the previously presented buffer.
SkRegion previous_damage_;
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc
index aadac97..43b6ce1 100644
--- a/content/common/cc_messages.cc
+++ b/content/common/cc_messages.cc
@@ -626,7 +626,7 @@ void ParamTraits<cc::CompositorFrame>::Log(const param_type& p,
void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
const param_type& p) {
WriteParam(m, p.resources);
- WriteParam(m, p.last_dib_id);
+ WriteParam(m, p.last_software_frame_id);
if (p.gl_frame_data) {
WriteParam(m, static_cast<int>(GL_FRAME));
WriteParam(m, *p.gl_frame_data);
@@ -641,7 +641,7 @@ bool ParamTraits<cc::CompositorFrameAck>::Read(const Message* m,
if (!ReadParam(m, iter, &p->resources))
return false;
- if (!ReadParam(m, iter, &p->last_dib_id))
+ if (!ReadParam(m, iter, &p->last_software_frame_id))
return false;
int compositor_frame_type;
@@ -667,7 +667,7 @@ void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
l->append("CompositorFrameAck(");
LogParam(p.resources, l);
l->append(", ");
- LogParam(p.last_dib_id, l);
+ LogParam(p.last_software_frame_id, l);
l->append(", ");
if (p.gl_frame_data)
LogParam(*p.gl_frame_data, l);
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h
index f09c9f2..4986dd3 100644
--- a/content/common/cc_messages.h
+++ b/content/common/cc_messages.h
@@ -233,7 +233,8 @@ IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::SoftwareFrameData)
+ IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(size)
IPC_STRUCT_TRAITS_MEMBER(damage_rect)
- IPC_STRUCT_TRAITS_MEMBER(dib_id)
+ IPC_STRUCT_TRAITS_MEMBER(handle)
IPC_STRUCT_TRAITS_END()
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index dc1c4ac..a99024d 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -29,7 +29,6 @@
#include "ui/gfx/size.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gpu_preference.h"
-#include "ui/surface/transport_dib.h"
namespace gpu {
struct Mailbox;
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 95de041..763e657 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -28,7 +28,6 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "ui/gl/gpu_preference.h"
-#include "ui/surface/transport_dib.h"
#if defined(OS_ANDROID)
#include "content/common/android/surface_texture_peer.h"
diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h
index 4de68a4..7b2d11d 100644
--- a/content/common/gpu/image_transport_surface.h
+++ b/content/common/gpu/image_transport_surface.h
@@ -20,7 +20,6 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "ui/gl/gl_surface.h"
-#include "ui/surface/transport_dib.h"
struct AcceleratedSurfaceMsg_BufferPresented_Params;
struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
diff --git a/content/renderer/gpu/compositor_software_output_device.cc b/content/renderer/gpu/compositor_software_output_device.cc
index cd22bed..23710ab 100644
--- a/content/renderer/gpu/compositor_software_output_device.cc
+++ b/content/renderer/gpu/compositor_software_output_device.cc
@@ -10,27 +10,56 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkPixelRef.h"
+#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/skia_util.h"
-#include "ui/surface/transport_dib.h"
namespace content {
-CompositorSoftwareOutputDevice::DIB::DIB(size_t size) {
- RenderProcess* render_process = RenderProcess::current();
- dib_ = render_process->CreateTransportDIB(size);
- CHECK(dib_);
- bool success = dib_->Map();
- CHECK(success);
+CompositorSoftwareOutputDevice::Buffer::Buffer(
+ unsigned id, scoped_ptr<base::SharedMemory> mem)
+ : id_(id),
+ mem_(mem.Pass()),
+ free_(true),
+ parent_(NULL) {
+}
+
+CompositorSoftwareOutputDevice::Buffer::~Buffer() {
}
-CompositorSoftwareOutputDevice::DIB::~DIB() {
- RenderProcess* render_process = RenderProcess::current();
- render_process->FreeTransportDIB(dib_);
+void CompositorSoftwareOutputDevice::Buffer::SetParent(
+ Buffer* parent, const gfx::Rect& damage) {
+ parent_ = parent;
+ damage_ = damage;
+}
+
+bool CompositorSoftwareOutputDevice::Buffer::FindDamageDifferenceFrom(
+ Buffer* buffer, SkRegion* result) const {
+ if (!buffer)
+ return false;
+
+ if (buffer == this) {
+ *result = SkRegion();
+ return true;
+ }
+
+ SkRegion damage;
+ const Buffer* current = this;
+ while (current->parent_) {
+ damage.op(RectToSkIRect(current->damage_), SkRegion::kUnion_Op);
+ if (current->parent_ == buffer) {
+ *result = damage;
+ return true;
+ }
+ current = current->parent_;
+ }
+
+ return false;
}
CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice()
- : front_buffer_(-1),
- num_free_buffers_(0) {
+ : current_index_(-1),
+ next_buffer_id_(1),
+ render_thread_(RenderThread::Get()) {
DetachFromThread();
}
@@ -38,10 +67,34 @@ CompositorSoftwareOutputDevice::~CompositorSoftwareOutputDevice() {
DCHECK(CalledOnValidThread());
}
-CompositorSoftwareOutputDevice::DIB*
-CompositorSoftwareOutputDevice::CreateDIB() {
- const size_t size = 4 * viewport_size_.GetArea();
- return new DIB(size);
+unsigned CompositorSoftwareOutputDevice::GetNextId() {
+ unsigned id = next_buffer_id_++;
+ // Zero is reserved to label invalid frame id.
+ if (id == 0)
+ id = next_buffer_id_++;
+ return id;
+}
+
+CompositorSoftwareOutputDevice::Buffer*
+CompositorSoftwareOutputDevice::CreateBuffer() {
+ const size_t size = 4 * viewport_size_.GetArea();
+ scoped_ptr<base::SharedMemory> mem =
+ render_thread_->HostAllocateSharedMemoryBuffer(size).Pass();
+ CHECK(mem);
+ bool success = mem->Map(size);
+ CHECK(success);
+ return new Buffer(GetNextId(), mem.Pass());
+}
+
+size_t CompositorSoftwareOutputDevice::FindFreeBuffer(size_t hint) {
+ for (size_t i = 0; i < buffers_.size(); ++i) {
+ size_t index = (hint + i) % buffers_.size();
+ if (buffers_[index]->free())
+ return index;
+ }
+
+ buffers_.push_back(CreateBuffer());
+ return buffers_.size() - 1;
}
void CompositorSoftwareOutputDevice::Resize(gfx::Size viewport_size) {
@@ -50,66 +103,76 @@ void CompositorSoftwareOutputDevice::Resize(gfx::Size viewport_size) {
if (viewport_size_ == viewport_size)
return;
- // Keep non-ACKed dibs open.
- int first_non_free = front_buffer_ + num_free_buffers_ + 1;
- int num_non_free = dibs_.size() - num_free_buffers_;
- for (int i = 0; i < num_non_free; ++i) {
- int index = (first_non_free + i) % dibs_.size();
- awaiting_ack_.push_back(dibs_[index]);
- dibs_[index] = NULL;
+ // Keep non-ACKed buffers in awaiting_ack_ until they get acknowledged.
+ for (size_t i = 0; i < buffers_.size(); ++i) {
+ if (!buffers_[i]->free()) {
+ awaiting_ack_.push_back(buffers_[i]);
+ buffers_[i] = NULL;
+ }
}
- dibs_.clear();
- front_buffer_ = -1;
- num_free_buffers_ = 0;
+ buffers_.clear();
+ current_index_ = -1;
viewport_size_ = viewport_size;
}
SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(gfx::Rect damage_rect) {
DCHECK(CalledOnValidThread());
- gfx::Rect last_damage_rect = damage_rect_;
- damage_rect_ = damage_rect;
-
- int last_buffer = front_buffer_;
- if (num_free_buffers_ == 0) {
- dibs_.insert(dibs_.begin() + (front_buffer_ + 1), CreateDIB());
- last_damage_rect = gfx::Rect(viewport_size_);
- } else {
- --num_free_buffers_;
- }
- front_buffer_ = (front_buffer_ + 1) % dibs_.size();
-
- TransportDIB* front_dib = dibs_[front_buffer_]->dib();
- DCHECK(front_dib);
- DCHECK(front_dib->memory());
+ Buffer* previous = NULL;
+ if (current_index_ != size_t(-1))
+ previous = buffers_[current_index_];
+ current_index_ = FindFreeBuffer(current_index_ + 1);
+ Buffer* current = buffers_[current_index_];
+ DCHECK(current->free());
+ current->SetFree(false);
// Set up a canvas for the current front buffer.
bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
viewport_size_.width(),
viewport_size_.height());
- bitmap_.setPixels(front_dib->memory());
+ bitmap_.setPixels(current->memory());
device_ = skia::AdoptRef(new SkDevice(bitmap_));
canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
- // Copy over previous damage.
- if (last_buffer != -1) {
- TransportDIB* last_dib = dibs_[last_buffer]->dib();
- SkBitmap back_bitmap;
- back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- viewport_size_.width(),
- viewport_size_.height());
- back_bitmap.setPixels(last_dib->memory());
-
- SkRegion region(RectToSkIRect(last_damage_rect));
+ if (!previous) {
+ DCHECK(damage_rect == gfx::Rect(viewport_size_));
+ } else {
+ // Find the smallest damage region that needs
+ // to be copied from the |previous| buffer.
+ SkRegion region;
+ bool found =
+ current->FindDamageDifferenceFrom(previous, &region) ||
+ previous->FindDamageDifferenceFrom(current, &region);
+ if (!found)
+ region = SkRegion(RectToSkIRect(gfx::Rect(viewport_size_)));
region.op(RectToSkIRect(damage_rect), SkRegion::kDifference_Op);
- for (SkRegion::Iterator it(region); !it.done(); it.next()) {
- const SkIRect& src_rect = it.rect();
- SkRect dst_rect = SkRect::Make(src_rect);
- canvas_->drawBitmapRect(back_bitmap, &src_rect, dst_rect, NULL);
+
+ // Copy over the damage region.
+ if (!region.isEmpty()) {
+ SkBitmap back_bitmap;
+ back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ viewport_size_.width(),
+ viewport_size_.height());
+ back_bitmap.setPixels(previous->memory());
+
+ for (SkRegion::Iterator it(region); !it.done(); it.next()) {
+ const SkIRect& src_rect = it.rect();
+ SkRect dst_rect = SkRect::Make(src_rect);
+ canvas_->drawBitmapRect(back_bitmap, &src_rect, dst_rect, NULL);
+ }
}
}
+ // Make |current| child of |previous| and orphan all of |current|'s children.
+ current->SetParent(previous, damage_rect);
+ for (size_t i = 0; i < buffers_.size(); ++i) {
+ Buffer* buffer = buffers_[i];
+ if (buffer->parent() == current)
+ buffer->SetParent(NULL, gfx::Rect(viewport_size_));
+ }
+ damage_rect_ = damage_rect;
+
return canvas_.get();
}
@@ -118,25 +181,27 @@ void CompositorSoftwareOutputDevice::EndPaint(
DCHECK(CalledOnValidThread());
if (frame_data) {
+ Buffer* buffer = buffers_[current_index_];
+ frame_data->id = buffer->id();
frame_data->size = viewport_size_;
frame_data->damage_rect = damage_rect_;
- frame_data->dib_id = dibs_[front_buffer_]->dib()->id();
+ frame_data->handle = buffer->handle();
}
}
-void CompositorSoftwareOutputDevice::ReclaimDIB(const TransportDIB::Id& id) {
+void CompositorSoftwareOutputDevice::ReclaimSoftwareFrame(unsigned id) {
DCHECK(CalledOnValidThread());
- if (!TransportDIB::is_valid_id(id))
+ if (!id)
return;
- // The reclaimed dib id might not be among the currently
- // active dibs if we got a resize event in the mean time.
- ScopedVector<DIB>::iterator it =
- std::find_if(dibs_.begin(), dibs_.end(), CompareById(id));
- if (it != dibs_.end()) {
- ++num_free_buffers_;
- DCHECK_LE(static_cast<size_t>(num_free_buffers_), dibs_.size());
+ // The reclaimed buffer id might not be among the currently
+ // active buffers if we got a resize event in the mean time.
+ ScopedVector<Buffer>::iterator it =
+ std::find_if(buffers_.begin(), buffers_.end(), CompareById(id));
+ if (it != buffers_.end()) {
+ DCHECK(!(*it)->free());
+ (*it)->SetFree(true);
return;
} else {
it = std::find_if(awaiting_ack_.begin(), awaiting_ack_.end(),
diff --git a/content/renderer/gpu/compositor_software_output_device.h b/content/renderer/gpu/compositor_software_output_device.h
index b82ffe2..49b90c2 100644
--- a/content/renderer/gpu/compositor_software_output_device.h
+++ b/content/renderer/gpu/compositor_software_output_device.h
@@ -5,11 +5,16 @@
#ifndef CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_H_
#define CONTENT_RENDERER_GPU_COMPOSITOR_SOFTWARE_OUTPUT_DEVICE_H_
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/memory/shared_memory.h"
#include "base/threading/non_thread_safe.h"
#include "cc/output/software_output_device.h"
+#include "content/public/renderer/render_thread.h"
#include "third_party/skia/include/core/SkBitmap.h"
+class SkRegion;
+
namespace content {
// This class can be created only on the main thread, but then becomes pinned
@@ -26,43 +31,63 @@ public:
virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE;
virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
- virtual void ReclaimDIB(const TransportDIB::Id& id) OVERRIDE;
+ virtual void ReclaimSoftwareFrame(unsigned id) OVERRIDE;
private:
- class DIB {
+ // Internal buffer class that manages shared memory lifetime and ownership.
+ // It also tracks buffers' history so we can calculate what's the minimum
+ // damage rect difference between any two given buffers (see SetParent and
+ // FindDamageDifferenceFrom).
+ class Buffer {
public:
- explicit DIB(size_t size);
- ~DIB();
+ explicit Buffer(unsigned id, scoped_ptr<base::SharedMemory> mem);
+ ~Buffer();
- TransportDIB* dib() const {
- return dib_;
- }
+ unsigned id() const { return id_; }
+
+ void* memory() const { return mem_->memory(); }
+ base::SharedMemoryHandle handle() const { return mem_->handle(); }
+
+ bool free() const { return free_; }
+ void SetFree(bool free) { free_ = free; }
+
+ Buffer* parent() const { return parent_; }
+ void SetParent(Buffer* parent, const gfx::Rect& damage);
+
+ bool FindDamageDifferenceFrom(Buffer* buffer, SkRegion* result) const;
private:
- TransportDIB* dib_;
+ const unsigned id_;
+ scoped_ptr<base::SharedMemory> mem_;
+ bool free_;
+ Buffer* parent_;
+ gfx::Rect damage_;
- DISALLOW_COPY_AND_ASSIGN(DIB);
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
};
class CompareById {
public:
- CompareById(const TransportDIB::Id& id) : id_(id) {}
+ CompareById(unsigned id) : id_(id) {}
- bool operator()(const DIB* dib) const {
- return dib->dib() && dib->dib()->id() == id_;
+ bool operator()(const Buffer* buffer) const {
+ return buffer->id() == id_;
}
private:
- TransportDIB::Id id_;
+ const unsigned id_;
};
- DIB* CreateDIB();
+ unsigned GetNextId();
+ Buffer* CreateBuffer();
+ size_t FindFreeBuffer(size_t hint);
- int front_buffer_;
- int num_free_buffers_;
- ScopedVector<DIB> dibs_;
- ScopedVector<DIB> awaiting_ack_;
+ size_t current_index_;
+ unsigned next_buffer_id_;
+ ScopedVector<Buffer> buffers_;
+ ScopedVector<Buffer> awaiting_ack_;
SkBitmap bitmap_;
+ RenderThread* render_thread_;
};
} // namespace content
diff --git a/gpu/command_buffer/common/mailbox.cc b/gpu/command_buffer/common/mailbox.cc
index 653d1d664..be2bebf 100644
--- a/gpu/command_buffer/common/mailbox.cc
+++ b/gpu/command_buffer/common/mailbox.cc
@@ -22,6 +22,10 @@ bool Mailbox::IsZero() const {
return true;
}
+void Mailbox::SetZero() {
+ memset(name, 0, sizeof(name));
+}
+
void Mailbox::SetName(const int8* n) {
GPU_DCHECK(IsZero() || !memcmp(name, n, sizeof(name)));
memcpy(name, n, sizeof(name));
diff --git a/gpu/command_buffer/common/mailbox.h b/gpu/command_buffer/common/mailbox.h
index ca24a71..d0e4c2c 100644
--- a/gpu/command_buffer/common/mailbox.h
+++ b/gpu/command_buffer/common/mailbox.h
@@ -13,6 +13,7 @@ namespace gpu {
struct GPU_EXPORT Mailbox {
Mailbox();
bool IsZero() const;
+ void SetZero();
void SetName(const int8* name);
int8 name[64];
};
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index 43d2d9e..7915d09 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -14,6 +14,8 @@
'../../base/base.gyp:base',
'../../base/base.gyp:base_i18n',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../../cc/cc.gyp:cc',
+ '../../gpu/gpu.gyp:gpu',
'../../skia/skia.gyp:skia',
'../compositor/compositor.gyp:compositor',
'../ui.gyp:ui',
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 5160bf6..dac1405 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -34,6 +34,15 @@
namespace aura {
+namespace {
+
+void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory,
+ unsigned sync_point, bool lost_resource) {
+ // NOTE: shared_memory will get released when we go out of scope.
+}
+
+} // namespace
+
Window::Window(WindowDelegate* delegate)
: type_(client::WINDOW_TYPE_UNKNOWN),
owned_by_parent_(true),
@@ -145,6 +154,9 @@ ui::Layer* Window::RecreateLayer() {
return NULL;
old_layer->set_delegate(NULL);
+ float mailbox_scale_factor;
+ cc::TextureMailbox old_mailbox =
+ old_layer->GetTextureMailbox(&mailbox_scale_factor);
scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
if (delegate_ && old_texture)
old_layer->SetExternalTexture(delegate_->CopyTexture());
@@ -158,8 +170,26 @@ ui::Layer* Window::RecreateLayer() {
// Move the original texture to the new layer if the old layer has a
// texture and we could copy it into the old layer,
// crbug.com/175211.
- if (delegate_ && old_texture)
+ if (delegate_ && old_texture) {
layer_->SetExternalTexture(old_texture);
+ } else if (old_mailbox.IsSharedMemory()) {
+ base::SharedMemory* old_buffer = old_mailbox.shared_memory();
+ const size_t size = old_mailbox.shared_memory_size_in_bytes();
+
+ scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
+ new_buffer->CreateAndMapAnonymous(size);
+
+ if (old_buffer->memory() && new_buffer->memory()) {
+ memcpy(new_buffer->memory(), old_buffer->memory(), size);
+ base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
+ cc::TextureMailbox::ReleaseCallback callback =
+ base::Bind(MailboxReleaseCallback, Passed(&new_buffer));
+ cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
+ old_mailbox.shared_memory_size(),
+ callback);
+ layer_->SetTextureMailbox(new_mailbox, mailbox_scale_factor);
+ }
+ }
UpdateLayerName(name_);
layer_->SetFillsBoundsOpaquely(!transparent_);
@@ -313,10 +343,6 @@ void Window::SchedulePaintInRect(const gfx::Rect& rect) {
}
}
-void Window::SetExternalTexture(ui::Texture* texture) {
- layer_->SetExternalTexture(texture);
-}
-
void Window::SetDefaultParentByRootWindow(RootWindow* root_window,
const gfx::Rect& bounds_in_screen) {
DCHECK(root_window);
diff --git a/ui/aura/window.h b/ui/aura/window.h
index a73f784..cbc700d 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -157,9 +157,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Marks the a portion of window as needing to be painted.
void SchedulePaintInRect(const gfx::Rect& rect);
- // Assigns a new external texture to the window's layer.
- void SetExternalTexture(ui::Texture* texture);
-
// Places this window per |root_window|'s stacking client. The final location
// may be a RootWindow other than the one passed in. |root_window| may not be
// NULL. |bounds_in_screen| may be empty; it is more optional context that
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index a2f0a95..3949402 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -86,6 +86,7 @@ Layer::Layer(LayerType type)
zoom_(1),
zoom_inset_(0),
delegate_(NULL),
+ cc_layer_(NULL),
scale_content_(true),
device_scale_factor_(1.0f) {
CreateWebLayer();
@@ -514,6 +515,32 @@ void Layer::SetExternalTexture(Texture* texture) {
RecomputeDrawsContentAndUVRect();
}
+void Layer::SetTextureMailbox(const cc::TextureMailbox& mailbox,
+ float scale_factor) {
+ DCHECK_EQ(type_, LAYER_TEXTURED);
+ DCHECK(!solid_color_layer_);
+ layer_updated_externally_ = true;
+ texture_ = NULL;
+ if (!texture_layer_ || !texture_layer_->uses_mailbox()) {
+ scoped_refptr<cc::TextureLayer> new_layer =
+ cc::TextureLayer::CreateForMailbox(this);
+ new_layer->SetFlipped(false);
+ SwitchToLayer(new_layer);
+ texture_layer_ = new_layer;
+ }
+ texture_layer_->SetTextureMailbox(mailbox);
+ mailbox_ = mailbox;
+ mailbox_scale_factor_ = scale_factor;
+ RecomputeDrawsContentAndUVRect();
+}
+
+cc::TextureMailbox Layer::GetTextureMailbox(float* scale_factor) {
+ if (scale_factor)
+ *scale_factor = mailbox_scale_factor_;
+ cc::TextureMailbox::ReleaseCallback callback;
+ return mailbox_.CopyWithNewCallback(callback);
+}
+
void Layer::SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData> frame,
gfx::Size frame_size_in_dip) {
DCHECK_EQ(type_, LAYER_TEXTURED);
@@ -640,7 +667,9 @@ unsigned Layer::PrepareTexture(cc::ResourceUpdateQueue* queue) {
WebKit::WebGraphicsContext3D* Layer::Context3d() {
DCHECK(texture_layer_.get());
- return texture_->HostContext3D();
+ if (texture_)
+ return texture_->HostContext3D();
+ return NULL;
}
bool Layer::PrepareTextureMailbox(cc::TextureMailbox* mailbox) {
@@ -918,11 +947,18 @@ void Layer::RecomputeDrawsContentAndUVRect() {
DCHECK(cc_layer_);
gfx::Size size(bounds_.size());
if (texture_layer_.get()) {
- DCHECK(texture_.get());
-
- float texture_scale_factor = 1.0f / texture_->device_scale_factor();
- gfx::Size texture_size = gfx::ToFlooredSize(
- gfx::ScaleSize(texture_->size(), texture_scale_factor));
+ gfx::Size texture_size;
+ if (!texture_layer_->uses_mailbox()) {
+ DCHECK(texture_);
+ float texture_scale_factor = 1.0f / texture_->device_scale_factor();
+ texture_size = gfx::ToFlooredSize(
+ gfx::ScaleSize(texture_->size(), texture_scale_factor));
+ } else {
+ DCHECK(mailbox_.IsSharedMemory());
+ float texture_scale_factor = 1.0f / mailbox_scale_factor_;
+ texture_size = gfx::ToFlooredSize(
+ gfx::ScaleSize(mailbox_.shared_memory_size(), texture_scale_factor));
+ }
size.SetToMin(texture_size);
gfx::PointF uv_top_left(0.f, 0.f);
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index a5afd6b..1159d0b 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -17,6 +17,7 @@
#include "cc/base/scoped_ptr_vector.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/texture_layer_client.h"
+#include "cc/resources/texture_mailbox.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/compositor/compositor.h"
@@ -250,6 +251,11 @@ class COMPOSITOR_EXPORT Layer
void SetExternalTexture(ui::Texture* texture);
ui::Texture* external_texture() { return texture_.get(); }
+ // Set new TextureMailbox for this layer. Note that |mailbox| may hold a
+ // shared memory resource or an actual mailbox for a texture.
+ void SetTextureMailbox(const cc::TextureMailbox& mailbox, float scale_factor);
+ cc::TextureMailbox GetTextureMailbox(float* scale_factor);
+
// Sets a delegated frame, coming from a child compositor.
void SetDelegatedFrame(scoped_ptr<cc::DelegatedFrameData> frame,
gfx::Size frame_size_in_dip);
@@ -465,6 +471,12 @@ class COMPOSITOR_EXPORT Layer
// A cached copy of |Compositor::device_scale_factor()|.
float device_scale_factor_;
+ // A cached copy of the TextureMailbox given texture_layer_.
+ cc::TextureMailbox mailbox_;
+
+ // Device scale factor in which mailbox_ was rendered in.
+ float mailbox_scale_factor_;
+
// The size of the delegated frame in DIP, set when SetDelegatedFrame was
// called.
gfx::Size delegated_frame_size_in_dip_;