Upstream version 9.38.198.0
[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 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);
37 }
38
39 gpu::CommandBuffer::State GetErrorState() {
40   gpu::CommandBuffer::State error_state;
41   error_state.error = gpu::error::kGenericError;
42   return error_state;
43 }
44
45 }  // namespace
46
47 Graphics3D::Graphics3D(const HostResource& resource)
48     : PPB_Graphics3D_Shared(resource) {
49 }
50
51 Graphics3D::~Graphics3D() {
52   DestroyGLES2Impl();
53 }
54
55 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) {
56   PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
57   if (!dispatcher)
58     return false;
59
60   command_buffer_.reset(
61       new PpapiCommandBufferProxy(host_resource(), dispatcher));
62
63   return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
64                          share_gles2);
65 }
66
67 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
68   return PP_FALSE;
69 }
70
71 PP_Bool Graphics3D::Flush(int32_t put_offset) {
72   return PP_FALSE;
73 }
74
75 scoped_refptr<gpu::Buffer> Graphics3D::CreateTransferBuffer(
76     uint32_t size,
77     int32_t* id) {
78   *id = -1;
79   return NULL;
80 }
81
82 PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
83   return PP_FALSE;
84 }
85
86 gpu::CommandBuffer::State Graphics3D::WaitForTokenInRange(int32_t start,
87                                                           int32_t end) {
88   return GetErrorState();
89 }
90
91 gpu::CommandBuffer::State Graphics3D::WaitForGetOffsetInRange(int32_t start,
92                                                               int32_t end) {
93   return GetErrorState();
94 }
95
96 uint32_t Graphics3D::InsertSyncPoint() {
97   NOTREACHED();
98   return 0;
99 }
100
101 uint32_t Graphics3D::InsertFutureSyncPoint() {
102   NOTREACHED();
103   return 0;
104 }
105
106 void Graphics3D::RetireSyncPoint(uint32_t sync_point) {
107   NOTREACHED();
108 }
109
110 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
111   return command_buffer_.get();
112 }
113
114 gpu::GpuControl* Graphics3D::GetGpuControl() {
115   return command_buffer_.get();
116 }
117
118 int32 Graphics3D::DoSwapBuffers() {
119   gles2_impl()->SwapBuffers();
120   IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
121       API_ID_PPB_GRAPHICS_3D, host_resource());
122   msg->set_unblock(true);
123   PluginDispatcher::GetForResource(this)->Send(msg);
124
125   return PP_OK_COMPLETIONPENDING;
126 }
127
128 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
129     : InterfaceProxy(dispatcher),
130       callback_factory_(this) {
131 }
132
133 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
134 }
135
136 // static
137 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
138     PP_Instance instance,
139     PP_Resource share_context,
140     const int32_t* attrib_list) {
141   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
142   if (!dispatcher)
143     return PP_ERROR_BADARGUMENT;
144
145   HostResource share_host;
146   gpu::gles2::GLES2Implementation* share_gles2 = NULL;
147   if (share_context != 0) {
148     EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
149     if (enter.failed())
150       return PP_ERROR_BADARGUMENT;
151
152     PPB_Graphics3D_Shared* share_graphics =
153         static_cast<PPB_Graphics3D_Shared*>(enter.object());
154     share_host = share_graphics->host_resource();
155     share_gles2 = share_graphics->gles2_impl();
156   }
157
158   std::vector<int32_t> attribs;
159   if (attrib_list) {
160     for (const int32_t* attr = attrib_list;
161          attr[0] != PP_GRAPHICS3DATTRIB_NONE;
162          attr += 2) {
163       attribs.push_back(attr[0]);
164       attribs.push_back(attr[1]);
165     }
166   }
167   attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
168
169   HostResource result;
170   dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(
171       API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result));
172   if (result.is_null())
173     return 0;
174
175   scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
176   if (!graphics_3d->Init(share_gles2))
177     return 0;
178   return graphics_3d->GetReference();
179 }
180
181 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
182   bool handled = true;
183   IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
184 #if !defined(OS_NACL)
185     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
186                         OnMsgCreate)
187     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
188                         OnMsgSetGetBuffer)
189     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange,
190                         OnMsgWaitForTokenInRange)
191     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange,
192                         OnMsgWaitForGetOffsetInRange)
193     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, OnMsgAsyncFlush)
194     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
195                         OnMsgCreateTransferBuffer)
196     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
197                         OnMsgDestroyTransferBuffer)
198     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
199                         OnMsgSwapBuffers)
200     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
201                         OnMsgInsertSyncPoint)
202     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint,
203                         OnMsgInsertFutureSyncPoint)
204     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_RetireSyncPoint,
205                         OnMsgRetireSyncPoint)
206 #endif  // !defined(OS_NACL)
207
208     IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
209                         OnMsgSwapBuffersACK)
210     IPC_MESSAGE_UNHANDLED(handled = false)
211
212   IPC_END_MESSAGE_MAP()
213   // FIXME(brettw) handle bad messages!
214   return handled;
215 }
216
217 #if !defined(OS_NACL)
218 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
219                                        HostResource share_context,
220                                        const std::vector<int32_t>& attribs,
221                                        HostResource* result) {
222   if (attribs.empty() ||
223       attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
224       !(attribs.size() & 1))
225     return;  // Bad message.
226
227   thunk::EnterResourceCreation enter(instance);
228
229   if (enter.succeeded()) {
230     result->SetHostResource(
231       instance,
232       enter.functions()->CreateGraphics3DRaw(instance,
233                                              share_context.host_resource(),
234                                              &attribs.front()));
235   }
236 }
237
238 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
239     const HostResource& context,
240     int32 transfer_buffer_id) {
241   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
242   if (enter.succeeded())
243     enter.object()->SetGetBuffer(transfer_buffer_id);
244 }
245
246 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
247     const HostResource& context,
248     int32 start,
249     int32 end,
250     gpu::CommandBuffer::State* state,
251     bool* success) {
252   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
253   if (enter.failed()) {
254     *success = false;
255     return;
256   }
257   *state = enter.object()->WaitForTokenInRange(start, end);
258   *success = true;
259 }
260
261 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
262     const HostResource& context,
263     int32 start,
264     int32 end,
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()->WaitForGetOffsetInRange(start, end);
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     ppapi::proxy::SerializedHandle* transfer_buffer) {
288   transfer_buffer->set_null_shmem();
289   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
290   if (enter.succeeded()) {
291     scoped_refptr<gpu::Buffer> buffer =
292         enter.object()->CreateTransferBuffer(size, id);
293     if (!buffer)
294       return;
295     gpu::SharedMemoryBufferBacking* backing =
296         static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing());
297     DCHECK(backing && backing->shared_memory());
298     transfer_buffer->set_shmem(
299         TransportSHMHandle(dispatcher(), backing->shared_memory()),
300         buffer->size());
301   } else {
302     *id = -1;
303   }
304 }
305
306 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
307     const HostResource& context,
308     int32 id) {
309   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
310   if (enter.succeeded())
311     enter.object()->DestroyTransferBuffer(id);
312 }
313
314 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) {
315   EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
316       context, callback_factory_,
317       &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
318   if (enter.succeeded())
319     enter.SetResult(enter.object()->SwapBuffers(enter.callback()));
320 }
321
322 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
323                                                 uint32* sync_point) {
324   *sync_point = 0;
325   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
326   if (enter.succeeded())
327     *sync_point = enter.object()->InsertSyncPoint();
328 }
329
330 void PPB_Graphics3D_Proxy::OnMsgInsertFutureSyncPoint(
331     const HostResource& context,
332     uint32* sync_point) {
333   *sync_point = 0;
334   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
335   if (enter.succeeded())
336     *sync_point = enter.object()->InsertFutureSyncPoint();
337 }
338
339 void PPB_Graphics3D_Proxy::OnMsgRetireSyncPoint(const HostResource& context,
340                                                 uint32 sync_point) {
341   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
342   if (enter.succeeded())
343     enter.object()->RetireSyncPoint(sync_point);
344 }
345 #endif  // !defined(OS_NACL)
346
347 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
348                                               int32_t pp_error) {
349   EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
350   if (enter.succeeded())
351     static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
352 }
353
354 #if !defined(OS_NACL)
355 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
356     int32_t result,
357     const HostResource& context) {
358   dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
359       API_ID_PPB_GRAPHICS_3D, context, result));
360 }
361 #endif  // !defined(OS_NACL)
362
363 }  // namespace proxy
364 }  // namespace ppapi
365