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 "ppapi/proxy/ppb_graphics_3d_proxy.h"
7 #include "gpu/command_buffer/client/gles2_implementation.h"
8 #include "gpu/command_buffer/common/command_buffer.h"
9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/proxy/enter_proxy.h"
11 #include "ppapi/proxy/plugin_dispatcher.h"
12 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/thunk/enter.h"
16 #include "ppapi/thunk/resource_creation_api.h"
17 #include "ppapi/thunk/thunk.h"
19 using ppapi::thunk::EnterResourceNoLock
;
20 using ppapi::thunk::PPB_Graphics3D_API
;
21 using ppapi::thunk::ResourceCreationAPI
;
28 const int32 kCommandBufferSize
= 1024 * 1024;
29 const int32 kTransferBufferSize
= 1024 * 1024;
31 base::SharedMemoryHandle
TransportSHMHandle(Dispatcher
* dispatcher
,
32 base::SharedMemory
* shm
) {
33 base::PlatformFile source
=
34 IPC::PlatformFileForTransitToPlatformFile(shm
->handle());
35 // Don't close the handle, it doesn't belong to us.
36 return dispatcher
->ShareHandleWithRemote(source
, false);
39 gpu::CommandBuffer::State
GetErrorState() {
40 gpu::CommandBuffer::State error_state
;
41 error_state
.error
= gpu::error::kGenericError
;
47 Graphics3D::Graphics3D(const HostResource
& resource
)
48 : PPB_Graphics3D_Shared(resource
) {
51 Graphics3D::~Graphics3D() {
55 bool Graphics3D::Init(gpu::gles2::GLES2Implementation
* share_gles2
) {
56 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(this);
60 command_buffer_
.reset(
61 new PpapiCommandBufferProxy(host_resource(), dispatcher
));
63 return CreateGLES2Impl(kCommandBufferSize
, kTransferBufferSize
,
67 PP_Bool
Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
71 PP_Bool
Graphics3D::Flush(int32_t put_offset
) {
75 scoped_refptr
<gpu::Buffer
> Graphics3D::CreateTransferBuffer(
82 PP_Bool
Graphics3D::DestroyTransferBuffer(int32_t id
) {
86 gpu::CommandBuffer::State
Graphics3D::WaitForTokenInRange(int32_t start
,
88 return GetErrorState();
91 gpu::CommandBuffer::State
Graphics3D::WaitForGetOffsetInRange(int32_t start
,
93 return GetErrorState();
96 uint32_t Graphics3D::InsertSyncPoint() {
101 gpu::CommandBuffer
* Graphics3D::GetCommandBuffer() {
102 return command_buffer_
.get();
105 gpu::GpuControl
* Graphics3D::GetGpuControl() {
106 return command_buffer_
.get();
109 int32
Graphics3D::DoSwapBuffers() {
110 gles2_impl()->SwapBuffers();
111 IPC::Message
* msg
= new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
112 API_ID_PPB_GRAPHICS_3D
, host_resource());
113 msg
->set_unblock(true);
114 PluginDispatcher::GetForResource(this)->Send(msg
);
116 return PP_OK_COMPLETIONPENDING
;
119 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher
* dispatcher
)
120 : InterfaceProxy(dispatcher
),
121 callback_factory_(this) {
124 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
128 PP_Resource
PPB_Graphics3D_Proxy::CreateProxyResource(
129 PP_Instance instance
,
130 PP_Resource share_context
,
131 const int32_t* attrib_list
) {
132 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
134 return PP_ERROR_BADARGUMENT
;
136 HostResource share_host
;
137 gpu::gles2::GLES2Implementation
* share_gles2
= NULL
;
138 if (share_context
!= 0) {
139 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(share_context
, true);
141 return PP_ERROR_BADARGUMENT
;
143 PPB_Graphics3D_Shared
* share_graphics
=
144 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
145 share_host
= share_graphics
->host_resource();
146 share_gles2
= share_graphics
->gles2_impl();
149 std::vector
<int32_t> attribs
;
151 for (const int32_t* attr
= attrib_list
;
152 attr
[0] != PP_GRAPHICS3DATTRIB_NONE
;
154 attribs
.push_back(attr
[0]);
155 attribs
.push_back(attr
[1]);
158 attribs
.push_back(PP_GRAPHICS3DATTRIB_NONE
);
161 dispatcher
->Send(new PpapiHostMsg_PPBGraphics3D_Create(
162 API_ID_PPB_GRAPHICS_3D
, instance
, share_host
, attribs
, &result
));
163 if (result
.is_null())
166 scoped_refptr
<Graphics3D
> graphics_3d(new Graphics3D(result
));
167 if (!graphics_3d
->Init(share_gles2
))
169 return graphics_3d
->GetReference();
172 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
174 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy
, msg
)
175 #if !defined(OS_NACL)
176 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create
,
178 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer
,
180 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange
,
181 OnMsgWaitForTokenInRange
)
182 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange
,
183 OnMsgWaitForGetOffsetInRange
)
184 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush
, OnMsgAsyncFlush
)
185 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer
,
186 OnMsgCreateTransferBuffer
)
187 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer
,
188 OnMsgDestroyTransferBuffer
)
189 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers
,
191 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint
,
192 OnMsgInsertSyncPoint
)
193 #endif // !defined(OS_NACL)
195 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK
,
197 IPC_MESSAGE_UNHANDLED(handled
= false)
199 IPC_END_MESSAGE_MAP()
200 // FIXME(brettw) handle bad messages!
204 #if !defined(OS_NACL)
205 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance
,
206 HostResource share_context
,
207 const std::vector
<int32_t>& attribs
,
208 HostResource
* result
) {
209 if (attribs
.empty() ||
210 attribs
.back() != PP_GRAPHICS3DATTRIB_NONE
||
211 !(attribs
.size() & 1))
212 return; // Bad message.
214 thunk::EnterResourceCreation
enter(instance
);
216 if (enter
.succeeded()) {
217 result
->SetHostResource(
219 enter
.functions()->CreateGraphics3DRaw(instance
,
220 share_context
.host_resource(),
225 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
226 const HostResource
& context
,
227 int32 transfer_buffer_id
) {
228 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
229 if (enter
.succeeded())
230 enter
.object()->SetGetBuffer(transfer_buffer_id
);
233 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
234 const HostResource
& context
,
237 gpu::CommandBuffer::State
* state
,
239 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
240 if (enter
.failed()) {
244 *state
= enter
.object()->WaitForTokenInRange(start
, end
);
248 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
249 const HostResource
& context
,
252 gpu::CommandBuffer::State
* state
,
254 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
255 if (enter
.failed()) {
259 *state
= enter
.object()->WaitForGetOffsetInRange(start
, end
);
263 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource
& context
,
265 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
266 if (enter
.succeeded())
267 enter
.object()->Flush(put_offset
);
270 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
271 const HostResource
& context
,
274 ppapi::proxy::SerializedHandle
* transfer_buffer
) {
275 transfer_buffer
->set_null_shmem();
276 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
277 if (enter
.succeeded()) {
278 scoped_refptr
<gpu::Buffer
> buffer
=
279 enter
.object()->CreateTransferBuffer(size
, id
);
282 gpu::SharedMemoryBufferBacking
* backing
=
283 static_cast<gpu::SharedMemoryBufferBacking
*>(buffer
->backing());
284 DCHECK(backing
&& backing
->shared_memory());
285 transfer_buffer
->set_shmem(
286 TransportSHMHandle(dispatcher(), backing
->shared_memory()),
293 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
294 const HostResource
& context
,
296 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
297 if (enter
.succeeded())
298 enter
.object()->DestroyTransferBuffer(id
);
301 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource
& context
) {
302 EnterHostFromHostResourceForceCallback
<PPB_Graphics3D_API
> enter(
303 context
, callback_factory_
,
304 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin
, context
);
305 if (enter
.succeeded())
306 enter
.SetResult(enter
.object()->SwapBuffers(enter
.callback()));
309 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource
& context
,
310 uint32
* sync_point
) {
312 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
313 if (enter
.succeeded())
314 *sync_point
= enter
.object()->InsertSyncPoint();
316 #endif // !defined(OS_NACL)
318 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource
& resource
,
320 EnterPluginFromHostResource
<PPB_Graphics3D_API
> enter(resource
);
321 if (enter
.succeeded())
322 static_cast<Graphics3D
*>(enter
.object())->SwapBuffersACK(pp_error
);
325 #if !defined(OS_NACL)
326 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
328 const HostResource
& context
) {
329 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
330 API_ID_PPB_GRAPHICS_3D
, context
, result
));
332 #endif // !defined(OS_NACL)