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(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 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
    102   return command_buffer_.get();
    103 }
    104 
    105 gpu::GpuControl* Graphics3D::GetGpuControl() {
    106   return command_buffer_.get();
    107 }
    108 
    109 int32 Graphics3D::DoSwapBuffers() {
    110   gles2_impl()->SwapBuffers();
    111   IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
    112       API_ID_PPB_GRAPHICS_3D, host_resource());
    113   msg->set_unblock(true);
    114   PluginDispatcher::GetForResource(this)->Send(msg);
    115 
    116   return PP_OK_COMPLETIONPENDING;
    117 }
    118 
    119 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
    120     : InterfaceProxy(dispatcher),
    121       callback_factory_(this) {
    122 }
    123 
    124 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
    125 }
    126 
    127 // static
    128 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
    129     PP_Instance instance,
    130     PP_Resource share_context,
    131     const int32_t* attrib_list) {
    132   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
    133   if (!dispatcher)
    134     return PP_ERROR_BADARGUMENT;
    135 
    136   HostResource share_host;
    137   gpu::gles2::GLES2Implementation* share_gles2 = NULL;
    138   if (share_context != 0) {
    139     EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
    140     if (enter.failed())
    141       return PP_ERROR_BADARGUMENT;
    142 
    143     PPB_Graphics3D_Shared* share_graphics =
    144         static_cast<PPB_Graphics3D_Shared*>(enter.object());
    145     share_host = share_graphics->host_resource();
    146     share_gles2 = share_graphics->gles2_impl();
    147   }
    148 
    149   std::vector<int32_t> attribs;
    150   if (attrib_list) {
    151     for (const int32_t* attr = attrib_list;
    152          attr[0] != PP_GRAPHICS3DATTRIB_NONE;
    153          attr += 2) {
    154       attribs.push_back(attr[0]);
    155       attribs.push_back(attr[1]);
    156     }
    157   }
    158   attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
    159 
    160   HostResource result;
    161   dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(
    162       API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result));
    163   if (result.is_null())
    164     return 0;
    165 
    166   scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
    167   if (!graphics_3d->Init(share_gles2))
    168     return 0;
    169   return graphics_3d->GetReference();
    170 }
    171 
    172 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
    173   bool handled = true;
    174   IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
    175 #if !defined(OS_NACL)
    176     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
    177                         OnMsgCreate)
    178     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
    179                         OnMsgSetGetBuffer)
    180     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange,
    181                         OnMsgWaitForTokenInRange)
    182     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange,
    183                         OnMsgWaitForGetOffsetInRange)
    184     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, OnMsgAsyncFlush)
    185     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
    186                         OnMsgCreateTransferBuffer)
    187     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
    188                         OnMsgDestroyTransferBuffer)
    189     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
    190                         OnMsgSwapBuffers)
    191     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
    192                         OnMsgInsertSyncPoint)
    193 #endif  // !defined(OS_NACL)
    194 
    195     IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
    196                         OnMsgSwapBuffersACK)
    197     IPC_MESSAGE_UNHANDLED(handled = false)
    198 
    199   IPC_END_MESSAGE_MAP()
    200   // FIXME(brettw) handle bad messages!
    201   return handled;
    202 }
    203 
    204 #if !defined(OS_NACL)
    205 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
    206                                        HostResource share_context,
    207                                        const std::vector<int32_t>& attribs,
    208                                        HostResource* result) {
    209   if (attribs.empty() ||
    210       attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
    211       !(attribs.size() & 1))
    212     return;  // Bad message.
    213 
    214   thunk::EnterResourceCreation enter(instance);
    215 
    216   if (enter.succeeded()) {
    217     result->SetHostResource(
    218       instance,
    219       enter.functions()->CreateGraphics3DRaw(instance,
    220                                              share_context.host_resource(),
    221                                              &attribs.front()));
    222   }
    223 }
    224 
    225 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
    226     const HostResource& context,
    227     int32 transfer_buffer_id) {
    228   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    229   if (enter.succeeded())
    230     enter.object()->SetGetBuffer(transfer_buffer_id);
    231 }
    232 
    233 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
    234     const HostResource& context,
    235     int32 start,
    236     int32 end,
    237     gpu::CommandBuffer::State* state,
    238     bool* success) {
    239   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    240   if (enter.failed()) {
    241     *success = false;
    242     return;
    243   }
    244   *state = enter.object()->WaitForTokenInRange(start, end);
    245   *success = true;
    246 }
    247 
    248 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
    249     const HostResource& context,
    250     int32 start,
    251     int32 end,
    252     gpu::CommandBuffer::State* state,
    253     bool* success) {
    254   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    255   if (enter.failed()) {
    256     *success = false;
    257     return;
    258   }
    259   *state = enter.object()->WaitForGetOffsetInRange(start, end);
    260   *success = true;
    261 }
    262 
    263 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
    264                                            int32 put_offset) {
    265   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    266   if (enter.succeeded())
    267     enter.object()->Flush(put_offset);
    268 }
    269 
    270 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
    271     const HostResource& context,
    272     uint32 size,
    273     int32* id,
    274     ppapi::proxy::SerializedHandle* transfer_buffer) {
    275   transfer_buffer->set_null_shmem();
    276   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    277   if (enter.succeeded()) {
    278     scoped_refptr<gpu::Buffer> buffer =
    279         enter.object()->CreateTransferBuffer(size, id);
    280     if (!buffer)
    281       return;
    282     gpu::SharedMemoryBufferBacking* backing =
    283         static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing());
    284     DCHECK(backing && backing->shared_memory());
    285     transfer_buffer->set_shmem(
    286         TransportSHMHandle(dispatcher(), backing->shared_memory()),
    287         buffer->size());
    288   } else {
    289     *id = -1;
    290   }
    291 }
    292 
    293 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
    294     const HostResource& context,
    295     int32 id) {
    296   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    297   if (enter.succeeded())
    298     enter.object()->DestroyTransferBuffer(id);
    299 }
    300 
    301 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) {
    302   EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
    303       context, callback_factory_,
    304       &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
    305   if (enter.succeeded())
    306     enter.SetResult(enter.object()->SwapBuffers(enter.callback()));
    307 }
    308 
    309 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
    310                                                 uint32* sync_point) {
    311   *sync_point = 0;
    312   EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
    313   if (enter.succeeded())
    314     *sync_point = enter.object()->InsertSyncPoint();
    315 }
    316 #endif  // !defined(OS_NACL)
    317 
    318 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
    319                                               int32_t pp_error) {
    320   EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
    321   if (enter.succeeded())
    322     static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
    323 }
    324 
    325 #if !defined(OS_NACL)
    326 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
    327     int32_t result,
    328     const HostResource& context) {
    329   dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
    330       API_ID_PPB_GRAPHICS_3D, context, result));
    331 }
    332 #endif  // !defined(OS_NACL)
    333 
    334 }  // namespace proxy
    335 }  // namespace ppapi
    336 
    337