summaryrefslogtreecommitdiffstats
path: root/content/renderer
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-12 20:09:57 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-12 20:09:57 +0000
commitce9eea60c922efff7c680a7a127480a799e06e94 (patch)
tree6e34093d78d48fe4d1132c4d8eef2817d32e2203 /content/renderer
parent8c3bd1d8c71d8432beb624ce1434ca962665de90 (diff)
downloadchromium_src-ce9eea60c922efff7c680a7a127480a799e06e94.zip
chromium_src-ce9eea60c922efff7c680a7a127480a799e06e94.tar.gz
chromium_src-ce9eea60c922efff7c680a7a127480a799e06e94.tar.bz2
implemented latch support in renderer process. this corresponds with a webkit patch.
https://bugs.webkit.org/show_bug.cgi?id=58003 BUG=72671 TEST=see attachment in bug for test. only green should be seen. Review URL: http://codereview.chromium.org/6810009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81295 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer')
-rw-r--r--content/renderer/command_buffer_proxy.cc9
-rw-r--r--content/renderer/command_buffer_proxy.h5
-rw-r--r--content/renderer/renderer_gl_context.cc171
-rw-r--r--content/renderer/renderer_gl_context.h18
-rw-r--r--content/renderer/webgraphicscontext3d_command_buffer_impl.cc35
-rw-r--r--content/renderer/webgraphicscontext3d_command_buffer_impl.h5
6 files changed, 233 insertions, 10 deletions
diff --git a/content/renderer/command_buffer_proxy.cc b/content/renderer/command_buffer_proxy.cc
index 865f90f..e374386 100644
--- a/content/renderer/command_buffer_proxy.cc
+++ b/content/renderer/command_buffer_proxy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -165,7 +165,7 @@ void CommandBufferProxy::SetGetOffset(int32 get_offset) {
NOTREACHED();
}
-int32 CommandBufferProxy::CreateTransferBuffer(size_t size) {
+int32 CommandBufferProxy::CreateTransferBuffer(size_t size, int32 id_request) {
if (last_state_.error != gpu::error::kNoError)
return -1;
@@ -198,6 +198,7 @@ int32 CommandBufferProxy::CreateTransferBuffer(size_t size) {
if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_,
handle,
size,
+ id_request,
&id))) {
return -1;
}
@@ -207,7 +208,8 @@ int32 CommandBufferProxy::CreateTransferBuffer(size_t size) {
int32 CommandBufferProxy::RegisterTransferBuffer(
base::SharedMemory* shared_memory,
- size_t size) {
+ size_t size,
+ int32 id_request) {
if (last_state_.error != gpu::error::kNoError)
return -1;
@@ -216,6 +218,7 @@ int32 CommandBufferProxy::RegisterTransferBuffer(
route_id_,
shared_memory->handle(), // Returns FileDescriptor with auto_close off.
size,
+ id_request,
&id))) {
return -1;
}
diff --git a/content/renderer/command_buffer_proxy.h b/content/renderer/command_buffer_proxy.h
index 77914d0..e63150c 100644
--- a/content/renderer/command_buffer_proxy.h
+++ b/content/renderer/command_buffer_proxy.h
@@ -51,9 +51,10 @@ class CommandBufferProxy : public gpu::CommandBuffer,
virtual void Flush(int32 put_offset);
virtual State FlushSync(int32 put_offset);
virtual void SetGetOffset(int32 get_offset);
- virtual int32 CreateTransferBuffer(size_t size);
+ virtual int32 CreateTransferBuffer(size_t size, int32 id_request);
virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory,
- size_t size);
+ size_t size,
+ int32 id_request);
virtual void DestroyTransferBuffer(int32 id);
virtual gpu::Buffer GetTransferBuffer(int32 handle);
virtual void SetToken(int32 token);
diff --git a/content/renderer/renderer_gl_context.cc b/content/renderer/renderer_gl_context.cc
index 235a0a5..e55357d 100644
--- a/content/renderer/renderer_gl_context.cc
+++ b/content/renderer/renderer_gl_context.cc
@@ -6,7 +6,12 @@
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
+#include "base/shared_memory.h"
+#include "chrome/renderer/render_thread.h"
+#include "content/common/view_messages.h"
#include "content/renderer/command_buffer_proxy.h"
#include "content/renderer/gpu_channel_host.h"
#include "content/renderer/gpu_video_service_host.h"
@@ -33,6 +38,9 @@ const int32 kCommandBufferSize = 1024 * 1024;
// creation attributes.
const int32 kTransferBufferSize = 1024 * 1024;
+const uint32 kMaxLatchesPerRenderer = 2048;
+const uint32 kInvalidLatchId = 0xffffffffu;
+
// Singleton used to initialize and terminate the gles2 library.
class GLES2Initializer {
public:
@@ -48,6 +56,95 @@ class GLES2Initializer {
DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
};
+// Shared memory allocator for latches. Creates a block of shared memory for
+// each renderer process.
+class LatchAllocator {
+ public:
+ static LatchAllocator* GetInstance();
+ static uint32 size() { return kMaxLatchesPerRenderer*sizeof(uint32); }
+ static const uint32_t kFreeLatch = 0xffffffffu;
+
+ LatchAllocator();
+ ~LatchAllocator();
+
+ base::SharedMemoryHandle handle() const { return shm_->handle(); }
+ base::SharedMemory* shared_memory() { return shm_.get(); }
+
+ bool AllocateLatch(uint32* latch_id);
+ bool FreeLatch(uint32 latch_id);
+
+ private:
+ friend struct DefaultSingletonTraits<LatchAllocator>;
+
+ scoped_ptr<base::SharedMemory> shm_;
+ // Pointer to mapped shared memory.
+ volatile uint32* latches_;
+
+ DISALLOW_COPY_AND_ASSIGN(LatchAllocator);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// LatchAllocator implementation
+
+LatchAllocator* LatchAllocator::GetInstance() {
+ return Singleton<LatchAllocator>::get();
+}
+
+LatchAllocator::LatchAllocator() {
+ base::SharedMemoryHandle handle;
+ RenderThread* render_thread = RenderThread::current();
+ if (!render_thread->Send(
+ new ViewHostMsg_AllocateSharedMemoryBuffer(size(), &handle))) {
+ NOTREACHED() << "failed to send sync IPC";
+ }
+
+ if (!base::SharedMemory::IsHandleValid(handle)) {
+ NOTREACHED() << "failed to create shared memory";
+ }
+
+ // Handle is closed by the SharedMemory object below. This stops
+ // base::FileDescriptor from closing it as well.
+#if defined(OS_POSIX)
+ handle.auto_close = false;
+#endif
+
+ shm_.reset(new base::SharedMemory(handle, false));
+ if (!shm_->Map(size())) {
+ NOTREACHED() << "failed to map shared memory";
+ }
+
+ latches_ = static_cast<uint32*>(shm_->memory());
+ // Mark all latches as unallocated.
+ for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i)
+ latches_[i] = kFreeLatch;
+}
+
+LatchAllocator::~LatchAllocator() {
+}
+
+bool LatchAllocator::AllocateLatch(uint32* latch_id) {
+ for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) {
+ if (latches_[i] == kFreeLatch) {
+ // mark latch as taken and blocked.
+ // 0 means waiter will block, 1 means waiter will pass.
+ latches_[i] = 0;
+ *latch_id = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LatchAllocator::FreeLatch(uint32 latch_id) {
+ if (latch_id < kMaxLatchesPerRenderer && latches_[latch_id] != kFreeLatch) {
+ latches_[latch_id] = kFreeLatch;
+ return true;
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
static base::LazyInstance<GLES2Initializer> g_gles2_initializer(
base::LINKER_INITIALIZED);
@@ -257,9 +354,12 @@ RendererGLContext::RendererGLContext(GpuChannelHost* channel,
parent_(parent ?
parent->AsWeakPtr() : base::WeakPtr<RendererGLContext>()),
parent_texture_id_(0),
+ child_to_parent_latch_(kInvalidLatchId),
+ parent_to_child_latch_(kInvalidLatchId),
+ latch_transfer_buffer_id_(-1),
command_buffer_(NULL),
gles2_helper_(NULL),
- transfer_buffer_id_(0),
+ transfer_buffer_id_(-1),
gles2_implementation_(NULL),
last_error_(SUCCESS) {
DCHECK(channel);
@@ -361,7 +461,8 @@ bool RendererGLContext::Initialize(bool onscreen,
// Create a transfer buffer used to copy resources between the renderer
// process and the GPU process.
transfer_buffer_id_ =
- command_buffer_->CreateTransferBuffer(kTransferBufferSize);
+ command_buffer_->CreateTransferBuffer(kTransferBufferSize,
+ gpu::kCommandBufferSharedMemoryId);
if (transfer_buffer_id_ < 0) {
Destroy();
return false;
@@ -375,6 +476,26 @@ bool RendererGLContext::Initialize(bool onscreen,
return false;
}
+ // Register transfer buffer so that the context can access latches.
+ LatchAllocator* latch_shm = LatchAllocator::GetInstance();
+ latch_transfer_buffer_id_ = command_buffer_->RegisterTransferBuffer(
+ latch_shm->shared_memory(), LatchAllocator::size(),
+ gpu::kLatchSharedMemoryId);
+ if (latch_transfer_buffer_id_ != gpu::kLatchSharedMemoryId) {
+ Destroy();
+ return false;
+ }
+
+ // If this is a child context, setup latches for synchronization between child
+ // and parent.
+ if (parent_.get()) {
+ if (!CreateLatch(&child_to_parent_latch_) ||
+ !CreateLatch(&parent_to_child_latch_)) {
+ Destroy();
+ return false;
+ }
+ }
+
// Create the object exposing the OpenGL API.
gles2_implementation_ = new gpu::gles2::GLES2Implementation(
gles2_helper_,
@@ -389,15 +510,30 @@ bool RendererGLContext::Initialize(bool onscreen,
}
void RendererGLContext::Destroy() {
- if (parent_.get() && parent_texture_id_ != 0)
+ if (parent_.get() && parent_texture_id_ != 0) {
parent_->gles2_implementation_->FreeTextureId(parent_texture_id_);
+ parent_texture_id_ = 0;
+ }
delete gles2_implementation_;
gles2_implementation_ = NULL;
- if (command_buffer_ && transfer_buffer_id_ != 0) {
+ if (child_to_parent_latch_ != kInvalidLatchId) {
+ DestroyLatch(child_to_parent_latch_);
+ child_to_parent_latch_ = kInvalidLatchId;
+ }
+ if (parent_to_child_latch_ != kInvalidLatchId) {
+ DestroyLatch(parent_to_child_latch_);
+ parent_to_child_latch_ = kInvalidLatchId;
+ }
+ if (command_buffer_ && latch_transfer_buffer_id_ != -1) {
+ command_buffer_->DestroyTransferBuffer(latch_transfer_buffer_id_);
+ latch_transfer_buffer_id_ = -1;
+ }
+
+ if (command_buffer_ && transfer_buffer_id_ != -1) {
command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
- transfer_buffer_id_ = 0;
+ transfer_buffer_id_ = -1;
}
delete gles2_helper_;
@@ -420,3 +556,28 @@ void RendererGLContext::OnContextLost() {
if (context_lost_callback_.get())
context_lost_callback_->Run();
}
+
+bool RendererGLContext::CreateLatch(uint32* ret_latch) {
+ return LatchAllocator::GetInstance()->AllocateLatch(ret_latch);
+}
+
+bool RendererGLContext::DestroyLatch(uint32 latch) {
+ return LatchAllocator::GetInstance()->FreeLatch(latch);
+}
+
+bool RendererGLContext::GetParentToChildLatch(uint32* parent_to_child_latch) {
+ if (parent_.get()) {
+ *parent_to_child_latch = parent_to_child_latch_;
+ return true;
+ }
+ return false;
+}
+
+bool RendererGLContext::GetChildToParentLatch(uint32* child_to_parent_latch) {
+ if (parent_.get()) {
+ *child_to_parent_latch = child_to_parent_latch_;
+ return true;
+ }
+ return false;
+}
+
diff --git a/content/renderer/renderer_gl_context.h b/content/renderer/renderer_gl_context.h
index f03fa40..a40f5e1 100644
--- a/content/renderer/renderer_gl_context.h
+++ b/content/renderer/renderer_gl_context.h
@@ -185,6 +185,21 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
CommandBufferProxy* GetCommandBufferProxy();
+ // Create a latch for synchronization between contexts using glSetLatch and
+ // glWaitLatch.
+ // CreateLatch will only fail if there is a generally unrecoverable
+ // error, in which case 0 is returned. Returns latch_id on success.
+ bool CreateLatch(uint32* ret_latch);
+
+ // Destroy a latch.
+ bool DestroyLatch(uint32 latch);
+
+ // All child contexts get a latch pair automatically. These latches are used
+ // for synchronization with parent context. If *this* context does not have a
+ // parent context, these methods will return false.
+ bool GetParentToChildLatch(uint32* parent_to_child_latch);
+ bool GetChildToParentLatch(uint32* child_to_parent_latch);
+
private:
RendererGLContext(GpuChannelHost* channel,
RendererGLContext* parent);
@@ -205,6 +220,9 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> {
scoped_ptr<Callback0::Type> swap_buffers_callback_;
scoped_ptr<Callback0::Type> context_lost_callback_;
uint32 parent_texture_id_;
+ uint32 child_to_parent_latch_;
+ uint32 parent_to_child_latch_;
+ int32 latch_transfer_buffer_id_;
CommandBufferProxy* command_buffer_;
gpu::gles2::GLES2CmdHelper* gles2_helper_;
int32 transfer_buffer_id_;
diff --git a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
index ad4cec0..6f23d2da 100644
--- a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc
@@ -340,6 +340,41 @@ void WebGraphicsContext3DCommandBufferImpl::copyTextureToParentTextureCHROMIUM(
copyTextureToCompositor(texture, parentTexture);
}
+void WebGraphicsContext3DCommandBufferImpl::getParentToChildLatchCHROMIUM(
+ WGC3Duint* latch_id)
+{
+ if (!context_->GetParentToChildLatch(latch_id)) {
+ LOG(ERROR) << "getLatch must only be called on child context";
+ synthesizeGLError(GL_INVALID_OPERATION);
+ *latch_id = 0xffffffffu;
+ }
+}
+
+void WebGraphicsContext3DCommandBufferImpl::getChildToParentLatchCHROMIUM(
+ WGC3Duint* latch_id)
+{
+ if (!context_->GetChildToParentLatch(latch_id)) {
+ LOG(ERROR) << "getLatch must only be called on child context";
+ synthesizeGLError(GL_INVALID_OPERATION);
+ *latch_id = 0xffffffffu;
+ }
+}
+
+void WebGraphicsContext3DCommandBufferImpl::waitLatchCHROMIUM(
+ WGC3Duint latch_id)
+{
+ makeContextCurrent();
+ glWaitLatchCHROMIUM(latch_id);
+}
+
+void WebGraphicsContext3DCommandBufferImpl::setLatchCHROMIUM(
+ WGC3Duint latch_id)
+{
+ makeContextCurrent();
+ glSetLatchCHROMIUM(latch_id);
+ glFlush(); // required to ensure set command is sent to GPU process
+}
+
WebKit::WebString WebGraphicsContext3DCommandBufferImpl::
getRequestableExtensionsCHROMIUM() {
return WebKit::WebString::fromUTF8(glGetRequestableExtensionsCHROMIUM());
diff --git a/content/renderer/webgraphicscontext3d_command_buffer_impl.h b/content/renderer/webgraphicscontext3d_command_buffer_impl.h
index f1cdc00..93c70ca 100644
--- a/content/renderer/webgraphicscontext3d_command_buffer_impl.h
+++ b/content/renderer/webgraphicscontext3d_command_buffer_impl.h
@@ -403,6 +403,11 @@ class WebGraphicsContext3DCommandBufferImpl
virtual void copyTextureToParentTextureCHROMIUM(
WebGLId texture, WebGLId parentTexture);
+ virtual void getParentToChildLatchCHROMIUM(WGC3Duint* latch_id);
+ virtual void getChildToParentLatchCHROMIUM(WGC3Duint* latch_id);
+ virtual void waitLatchCHROMIUM(WGC3Duint latch_id);
+ virtual void setLatchCHROMIUM(WGC3Duint latch_id);
+
virtual WebKit::WebString getRequestableExtensionsCHROMIUM();
virtual void requestExtensionCHROMIUM(const char*);