Chromium Code Reviews| Index: content/renderer/pepper_platform_context_3d_impl.cc |
| =================================================================== |
| --- content/renderer/pepper_platform_context_3d_impl.cc (revision 106079) |
| +++ content/renderer/pepper_platform_context_3d_impl.cc (working copy) |
| @@ -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 @@ |
| DCHECK(channel_.get()); |
| channel_->DestroyCommandBuffer(command_buffer_); |
| command_buffer_ = NULL; |
| + if (channel_->WillGpuSwitchOccur(false, gfx::PreferDiscreteGpu)) { |
| + channel_->ForciblyCloseChannel(); |
| + } |
| } |
| channel_ = NULL; |
| @@ -47,27 +52,36 @@ |
| 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; |
| + bool retry = false; |
| + gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
| - DCHECK(channel_->state() == GpuChannelHost::kConnected); |
| + // 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); |
| - // 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(); |
| - |
| gfx::Size surface_size; |
| std::vector<int32> attribs; |
| // TODO(alokp): Change GpuChannelHost::CreateOffscreenCommandBuffer() |
| @@ -93,25 +107,42 @@ |
| 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_ = parent_context->AsWeakPtr(); |
| + |
|
apatrick_chromium
2011/10/19 18:24:27
You could null parent_context_provider_ here since
Ken Russell (switch to Gerrit)
2011/10/19 22:04:45
Done.
|
| + // 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; |
| } |