ppb_graphics_3d_proxy.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/ppb_graphics_3d_proxy.h" 6 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" 18 19using ppapi::thunk::EnterResourceNoLock; 20using ppapi::thunk::PPB_Graphics3D_API; 21using ppapi::thunk::ResourceCreationAPI; 22 23namespace ppapi { 24namespace proxy { 25 26namespace { 27 28const int32 kCommandBufferSize = 1024 * 1024; 29const int32 kTransferBufferSize = 1024 * 1024; 30 31base::SharedMemoryHandle TransportSHMHandleFromInt(Dispatcher* dispatcher, 32 int shm_handle) { 33 // TODO(piman): Change trusted interface to return a PP_FileHandle, those 34 // casts are ugly. 35 base::PlatformFile source = 36#if defined(OS_WIN) 37 reinterpret_cast<HANDLE>(static_cast<intptr_t>(shm_handle)); 38#elif defined(OS_POSIX) 39 shm_handle; 40#else 41 #error Not implemented. 42#endif 43 // Don't close the handle, it doesn't belong to us. 44 return dispatcher->ShareHandleWithRemote(source, false); 45} 46 47gpu::CommandBuffer::State GetErrorState() { 48 gpu::CommandBuffer::State error_state; 49 error_state.error = gpu::error::kGenericError; 50 return error_state; 51} 52 53} // namespace 54 55Graphics3D::Graphics3D(const HostResource& resource) 56 : PPB_Graphics3D_Shared(resource) { 57} 58 59Graphics3D::~Graphics3D() { 60 DestroyGLES2Impl(); 61} 62 63bool Graphics3D::Init(gpu::gles2::GLES2Implementation* share_gles2) { 64 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this); 65 if (!dispatcher) 66 return false; 67 68 command_buffer_.reset( 69 new PpapiCommandBufferProxy(host_resource(), dispatcher)); 70 71 return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, 72 share_gles2); 73} 74 75PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) { 76 return PP_FALSE; 77} 78 79gpu::CommandBuffer::State Graphics3D::GetState() { 80 return GetErrorState(); 81} 82 83PP_Bool Graphics3D::Flush(int32_t put_offset) { 84 return PP_FALSE; 85} 86 87gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) { 88 return GetErrorState(); 89} 90 91int32_t Graphics3D::CreateTransferBuffer(uint32_t size) { 92 return PP_FALSE; 93} 94 95PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) { 96 return PP_FALSE; 97} 98 99PP_Bool Graphics3D::GetTransferBuffer(int32_t id, 100 int* shm_handle, 101 uint32_t* shm_size) { 102 return PP_FALSE; 103} 104 105gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset, 106 int32_t last_known_get) { 107 return GetErrorState(); 108} 109 110uint32_t Graphics3D::InsertSyncPoint() { 111 NOTREACHED(); 112 return 0; 113} 114 115gpu::CommandBuffer* Graphics3D::GetCommandBuffer() { 116 return command_buffer_.get(); 117} 118 119gpu::GpuControl* Graphics3D::GetGpuControl() { 120 return command_buffer_.get(); 121} 122 123int32 Graphics3D::DoSwapBuffers() { 124 gles2_impl()->SwapBuffers(); 125 IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( 126 API_ID_PPB_GRAPHICS_3D, host_resource()); 127 msg->set_unblock(true); 128 PluginDispatcher::GetForResource(this)->Send(msg); 129 130 return PP_OK_COMPLETIONPENDING; 131} 132 133PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher) 134 : InterfaceProxy(dispatcher), 135 callback_factory_(this) { 136} 137 138PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() { 139} 140 141// static 142PP_Resource PPB_Graphics3D_Proxy::CreateProxyResource( 143 PP_Instance instance, 144 PP_Resource share_context, 145 const int32_t* attrib_list) { 146 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); 147 if (!dispatcher) 148 return PP_ERROR_BADARGUMENT; 149 150 HostResource share_host; 151 gpu::gles2::GLES2Implementation* share_gles2 = NULL; 152 if (share_context != 0) { 153 EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true); 154 if (enter.failed()) 155 return PP_ERROR_BADARGUMENT; 156 157 PPB_Graphics3D_Shared* share_graphics = 158 static_cast<PPB_Graphics3D_Shared*>(enter.object()); 159 share_host = share_graphics->host_resource(); 160 share_gles2 = share_graphics->gles2_impl(); 161 } 162 163 std::vector<int32_t> attribs; 164 if (attrib_list) { 165 for (const int32_t* attr = attrib_list; 166 attr[0] != PP_GRAPHICS3DATTRIB_NONE; 167 attr += 2) { 168 attribs.push_back(attr[0]); 169 attribs.push_back(attr[1]); 170 } 171 } 172 attribs.push_back(PP_GRAPHICS3DATTRIB_NONE); 173 174 HostResource result; 175 dispatcher->Send(new PpapiHostMsg_PPBGraphics3D_Create( 176 API_ID_PPB_GRAPHICS_3D, instance, share_host, attribs, &result)); 177 if (result.is_null()) 178 return 0; 179 180 scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result)); 181 if (!graphics_3d->Init(share_gles2)) 182 return 0; 183 return graphics_3d->GetReference(); 184} 185 186bool PPB_Graphics3D_Proxy::OnMessageReceived(const IPC::Message& msg) { 187 bool handled = true; 188 IPC_BEGIN_MESSAGE_MAP(PPB_Graphics3D_Proxy, msg) 189#if !defined(OS_NACL) 190 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Create, 191 OnMsgCreate) 192 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SetGetBuffer, 193 OnMsgSetGetBuffer) 194 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetState, 195 OnMsgGetState) 196 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_Flush, 197 OnMsgFlush) 198 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_AsyncFlush, 199 OnMsgAsyncFlush) 200 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer, 201 OnMsgCreateTransferBuffer) 202 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer, 203 OnMsgDestroyTransferBuffer) 204 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer, 205 OnMsgGetTransferBuffer) 206 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_SwapBuffers, 207 OnMsgSwapBuffers) 208 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBGraphics3D_InsertSyncPoint, 209 OnMsgInsertSyncPoint) 210#endif // !defined(OS_NACL) 211 212 IPC_MESSAGE_HANDLER(PpapiMsg_PPBGraphics3D_SwapBuffersACK, 213 OnMsgSwapBuffersACK) 214 IPC_MESSAGE_UNHANDLED(handled = false) 215 216 IPC_END_MESSAGE_MAP() 217 // FIXME(brettw) handle bad messages! 218 return handled; 219} 220 221#if !defined(OS_NACL) 222void PPB_Graphics3D_Proxy::OnMsgCreate(PP_Instance instance, 223 HostResource share_context, 224 const std::vector<int32_t>& attribs, 225 HostResource* result) { 226 if (attribs.empty() || 227 attribs.back() != PP_GRAPHICS3DATTRIB_NONE || 228 !(attribs.size() & 1)) 229 return; // Bad message. 230 231 thunk::EnterResourceCreation enter(instance); 232 233 if (enter.succeeded()) { 234 result->SetHostResource( 235 instance, 236 enter.functions()->CreateGraphics3DRaw(instance, 237 share_context.host_resource(), 238 &attribs.front())); 239 } 240} 241 242void PPB_Graphics3D_Proxy::OnMsgSetGetBuffer( 243 const HostResource& context, 244 int32 transfer_buffer_id) { 245 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 246 if (enter.succeeded()) 247 enter.object()->SetGetBuffer(transfer_buffer_id); 248} 249 250void PPB_Graphics3D_Proxy::OnMsgGetState(const HostResource& context, 251 gpu::CommandBuffer::State* state, 252 bool* success) { 253 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 254 if (enter.failed()) { 255 *success = false; 256 return; 257 } 258 *state = enter.object()->GetState(); 259 *success = true; 260} 261 262void PPB_Graphics3D_Proxy::OnMsgFlush(const HostResource& context, 263 int32 put_offset, 264 int32 last_known_get, 265 gpu::CommandBuffer::State* state, 266 bool* success) { 267 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 268 if (enter.failed()) { 269 *success = false; 270 return; 271 } 272 *state = enter.object()->FlushSyncFast(put_offset, last_known_get); 273 *success = true; 274} 275 276void PPB_Graphics3D_Proxy::OnMsgAsyncFlush(const HostResource& context, 277 int32 put_offset) { 278 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 279 if (enter.succeeded()) 280 enter.object()->Flush(put_offset); 281} 282 283void PPB_Graphics3D_Proxy::OnMsgCreateTransferBuffer( 284 const HostResource& context, 285 uint32 size, 286 int32* id) { 287 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 288 if (enter.succeeded()) 289 *id = enter.object()->CreateTransferBuffer(size); 290 else 291 *id = -1; 292} 293 294void PPB_Graphics3D_Proxy::OnMsgDestroyTransferBuffer( 295 const HostResource& context, 296 int32 id) { 297 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 298 if (enter.succeeded()) 299 enter.object()->DestroyTransferBuffer(id); 300} 301 302void PPB_Graphics3D_Proxy::OnMsgGetTransferBuffer( 303 const HostResource& context, 304 int32 id, 305 ppapi::proxy::SerializedHandle* transfer_buffer) { 306 transfer_buffer->set_null_shmem(); 307 308 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 309 int shm_handle = 0; 310 uint32_t shm_size = 0; 311 if (enter.succeeded() && 312 enter.object()->GetTransferBuffer(id, &shm_handle, &shm_size)) { 313 transfer_buffer->set_shmem( 314 TransportSHMHandleFromInt(dispatcher(), shm_handle), 315 shm_size); 316 } 317} 318 319void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context) { 320 EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter( 321 context, callback_factory_, 322 &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context); 323 if (enter.succeeded()) 324 enter.SetResult(enter.object()->SwapBuffers(enter.callback())); 325} 326 327void PPB_Graphics3D_Proxy::OnMsgInsertSyncPoint(const HostResource& context, 328 uint32* sync_point) { 329 *sync_point = 0; 330 EnterHostFromHostResource<PPB_Graphics3D_API> enter(context); 331 if (enter.succeeded()) 332 *sync_point = enter.object()->InsertSyncPoint(); 333} 334#endif // !defined(OS_NACL) 335 336void PPB_Graphics3D_Proxy::OnMsgSwapBuffersACK(const HostResource& resource, 337 int32_t pp_error) { 338 EnterPluginFromHostResource<PPB_Graphics3D_API> enter(resource); 339 if (enter.succeeded()) 340 static_cast<Graphics3D*>(enter.object())->SwapBuffersACK(pp_error); 341} 342 343#if !defined(OS_NACL) 344void PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin( 345 int32_t result, 346 const HostResource& context) { 347 dispatcher()->Send(new PpapiMsg_PPBGraphics3D_SwapBuffersACK( 348 API_ID_PPB_GRAPHICS_3D, context, result)); 349} 350#endif // !defined(OS_NACL) 351 352} // namespace proxy 353} // namespace ppapi 354 355