Home | History | Annotate | Download | only in proxy
      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 
    355