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 "base/numerics/safe_conversions.h"
8 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include "gpu/command_buffer/common/command_buffer.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/proxy/enter_proxy.h"
12 #include "ppapi/proxy/plugin_dispatcher.h"
13 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
14 #include "ppapi/proxy/ppapi_messages.h"
15 #include "ppapi/shared_impl/ppapi_globals.h"
16 #include "ppapi/thunk/enter.h"
17 #include "ppapi/thunk/resource_creation_api.h"
18 #include "ppapi/thunk/thunk.h"
20 using ppapi::thunk::EnterResourceNoLock
;
21 using ppapi::thunk::PPB_Graphics3D_API
;
22 using ppapi::thunk::ResourceCreationAPI
;
29 const int32 kCommandBufferSize
= 1024 * 1024;
30 const int32 kTransferBufferSize
= 1024 * 1024;
33 base::SharedMemoryHandle
TransportSHMHandle(
34 Dispatcher
* dispatcher
,
35 const base::SharedMemoryHandle
& handle
) {
36 // Don't close the handle, it doesn't belong to us.
37 return dispatcher
->ShareSharedMemoryHandleWithRemote(handle
);
39 #endif // !defined(OS_NACL)
41 gpu::CommandBuffer::State
GetErrorState() {
42 gpu::CommandBuffer::State error_state
;
43 error_state
.error
= gpu::error::kGenericError
;
49 Graphics3D::Graphics3D(const HostResource
& resource
)
50 : PPB_Graphics3D_Shared(resource
) {
53 Graphics3D::~Graphics3D() {
57 bool Graphics3D::Init(gpu::gles2::GLES2Implementation
* share_gles2
,
58 const gpu::Capabilities
& capabilities
,
59 const SerializedHandle
& shared_state
,
60 uint64_t command_buffer_id
) {
61 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(this);
65 command_buffer_
.reset(new PpapiCommandBufferProxy(
66 host_resource(), dispatcher
, capabilities
, shared_state
,
69 return CreateGLES2Impl(kCommandBufferSize
, kTransferBufferSize
,
73 PP_Bool
Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
77 PP_Bool
Graphics3D::Flush(int32_t put_offset
) {
81 scoped_refptr
<gpu::Buffer
> Graphics3D::CreateTransferBuffer(
88 PP_Bool
Graphics3D::DestroyTransferBuffer(int32_t id
) {
92 gpu::CommandBuffer::State
Graphics3D::WaitForTokenInRange(int32_t start
,
94 return GetErrorState();
97 gpu::CommandBuffer::State
Graphics3D::WaitForGetOffsetInRange(int32_t start
,
99 return GetErrorState();
102 uint32_t Graphics3D::InsertSyncPoint() {
107 uint32_t Graphics3D::InsertFutureSyncPoint() {
112 void Graphics3D::RetireSyncPoint(uint32_t sync_point
) {
116 gpu::CommandBuffer
* Graphics3D::GetCommandBuffer() {
117 return command_buffer_
.get();
120 gpu::GpuControl
* Graphics3D::GetGpuControl() {
121 return command_buffer_
.get();
124 int32
Graphics3D::DoSwapBuffers() {
125 gles2_impl()->SwapBuffers();
126 IPC::Message
* msg
= new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
127 API_ID_PPB_GRAPHICS_3D
, host_resource());
128 msg
->set_unblock(true);
129 PluginDispatcher::GetForResource(this)->Send(msg
);
131 return PP_OK_COMPLETIONPENDING
;
134 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher
* dispatcher
)
135 : InterfaceProxy(dispatcher
),
136 callback_factory_(this) {
139 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
143 PP_Resource
PPB_Graphics3D_Proxy::CreateProxyResource(
144 PP_Instance instance
,
145 PP_Resource share_context
,
146 const int32_t* attrib_list
) {
147 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
149 return PP_ERROR_BADARGUMENT
;
151 HostResource share_host
;
152 gpu::gles2::GLES2Implementation
* share_gles2
= NULL
;
153 if (share_context
!= 0) {
154 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(share_context
, true);
156 return PP_ERROR_BADARGUMENT
;
158 PPB_Graphics3D_Shared
* share_graphics
=
159 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
160 share_host
= share_graphics
->host_resource();
161 share_gles2
= share_graphics
->gles2_impl();
164 std::vector
<int32_t> attribs
;
166 for (const int32_t* attr
= attrib_list
;
167 attr
[0] != PP_GRAPHICS3DATTRIB_NONE
;
169 attribs
.push_back(attr
[0]);
170 attribs
.push_back(attr
[1]);
173 attribs
.push_back(PP_GRAPHICS3DATTRIB_NONE
);
176 gpu::Capabilities capabilities
;
177 ppapi::proxy::SerializedHandle shared_state
;
178 uint64_t command_buffer_id
= 0;
179 dispatcher
->Send(new PpapiHostMsg_PPBGraphics3D_Create(API_ID_PPB_GRAPHICS_3D
,
180 instance
, share_host
, attribs
, &result
, &capabilities
, &shared_state
,
181 &command_buffer_id
));
183 if (result
.is_null())
186 scoped_refptr
<Graphics3D
> graphics_3d(new Graphics3D(result
));
187 if (!graphics_3d
->Init(share_gles2
, capabilities
, shared_state
,
188 command_buffer_id
)) {
191 return graphics_3d
->GetReference();
194 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
196 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy
, msg
)
197 #if !defined(OS_NACL)
198 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create
,
200 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer
,
202 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange
,
203 OnMsgWaitForTokenInRange
)
204 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange
,
205 OnMsgWaitForGetOffsetInRange
)
206 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush
, OnMsgAsyncFlush
)
207 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer
,
208 OnMsgCreateTransferBuffer
)
209 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer
,
210 OnMsgDestroyTransferBuffer
)
211 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers
,
213 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint
,
214 OnMsgInsertSyncPoint
)
215 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint
,
216 OnMsgInsertFutureSyncPoint
)
217 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_RetireSyncPoint
,
218 OnMsgRetireSyncPoint
)
219 #endif // !defined(OS_NACL)
221 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK
,
223 IPC_MESSAGE_UNHANDLED(handled
= false)
225 IPC_END_MESSAGE_MAP()
226 // FIXME(brettw) handle bad messages!
230 #if !defined(OS_NACL)
231 void PPB_Graphics3D_Proxy::OnMsgCreate(
232 PP_Instance instance
,
233 HostResource share_context
,
234 const std::vector
<int32_t>& attribs
,
235 HostResource
* result
,
236 gpu::Capabilities
* capabilities
,
237 SerializedHandle
* shared_state
,
238 uint64
* command_buffer_id
) {
239 shared_state
->set_null_shmem();
240 if (attribs
.empty() ||
241 attribs
.back() != PP_GRAPHICS3DATTRIB_NONE
||
242 !(attribs
.size() & 1))
243 return; // Bad message.
245 thunk::EnterResourceCreation
enter(instance
);
247 if (!enter
.succeeded())
250 base::SharedMemoryHandle handle
= base::SharedMemory::NULLHandle();
251 result
->SetHostResource(
253 enter
.functions()->CreateGraphics3DRaw(instance
,
254 share_context
.host_resource(),
259 if (!result
->is_null()) {
260 shared_state
->set_shmem(TransportSHMHandle(dispatcher(), handle
),
261 sizeof(gpu::CommandBuffer::State
));
265 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
266 const HostResource
& context
,
267 int32 transfer_buffer_id
) {
268 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
269 if (enter
.succeeded())
270 enter
.object()->SetGetBuffer(transfer_buffer_id
);
273 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
274 const HostResource
& context
,
277 gpu::CommandBuffer::State
* state
,
279 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
280 if (enter
.failed()) {
284 *state
= enter
.object()->WaitForTokenInRange(start
, end
);
288 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
289 const HostResource
& context
,
292 gpu::CommandBuffer::State
* state
,
294 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
295 if (enter
.failed()) {
299 *state
= enter
.object()->WaitForGetOffsetInRange(start
, end
);
303 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource
& context
,
305 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
306 if (enter
.succeeded())
307 enter
.object()->Flush(put_offset
);
310 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
311 const HostResource
& context
,
314 SerializedHandle
* transfer_buffer
) {
315 transfer_buffer
->set_null_shmem();
316 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
317 if (enter
.succeeded()) {
318 scoped_refptr
<gpu::Buffer
> buffer
=
319 enter
.object()->CreateTransferBuffer(size
, id
);
322 gpu::SharedMemoryBufferBacking
* backing
=
323 static_cast<gpu::SharedMemoryBufferBacking
*>(buffer
->backing());
324 DCHECK(backing
&& backing
->shared_memory());
325 transfer_buffer
->set_shmem(
326 TransportSHMHandle(dispatcher(), backing
->shared_memory()->handle()),
327 base::checked_cast
<uint32_t>(buffer
->size()));
333 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
334 const HostResource
& context
,
336 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
337 if (enter
.succeeded())
338 enter
.object()->DestroyTransferBuffer(id
);
341 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource
& context
) {
342 EnterHostFromHostResourceForceCallback
<PPB_Graphics3D_API
> enter(
343 context
, callback_factory_
,
344 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin
, context
);
345 if (enter
.succeeded())
346 enter
.SetResult(enter
.object()->SwapBuffers(enter
.callback()));
349 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource
& context
,
350 uint32
* sync_point
) {
352 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
353 if (enter
.succeeded())
354 *sync_point
= enter
.object()->InsertSyncPoint();
357 void PPB_Graphics3D_Proxy::OnMsgInsertFutureSyncPoint(
358 const HostResource
& context
,
359 uint32
* sync_point
) {
361 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
362 if (enter
.succeeded())
363 *sync_point
= enter
.object()->InsertFutureSyncPoint();
366 void PPB_Graphics3D_Proxy::OnMsgRetireSyncPoint(const HostResource
& context
,
368 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
369 if (enter
.succeeded())
370 enter
.object()->RetireSyncPoint(sync_point
);
372 #endif // !defined(OS_NACL)
374 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource
& resource
,
376 EnterPluginFromHostResource
<PPB_Graphics3D_API
> enter(resource
);
377 if (enter
.succeeded())
378 static_cast<Graphics3D
*>(enter
.object())->SwapBuffersACK(pp_error
);
381 #if !defined(OS_NACL)
382 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
384 const HostResource
& context
) {
385 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
386 API_ID_PPB_GRAPHICS_3D
, context
, result
));
388 #endif // !defined(OS_NACL)