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/ppapi_command_buffer_proxy.h"
      6 
      7 #include "ppapi/proxy/ppapi_messages.h"
      8 #include "ppapi/proxy/proxy_channel.h"
      9 #include "ppapi/shared_impl/api_id.h"
     10 #include "ppapi/shared_impl/host_resource.h"
     11 #include "ppapi/shared_impl/proxy_lock.h"
     12 
     13 namespace ppapi {
     14 namespace proxy {
     15 
     16 PpapiCommandBufferProxy::PpapiCommandBufferProxy(
     17     const ppapi::HostResource& resource,
     18     ProxyChannel* channel)
     19     : resource_(resource),
     20       channel_(channel) {
     21 }
     22 
     23 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
     24   // gpu::Buffers are no longer referenced, allowing shared memory objects to be
     25   // deleted, closing the handle in this process.
     26 }
     27 
     28 bool PpapiCommandBufferProxy::Initialize() {
     29   return true;
     30 }
     31 
     32 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
     33   ppapi::ProxyLock::AssertAcquiredDebugOnly();
     34   return last_state_;
     35 }
     36 
     37 int32 PpapiCommandBufferProxy::GetLastToken() {
     38   ppapi::ProxyLock::AssertAcquiredDebugOnly();
     39   return last_state_.token;
     40 }
     41 
     42 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
     43   if (last_state_.error != gpu::error::kNoError)
     44     return;
     45 
     46   IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
     47       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
     48 
     49   // Do not let a synchronous flush hold up this message. If this handler is
     50   // deferred until after the synchronous flush completes, it will overwrite the
     51   // cached last_state_ with out-of-date data.
     52   message->set_unblock(true);
     53   Send(message);
     54 }
     55 
     56 void PpapiCommandBufferProxy::WaitForTokenInRange(int32 start, int32 end) {
     57   if (last_state_.error != gpu::error::kNoError)
     58     return;
     59 
     60   bool success;
     61   gpu::CommandBuffer::State state;
     62   if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
     63           ppapi::API_ID_PPB_GRAPHICS_3D,
     64           resource_,
     65           start,
     66           end,
     67           &state,
     68           &success)))
     69     UpdateState(state, success);
     70 }
     71 
     72 void PpapiCommandBufferProxy::WaitForGetOffsetInRange(int32 start, int32 end) {
     73   if (last_state_.error != gpu::error::kNoError)
     74     return;
     75 
     76   bool success;
     77   gpu::CommandBuffer::State state;
     78   if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
     79           ppapi::API_ID_PPB_GRAPHICS_3D,
     80           resource_,
     81           start,
     82           end,
     83           &state,
     84           &success)))
     85     UpdateState(state, success);
     86 }
     87 
     88 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
     89   if (last_state_.error == gpu::error::kNoError) {
     90     Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
     91          ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
     92   }
     93 }
     94 
     95 scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
     96     size_t size,
     97     int32* id) {
     98   *id = -1;
     99 
    100   if (last_state_.error != gpu::error::kNoError)
    101     return NULL;
    102 
    103   // Assuming we are in the renderer process, the service is responsible for
    104   // duplicating the handle. This might not be true for NaCl.
    105   ppapi::proxy::SerializedHandle handle(
    106       ppapi::proxy::SerializedHandle::SHARED_MEMORY);
    107   if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
    108             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id, &handle))) {
    109     return NULL;
    110   }
    111 
    112   if (*id <= 0 || !handle.is_shmem())
    113     return NULL;
    114 
    115   scoped_ptr<base::SharedMemory> shared_memory(
    116       new base::SharedMemory(handle.shmem(), false));
    117 
    118   // Map the shared memory on demand.
    119   if (!shared_memory->memory()) {
    120     if (!shared_memory->Map(handle.size())) {
    121       *id = -1;
    122       return NULL;
    123     }
    124   }
    125 
    126   return gpu::MakeBufferFromSharedMemory(shared_memory.Pass(), handle.size());
    127 }
    128 
    129 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
    130   if (last_state_.error != gpu::error::kNoError)
    131     return;
    132 
    133   Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
    134       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
    135 }
    136 
    137 void PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
    138   NOTREACHED();
    139 }
    140 
    141 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
    142   NOTREACHED();
    143   return 0;
    144 }
    145 
    146 uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
    147   uint32 sync_point = 0;
    148   if (last_state_.error == gpu::error::kNoError) {
    149     Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
    150          ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
    151   }
    152   return sync_point;
    153 }
    154 
    155 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
    156                                               const base::Closure& callback) {
    157   NOTREACHED();
    158 }
    159 
    160 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
    161                                           const base::Closure& callback) {
    162   NOTREACHED();
    163 }
    164 
    165 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
    166   NOTREACHED();
    167 }
    168 
    169 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() {
    170   // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in
    171   // crbug.com/325391.
    172   return gpu::Capabilities();
    173 }
    174 
    175 gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer(
    176     size_t width,
    177     size_t height,
    178     unsigned internalformat,
    179     unsigned usage,
    180     int32* id) {
    181   NOTREACHED();
    182   return NULL;
    183 }
    184 
    185 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) {
    186   NOTREACHED();
    187 }
    188 
    189 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
    190   DCHECK(last_state_.error == gpu::error::kNoError);
    191 
    192   if (channel_->Send(msg))
    193     return true;
    194 
    195   last_state_.error = gpu::error::kLostContext;
    196   return false;
    197 }
    198 
    199 void PpapiCommandBufferProxy::UpdateState(
    200     const gpu::CommandBuffer::State& state,
    201     bool success) {
    202   // Handle wraparound. It works as long as we don't have more than 2B state
    203   // updates in flight across which reordering occurs.
    204   if (success) {
    205     if (state.generation - last_state_.generation < 0x80000000U) {
    206       last_state_ = state;
    207     }
    208   } else {
    209     last_state_.error = gpu::error::kLostContext;
    210     ++last_state_.generation;
    211   }
    212 }
    213 
    214 }  // namespace proxy
    215 }  // namespace ppapi
    216