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   // Delete all the locally cached shared memory objects, closing the handle
     25   // in this process.
     26   for (TransferBufferMap::iterator it = transfer_buffers_.begin();
     27        it != transfer_buffers_.end(); ++it) {
     28     delete it->second.shared_memory;
     29     it->second.shared_memory = NULL;
     30   }
     31 }
     32 
     33 bool PpapiCommandBufferProxy::Initialize() {
     34   return true;
     35 }
     36 
     37 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetState() {
     38   // Send will flag state with lost context if IPC fails.
     39   if (last_state_.error == gpu::error::kNoError) {
     40     gpu::CommandBuffer::State state;
     41     bool success = false;
     42     if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
     43              ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) {
     44       UpdateState(state, success);
     45     }
     46   }
     47 
     48   return last_state_;
     49 }
     50 
     51 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
     52   ppapi::ProxyLock::AssertAcquiredDebugOnly();
     53   return last_state_;
     54 }
     55 
     56 int32 PpapiCommandBufferProxy::GetLastToken() {
     57   ppapi::ProxyLock::AssertAcquiredDebugOnly();
     58   return last_state_.token;
     59 }
     60 
     61 void PpapiCommandBufferProxy::Flush(int32 put_offset) {
     62   if (last_state_.error != gpu::error::kNoError)
     63     return;
     64 
     65   IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
     66       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset);
     67 
     68   // Do not let a synchronous flush hold up this message. If this handler is
     69   // deferred until after the synchronous flush completes, it will overwrite the
     70   // cached last_state_ with out-of-date data.
     71   message->set_unblock(true);
     72   Send(message);
     73 }
     74 
     75 gpu::CommandBuffer::State PpapiCommandBufferProxy::FlushSync(int32 put_offset,
     76                                                    int32 last_known_get) {
     77   if (last_known_get == last_state_.get_offset) {
     78     // Send will flag state with lost context if IPC fails.
     79     if (last_state_.error == gpu::error::kNoError) {
     80       gpu::CommandBuffer::State state;
     81       bool success = false;
     82       if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
     83                ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset,
     84               last_known_get, &state, &success))) {
     85         UpdateState(state, success);
     86       }
     87     }
     88   } else {
     89     Flush(put_offset);
     90   }
     91   return last_state_;
     92 }
     93 
     94 void PpapiCommandBufferProxy::SetGetBuffer(int32 transfer_buffer_id) {
     95   if (last_state_.error == gpu::error::kNoError) {
     96     Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
     97          ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
     98   }
     99 }
    100 
    101 void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
    102   // Not implemented in proxy.
    103   NOTREACHED();
    104 }
    105 
    106 gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size,
    107                                                           int32* id) {
    108   *id = -1;
    109 
    110   if (last_state_.error != gpu::error::kNoError)
    111     return gpu::Buffer();
    112 
    113   if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
    114             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) {
    115     return gpu::Buffer();
    116   }
    117 
    118   if ((*id) <= 0)
    119     return gpu::Buffer();
    120 
    121   return GetTransferBuffer(*id);
    122 }
    123 
    124 void PpapiCommandBufferProxy::DestroyTransferBuffer(int32 id) {
    125   if (last_state_.error != gpu::error::kNoError)
    126     return;
    127 
    128   // Remove the transfer buffer from the client side4 cache.
    129   TransferBufferMap::iterator it = transfer_buffers_.find(id);
    130 
    131   if (it != transfer_buffers_.end()) {
    132     // Delete the shared memory object, closing the handle in this process.
    133     delete it->second.shared_memory;
    134 
    135     transfer_buffers_.erase(it);
    136   }
    137 
    138   Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
    139       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
    140 }
    141 
    142 void PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
    143   NOTREACHED();
    144 }
    145 
    146 gpu::Buffer PpapiCommandBufferProxy::GetTransferBuffer(int32 id) {
    147   if (last_state_.error != gpu::error::kNoError)
    148     return gpu::Buffer();
    149 
    150   // Check local cache to see if there is already a client side shared memory
    151   // object for this id.
    152   TransferBufferMap::iterator it = transfer_buffers_.find(id);
    153   if (it != transfer_buffers_.end()) {
    154     return it->second;
    155   }
    156 
    157   // Assuming we are in the renderer process, the service is responsible for
    158   // duplicating the handle. This might not be true for NaCl.
    159   ppapi::proxy::SerializedHandle handle(
    160       ppapi::proxy::SerializedHandle::SHARED_MEMORY);
    161   if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
    162             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
    163     return gpu::Buffer();
    164   }
    165   if (!handle.is_shmem())
    166     return gpu::Buffer();
    167 
    168   // Cache the transfer buffer shared memory object client side.
    169   scoped_ptr<base::SharedMemory> shared_memory(
    170       new base::SharedMemory(handle.shmem(), false));
    171 
    172   // Map the shared memory on demand.
    173   if (!shared_memory->memory()) {
    174     if (!shared_memory->Map(handle.size())) {
    175       return gpu::Buffer();
    176     }
    177   }
    178 
    179   gpu::Buffer buffer;
    180   buffer.ptr = shared_memory->memory();
    181   buffer.size = handle.size();
    182   buffer.shared_memory = shared_memory.release();
    183   transfer_buffers_[id] = buffer;
    184 
    185   return buffer;
    186 }
    187 
    188 void PpapiCommandBufferProxy::SetToken(int32 token) {
    189   NOTREACHED();
    190 }
    191 
    192 void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
    193   NOTREACHED();
    194 }
    195 
    196 void PpapiCommandBufferProxy::SetContextLostReason(
    197     gpu::error::ContextLostReason reason) {
    198   NOTREACHED();
    199 }
    200 
    201 uint32 PpapiCommandBufferProxy::InsertSyncPoint() {
    202   uint32 sync_point = 0;
    203   if (last_state_.error == gpu::error::kNoError) {
    204     Send(new PpapiHostMsg_PPBGraphics3D_InsertSyncPoint(
    205          ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &sync_point));
    206   }
    207   return sync_point;
    208 }
    209 
    210 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
    211                                               const base::Closure& callback) {
    212   NOTREACHED();
    213 }
    214 
    215 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
    216                                           const base::Closure& callback) {
    217   NOTREACHED();
    218 }
    219 
    220 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
    221   NOTREACHED();
    222 }
    223 
    224 void PpapiCommandBufferProxy::SendManagedMemoryStats(
    225     const gpu::ManagedMemoryStats& stats) {
    226   NOTREACHED();
    227 }
    228 
    229 gpu::Capabilities PpapiCommandBufferProxy::GetCapabilities() {
    230   // TODO(boliu): Need to implement this to use cc in Pepper. Tracked in
    231   // crbug.com/325391.
    232   return gpu::Capabilities();
    233 }
    234 
    235 gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer(
    236     size_t width,
    237     size_t height,
    238     unsigned internalformat,
    239     int32* id) {
    240   NOTREACHED();
    241   return NULL;
    242 }
    243 
    244 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) {
    245   NOTREACHED();
    246 }
    247 
    248 bool PpapiCommandBufferProxy::GenerateMailboxNames(
    249     unsigned num, std::vector<gpu::Mailbox>* names) {
    250   // TODO(piman): implement this so we can expose mailboxes to pepper
    251   // eventually.
    252   NOTREACHED();
    253   return false;
    254 }
    255 
    256 
    257 bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
    258   DCHECK(last_state_.error == gpu::error::kNoError);
    259 
    260   if (channel_->Send(msg))
    261     return true;
    262 
    263   last_state_.error = gpu::error::kLostContext;
    264   return false;
    265 }
    266 
    267 void PpapiCommandBufferProxy::UpdateState(
    268     const gpu::CommandBuffer::State& state,
    269     bool success) {
    270   // Handle wraparound. It works as long as we don't have more than 2B state
    271   // updates in flight across which reordering occurs.
    272   if (success) {
    273     if (state.generation - last_state_.generation < 0x80000000U) {
    274       last_state_ = state;
    275     }
    276   } else {
    277     last_state_.error = gpu::error::kLostContext;
    278     ++last_state_.generation;
    279   }
    280 }
    281 
    282 }  // namespace proxy
    283 }  // namespace ppapi
    284