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 8bd66189394dad6eda3df5b50ded1be4aae2d666..4fd08f16fc02e1246f57c77d780ad4721676f8ea 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" |
| @@ -43,13 +42,29 @@ namespace content { |
| namespace { |
| static base::LazyInstance<base::Lock>::Leaky |
| - g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER; |
| + g_default_share_groups_lock = LAZY_INSTANCE_INITIALIZER; |
| -typedef std::multimap<GpuChannelHost*, WebGraphicsContext3DCommandBufferImpl*> |
| - ContextMap; |
| -static base::LazyInstance<ContextMap> g_all_shared_contexts = |
| +typedef std::map<GpuChannelHost*, |
| + scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup> > |
| + ShareGroupMap; |
| +static base::LazyInstance<ShareGroupMap> g_default_share_groups = |
| LAZY_INSTANCE_INITIALIZER; |
| +scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup> |
| + GetDefaultShareGroupForHost(GpuChannelHost* host) { |
| + base::AutoLock lock(g_default_share_groups_lock.Get()); |
| + |
| + ShareGroupMap& share_groups = g_default_share_groups.Get(); |
| + ShareGroupMap::iterator it = share_groups.find(host); |
| + if (it == share_groups.end()) { |
| + scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup> group = |
| + new WebGraphicsContext3DCommandBufferImpl::ShareGroup(); |
| + share_groups[host] = group; |
| + return group; |
| + } |
| + return it->second; |
| +} |
| + |
| uint32_t GenFlushID() { |
| static base::subtle::Atomic32 flush_id = 0; |
| @@ -202,13 +217,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 +249,15 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( |
| bind_generates_resources_(bind_generates_resources), |
| mem_limits_(limits), |
| flush_id_(0) { |
| + if (share_context) { |
| + DCHECK(!attributes_.shareResources); |
| + share_group_ = share_context->share_group_; |
| + } else { |
| + share_group_ = attributes_.shareResources |
| + ? GetDefaultShareGroupForHost(host) |
| + : scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup>( |
| + new ShareGroup()); |
| + } |
| } |
| WebGraphicsContext3DCommandBufferImpl:: |
| @@ -295,19 +327,14 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() { |
| } |
| bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer( |
| - bool onscreen) { |
| + bool onscreen, WebGraphicsContext3DCommandBufferImpl* share_context) { |
| if (!host_.get()) |
| return false; |
| - // 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) { |
| - 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(); |
| + |
| + CommandBufferProxyImpl* share_group_command_buffer = NULL; |
| + |
| + if (share_context) { |
| + share_group_command_buffer = share_context->command_buffer_.get(); |
| } |
| std::vector<int32> attribs; |
| @@ -329,14 +356,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 +376,26 @@ 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; |
| + |
| + scoped_ptr<base::AutoLock> share_group_lock; |
| + if (!command_buffer_) { |
| + WebGraphicsContext3DCommandBufferImpl* share_context = NULL; |
| + |
| + share_group_lock.reset(new base::AutoLock(share_group_->lock())); |
| + share_context = share_group_->GetAnyContextLocked(); |
| + |
| + if (!InitializeCommandBuffer(onscreen, share_context)) |
| + return false; |
| + |
| + if (share_context) |
| + gles2_share_group = share_context->GetImplementation()->share_group(); |
| + |
| + share_group_->AddContextLocked(this); |
| } |
| // Create the GLES2 helper, which writes the command buffer protocol. |
| @@ -372,19 +411,6 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( |
| transfer_buffer_ .reset(new gpu::TransferBuffer(gles2_helper_.get())); |
| DCHECK(host_.get()); |
| - scoped_ptr<base::AutoLock> lock; |
| - scoped_refptr<gpu::gles2::ShareGroup> share_group; |
| - if (attributes_.shareResources) { |
| - // 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); |
| - } |
| - } |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| bool free_command_buffer_when_invisible = |
| @@ -393,19 +419,13 @@ 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, |
| command_buffer_.get())); |
| gl_ = real_gl_.get(); |
| - if (attributes_.shareResources) { |
| - // Don't add ourselves to the list before others can get to our ShareGroup. |
| - g_all_shared_contexts.Get().insert(std::make_pair(host_.get(), this)); |
| - lock.reset(); |
| - } |
| - |
| if (!real_gl_->Initialize( |
| mem_limits_.start_transfer_buffer_size, |
| mem_limits_.min_transfer_buffer_size, |
| @@ -440,17 +460,7 @@ uint32_t WebGraphicsContext3DCommandBufferImpl::lastFlushID() { |
| DELEGATE_TO_GL_R(insertSyncPoint, InsertSyncPointCHROMIUM, unsigned int) |
| void WebGraphicsContext3DCommandBufferImpl::Destroy() { |
| - if (host_.get()) { |
| - base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| - ContextMap& all_contexts = g_all_shared_contexts.Get(); |
| - ContextMap::iterator it = std::find( |
| - all_contexts.begin(), |
| - all_contexts.end(), |
| - std::pair<GpuChannelHost* const, |
| - WebGraphicsContext3DCommandBufferImpl*>(host_.get(), this)); |
| - if (it != all_contexts.end()) |
| - all_contexts.erase(it); |
| - } |
| + share_group_->RemoveContext(this); |
| if (gl_) { |
| // First flush the context to ensure that any pending frees of resources |
| @@ -1168,15 +1178,21 @@ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( |
| GpuChannelHost* host, |
| const WebGraphicsContext3D::Attributes& attributes, |
| const GURL& active_url, |
| - const SharedMemoryLimits& limits) { |
| + const SharedMemoryLimits& limits, |
| + WebGraphicsContext3DCommandBufferImpl* share_context) { |
| if (!host) |
| return NULL; |
| + |
| + if (share_context && share_context->IsCommandBufferContextLost()) |
| + return NULL; |
|
Ken Russell (switch to Gerrit)
2014/02/19 22:38:26
If this check is necessary, then it seems to me th
|
| + |
| return new WebGraphicsContext3DCommandBufferImpl(0, |
| active_url, |
| host, |
| attributes, |
| false, |
| - limits); |
| + limits, |
| + share_context); |
| } |
| DELEGATE_TO_GL_5(texImageIOSurface2DCHROMIUM, TexImageIOSurface2DCHROMIUM, |
| @@ -1349,10 +1365,12 @@ void WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost() { |
| context_lost_callback_->onContextLost(); |
| } |
| + share_group_->RemoveAllContexts(); |
| + |
| DCHECK(host_.get()); |
| { |
| - base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
| - g_all_shared_contexts.Get().erase(host_.get()); |
| + base::AutoLock lock(g_default_share_groups_lock.Get()); |
| + g_default_share_groups.Get().erase(host_.get()); |
| } |
| } |