Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / proxy / ppb_graphics_3d_proxy.cc
blob81b6a70c927ddbb63cd63ce8eff4f66225185659
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.
5 #include "ppapi/proxy/ppb_graphics_3d_proxy.h"
7 #include "base/numerics/safe_conversions.h"
8 #include "gpu/command_buffer/client/gles2_implementation.h"
9 #include "gpu/command_buffer/common/command_buffer.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/proxy/enter_proxy.h"
12 #include "ppapi/proxy/plugin_dispatcher.h"
13 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
14 #include "ppapi/proxy/ppapi_messages.h"
15 #include "ppapi/shared_impl/ppapi_globals.h"
16 #include "ppapi/thunk/enter.h"
17 #include "ppapi/thunk/resource_creation_api.h"
18 #include "ppapi/thunk/thunk.h"
20 using ppapi::thunk::EnterResourceNoLock;
21 using ppapi::thunk::PPB_Graphics3D_API;
22 using ppapi::thunk::ResourceCreationAPI;
24 namespace ppapi {
25 namespace proxy {
27 namespace {
29 const int32 kCommandBufferSize = 1024 * 1024;
30 const int32 kTransferBufferSize = 1024 * 1024;
32 #if !defined(OS_NACL)
33 base::SharedMemoryHandle TransportSHMHandle(
34 Dispatcher* dispatcher,
35 const base::SharedMemoryHandle& handle) {
36 // Don't close the handle, it doesn't belong to us.
37 return dispatcher->ShareSharedMemoryHandleWithRemote(handle);
39 #endif // !defined(OS_NACL)
41 gpu::CommandBuffer::State GetErrorState() {
42 gpu::CommandBuffer::State error_state;
43 error_state.error = gpu::error::kGenericError;
44 return error_state;
47 } // namespace
49 Graphics3D::Graphics3D(const HostResource& resource)
50 : PPB_Graphics3D_Shared(resource) {
53 Graphics3D::~Graphics3D() {
54 DestroyGLES2Impl();
57 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2,
58 const gpu::Capabilities& capabilities,
59 const SerializedHandle& shared_state,
60 uint64_t command_buffer_id) {
61 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
62 if (!dispatcher)
63 return false;
65 command_buffer_.reset(new PpapiCommandBufferProxy(
66 host_resource(), dispatcher, capabilities, shared_state,
67 command_buffer_id));
69 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
70 share_gles2);
73 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
74 return PP_FALSE;
77 PP_Bool Graphics3D::Flush(int32_t put_offset) {
78 return PP_FALSE;
81 scoped_refptr<gpu::Buffer> Graphics3D::CreateTransferBuffer(
82 uint32_t size,
83 int32_t* id) {
84 *id = -1;
85 return NULL;
88 PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
89 return PP_FALSE;
92 gpu::CommandBuffer::State Graphics3D::WaitForTokenInRange(int32_t start,
93 int32_t end) {
94 return GetErrorState();
97 gpu::CommandBuffer::State Graphics3D::WaitForGetOffsetInRange(int32_t start,
98 int32_t end) {
99 return GetErrorState();
102 uint32_t Graphics3D::InsertSyncPoint() {
103 NOTREACHED();
104 return 0;
107 uint32_t Graphics3D::InsertFutureSyncPoint() {
108 NOTREACHED();
109 return 0;
112 void Graphics3D::RetireSyncPoint(uint32_t sync_point) {
113 NOTREACHED();
116 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
117 return command_buffer_.get();
120 gpu::GpuControl* Graphics3D::GetGpuControl() {
121 return command_buffer_.get();
124 int32 Graphics3D::DoSwapBuffers() {
125 gles2_impl()->SwapBuffers();
126 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
127 API_ID_PPB_GRAPHICS_3D, host_resource());
128 msg->set_unblock(true);
129 PluginDispatcher::GetForResource(this)->Send(msg);
131 return PP_OK_COMPLETIONPENDING;
134 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
135 : InterfaceProxy(dispatcher),
136 callback_factory_(this) {
139 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
142 // static
143 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
144 PP_Instance instance,
145 PP_Resource share_context,
146 const int32_t* attrib_list) {
147 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
148 if (!dispatcher)
149 return PP_ERROR_BADARGUMENT;
151 HostResource share_host;
152 gpu::gles2::GLES2Implementation* share_gles2 = NULL;
153 if (share_context != 0) {
154 EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
155 if (enter.failed())
156 return PP_ERROR_BADARGUMENT;
158 PPB_Graphics3D_Shared* share_graphics =
159 static_cast<PPB_Graphics3D_Shared*>(enter.object());
160 share_host = share_graphics->host_resource();
161 share_gles2 = share_graphics->gles2_impl();
164 std::vector<int32_t> attribs;
165 if (attrib_list) {
166 for (const int32_t* attr = attrib_list;
167 attr[0] != PP_GRAPHICS3DATTRIB_NONE;
168 attr += 2) {
169 attribs.push_back(attr[0]);
170 attribs.push_back(attr[1]);
173 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
175 HostResource result;
176 gpu::Capabilities capabilities;
177 ppapi::proxy::SerializedHandle shared_state;
178 uint64_t command_buffer_id = 0;
179 dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(API_ID_PPB_GRAPHICS_3D,
180 instance, share_host, attribs, &result, &capabilities, &shared_state,
181 &command_buffer_id));
183 if (result.is_null())
184 return 0;
186 scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
187 if (!graphics_3d->Init(share_gles2, capabilities, shared_state,
188 command_buffer_id)) {
189 return 0;
191 return graphics_3d->GetReference();
194 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
195 bool handled = true;
196 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
197 #if !defined(OS_NACL)
198 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
199 OnMsgCreate)
200 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
201 OnMsgSetGetBuffer)
202 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange,
203 OnMsgWaitForTokenInRange)
204 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange,
205 OnMsgWaitForGetOffsetInRange)
206 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, OnMsgAsyncFlush)
207 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
208 OnMsgCreateTransferBuffer)
209 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
210 OnMsgDestroyTransferBuffer)
211 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
212 OnMsgSwapBuffers)
213 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
214 OnMsgInsertSyncPoint)
215 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint,
216 OnMsgInsertFutureSyncPoint)
217 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_RetireSyncPoint,
218 OnMsgRetireSyncPoint)
219 #endif // !defined(OS_NACL)
221 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
222 OnMsgSwapBuffersACK)
223 IPC_MESSAGE_UNHANDLED(handled = false)
225 IPC_END_MESSAGE_MAP()
226 // FIXME(brettw) handle bad messages!
227 return handled;
230 #if !defined(OS_NACL)
231 void PPB_Graphics3D_Proxy::OnMsgCreate(
232 PP_Instance instance,
233 HostResource share_context,
234 const std::vector<int32_t>& attribs,
235 HostResource* result,
236 gpu::Capabilities* capabilities,
237 SerializedHandle* shared_state,
238 uint64* command_buffer_id) {
239 shared_state->set_null_shmem();
240 if (attribs.empty() ||
241 attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
242 !(attribs.size() & 1))
243 return; // Bad message.
245 thunk::EnterResourceCreation enter(instance);
247 if (!enter.succeeded())
248 return;
250 base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
251 result->SetHostResource(
252 instance,
253 enter.functions()->CreateGraphics3DRaw(instance,
254 share_context.host_resource(),
255 &attribs.front(),
256 capabilities,
257 &handle,
258 command_buffer_id));
259 if (!result->is_null()) {
260 shared_state->set_shmem(TransportSHMHandle(dispatcher(), handle),
261 sizeof(gpu::CommandBuffer::State));
265 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
266 const HostResource& context,
267 int32 transfer_buffer_id) {
268 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
269 if (enter.succeeded())
270 enter.object()->SetGetBuffer(transfer_buffer_id);
273 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
274 const HostResource& context,
275 int32 start,
276 int32 end,
277 gpu::CommandBuffer::State* state,
278 bool* success) {
279 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
280 if (enter.failed()) {
281 *success = false;
282 return;
284 *state = enter.object()->WaitForTokenInRange(start, end);
285 *success = true;
288 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
289 const HostResource& context,
290 int32 start,
291 int32 end,
292 gpu::CommandBuffer::State* state,
293 bool* success) {
294 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
295 if (enter.failed()) {
296 *success = false;
297 return;
299 *state = enter.object()->WaitForGetOffsetInRange(start, end);
300 *success = true;
303 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
304 int32 put_offset) {
305 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
306 if (enter.succeeded())
307 enter.object()->Flush(put_offset);
310 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
311 const HostResource& context,
312 uint32 size,
313 int32* id,
314 SerializedHandle* transfer_buffer) {
315 transfer_buffer->set_null_shmem();
316 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
317 if (enter.succeeded()) {
318 scoped_refptr<gpu::Buffer> buffer =
319 enter.object()->CreateTransferBuffer(size, id);
320 if (!buffer.get())
321 return;
322 gpu::SharedMemoryBufferBacking* backing =
323 static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing());
324 DCHECK(backing && backing->shared_memory());
325 transfer_buffer->set_shmem(
326 TransportSHMHandle(dispatcher(), backing->shared_memory()->handle()),
327 base::checked_cast<uint32_t>(buffer->size()));
328 } else {
329 *id = -1;
333 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
334 const HostResource& context,
335 int32 id) {
336 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
337 if (enter.succeeded())
338 enter.object()->DestroyTransferBuffer(id);
341 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) {
342 EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
343 context, callback_factory_,
344 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
345 if (enter.succeeded())
346 enter.SetResult(enter.object()->SwapBuffers(enter.callback()));
349 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
350 uint32* sync_point) {
351 *sync_point = 0;
352 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
353 if (enter.succeeded())
354 *sync_point = enter.object()->InsertSyncPoint();
357 void PPB_Graphics3D_Proxy::OnMsgInsertFutureSyncPoint(
358 const HostResource& context,
359 uint32* sync_point) {
360 *sync_point = 0;
361 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
362 if (enter.succeeded())
363 *sync_point = enter.object()->InsertFutureSyncPoint();
366 void PPB_Graphics3D_Proxy::OnMsgRetireSyncPoint(const HostResource& context,
367 uint32 sync_point) {
368 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
369 if (enter.succeeded())
370 enter.object()->RetireSyncPoint(sync_point);
372 #endif // !defined(OS_NACL)
374 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
375 int32_t pp_error) {
376 EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
377 if (enter.succeeded())
378 static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
381 #if !defined(OS_NACL)
382 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
383 int32_t result,
384 const HostResource& context) {
385 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
386 API_ID_PPB_GRAPHICS_3D, context, result));
388 #endif // !defined(OS_NACL)
390 } // namespace proxy
391 } // namespace ppapi