Index: content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc |
diff --git a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc |
index fb4cdb352914feaf3ebc39189e7608d886cc2b86..c61a79afd21aa6534c9d785fa9b503ad3efbe93d 100644 |
--- a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc |
+++ b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc |
@@ -21,6 +21,7 @@ |
#include "base/debug/trace_event.h" |
#include "base/logging.h" |
#include "base/metrics/histogram.h" |
+#include "base/synchronization/lock.h" |
#include "content/common/content_switches.h" |
#include "content/renderer/gpu/gpu_channel_host.h" |
#include "content/renderer/render_thread.h" |
@@ -32,11 +33,14 @@ |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
#include "webkit/glue/gl_bindings_skia_cmd_buffer.h" |
+static base::LazyInstance<base::Lock> |
+ g_all_shared_contexts_lock(base::LINKER_INITIALIZED); |
static base::LazyInstance<std::set<WebGraphicsContext3DCommandBufferImpl*> > |
g_all_shared_contexts(base::LINKER_INITIALIZED); |
WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl() |
- : context_(NULL), |
+ : initialize_failed_(false), |
+ context_(NULL), |
gl_(NULL), |
#ifndef WTF_USE_THREADED_COMPOSITING |
web_view_(NULL), |
@@ -55,7 +59,10 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl() |
WebGraphicsContext3DCommandBufferImpl:: |
~WebGraphicsContext3DCommandBufferImpl() { |
- g_all_shared_contexts.Pointer()->erase(this); |
+ { |
+ base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
+ g_all_shared_contexts.Pointer()->erase(this); |
+ } |
delete context_; |
} |
@@ -71,39 +78,19 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( |
WebGraphicsContext3D::Attributes attributes, |
WebKit::WebView* web_view, |
bool render_directly_to_web_view) { |
+ DCHECK(!context_); |
TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::initialize"); |
RenderThread* render_thread = RenderThread::current(); |
if (!render_thread) |
return false; |
- GpuChannelHost* host = render_thread->EstablishGpuChannelSync( |
+ host_ = render_thread->EstablishGpuChannelSync( |
content:: |
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); |
- if (!host) |
+ if (!host_) |
return false; |
- DCHECK(host->state() == GpuChannelHost::kConnected); |
- |
- // Convert WebGL context creation attributes into RendererGLContext / EGL size |
- // requests. |
- const int alpha_size = attributes.alpha ? 8 : 0; |
- const int depth_size = attributes.depth ? 24 : 0; |
- const int stencil_size = attributes.stencil ? 8 : 0; |
- const int samples = attributes.antialias ? 4 : 0; |
- const int sample_buffers = attributes.antialias ? 1 : 0; |
- const int32 attribs[] = { |
- RendererGLContext::ALPHA_SIZE, alpha_size, |
- RendererGLContext::DEPTH_SIZE, depth_size, |
- RendererGLContext::STENCIL_SIZE, stencil_size, |
- RendererGLContext::SAMPLES, samples, |
- RendererGLContext::SAMPLE_BUFFERS, sample_buffers, |
- RendererGLContext::SHARE_RESOURCES, attributes.shareResources ? 1 : 0, |
- RendererGLContext::BIND_GENERATES_RESOURCES, 0, |
- RendererGLContext::NONE, |
- }; |
- |
- const char* preferred_extensions = attributes.noExtensions ? |
- kWebGLPreferredGLExtensions : "*"; |
+ DCHECK(host_->state() == GpuChannelHost::kConnected); |
- const GPUInfo& gpu_info = host->gpu_info(); |
+ const GPUInfo& gpu_info = host_->gpu_info(); |
UMA_HISTOGRAM_ENUMERATION( |
"GPU.WebGraphicsContext3D_Init_CanLoseContext", |
attributes.canRecoverFromContextLoss * 2 + gpu_info.can_lose_context, |
@@ -113,43 +100,82 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( |
return false; |
} |
- GURL active_url; |
if (web_view && web_view->mainFrame()) |
- active_url = GURL(web_view->mainFrame()->document().url()); |
- |
- RendererGLContext* share_group = NULL; |
- if (attributes.shareResources) { |
- share_group = g_all_shared_contexts.Pointer()->empty() ? |
- NULL : (*g_all_shared_contexts.Pointer()->begin())->context_; |
- } |
+ active_url_ = GURL(web_view->mainFrame()->document().url()); |
+ attributes_ = attributes; |
render_directly_to_web_view_ = render_directly_to_web_view; |
- if (render_directly_to_web_view) { |
-#ifndef WTF_USE_THREADED_COMPOSITING |
- RenderView* renderview = RenderView::FromWebView(web_view); |
- if (!renderview) |
+ if (render_directly_to_web_view_) { |
+ RenderView* render_view = RenderView::FromWebView(web_view); |
+ if (!render_view) |
return false; |
- web_view_ = web_view; |
-#endif |
- context_ = RendererGLContext::CreateViewContext( |
- host, |
- renderview->routing_id(), |
- share_group, |
- preferred_extensions, |
- attribs, |
- active_url); |
- } else { |
- context_ = RendererGLContext::CreateOffscreenContext( |
- host, |
- gfx::Size(1, 1), |
- share_group, |
- preferred_extensions, |
- attribs, |
- active_url); |
+ render_view_routing_id_ = render_view->routing_id(); |
#ifndef WTF_USE_THREADED_COMPOSITING |
- web_view_ = NULL; |
+ web_view_ = web_view; |
#endif |
} |
+ return true; |
+} |
+ |
+bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() { |
+ if (context_) |
+ return true; |
+ if (initialize_failed_) |
+ return false; |
+ |
+ TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL"); |
+ |
+ // Convert WebGL context creation attributes into RendererGLContext / EGL size |
+ // requests. |
+ const int alpha_size = attributes_.alpha ? 8 : 0; |
+ const int depth_size = attributes_.depth ? 24 : 0; |
+ const int stencil_size = attributes_.stencil ? 8 : 0; |
+ const int samples = attributes_.antialias ? 4 : 0; |
+ const int sample_buffers = attributes_.antialias ? 1 : 0; |
+ const int32 attribs[] = { |
+ RendererGLContext::ALPHA_SIZE, alpha_size, |
+ RendererGLContext::DEPTH_SIZE, depth_size, |
+ RendererGLContext::STENCIL_SIZE, stencil_size, |
+ RendererGLContext::SAMPLES, samples, |
+ RendererGLContext::SAMPLE_BUFFERS, sample_buffers, |
+ RendererGLContext::SHARE_RESOURCES, attributes_.shareResources ? 1 : 0, |
+ RendererGLContext::BIND_GENERATES_RESOURCES, 0, |
+ RendererGLContext::NONE, |
+ }; |
+ |
+ const char* preferred_extensions = attributes_.noExtensions ? |
+ kWebGLPreferredGLExtensions : "*"; |
+ |
+ // We need to lock g_all_shared_contexts until after RendererGLContext::Create |
+ // 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()); |
+ RendererGLContext* share_group = NULL; |
+ if (attributes_.shareResources) { |
+ share_group = g_all_shared_contexts.Pointer()->empty() ? |
+ NULL : (*g_all_shared_contexts.Pointer()->begin())->context_; |
+ } |
+ |
+ if (render_directly_to_web_view_) { |
+ context_ = RendererGLContext::CreateViewContext( |
+ host_, |
+ render_view_routing_id_, |
+ share_group, |
+ preferred_extensions, |
+ attribs, |
+ active_url_); |
+ } else { |
+ context_ = RendererGLContext::CreateOffscreenContext( |
+ host_, |
+ gfx::Size(1, 1), |
+ share_group, |
+ preferred_extensions, |
+ attribs, |
+ active_url_); |
+ } |
+ } |
+ |
if (!context_) |
return false; |
@@ -166,7 +192,6 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( |
// Set attributes_ from created offscreen context. |
{ |
- attributes_ = attributes; |
GLint alpha_bits = 0; |
getIntegerv(GL_ALPHA_BITS, &alpha_bits); |
attributes_.alpha = alpha_bits > 0; |
@@ -181,13 +206,17 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( |
attributes_.antialias = samples > 0; |
} |
- if (attributes.shareResources) |
+ if (attributes_.shareResources) { |
+ base::AutoLock lock(g_all_shared_contexts_lock.Get()); |
g_all_shared_contexts.Pointer()->insert(this); |
+ } |
return true; |
} |
bool WebGraphicsContext3DCommandBufferImpl::makeContextCurrent() { |
+ if (!MaybeInitializeGL()) |
+ return false; |
return RendererGLContext::MakeCurrent(context_); |
} |
@@ -212,7 +241,6 @@ bool WebGraphicsContext3DCommandBufferImpl::setParentContext( |
} |
WebGLId WebGraphicsContext3DCommandBufferImpl::getPlatformTextureId() { |
- DCHECK(context_); |
return context_->GetParentTextureId(); |
} |
@@ -666,7 +694,8 @@ WGC3Denum WebGraphicsContext3DCommandBufferImpl::getError() { |
} |
bool WebGraphicsContext3DCommandBufferImpl::isContextLost() { |
- return context_->IsCommandBufferContextLost() || |
+ return initialize_failed_ || |
+ (context_ && context_->IsCommandBufferContextLost()) || |
context_lost_reason_ != GL_NO_ERROR; |
} |