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 "gpu/command_buffer/client/gles2_implementation.h"
8 #include "gpu/command_buffer/common/command_buffer.h"
9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/proxy/enter_proxy.h"
11 #include "ppapi/proxy/plugin_dispatcher.h"
12 #include "ppapi/proxy/ppapi_command_buffer_proxy.h"
13 #include "ppapi/proxy/ppapi_messages.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/thunk/enter.h"
16 #include "ppapi/thunk/resource_creation_api.h"
17 #include "ppapi/thunk/thunk.h"
19 using ppapi::thunk::EnterResourceNoLock;
20 using ppapi::thunk::PPB_Graphics3D_API;
21 using ppapi::thunk::ResourceCreationAPI;
28 const int32 kCommandBufferSize = 1024 * 1024;
29 const int32 kTransferBufferSize = 1024 * 1024;
31 base::SharedMemoryHandle TransportSHMHandle(
32 Dispatcher* dispatcher,
33 const base::SharedMemoryHandle& handle) {
34 base::PlatformFile source = IPC::PlatformFileForTransitToPlatformFile(handle);
35 // Don't close the handle, it doesn't belong to us.
36 return dispatcher->ShareHandleWithRemote(source, false);
39 gpu::CommandBuffer::State GetErrorState() {
40 gpu::CommandBuffer::State error_state;
41 error_state.error = gpu::error::kGenericError;
47 Graphics3D::Graphics3D(const HostResource& resource)
48 : PPB_Graphics3D_Shared(resource) {
51 Graphics3D::~Graphics3D() {
55 bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2,
56 const SerializedHandle& shared_state) {
57 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this);
61 command_buffer_.reset(
62 new PpapiCommandBufferProxy(host_resource(), dispatcher, shared_state));
64 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize,
68 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) {
72 PP_Bool Graphics3D::Flush(int32_t put_offset) {
76 scoped_refptr<gpu::Buffer> Graphics3D::CreateTransferBuffer(
83 PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) {
87 gpu::CommandBuffer::State Graphics3D::WaitForTokenInRange(int32_t start,
89 return GetErrorState();
92 gpu::CommandBuffer::State Graphics3D::WaitForGetOffsetInRange(int32_t start,
94 return GetErrorState();
97 uint32_t Graphics3D::InsertSyncPoint() {
102 uint32_t Graphics3D::InsertFutureSyncPoint() {
107 void Graphics3D::RetireSyncPoint(uint32_t sync_point) {
111 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() {
112 return command_buffer_.get();
115 gpu::GpuControl* Graphics3D::GetGpuControl() {
116 return command_buffer_.get();
119 int32 Graphics3D::DoSwapBuffers() {
120 gles2_impl()->SwapBuffers();
121 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers(
122 API_ID_PPB_GRAPHICS_3D, host_resource());
123 msg->set_unblock(true);
124 PluginDispatcher::GetForResource(this)->Send(msg);
126 return PP_OK_COMPLETIONPENDING;
129 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher)
130 : InterfaceProxy(dispatcher),
131 callback_factory_(this) {
134 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() {
138 PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource(
139 PP_Instance instance,
140 PP_Resource share_context,
141 const int32_t* attrib_list) {
142 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
144 return PP_ERROR_BADARGUMENT;
146 HostResource share_host;
147 gpu::gles2::GLES2Implementation* share_gles2 = NULL;
148 if (share_context != 0) {
149 EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
151 return PP_ERROR_BADARGUMENT;
153 PPB_Graphics3D_Shared* share_graphics =
154 static_cast<PPB_Graphics3D_Shared*>(enter.object());
155 share_host = share_graphics->host_resource();
156 share_gles2 = share_graphics->gles2_impl();
159 std::vector<int32_t> attribs;
161 for (const int32_t* attr = attrib_list;
162 attr[0] != PP_GRAPHICS3DATTRIB_NONE;
164 attribs.push_back(attr[0]);
165 attribs.push_back(attr[1]);
168 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
171 ppapi::proxy::SerializedHandle shared_state;
172 dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create(API_ID_PPB_GRAPHICS_3D,
173 instance, share_host, attribs, &result, &shared_state));
175 if (result.is_null())
178 scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result));
179 if (!graphics_3d->Init(share_gles2, shared_state))
181 return graphics_3d->GetReference();
184 bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) {
186 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg)
187 #if !defined(OS_NACL)
188 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create,
190 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer,
192 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange,
193 OnMsgWaitForTokenInRange)
194 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange,
195 OnMsgWaitForGetOffsetInRange)
196 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, OnMsgAsyncFlush)
197 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer,
198 OnMsgCreateTransferBuffer)
199 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer,
200 OnMsgDestroyTransferBuffer)
201 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers,
203 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint,
204 OnMsgInsertSyncPoint)
205 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertFutureSyncPoint,
206 OnMsgInsertFutureSyncPoint)
207 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_RetireSyncPoint,
208 OnMsgRetireSyncPoint)
209 #endif // !defined(OS_NACL)
211 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK,
213 IPC_MESSAGE_UNHANDLED(handled = false)
215 IPC_END_MESSAGE_MAP()
216 // FIXME(brettw) handle bad messages!
220 #if !defined(OS_NACL)
221 void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance,
222 HostResource share_context,
223 const std::vector<int32_t>& attribs,
224 HostResource* result,
225 SerializedHandle* shared_state) {
226 shared_state->set_null_shmem();
227 if (attribs.empty() ||
228 attribs.back() != PP_GRAPHICS3DATTRIB_NONE ||
229 !(attribs.size() & 1))
230 return; // Bad message.
232 thunk::EnterResourceCreation enter(instance);
234 if (!enter.succeeded())
237 base::SharedMemoryHandle handle = IPC::InvalidPlatformFileForTransit();
238 result->SetHostResource(
240 enter.functions()->CreateGraphics3DRaw(instance,
241 share_context.host_resource(),
244 if (!result->is_null()) {
245 shared_state->set_shmem(TransportSHMHandle(dispatcher(), handle),
246 sizeof(gpu::CommandBuffer::State));
250 void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer(
251 const HostResource& context,
252 int32 transfer_buffer_id) {
253 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
254 if (enter.succeeded())
255 enter.object()->SetGetBuffer(transfer_buffer_id);
258 void PPB_Graphics3D_Proxy::OnMsgWaitForTokenInRange(
259 const HostResource& context,
262 gpu::CommandBuffer::State* state,
264 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
265 if (enter.failed()) {
269 *state = enter.object()->WaitForTokenInRange(start, end);
273 void PPB_Graphics3D_Proxy::OnMsgWaitForGetOffsetInRange(
274 const HostResource& context,
277 gpu::CommandBuffer::State* state,
279 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
280 if (enter.failed()) {
284 *state = enter.object()->WaitForGetOffsetInRange(start, end);
288 void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context,
290 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
291 if (enter.succeeded())
292 enter.object()->Flush(put_offset);
295 void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer(
296 const HostResource& context,
299 SerializedHandle* transfer_buffer) {
300 transfer_buffer->set_null_shmem();
301 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
302 if (enter.succeeded()) {
303 scoped_refptr<gpu::Buffer> buffer =
304 enter.object()->CreateTransferBuffer(size, id);
307 gpu::SharedMemoryBufferBacking* backing =
308 static_cast<gpu::SharedMemoryBufferBacking*>(buffer->backing());
309 DCHECK(backing && backing->shared_memory());
310 transfer_buffer->set_shmem(
311 TransportSHMHandle(dispatcher(), backing->shared_memory()->handle()),
318 void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer(
319 const HostResource& context,
321 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
322 if (enter.succeeded())
323 enter.object()->DestroyTransferBuffer(id);
326 void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) {
327 EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter(
328 context, callback_factory_,
329 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context);
330 if (enter.succeeded())
331 enter.SetResult(enter.object()->SwapBuffers(enter.callback()));
334 void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context,
335 uint32* sync_point) {
337 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
338 if (enter.succeeded())
339 *sync_point = enter.object()->InsertSyncPoint();
342 void PPB_Graphics3D_Proxy::OnMsgInsertFutureSyncPoint(
343 const HostResource& context,
344 uint32* sync_point) {
346 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
347 if (enter.succeeded())
348 *sync_point = enter.object()->InsertFutureSyncPoint();
351 void PPB_Graphics3D_Proxy::OnMsgRetireSyncPoint(const HostResource& context,
353 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context);
354 if (enter.succeeded())
355 enter.object()->RetireSyncPoint(sync_point);
357 #endif // !defined(OS_NACL)
359 void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource,
361 EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource);
362 if (enter.succeeded())
363 static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error);
366 #if !defined(OS_NACL)
367 void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin(
369 const HostResource& context) {
370 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK(
371 API_ID_PPB_GRAPHICS_3D, context, result));
373 #endif // !defined(OS_NACL)