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