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