diff options
author | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-12 20:09:57 +0000 |
---|---|---|
committer | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-12 20:09:57 +0000 |
commit | ce9eea60c922efff7c680a7a127480a799e06e94 (patch) | |
tree | 6e34093d78d48fe4d1132c4d8eef2817d32e2203 /content/renderer | |
parent | 8c3bd1d8c71d8432beb624ce1434ca962665de90 (diff) | |
download | chromium_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.cc | 9 | ||||
-rw-r--r-- | content/renderer/command_buffer_proxy.h | 5 | ||||
-rw-r--r-- | content/renderer/renderer_gl_context.cc | 171 | ||||
-rw-r--r-- | content/renderer/renderer_gl_context.h | 18 | ||||
-rw-r--r-- | content/renderer/webgraphicscontext3d_command_buffer_impl.cc | 35 | ||||
-rw-r--r-- | content/renderer/webgraphicscontext3d_command_buffer_impl.h | 5 |
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*); |