blob: a6da210795d5910165b709baea0d04593ebf0d34 [file] [log] [blame]
[email protected]aaa11b32012-03-08 12:30:131// 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"
[email protected]4e46a732013-09-30 18:35:5911#include "ppapi/shared_impl/proxy_lock.h"
[email protected]aaa11b32012-03-08 12:30:1312
13namespace ppapi {
14namespace proxy {
15
16PpapiCommandBufferProxy::PpapiCommandBufferProxy(
17 const ppapi::HostResource& resource,
18 ProxyChannel* channel)
19 : resource_(resource),
20 channel_(channel) {
21}
22
23PpapiCommandBufferProxy::~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
[email protected]aaa11b32012-03-08 12:30:1333bool PpapiCommandBufferProxy::Initialize() {
[email protected]30de8552013-05-31 20:11:4134 return true;
[email protected]aaa11b32012-03-08 12:30:1335}
36
37gpu::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;
[email protected]571b35e82012-05-19 00:04:3541 bool success = false;
[email protected]aaa11b32012-03-08 12:30:1342 if (Send(new PpapiHostMsg_PPBGraphics3D_GetState(
[email protected]571b35e82012-05-19 00:04:3543 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, &state, &success))) {
44 UpdateState(state, success);
[email protected]aaa11b32012-03-08 12:30:1345 }
46 }
47
48 return last_state_;
49}
50
51gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
[email protected]4e46a732013-09-30 18:35:5952 ppapi::ProxyLock::AssertAcquiredDebugOnly();
[email protected]aaa11b32012-03-08 12:30:1353 return last_state_;
54}
55
[email protected]a597c622013-01-25 05:08:3856int32 PpapiCommandBufferProxy::GetLastToken() {
[email protected]4e46a732013-09-30 18:35:5957 ppapi::ProxyLock::AssertAcquiredDebugOnly();
[email protected]a597c622013-01-25 05:08:3858 return last_state_.token;
59}
60
[email protected]aaa11b32012-03-08 12:30:1361void 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
75gpu::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;
[email protected]571b35e82012-05-19 00:04:3581 bool success = false;
[email protected]aaa11b32012-03-08 12:30:1382 if (Send(new PpapiHostMsg_PPBGraphics3D_Flush(
83 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, put_offset,
[email protected]571b35e82012-05-19 00:04:3584 last_known_get, &state, &success))) {
85 UpdateState(state, success);
[email protected]aaa11b32012-03-08 12:30:1386 }
87 }
88 } else {
89 Flush(put_offset);
90 }
91 return last_state_;
92}
93
94void 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
101void PpapiCommandBufferProxy::SetGetOffset(int32 get_offset) {
102 // Not implemented in proxy.
103 NOTREACHED();
104}
105
[email protected]67c80782012-12-21 01:16:52106gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size,
107 int32* id) {
108 *id = -1;
[email protected]9cef7702012-12-13 03:33:59109
[email protected]67c80782012-12-21 01:16:52110 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);
[email protected]aaa11b32012-03-08 12:30:13122}
123
124void 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);
[email protected]aaa11b32012-03-08 12:30:13130
[email protected]852ab722012-10-25 21:08:25131 if (it != transfer_buffers_.end()) {
132 // Delete the shared memory object, closing the handle in this process.
133 delete it->second.shared_memory;
[email protected]aaa11b32012-03-08 12:30:13134
[email protected]852ab722012-10-25 21:08:25135 transfer_buffers_.erase(it);
136 }
[email protected]aaa11b32012-03-08 12:30:13137
138 Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
139 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
140}
141
[email protected]d9a54602013-12-10 07:01:59142void PpapiCommandBufferProxy::Echo(const base::Closure& callback) {
143 NOTREACHED();
144}
145
[email protected]aaa11b32012-03-08 12:30:13146gpu::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.
[email protected]246fc492012-08-27 20:28:18159 ppapi::proxy::SerializedHandle handle(
160 ppapi::proxy::SerializedHandle::SHARED_MEMORY);
[email protected]aaa11b32012-03-08 12:30:13161 if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
[email protected]246fc492012-08-27 20:28:18162 ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
[email protected]aaa11b32012-03-08 12:30:13163 return gpu::Buffer();
164 }
[email protected]246fc492012-08-27 20:28:18165 if (!handle.is_shmem())
166 return gpu::Buffer();
[email protected]aaa11b32012-03-08 12:30:13167
168 // Cache the transfer buffer shared memory object client side.
169 scoped_ptr<base::SharedMemory> shared_memory(
[email protected]246fc492012-08-27 20:28:18170 new base::SharedMemory(handle.shmem(), false));
[email protected]aaa11b32012-03-08 12:30:13171
172 // Map the shared memory on demand.
173 if (!shared_memory->memory()) {
[email protected]246fc492012-08-27 20:28:18174 if (!shared_memory->Map(handle.size())) {
[email protected]aaa11b32012-03-08 12:30:13175 return gpu::Buffer();
176 }
177 }
178
179 gpu::Buffer buffer;
180 buffer.ptr = shared_memory->memory();
[email protected]246fc492012-08-27 20:28:18181 buffer.size = handle.size();
[email protected]aaa11b32012-03-08 12:30:13182 buffer.shared_memory = shared_memory.release();
183 transfer_buffers_[id] = buffer;
184
185 return buffer;
186}
187
188void PpapiCommandBufferProxy::SetToken(int32 token) {
189 NOTREACHED();
190}
191
192void PpapiCommandBufferProxy::SetParseError(gpu::error::Error error) {
193 NOTREACHED();
194}
195
196void PpapiCommandBufferProxy::SetContextLostReason(
197 gpu::error::ContextLostReason reason) {
198 NOTREACHED();
199}
200
[email protected]b096d032013-03-08 03:08:01201uint32 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
[email protected]fff7cb32013-10-02 07:07:37210void PpapiCommandBufferProxy::SignalSyncPoint(uint32 sync_point,
211 const base::Closure& callback) {
212 NOTREACHED();
213}
214
[email protected]b88a48cc2013-10-05 05:10:10215void PpapiCommandBufferProxy::SignalQuery(uint32 query,
216 const base::Closure& callback) {
217 NOTREACHED();
218}
219
[email protected]ebac3e52013-12-08 07:20:43220void PpapiCommandBufferProxy::SetSurfaceVisible(bool visible) {
221 NOTREACHED();
222}
223
[email protected]f44d5552013-10-29 04:56:29224void PpapiCommandBufferProxy::SendManagedMemoryStats(
225 const gpu::ManagedMemoryStats& stats) {
226 NOTREACHED();
227}
228
[email protected]6d668892013-12-04 21:37:12229gpu::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();
[email protected]744e0792013-09-27 01:18:35233}
234
235gfx::GpuMemoryBuffer* PpapiCommandBufferProxy::CreateGpuMemoryBuffer(
236 size_t width,
237 size_t height,
238 unsigned internalformat,
239 int32* id) {
240 NOTREACHED();
241 return NULL;
242}
243
244void PpapiCommandBufferProxy::DestroyGpuMemoryBuffer(int32 id) {
245 NOTREACHED();
246}
247
[email protected]baed42c2013-10-01 05:06:35248bool 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
[email protected]aaa11b32012-03-08 12:30:13257bool 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
267void PpapiCommandBufferProxy::UpdateState(
[email protected]571b35e82012-05-19 00:04:35268 const gpu::CommandBuffer::State& state,
269 bool success) {
[email protected]aaa11b32012-03-08 12:30:13270 // Handle wraparound. It works as long as we don't have more than 2B state
271 // updates in flight across which reordering occurs.
[email protected]571b35e82012-05-19 00:04:35272 if (success) {
273 if (state.generation - last_state_.generation < 0x80000000U) {
274 last_state_ = state;
[email protected]b44a9862012-05-22 22:08:43275 }
276 } else {
[email protected]571b35e82012-05-19 00:04:35277 last_state_.error = gpu::error::kLostContext;
278 ++last_state_.generation;
279 }
[email protected]aaa11b32012-03-08 12:30:13280}
281
282} // namespace proxy
283} // namespace ppapi