ppb_graphics_3d_proxy.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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
19using ppapi::thunk::EnterResourceNoLock;
20using ppapi::thunk::PPB_Graphics3D_API;
21using ppapi::thunk::ResourceCreationAPI;
22
23namespace ppapi {
24namespace proxy {
25
26namespace {
27
28const int32 kCommandBufferSize = 1024 * 1024;
29const int32 kTransferBufferSize = 1024 * 1024;
30
31base::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
47gpu::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
55Graphics3D::Graphics3D(const HostResource& resource)
56    : PPB_Graphics3D_Shared(resource) {
57}
58
59Graphics3D::~Graphics3D() {
60  DestroyGLES2Impl();
61}
62
63bool 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
75PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
76  return PP_FALSE;
77}
78
79gpu::CommandBuffer::State Graphics3D::GetState() {
80  return GetErrorState();
81}
82
83PP_Bool Graphics3D::Flush(int32_t put_offset) {
84  return PP_FALSE;
85}
86
87gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) {
88  return GetErrorState();
89}
90
91int32_t Graphics3D::CreateTransferBuffer(uint32_t size) {
92  return PP_FALSE;
93}
94
95PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
96  return PP_FALSE;
97}
98
99PP_Bool Graphics3D::GetTransferBuffer(int32_t id,
100                                      int* shm_handle,
101                                      uint32_t* shm_size) {
102  return PP_FALSE;
103}
104
105gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset,
106                                                    int32_t last_known_get) {
107  return GetErrorState();
108}
109
110uint32_t Graphics3D::InsertSyncPoint() {
111  NOTREACHED();
112  return 0;
113}
114
115gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
116  return command_buffer_.get();
117}
118
119gpu::GpuControl* Graphics3D::GetGpuControl() {
120  return command_buffer_.get();
121}
122
123int32 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
133PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
134    : InterfaceProxy(dispatcher),
135      callback_factory_(this) {
136}
137
138PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
139}
140
141// static
142PP_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
186bool 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)
222void 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
242void 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
250void 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
262void 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
276void 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
283void 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
294void 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
302void 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
319void 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
327void 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
336void 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)
344void 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
355