1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/pepper/pepper_platform_context_3d_impl.h"
8 #include "content/common/gpu/client/context_provider_command_buffer.h"
9 #include "content/common/gpu/client/gpu_channel_host.h"
10 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
11 #include "content/renderer/render_thread_impl.h"
12 #include "googleurl/src/gurl.h"
13 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
14 #include "gpu/command_buffer/client/gles2_implementation.h"
15 #include "gpu/ipc/command_buffer_proxy.h"
16 #include "ppapi/c/pp_graphics_3d.h"
17 #include "ui/gl/gpu_preference.h"
23 PlatformContext3DImpl::PlatformContext3DImpl()
24 : parent_texture_id_(0),
26 command_buffer_(NULL
),
27 weak_ptr_factory_(this) {
30 PlatformContext3DImpl::~PlatformContext3DImpl() {
31 DestroyParentContextProviderAndBackingTexture();
33 if (command_buffer_
) {
34 DCHECK(channel_
.get());
35 channel_
->DestroyCommandBuffer(command_buffer_
);
36 command_buffer_
= NULL
;
42 bool PlatformContext3DImpl::Init(const int32
* attrib_list
,
43 PlatformContext3D
* share_context
) {
44 // Ignore initializing more than once.
48 RenderThreadImpl
* render_thread
= RenderThreadImpl::current();
52 gfx::GpuPreference gpu_preference
= gfx::PreferDiscreteGpu
;
54 channel_
= render_thread
->EstablishGpuChannelSync(
55 CAUSE_FOR_GPU_LAUNCH_PEPPERPLATFORMCONTEXT3DIMPL_INITIALIZE
);
58 DCHECK(channel_
->state() == GpuChannelHost::kConnected
);
60 gfx::Size surface_size
;
61 std::vector
<int32
> attribs
;
62 // TODO(alokp): Change GpuChannelHost::CreateOffscreenCommandBuffer()
63 // interface to accept width and height in the attrib_list so that
64 // we do not need to filter for width and height here.
66 for (const int32_t* attr
= attrib_list
;
67 attr
[0] != PP_GRAPHICS3DATTRIB_NONE
;
70 case PP_GRAPHICS3DATTRIB_WIDTH
:
71 surface_size
.set_width(attr
[1]);
73 case PP_GRAPHICS3DATTRIB_HEIGHT
:
74 surface_size
.set_height(attr
[1]);
76 case PP_GRAPHICS3DATTRIB_GPU_PREFERENCE
:
78 (attr
[1] == PP_GRAPHICS3DATTRIB_GPU_PREFERENCE_LOW_POWER
) ?
79 gfx::PreferIntegratedGpu
: gfx::PreferDiscreteGpu
;
81 case PP_GRAPHICS3DATTRIB_ALPHA_SIZE
:
82 has_alpha_
= attr
[1] > 0;
85 attribs
.push_back(attr
[0]);
86 attribs
.push_back(attr
[1]);
90 attribs
.push_back(PP_GRAPHICS3DATTRIB_NONE
);
93 CommandBufferProxyImpl
* share_buffer
= NULL
;
95 PlatformContext3DImpl
* share_impl
=
96 static_cast<PlatformContext3DImpl
*>(share_context
);
97 share_buffer
= share_impl
->command_buffer_
;
100 command_buffer_
= channel_
->CreateOffscreenCommandBuffer(
107 if (!command_buffer_
)
110 command_buffer_
->SetChannelErrorCallback(
111 base::Bind(&PlatformContext3DImpl::OnContextLost
,
112 weak_ptr_factory_
.GetWeakPtr()));
113 command_buffer_
->SetOnConsoleMessageCallback(
114 base::Bind(&PlatformContext3DImpl::OnConsoleMessage
,
115 weak_ptr_factory_
.GetWeakPtr()));
117 return SetParentAndCreateBackingTextureIfNeeded();
120 bool PlatformContext3DImpl::SetParentAndCreateBackingTextureIfNeeded() {
121 if (parent_context_provider_
&&
122 !parent_context_provider_
->DestroyedOnMainThread() &&
126 parent_context_provider_
=
127 RenderThreadImpl::current()->OffscreenContextProviderForMainThread();
128 parent_texture_id_
= 0;
129 if (!parent_context_provider_
)
132 // Flush any remaining commands in the parent context to make sure the
133 // texture id accounting stays consistent.
134 gpu::gles2::GLES2Implementation
* parent_gles2
=
135 parent_context_provider_
->Context3d()->GetImplementation();
136 parent_gles2
->helper()->CommandBufferHelper::Finish();
137 parent_texture_id_
= parent_gles2
->MakeTextureId();
139 CommandBufferProxyImpl
* parent_command_buffer
=
140 parent_context_provider_
->Context3d()->GetCommandBufferProxy();
141 if (!command_buffer_
->SetParent(parent_command_buffer
, parent_texture_id_
))
147 void PlatformContext3DImpl::DestroyParentContextProviderAndBackingTexture() {
148 if (!parent_context_provider_
)
151 if (parent_texture_id_
) {
152 // Flush any remaining commands in the parent context to make sure the
153 // texture id accounting stays consistent.
154 gpu::gles2::GLES2Implementation
* parent_gles2
=
155 parent_context_provider_
->Context3d()->GetImplementation();
156 parent_gles2
->helper()->CommandBufferHelper::Finish();
157 parent_gles2
->FreeTextureId(parent_texture_id_
);
158 parent_texture_id_
= 0;
161 parent_context_provider_
= NULL
;
164 unsigned PlatformContext3DImpl::GetBackingTextureId() {
165 DCHECK(command_buffer_
);
166 return parent_texture_id_
;
169 WebKit::WebGraphicsContext3D
* PlatformContext3DImpl::GetParentContext() {
170 if (!parent_context_provider_
)
172 return parent_context_provider_
->Context3d();
175 bool PlatformContext3DImpl::IsOpaque() {
176 DCHECK(command_buffer_
);
180 gpu::CommandBuffer
* PlatformContext3DImpl::GetCommandBuffer() {
181 return command_buffer_
;
184 int PlatformContext3DImpl::GetCommandBufferRouteId() {
185 DCHECK(command_buffer_
);
186 return command_buffer_
->GetRouteID();
189 void PlatformContext3DImpl::SetContextLostCallback(const base::Closure
& task
) {
190 context_lost_callback_
= task
;
193 void PlatformContext3DImpl::SetOnConsoleMessageCallback(
194 const ConsoleMessageCallback
& task
) {
195 console_message_callback_
= task
;
198 bool PlatformContext3DImpl::Echo(const base::Closure
& task
) {
199 return command_buffer_
->Echo(task
);
202 void PlatformContext3DImpl::OnContextLost() {
203 DCHECK(command_buffer_
);
205 if (!context_lost_callback_
.is_null())
206 context_lost_callback_
.Run();
209 void PlatformContext3DImpl::OnConsoleMessage(const std::string
& msg
, int id
) {
210 DCHECK(command_buffer_
);
212 if (!console_message_callback_
.is_null())
213 console_message_callback_
.Run(msg
, id
);
216 } // namespace content