• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PpapiCommandBufferProxy(const ppapi::HostResource & resource,ProxyChannel * channel)16 PpapiCommandBufferProxy::PpapiCommandBufferProxy(
17     const ppapi::HostResource& resource,
18     ProxyChannel* channel)
19     : resource_(resource),
20       channel_(channel) {
21 }
22 
~PpapiCommandBufferProxy()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 
Initialize()28 bool PpapiCommandBufferProxy::Initialize() {
29   return true;
30 }
31 
GetLastState()32 gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
33   ppapi::ProxyLock::AssertAcquiredDebugOnly();
34   return last_state_;
35 }
36 
GetLastToken()37 int32 PpapiCommandBufferProxy::GetLastToken() {
38   ppapi::ProxyLock::AssertAcquiredDebugOnly();
39   return last_state_.token;
40 }
41 
Flush(int32 put_offset)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 
WaitForTokenInRange(int32 start,int32 end)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 
WaitForGetOffsetInRange(int32 start,int32 end)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 
SetGetBuffer(int32 transfer_buffer_id)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 
CreateTransferBuffer(size_t size,int32 * id)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 
DestroyTransferBuffer(int32 id)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 
Echo(const base::Closure & callback)137 void PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
138   NOTREACHED();
139 }
140 
CreateStreamTexture(uint32 texture_id)141 uint32 PpapiCommandBufferProxy::CreateStreamTexture(uint32 texture_id) {
142   NOTREACHED();
143   return 0;
144 }
145 
InsertSyncPoint()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 
SignalSyncPoint(uint32 sync_point,const base::Closure & callback)155 void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
156                                               const base::Closure& callback) {
157   NOTREACHED();
158 }
159 
SignalQuery(uint32 query,const base::Closure & callback)160 void PpapiCommandBufferProxy::SignalQuery(uint32 query,
161                                           const base::Closure& callback) {
162   NOTREACHED();
163 }
164 
SetSurfaceVisible(bool visible)165 void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
166   NOTREACHED();
167 }
168 
GetCapabilities()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 
CreateGpuMemoryBuffer(size_t width,size_t height,unsigned internalformat,unsigned usage,int32 * id)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 
DestroyGpuMemoryBuffer(int32 id)185 void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) {
186   NOTREACHED();
187 }
188 
Send(IPC::Message * msg)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 
UpdateState(const gpu::CommandBuffer::State & state,bool success)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