summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-19 22:05:43 +0000
committerkbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-19 22:05:43 +0000
commit590cd0933bc5e650f7fcf94440201e7b8dcc9bbd (patch)
tree6fec35b29740bc2683733a0a6ad866289a50225d
parent2fdad49da6be57fa0c6d660fc9c5e94a6361edd1 (diff)
downloadchromium_src-590cd0933bc5e650f7fcf94440201e7b8dcc9bbd.zip
chromium_src-590cd0933bc5e650f7fcf94440201e7b8dcc9bbd.tar.gz
chromium_src-590cd0933bc5e650f7fcf94440201e7b8dcc9bbd.tar.bz2
Fixed bugs with Pepper 3D under dynamic GPU switching.
Made Pepper 3D context creation code fully aware of GPU switching and changed the order of context creation and and fetching of the parent context. Creating the context potentially causes all existing contexts for that renderer, including the parent, to be lost. Detect shutting down of the GPU channel more quickly on the renderer side. Only reject context creation in GLContextCGL upon GpuPreference mismatch if the system supports dual GPUs. Will update tools/histograms/histograms.xml as soon as this is committed; must occur in a separate CL. BUG=100507 TEST=tested navigating to and from, and reloading, NaCl Pepper 3D samples on Mac 10.6.8 and 10.7.1; WebGL tests Review URL: http://codereview.chromium.org/8342024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106394 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/common/gpu/gpu_process_launch_causes.h1
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/renderer/gpu/renderer_gl_context.cc4
-rw-r--r--content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc1
-rw-r--r--content/renderer/pepper_parent_context_provider.cc11
-rw-r--r--content/renderer/pepper_parent_context_provider.h27
-rw-r--r--content/renderer/pepper_platform_context_3d_impl.cc76
-rw-r--r--content/renderer/pepper_platform_context_3d_impl.h6
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.cc30
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.h7
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.cc17
-rw-r--r--content/renderer/render_widget_fullscreen_pepper.h7
-rw-r--r--ui/gfx/gl/gl_context_cgl.cc10
13 files changed, 151 insertions, 48 deletions
diff --git a/content/common/gpu/gpu_process_launch_causes.h b/content/common/gpu/gpu_process_launch_causes.h
index e9b3970..dfbd7e3 100644
--- a/content/common/gpu/gpu_process_launch_causes.h
+++ b/content/common/gpu/gpu_process_launch_causes.h
@@ -17,6 +17,7 @@ enum CauseForGpuLaunch {
CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETFULLSCREENPEPPER_CREATECONTEXT,
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE,
CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE,
+ CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE,
CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
CAUSE_FOR_GPU_LAUNCH_MAX_ENUM
};
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 69fce11..188f5fc 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -107,6 +107,8 @@
'renderer/notification_provider.h',
'renderer/paint_aggregator.cc',
'renderer/paint_aggregator.h',
+ 'renderer/pepper_parent_context_provider.cc',
+ 'renderer/pepper_parent_context_provider.h',
'renderer/pepper_platform_context_3d_impl.cc',
'renderer/pepper_platform_context_3d_impl.h',
'renderer/pepper_platform_video_decoder_impl.cc',
diff --git a/content/renderer/gpu/renderer_gl_context.cc b/content/renderer/gpu/renderer_gl_context.cc
index 97b100f..4bf402d 100644
--- a/content/renderer/gpu/renderer_gl_context.cc
+++ b/content/renderer/gpu/renderer_gl_context.cc
@@ -258,6 +258,10 @@ RendererGLContext::Error RendererGLContext::GetError() {
}
bool RendererGLContext::IsCommandBufferContextLost() {
+ // If the channel shut down unexpectedly, let that supersede the
+ // command buffer's state.
+ if (channel_->state() == GpuChannelHost::kLost)
+ return true;
gpu::CommandBuffer::State state = command_buffer_->GetLastState();
return state.error == gpu::error::kLostContext;
}
diff --git a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
index f9f1b72..cbd9d06 100644
--- a/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
+++ b/content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.cc
@@ -91,6 +91,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize(
bool retry = false;
+ // Note similar code in Pepper PlatformContext3DImpl::Init.
do {
host_ = render_thread->EstablishGpuChannelSync(
content::
diff --git a/content/renderer/pepper_parent_context_provider.cc b/content/renderer/pepper_parent_context_provider.cc
new file mode 100644
index 0000000..2b67469
--- /dev/null
+++ b/content/renderer/pepper_parent_context_provider.cc
@@ -0,0 +1,11 @@
+// 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.
+
+#include "content/renderer/pepper_parent_context_provider.h"
+
+PepperParentContextProvider::PepperParentContextProvider() {
+}
+
+PepperParentContextProvider::~PepperParentContextProvider() {
+}
diff --git a/content/renderer/pepper_parent_context_provider.h b/content/renderer/pepper_parent_context_provider.h
new file mode 100644
index 0000000..7a9c6fe
--- /dev/null
+++ b/content/renderer/pepper_parent_context_provider.h
@@ -0,0 +1,27 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_PEPPER_PARENT_CONTEXT_PROVIDER_H_
+#define CONTENT_RENDERER_PEPPER_PARENT_CONTEXT_PROVIDER_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+class RendererGLContext;
+
+// Defines the mechanism by which a Pepper 3D context fetches its
+// parent context for display to the screen.
+class PepperParentContextProvider {
+ public:
+ virtual ~PepperParentContextProvider();
+ virtual RendererGLContext* GetParentContextForPlatformContext3D() = 0;
+
+ protected:
+ PepperParentContextProvider();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PepperParentContextProvider);
+};
+
+#endif // CONTENT_RENDERER_PEPPER_PARENT_CONTEXT_PROVIDER_H_
diff --git a/content/renderer/pepper_platform_context_3d_impl.cc b/content/renderer/pepper_platform_context_3d_impl.cc
index 373418b..cba3c7b 100644
--- a/content/renderer/pepper_platform_context_3d_impl.cc
+++ b/content/renderer/pepper_platform_context_3d_impl.cc
@@ -5,6 +5,7 @@
#include "content/renderer/pepper_platform_context_3d_impl.h"
#include "base/bind.h"
+#include "content/renderer/pepper_parent_context_provider.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/gpu/renderer_gl_context.h"
#include "content/renderer/gpu/gpu_channel_host.h"
@@ -16,8 +17,9 @@
#ifdef ENABLE_GPU
-PlatformContext3DImpl::PlatformContext3DImpl(RendererGLContext* parent_context)
- : parent_context_(parent_context->AsWeakPtr()),
+PlatformContext3DImpl::PlatformContext3DImpl(
+ PepperParentContextProvider* parent_context_provider)
+ : parent_context_provider_(parent_context_provider),
parent_texture_id_(0),
command_buffer_(NULL),
weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
@@ -37,6 +39,9 @@ PlatformContext3DImpl::~PlatformContext3DImpl() {
DCHECK(channel_.get());
channel_->DestroyCommandBuffer(command_buffer_);
command_buffer_ = NULL;
+ if (channel_->WillGpuSwitchOccur(false, gfx::PreferDiscreteGpu)) {
+ channel_->ForciblyCloseChannel();
+ }
}
channel_ = NULL;
@@ -47,26 +52,35 @@ bool PlatformContext3DImpl::Init(const int32* attrib_list) {
if (command_buffer_)
return true;
- // Parent may already have been deleted.
- if (!parent_context_.get())
+ if (!parent_context_provider_)
return false;
RenderThreadImpl* render_thread = RenderThreadImpl::current();
if (!render_thread)
return false;
- channel_ = render_thread->GetGpuChannel();
- if (!channel_.get())
- return false;
-
- DCHECK(channel_->state() == GpuChannelHost::kConnected);
-
- // Flush any remaining commands in the parent context to make sure the
- // texture id accounting stays consistent.
- gpu::gles2::GLES2Implementation* parent_gles2 =
- parent_context_->GetImplementation();
- parent_gles2->helper()->CommandBufferHelper::Finish();
- parent_texture_id_ = parent_gles2->MakeTextureId();
+ bool retry = false;
+ gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
+
+ // Note similar code in WebGraphicsContext3DCommandBufferImpl::initialize.
+ do {
+ channel_ = render_thread->EstablishGpuChannelSync(
+ content::CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE);
+ if (!channel_.get())
+ return false;
+ DCHECK(channel_->state() == GpuChannelHost::kConnected);
+ if (!retry) {
+ // If the creation of this context requires all contexts for this
+ // renderer to be destroyed on the GPU process side, then drop the
+ // channel and recreate it.
+ if (channel_->WillGpuSwitchOccur(true, gpu_preference)) {
+ channel_->ForciblyCloseChannel();
+ retry = true;
+ }
+ } else {
+ retry = false;
+ }
+ } while (retry);
gfx::Size surface_size;
std::vector<int32> attribs;
@@ -93,25 +107,43 @@ bool PlatformContext3DImpl::Init(const int32* attrib_list) {
attribs.push_back(RendererGLContext::NONE);
}
- CommandBufferProxy* parent_command_buffer =
- parent_context_->GetCommandBufferProxy();
command_buffer_ = channel_->CreateOffscreenCommandBuffer(
surface_size,
NULL,
"*",
attribs,
GURL::EmptyGURL(),
- gfx::PreferDiscreteGpu);
+ gpu_preference);
if (!command_buffer_)
return false;
- if (!command_buffer_->SetParent(parent_command_buffer, parent_texture_id_))
- return false;
-
command_buffer_->SetChannelErrorCallback(
base::Bind(&PlatformContext3DImpl::OnContextLost,
weak_ptr_factory_.GetWeakPtr()));
+ // Fetch the parent context now, after any potential shutdown of the
+ // channel due to GPU switching, and creation of the Pepper 3D
+ // context with the discrete GPU preference.
+ RendererGLContext* parent_context =
+ parent_context_provider_->GetParentContextForPlatformContext3D();
+ if (!parent_context)
+ return false;
+
+ parent_context_provider_ = NULL;
+ parent_context_ = parent_context->AsWeakPtr();
+
+ // Flush any remaining commands in the parent context to make sure the
+ // texture id accounting stays consistent.
+ gpu::gles2::GLES2Implementation* parent_gles2 =
+ parent_context_->GetImplementation();
+ parent_gles2->helper()->CommandBufferHelper::Finish();
+ parent_texture_id_ = parent_gles2->MakeTextureId();
+
+ CommandBufferProxy* parent_command_buffer =
+ parent_context_->GetCommandBufferProxy();
+ if (!command_buffer_->SetParent(parent_command_buffer, parent_texture_id_))
+ return false;
+
return true;
}
diff --git a/content/renderer/pepper_platform_context_3d_impl.h b/content/renderer/pepper_platform_context_3d_impl.h
index ff4c1c2..8f8937e 100644
--- a/content/renderer/pepper_platform_context_3d_impl.h
+++ b/content/renderer/pepper_platform_context_3d_impl.h
@@ -19,12 +19,14 @@ class CommandBuffer;
class CommandBufferProxy;
class GpuChannelHost;
+class PepperParentContextProvider;
class RendererGLContext;
class PlatformContext3DImpl
: public webkit::ppapi::PluginDelegate::PlatformContext3D {
public:
- explicit PlatformContext3DImpl(RendererGLContext* parent_context);
+ explicit PlatformContext3DImpl(
+ PepperParentContextProvider* parent_context_provider);
virtual ~PlatformContext3DImpl();
virtual bool Init(const int32* attrib_list);
@@ -38,6 +40,8 @@ class PlatformContext3DImpl
bool InitRaw();
void OnContextLost();
+ // Implicitly weak pointer; must outlive this instance.
+ PepperParentContextProvider* parent_context_provider_;
base::WeakPtr<RendererGLContext> parent_context_;
scoped_refptr<GpuChannelHost> channel_;
unsigned int parent_texture_id_;
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc
index 0a0e621..9206bcc 100644
--- a/content/renderer/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper_plugin_delegate_impl.cc
@@ -1033,19 +1033,7 @@ webkit::ppapi::PluginDelegate::PlatformContext3D*
// modules.
if (!render_view_->webkit_preferences().accelerated_plugins_enabled)
return NULL;
- WebGraphicsContext3DCommandBufferImpl* context =
- static_cast<WebGraphicsContext3DCommandBufferImpl*>(
- render_view_->webview()->graphicsContext3D());
- if (!context)
- return NULL;
- if (!context->makeContextCurrent() || context->isContextLost())
- return NULL;
-
- RendererGLContext* parent_context = context->context();
- if (!parent_context)
- return NULL;
-
- return new PlatformContext3DImpl(parent_context);
+ return new PlatformContext3DImpl(this);
#else
return NULL;
#endif
@@ -1753,6 +1741,22 @@ int PepperPluginDelegateImpl::GetRoutingId() const {
return render_view_->routing_id();
}
+RendererGLContext*
+PepperPluginDelegateImpl::GetParentContextForPlatformContext3D() {
+ WebGraphicsContext3DCommandBufferImpl* context =
+ static_cast<WebGraphicsContext3DCommandBufferImpl*>(
+ render_view_->webview()->graphicsContext3D());
+ if (!context)
+ return NULL;
+ if (!context->makeContextCurrent() || context->isContextLost())
+ return NULL;
+
+ RendererGLContext* parent_context = context->context();
+ if (!parent_context)
+ return NULL;
+ return parent_context;
+}
+
void PepperPluginDelegateImpl::PublishInitialPolicy(
scoped_refptr<webkit::ppapi::PluginInstance> instance,
const std::string& policy) {
diff --git a/content/renderer/pepper_plugin_delegate_impl.h b/content/renderer/pepper_plugin_delegate_impl.h
index 4054433..84ec4b7 100644
--- a/content/renderer/pepper_plugin_delegate_impl.h
+++ b/content/renderer/pepper_plugin_delegate_impl.h
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/renderer/pepper_parent_context_provider.h"
#include "ppapi/proxy/broker_dispatcher.h"
#include "ppapi/proxy/proxy_channel.h"
#include "ui/base/ime/text_input_type.h"
@@ -119,7 +120,8 @@ class PpapiBrokerImpl : public webkit::ppapi::PluginDelegate::PpapiBroker,
class PepperPluginDelegateImpl
: public webkit::ppapi::PluginDelegate,
- public base::SupportsWeakPtr<PepperPluginDelegateImpl> {
+ public base::SupportsWeakPtr<PepperPluginDelegateImpl>,
+ public PepperParentContextProvider {
public:
explicit PepperPluginDelegateImpl(RenderViewImpl* render_view);
virtual ~PepperPluginDelegateImpl();
@@ -358,6 +360,9 @@ class PepperPluginDelegateImpl
return mouse_locked_ || pending_lock_request_ || pending_unlock_request_;
}
+ // Implementation of PepperParentContextProvider.
+ virtual RendererGLContext* GetParentContextForPlatformContext3D();
+
// Pointer to the RenderView that owns us.
RenderViewImpl* render_view_;
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index 088be94..9fe688d 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -277,13 +277,8 @@ void RenderWidgetFullscreenPepper::DidChangeCursor(
webkit::ppapi::PluginDelegate::PlatformContext3D*
RenderWidgetFullscreenPepper::CreateContext3D() {
- if (!context_) {
- CreateContext();
- }
- if (!context_)
- return NULL;
#ifdef ENABLE_GPU
- return new PlatformContext3DImpl(context_);
+ return new PlatformContext3DImpl(this);
#else
return NULL;
#endif
@@ -513,3 +508,13 @@ void RenderWidgetFullscreenPepper::OnLostContext(
void RenderWidgetFullscreenPepper::OnSwapBuffersCompleteByRendererGLContext() {
OnSwapBuffersComplete();
}
+
+RendererGLContext*
+RenderWidgetFullscreenPepper::GetParentContextForPlatformContext3D() {
+ if (!context_) {
+ CreateContext();
+ }
+ if (!context_)
+ return NULL;
+ return context_;
+}
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h
index 867de9b..5d47ec9 100644
--- a/content/renderer/render_widget_fullscreen_pepper.h
+++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_RENDER_WIDGET_FULLSCREEN_PEPPER_H_
#include "base/memory/weak_ptr.h"
+#include "content/renderer/pepper_parent_context_provider.h"
#include "content/renderer/render_widget_fullscreen.h"
#include "content/renderer/gpu/renderer_gl_context.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
@@ -23,7 +24,8 @@ class PluginInstance;
// FullscreenContainer that the plugin instance can callback into to e.g.
// invalidate rects.
class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
- public webkit::ppapi::FullscreenContainer {
+ public webkit::ppapi::FullscreenContainer,
+ public PepperParentContextProvider {
public:
static RenderWidgetFullscreenPepper* Create(
int32 opener_id,
@@ -86,6 +88,9 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
// RenderWidget::OnSwapBuffersCompleted.
void OnSwapBuffersCompleteByRendererGLContext();
+ // Implementation of PepperParentContextProvider.
+ virtual RendererGLContext* GetParentContextForPlatformContext3D();
+
// URL that is responsible for this widget, passed to ggl::CreateViewContext.
GURL active_url_;
diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc
index 86933b64..0e96bd4 100644
--- a/ui/gfx/gl/gl_context_cgl.cc
+++ b/ui/gfx/gl/gl_context_cgl.cc
@@ -26,12 +26,14 @@ bool GLContextCGL::Initialize(
GLSurface* compatible_surface, GpuPreference gpu_preference) {
DCHECK(compatible_surface);
- // Ensure the GPU preference is compatible with contexts already in the
- // share group.
GLContextCGL* share_context = share_group() ?
static_cast<GLContextCGL*>(share_group()->GetContext()) : NULL;
- if (share_context && gpu_preference != share_context->GetGpuPreference())
- return false;
+ if (SupportsDualGpus()) {
+ // Ensure the GPU preference is compatible with contexts already in the
+ // share group.
+ if (share_context && gpu_preference != share_context->GetGpuPreference())
+ return false;
+ }
std::vector<CGLPixelFormatAttribute> attribs;
attribs.push_back(kCGLPFAPBuffer);