Chromium Code Reviews| Index: content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc |
| diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc |
| index 52e99bc21546408ace761a6098daef49a0b268e6..97d79bef2b8a905b5854bc79e8347e4110911d33 100644 |
| --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc |
| +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc |
| @@ -22,7 +22,6 @@ |
| #include "base/message_loop/message_loop.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram.h" |
| -#include "base/synchronization/lock.h" |
| #include "content/common/gpu/client/gpu_channel_host.h" |
| #include "content/public/common/content_constants.h" |
| #include "content/public/common/content_switches.h" |
| @@ -202,13 +201,21 @@ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits() |
| max_transfer_buffer_size(kDefaultMaxTransferBufferSize), |
| mapped_memory_reclaim_limit(gpu::gles2::GLES2Implementation::kNoLimit) {} |
| +WebGraphicsContext3DCommandBufferImpl::ShareGroup::ShareGroup() { |
| +} |
| + |
| +WebGraphicsContext3DCommandBufferImpl::ShareGroup::~ShareGroup() { |
| + DCHECK(contexts_.empty()); |
| +} |
| + |
| WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( |
| int surface_id, |
| const GURL& active_url, |
| GpuChannelHost* host, |
| const Attributes& attributes, |
| bool bind_generates_resources, |
| - const SharedMemoryLimits& limits) |
| + const SharedMemoryLimits& limits, |
| + WebGraphicsContext3DCommandBufferImpl* share_context) |
| : initialize_failed_(false), |
| visible_(false), |
| host_(host), |
| @@ -226,6 +233,12 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( |
| bind_generates_resources_(bind_generates_resources), |
| mem_limits_(limits), |
| flush_id_(0) { |
| + if (share_context) { |
| + share_group_ = share_context->share_group_; |
| + } else { |
| + share_group_ = attributes_.shareResources ? NULL |
| + : new ShareGroup(); |
| + } |
| } |
| WebGraphicsContext3DCommandBufferImpl:: |
| @@ -295,19 +308,26 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() { |
| } |
| bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( |
| - bool onscreen) { |
| + bool onscreen, WebGraphicsContext3DCommandBufferImpl* share_context) { |
| if (!host_.get()) |
| return false; |
| + |
| + CommandBufferProxyImpl* share_group_command_buffer = NULL; |
| + |
| + if (share_context) { |
| + share_group_command_buffer = share_context->command_buffer_.get(); |
| + } |
| + |
| // We need to lock g_all_shared_contexts to ensure that the context we picked |
| // for our share group isn't deleted. |
| // (There's also a lock in our destructor.) |
| base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| - CommandBufferProxyImpl* share_group = NULL; |
| - if (attributes_.shareResources) { |
| + |
| + if (attributes_.shareResources && !share_group_command_buffer) { |
| ContextMap& all_contexts = g_all_shared_contexts.Get(); |
| ContextMap::const_iterator it = all_contexts.find(host_.get()); |
| if (it != all_contexts.end()) |
| - share_group = it->second->command_buffer_.get(); |
| + share_group_command_buffer = it->second->command_buffer_.get(); |
| } |
| std::vector<int32> attribs; |
| @@ -329,14 +349,14 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( |
| if (onscreen) { |
| command_buffer_.reset(host_->CreateViewCommandBuffer( |
| surface_id_, |
| - share_group, |
| + share_group_command_buffer, |
| attribs, |
| active_url_, |
| gpu_preference_)); |
| } else { |
| command_buffer_.reset(host_->CreateOffscreenCommandBuffer( |
| gfx::Size(1, 1), |
| - share_group, |
| + share_group_command_buffer, |
| attribs, |
| active_url_, |
| gpu_preference_)); |
| @@ -349,14 +369,29 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( |
| return command_buffer_->Initialize(); |
| } |
| -bool WebGraphicsContext3DCommandBufferImpl::CreateContext( |
| - bool onscreen) { |
| +bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) { |
| // Ensure the gles2 library is initialized first in a thread safe way. |
| g_gles2_initializer.Get(); |
| - if (!command_buffer_ && |
| - !InitializeCommandBuffer(onscreen)) { |
| - return false; |
| + scoped_refptr<gpu::gles2::ShareGroup> gles2_share_group; |
| + |
| + if (!command_buffer_) { |
| + scoped_ptr<base::AutoLock> share_group_lock; |
| + WebGraphicsContext3DCommandBufferImpl* share_context = NULL; |
| + |
| + if (share_group_) { |
| + share_group_lock.reset(new base::AutoLock(share_group_->lock())); |
| + share_context = share_group_->GetAnyContext(); |
| + } |
| + |
| + if (!InitializeCommandBuffer(onscreen, share_context)) |
| + return false; |
| + |
| + if (share_context) |
| + gles2_share_group = share_context->GetImplementation()->share_group(); |
| + |
| + if (share_group_) |
| + share_group_->AddContext(this); |
| } |
|
piman
2013/12/12 23:56:39
So, there is a race risk here.
After you release t
bajones
2013/12/13 00:17:20
I like it! I was thinking about replacing g_all_sh
|
| // Create the GLES2 helper, which writes the command buffer protocol. |
| @@ -373,16 +408,16 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( |
| DCHECK(host_.get()); |
| scoped_ptr<base::AutoLock> lock; |
| - scoped_refptr<gpu::gles2::ShareGroup> share_group; |
| - if (attributes_.shareResources) { |
| + |
| + if (attributes_.shareResources && !gles2_share_group) { |
| // Make sure two clients don't try to create a new ShareGroup |
| // simultaneously. |
| lock.reset(new base::AutoLock(g_all_shared_contexts_lock.Get())); |
| ContextMap& all_contexts = g_all_shared_contexts.Get(); |
| ContextMap::const_iterator it = all_contexts.find(host_.get()); |
| if (it != all_contexts.end()) { |
| - share_group = it->second->GetImplementation()->share_group(); |
| - DCHECK(share_group); |
| + gles2_share_group = it->second->GetImplementation()->share_group(); |
| + DCHECK(gles2_share_group); |
| } |
| } |
| @@ -393,7 +428,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( |
| // Create the object exposing the OpenGL API. |
| real_gl_.reset(new gpu::gles2::GLES2Implementation( |
| gles2_helper_.get(), |
| - share_group, |
| + gles2_share_group, |
| transfer_buffer_.get(), |
| bind_generates_resources_, |
| free_command_buffer_when_invisible, |
| @@ -440,6 +475,10 @@ uint32_t WebGraphicsContext3DCommandBufferImpl::lastFlushID() { |
| DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int) |
| void WebGraphicsContext3DCommandBufferImpl::Destroy() { |
| + if (share_group_) { |
| + share_group_->RemoveContext(this); |
| + } |
| + |
| if (host_.get()) { |
| base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| ContextMap& all_contexts = g_all_shared_contexts.Get(); |
| @@ -1192,15 +1231,24 @@ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( |
| GpuChannelHost* host, |
| const WebGraphicsContext3D::Attributes& attributes, |
| const GURL& active_url, |
| - const SharedMemoryLimits& limits) { |
| + const SharedMemoryLimits& limits, |
| + WebGraphicsContext3D* share_context) { |
|
piman
2013/12/12 23:56:39
nit: pass a WebGraphicsContext3DCommandBufferImpl
|
| if (!host) |
| return NULL; |
| + |
| + WebGraphicsContext3DCommandBufferImpl* share_context_impl = NULL; |
| + if (share_context) { |
| + share_context_impl = |
| + static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context); |
| + } |
| + |
| return new WebGraphicsContext3DCommandBufferImpl(0, |
| active_url, |
| host, |
| attributes, |
| false, |
| - limits); |
| + limits, |
| + share_context_impl); |
| } |
| DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM, |
| @@ -1370,6 +1418,9 @@ void WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost() { |
| base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| g_all_shared_contexts.Get().erase(host_.get()); |
| } |
| + |
| + if (share_group_) |
| + share_group_->RemoveAllContexts(); |
| } |
| void WebGraphicsContext3DCommandBufferImpl::OnErrorMessage( |