- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / ppb_graphics_3d_proxy.cc
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.
4
5 #include "ppapi/proxy/ppb_graphics_3d_proxy.h"
6
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"
18
19 using ppapi::thunk::EnterResourceNoLock;
20 using ppapi::thunk::PPB_Graphics3D_API;
21 using ppapi::thunk::ResourceCreationAPI;
22
23 namespace ppapi {
24 namespace proxy {
25
26 namespace {
27
28 const int32 kCommandBufferSize = 1024 * 1024;
29 const int32 kTransferBufferSize = 1024 * 1024;
30
31 base::SharedMemoryHandle TransportSHMHandleFromInt(Dispatcher* dispatcher,
32                                                    int shm_handle) {
33   // TODO(piman): Change trusted interface to return a PP_FileHandle, those
34   // casts are ugly.
35   base::PlatformFile source =
36 #if defined(OS_WIN)
37       reinterpret_cast<HANDLE>(static_cast<intptr_t>(shm_handle));
38 #elif defined(OS_POSIX)
39       shm_handle;
40 #else
41   #error Not implemented.
42 #endif
43   // Don't close the handle, it doesn't belong to us.
44   return dispatcher->ShareHandleWithRemote(source, false);
45 }
46
47 gpu::CommandBuffer::State GetErrorState() {
48   gpu::CommandBuffer::State error_state;
49   error_state.error = gpu::error::kGenericError;
50   return error_state;
51 }
52
53 }  // namespace
54
55 Graphics3D::Graphics3D(const HostResource& resource)
56     : PPB_Graphics3D_Shared(resource) {
57 }
58
59 Graphics3D::~Graphics3D() {
60   DestroyGLES2Impl();
61 }
62
63 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) {
64   PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
65   if (!dispatcher)
66     return false;
67
68   command_buffer_.reset(
69       new PpapiCommandBufferProxy(host_resource(), dispatcher));
70
71   return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
72                          share_gles2);
73 }
74
75 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
76   return PP_FALSE;
77 }
78
79 gpu::CommandBuffer::State Graphics3D::GetState() {
80   return GetErrorState();
81 }
82
83 PP_Bool Graphics3D::Flush(int32_t put_offset) {
84   return PP_FALSE;
85 }
86
87 gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) {
88   return GetErrorState();
89 }
90
91 int32_t Graphics3D::CreateTransferBuffer(uint32_t size) {
92   return PP_FALSE;
93 }
94
95 PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
96   return PP_FALSE;
97 }
98
99 PP_Bool Graphics3D::GetTransferBuffer(int32_t id,
100                                       int* shm_handle,
101                                       uint32_t* shm_size) {
102   return PP_FALSE;
103 }
104
105 gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset,
106                                                     int32_t last_known_get) {
107   return GetErrorState();
108 }
109
110 uint32_t Graphics3D::InsertSyncPoint() {
111   NOTREACHED();
112   return 0;
113 }
114
115 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
116   return command_buffer_.get();
117 }
118
119 gpu::GpuControl* Graphics3D::GetGpuControl() {
120   return command_buffer_.get();
121 }
122
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);
129
130   return PP_OK_COMPLETIONPENDING;
131 }
132
133 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
134     : InterfaceProxy(dispatcher),
135       callback_factory_(this) {
136 }
137
138 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
139 }
140
141 // static
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);
147   if (!dispatcher)
148     return PP_ERROR_BADARGUMENT;
149
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);
154     if (enter.failed())
155       return PP_ERROR_BADARGUMENT;
156
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();
161   }
162
163   std::vector<int32_t> attribs;
164   if (attrib_list) {
165     for (const int32_t* attr = attrib_list;
166          attr[0] != PP_GRAPHICS3DATTRIB_NONE;
167          attr += 2) {
168       attribs.push_back(attr[0]);
169       attribs.push_back(attr[1]);
170     }
171   }
172   attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
173
174   HostResource result;
175   dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(
176       API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result));
177   if (result.is_null())
178     return 0;
179
180   scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
181   if (!graphics_3d->Init(share_gles2))
182     return 0;
183   return graphics_3d->GetReference();
184 }
185
186 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
187   bool handled = true;
188   IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
189 #if !defined(OS_NACL)
190     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
191                         OnMsgCreate)
192     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
193                         OnMsgSetGetBuffer)
194     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState,
195                         OnMsgGetState)
196     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush,
197                         OnMsgFlush)
198     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush,
199                         OnMsgAsyncFlush)
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,
207                         OnMsgSwapBuffers)
208     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
209                         OnMsgInsertSyncPoint)
210 #endif  // !defined(OS_NACL)
211
212     IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
213                         OnMsgSwapBuffersACK)
214     IPC_MESSAGE_UNHANDLED(handled = false)
215
216   IPC_END_MESSAGE_MAP()
217   // FIXME(brettw) handle bad messages!
218   return handled;
219 }
220
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.
230
231   thunk::EnterResourceCreation enter(instance);
232
233   if (enter.succeeded()) {
234     result->SetHostResource(
235       instance,
236       enter.functions()->CreateGraphics3DRaw(instance,
237                                              share_context.host_resource(),
238                                              &attribs.front()));
239   }
240 }
241
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);
248 }
249
250 void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource& context,
251                                          gpu::CommandBuffer::State* state,
252                                          bool* success) {
253   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
254   if (enter.failed()) {
255     *success = false;
256     return;
257   }
258   *state = enter.object()->GetState();
259   *success = true;
260 }
261
262 void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource& context,
263                                       int32 put_offset,
264                                       int32 last_known_get,
265                                       gpu::CommandBuffer::State* state,
266                                       bool* success) {
267   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
268   if (enter.failed()) {
269     *success = false;
270     return;
271   }
272   *state = enter.object()->FlushSyncFast(put_offset, last_known_get);
273   *success = true;
274 }
275
276 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
277                                            int32 put_offset) {
278   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
279   if (enter.succeeded())
280     enter.object()->Flush(put_offset);
281 }
282
283 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
284     const HostResource& context,
285     uint32 size,
286     int32* id) {
287   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
288   if (enter.succeeded())
289     *id = enter.object()->CreateTransferBuffer(size);
290   else
291     *id = -1;
292 }
293
294 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
295     const HostResource& context,
296     int32 id) {
297   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
298   if (enter.succeeded())
299     enter.object()->DestroyTransferBuffer(id);
300 }
301
302 void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer(
303     const HostResource& context,
304     int32 id,
305     ppapi::proxy::SerializedHandle* transfer_buffer) {
306   transfer_buffer->set_null_shmem();
307
308   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
309   int shm_handle = 0;
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),
315         shm_size);
316   }
317 }
318
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()));
325 }
326
327 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
328                                                 uint32* sync_point) {
329   *sync_point = 0;
330   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
331   if (enter.succeeded())
332     *sync_point = enter.object()->InsertSyncPoint();
333 }
334 #endif  // !defined(OS_NACL)
335
336 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
337                                               int32_t pp_error) {
338   EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
339   if (enter.succeeded())
340     static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
341 }
342
343 #if !defined(OS_NACL)
344 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
345     int32_t result,
346     const HostResource& context) {
347   dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
348       API_ID_PPB_GRAPHICS_3D, context, result));
349 }
350 #endif  // !defined(OS_NACL)
351
352 }  // namespace proxy
353 }  // namespace ppapi
354