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