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
TransportSHMHandleFromInt(Dispatcher
* dispatcher
,
33 // TODO(piman): Change trusted interface to return a PP_FileHandle, those
35 base::PlatformFile source
=
37 reinterpret_cast<HANDLE
>(static_cast<intptr_t>(shm_handle
));
38 #elif defined(OS_POSIX)
41 #error Not implemented.
43 // Don't close the handle, it doesn't belong to us.
44 return dispatcher
->ShareHandleWithRemote(source
, false);
47 gpu::CommandBuffer::State
GetErrorState() {
48 gpu::CommandBuffer::State error_state
;
49 error_state
.error
= gpu::error::kGenericError
;
55 Graphics3D::Graphics3D(const HostResource
& resource
)
56 : PPB_Graphics3D_Shared(resource
) {
59 Graphics3D::~Graphics3D() {
63 bool Graphics3D::Init(gpu::gles2::GLES2Implementation
* share_gles2
) {
64 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(this);
68 command_buffer_
.reset(
69 new PpapiCommandBufferProxy(host_resource(), dispatcher
));
71 return CreateGLES2Impl(kCommandBufferSize
, kTransferBufferSize
,
75 PP_Bool
Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
79 gpu::CommandBuffer::State
Graphics3D::GetState() {
80 return GetErrorState();
83 PP_Bool
Graphics3D::Flush(int32_t put_offset
) {
87 gpu::CommandBuffer::State
Graphics3D::FlushSync(int32_t put_offset
) {
88 return GetErrorState();
91 int32_t Graphics3D::CreateTransferBuffer(uint32_t size
) {
95 PP_Bool
Graphics3D::DestroyTransferBuffer(int32_t id
) {
99 PP_Bool
Graphics3D::GetTransferBuffer(int32_t id
,
101 uint32_t* shm_size
) {
105 gpu::CommandBuffer::State
Graphics3D::FlushSyncFast(int32_t put_offset
,
106 int32_t last_known_get
) {
107 return GetErrorState();
110 uint32_t Graphics3D::InsertSyncPoint() {
115 gpu::CommandBuffer
* Graphics3D::GetCommandBuffer() {
116 return command_buffer_
.get();
119 gpu::GpuControl
* Graphics3D::GetGpuControl() {
120 return command_buffer_
.get();
123 int32
Graphics3D::DoSwapBuffers() {
124 gles2_impl()->SwapBuffers();
125 IPC::Message
* msg
= new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
126 API_ID_PPB_GRAPHICS_3D
, host_resource());
127 msg
->set_unblock(true);
128 PluginDispatcher::GetForResource(this)->Send(msg
);
130 return PP_OK_COMPLETIONPENDING
;
133 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher
* dispatcher
)
134 : InterfaceProxy(dispatcher
),
135 callback_factory_(this) {
138 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
142 PP_Resource
PPB_Graphics3D_Proxy::CreateProxyResource(
143 PP_Instance instance
,
144 PP_Resource share_context
,
145 const int32_t* attrib_list
) {
146 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
148 return PP_ERROR_BADARGUMENT
;
150 HostResource share_host
;
151 gpu::gles2::GLES2Implementation
* share_gles2
= NULL
;
152 if (share_context
!= 0) {
153 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(share_context
, true);
155 return PP_ERROR_BADARGUMENT
;
157 PPB_Graphics3D_Shared
* share_graphics
=
158 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
159 share_host
= share_graphics
->host_resource();
160 share_gles2
= share_graphics
->gles2_impl();
163 std::vector
<int32_t> attribs
;
165 for (const int32_t* attr
= attrib_list
;
166 attr
[0] != PP_GRAPHICS3DATTRIB_NONE
;
168 attribs
.push_back(attr
[0]);
169 attribs
.push_back(attr
[1]);
172 attribs
.push_back(PP_GRAPHICS3DATTRIB_NONE
);
175 dispatcher
->Send(new PpapiHostMsg_PPBGraphics3D_Create(
176 API_ID_PPB_GRAPHICS_3D
, instance
, share_host
, attribs
, &result
));
177 if (result
.is_null())
180 scoped_refptr
<Graphics3D
> graphics_3d(new Graphics3D(result
));
181 if (!graphics_3d
->Init(share_gles2
))
183 return graphics_3d
->GetReference();
186 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
188 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy
, msg
)
189 #if !defined(OS_NACL)
190 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create
,
192 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer
,
194 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState
,
196 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush
,
198 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush
,
200 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer
,
201 OnMsgCreateTransferBuffer
)
202 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer
,
203 OnMsgDestroyTransferBuffer
)
204 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer
,
205 OnMsgGetTransferBuffer
)
206 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers
,
208 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint
,
209 OnMsgInsertSyncPoint
)
210 #endif // !defined(OS_NACL)
212 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK
,
214 IPC_MESSAGE_UNHANDLED(handled
= false)
216 IPC_END_MESSAGE_MAP()
217 // FIXME(brettw) handle bad messages!
221 #if !defined(OS_NACL)
222 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance
,
223 HostResource share_context
,
224 const std::vector
<int32_t>& attribs
,
225 HostResource
* result
) {
226 if (attribs
.empty() ||
227 attribs
.back() != PP_GRAPHICS3DATTRIB_NONE
||
228 !(attribs
.size() & 1))
229 return; // Bad message.
231 thunk::EnterResourceCreation
enter(instance
);
233 if (enter
.succeeded()) {
234 result
->SetHostResource(
236 enter
.functions()->CreateGraphics3DRaw(instance
,
237 share_context
.host_resource(),
242 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
243 const HostResource
& context
,
244 int32 transfer_buffer_id
) {
245 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
246 if (enter
.succeeded())
247 enter
.object()->SetGetBuffer(transfer_buffer_id
);
250 void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource
& context
,
251 gpu::CommandBuffer::State
* state
,
253 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
254 if (enter
.failed()) {
258 *state
= enter
.object()->GetState();
262 void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource
& context
,
264 int32 last_known_get
,
265 gpu::CommandBuffer::State
* state
,
267 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
268 if (enter
.failed()) {
272 *state
= enter
.object()->FlushSyncFast(put_offset
, last_known_get
);
276 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource
& context
,
278 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
279 if (enter
.succeeded())
280 enter
.object()->Flush(put_offset
);
283 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
284 const HostResource
& context
,
287 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
288 if (enter
.succeeded())
289 *id
= enter
.object()->CreateTransferBuffer(size
);
294 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
295 const HostResource
& context
,
297 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
298 if (enter
.succeeded())
299 enter
.object()->DestroyTransferBuffer(id
);
302 void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer(
303 const HostResource
& context
,
305 ppapi::proxy::SerializedHandle
* transfer_buffer
) {
306 transfer_buffer
->set_null_shmem();
308 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
310 uint32_t shm_size
= 0;
311 if (enter
.succeeded() &&
312 enter
.object()->GetTransferBuffer(id
, &shm_handle
, &shm_size
)) {
313 transfer_buffer
->set_shmem(
314 TransportSHMHandleFromInt(dispatcher(), shm_handle
),
319 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource
& context
) {
320 EnterHostFromHostResourceForceCallback
<PPB_Graphics3D_API
> enter(
321 context
, callback_factory_
,
322 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin
, context
);
323 if (enter
.succeeded())
324 enter
.SetResult(enter
.object()->SwapBuffers(enter
.callback()));
327 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource
& context
,
328 uint32
* sync_point
) {
330 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
331 if (enter
.succeeded())
332 *sync_point
= enter
.object()->InsertSyncPoint();
334 #endif // !defined(OS_NACL)
336 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource
& resource
,
338 EnterPluginFromHostResource
<PPB_Graphics3D_API
> enter(resource
);
339 if (enter
.succeeded())
340 static_cast<Graphics3D
*>(enter
.object())->SwapBuffersACK(pp_error
);
343 #if !defined(OS_NACL)
344 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
346 const HostResource
& context
) {
347 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
348 API_ID_PPB_GRAPHICS_3D
, context
, result
));
350 #endif // !defined(OS_NACL)