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 "ppapi/c/pp_errors.h"
9 #include "ppapi/proxy/enter_proxy.h"
10 #include "ppapi/proxy/plugin_dispatcher.h"
11 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
12 #include "ppapi/proxy/ppapi_messages.h"
13 #include "ppapi/thunk/enter.h"
14 #include "ppapi/thunk/resource_creation_api.h"
15 #include "ppapi/thunk/thunk.h"
17 using ppapi::thunk::EnterResourceNoLock
;
18 using ppapi::thunk::PPB_Graphics3D_API
;
19 using ppapi::thunk::ResourceCreationAPI
;
25 const int32 kCommandBufferSize
= 1024 * 1024;
26 const int32 kTransferBufferSize
= 1024 * 1024;
28 base::SharedMemoryHandle
TransportSHMHandleFromInt(Dispatcher
* dispatcher
,
30 // TODO(piman): Change trusted interface to return a PP_FileHandle, those
32 base::PlatformFile source
=
34 reinterpret_cast<HANDLE
>(static_cast<intptr_t>(shm_handle
));
35 #elif defined(OS_POSIX)
38 #error Not implemented.
40 // Don't close the handle, it doesn't belong to us.
41 return dispatcher
->ShareHandleWithRemote(source
, false);
44 PP_Graphics3DTrustedState
GetErrorState() {
45 PP_Graphics3DTrustedState error_state
= { 0 };
46 error_state
.error
= PPB_GRAPHICS3D_TRUSTED_ERROR_GENERICERROR
;
50 gpu::CommandBuffer::State
GPUStateFromPPState(
51 const PP_Graphics3DTrustedState
& s
) {
52 gpu::CommandBuffer::State state
;
53 state
.num_entries
= s
.num_entries
;
54 state
.get_offset
= s
.get_offset
;
55 state
.put_offset
= s
.put_offset
;
56 state
.token
= s
.token
;
57 state
.error
= static_cast<gpu::error::Error
>(s
.error
);
58 state
.generation
= s
.generation
;
64 Graphics3D::Graphics3D(const HostResource
& resource
)
65 : PPB_Graphics3D_Shared(resource
) {
68 Graphics3D::~Graphics3D() {
72 bool Graphics3D::Init(gpu::gles2::GLES2Implementation
* share_gles2
) {
73 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForResource(this);
77 command_buffer_
.reset(
78 new PpapiCommandBufferProxy(host_resource(), dispatcher
));
79 if (!command_buffer_
->Initialize())
82 return CreateGLES2Impl(kCommandBufferSize
, kTransferBufferSize
,
86 PP_Bool
Graphics3D::InitCommandBuffer() {
90 PP_Bool
Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
94 PP_Graphics3DTrustedState
Graphics3D::GetState() {
95 return GetErrorState();
98 PP_Bool
Graphics3D::Flush(int32_t put_offset
) {
102 PP_Graphics3DTrustedState
Graphics3D::FlushSync(int32_t put_offset
) {
103 return GetErrorState();
106 int32_t Graphics3D::CreateTransferBuffer(uint32_t size
) {
110 PP_Bool
Graphics3D::DestroyTransferBuffer(int32_t id
) {
114 PP_Bool
Graphics3D::GetTransferBuffer(int32_t id
,
116 uint32_t* shm_size
) {
120 PP_Graphics3DTrustedState
Graphics3D::FlushSyncFast(int32_t put_offset
,
121 int32_t last_known_get
) {
122 return GetErrorState();
125 gpu::CommandBuffer
* Graphics3D::GetCommandBuffer() {
126 return command_buffer_
.get();
129 int32
Graphics3D::DoSwapBuffers() {
130 gles2_impl()->SwapBuffers();
131 IPC::Message
* msg
= new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
132 API_ID_PPB_GRAPHICS_3D
, host_resource());
133 msg
->set_unblock(true);
134 PluginDispatcher::GetForResource(this)->Send(msg
);
136 return PP_OK_COMPLETIONPENDING
;
139 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher
* dispatcher
)
140 : InterfaceProxy(dispatcher
),
141 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
144 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
148 PP_Resource
PPB_Graphics3D_Proxy::CreateProxyResource(
149 PP_Instance instance
,
150 PP_Resource share_context
,
151 const int32_t* attrib_list
) {
152 PluginDispatcher
* dispatcher
= PluginDispatcher::GetForInstance(instance
);
154 return PP_ERROR_BADARGUMENT
;
156 HostResource share_host
;
157 gpu::gles2::GLES2Implementation
* share_gles2
= NULL
;
158 if (share_context
!= 0) {
159 EnterResourceNoLock
<PPB_Graphics3D_API
> enter(share_context
, true);
161 return PP_ERROR_BADARGUMENT
;
163 PPB_Graphics3D_Shared
* share_graphics
=
164 static_cast<PPB_Graphics3D_Shared
*>(enter
.object());
165 share_host
= share_graphics
->host_resource();
166 share_gles2
= share_graphics
->gles2_impl();
169 std::vector
<int32_t> attribs
;
171 for (const int32_t* attr
= attrib_list
;
172 attr
[0] != PP_GRAPHICS3DATTRIB_NONE
;
174 attribs
.push_back(attr
[0]);
175 attribs
.push_back(attr
[1]);
178 attribs
.push_back(PP_GRAPHICS3DATTRIB_NONE
);
181 dispatcher
->Send(new PpapiHostMsg_PPBGraphics3D_Create(
182 API_ID_PPB_GRAPHICS_3D
, instance
, share_host
, attribs
, &result
));
183 if (result
.is_null())
186 scoped_refptr
<Graphics3D
> graphics_3d(new Graphics3D(result
));
187 if (!graphics_3d
->Init(share_gles2
))
189 return graphics_3d
->GetReference();
192 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message
& msg
) {
194 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy
, msg
)
195 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create
,
197 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InitCommandBuffer
,
198 OnMsgInitCommandBuffer
)
199 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer
,
201 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState
,
203 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush
,
205 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush
,
207 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer
,
208 OnMsgCreateTransferBuffer
)
209 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer
,
210 OnMsgDestroyTransferBuffer
)
211 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer
,
212 OnMsgGetTransferBuffer
)
213 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers
,
216 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK
,
218 IPC_MESSAGE_UNHANDLED(handled
= false)
220 IPC_END_MESSAGE_MAP()
221 // FIXME(brettw) handle bad messages!
225 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance
,
226 HostResource share_context
,
227 const std::vector
<int32_t>& attribs
,
228 HostResource
* result
) {
229 if (attribs
.empty() || attribs
.back() != PP_GRAPHICS3DATTRIB_NONE
)
230 return; // Bad message.
232 thunk::EnterResourceCreation
enter(instance
);
234 if (enter
.succeeded()) {
235 result
->SetHostResource(
237 enter
.functions()->CreateGraphics3DRaw(instance
,
238 share_context
.host_resource(),
243 void PPB_Graphics3D_Proxy::OnMsgInitCommandBuffer(
244 const HostResource
& context
) {
245 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
249 if (!enter
.object()->InitCommandBuffer())
253 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
254 const HostResource
& context
,
255 int32 transfer_buffer_id
) {
256 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
257 if (enter
.succeeded())
258 enter
.object()->SetGetBuffer(transfer_buffer_id
);
261 void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource
& context
,
262 gpu::CommandBuffer::State
* state
,
264 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
265 if (enter
.failed()) {
269 PP_Graphics3DTrustedState pp_state
= enter
.object()->GetState();
270 *state
= GPUStateFromPPState(pp_state
);
274 void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource
& context
,
276 int32 last_known_get
,
277 gpu::CommandBuffer::State
* state
,
279 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
280 if (enter
.failed()) {
284 PP_Graphics3DTrustedState pp_state
= enter
.object()->FlushSyncFast(
285 put_offset
, last_known_get
);
286 *state
= GPUStateFromPPState(pp_state
);
290 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource
& context
,
292 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
293 if (enter
.succeeded())
294 enter
.object()->Flush(put_offset
);
297 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
298 const HostResource
& context
,
301 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
302 if (enter
.succeeded())
303 *id
= enter
.object()->CreateTransferBuffer(size
);
308 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
309 const HostResource
& context
,
311 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
312 if (enter
.succeeded())
313 enter
.object()->DestroyTransferBuffer(id
);
316 void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer(
317 const HostResource
& context
,
319 base::SharedMemoryHandle
* transfer_buffer
,
321 *transfer_buffer
= base::SharedMemory::NULLHandle();
324 EnterHostFromHostResource
<PPB_Graphics3D_API
> enter(context
);
326 uint32_t shm_size
= 0;
327 if (enter
.succeeded() &&
328 enter
.object()->GetTransferBuffer(id
, &shm_handle
, &shm_size
)) {
329 *transfer_buffer
= TransportSHMHandleFromInt(dispatcher(), shm_handle
);
334 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource
& context
) {
335 EnterHostFromHostResourceForceCallback
<PPB_Graphics3D_API
> enter(
336 context
, callback_factory_
,
337 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin
, context
);
338 if (enter
.succeeded())
339 enter
.SetResult(enter
.object()->SwapBuffers(enter
.callback()));
342 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource
& resource
,
344 EnterPluginFromHostResource
<PPB_Graphics3D_API
> enter(resource
);
345 if (enter
.succeeded())
346 static_cast<Graphics3D
*>(enter
.object())->SwapBuffersACK(pp_error
);
349 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
351 const HostResource
& context
) {
352 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
353 API_ID_PPB_GRAPHICS_3D
, context
, result
));