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 19 using ppapi::thunk::EnterResourceNoLock; 20 using ppapi::thunk::PPB_Graphics3D_API; 21 using ppapi::thunk::ResourceCreationAPI; 22 23 namespace ppapi { 24 namespace proxy { 25 26 namespace { 27 28 const int32 kCommandBufferSize = 1024 * 1024; 29 const int32 kTransferBufferSize = 1024 * 1024; 30 31 base::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 47 gpu::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 55 Graphics3D::Graphics3D(const HostResource& resource) 56 : PPB_Graphics3D_Shared(resource) { 57 } 58 59 Graphics3D::~Graphics3D() { 60 DestroyGLES2Impl(); 61 } 62 63 bool 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 75 PP_Bool Graphics3D::SetGetBuffer(int32_t /* transfer_buffer_id */) { 76 return PP_FALSE; 77 } 78 79 gpu::CommandBuffer::State Graphics3D::GetState() { 80 return GetErrorState(); 81 } 82 83 PP_Bool Graphics3D::Flush(int32_t put_offset) { 84 return PP_FALSE; 85 } 86 87 gpu::CommandBuffer::State Graphics3D::FlushSync(int32_t put_offset) { 88 return GetErrorState(); 89 } 90 91 int32_t Graphics3D::CreateTransferBuffer(uint32_t size) { 92 return PP_FALSE; 93 } 94 95 PP_Bool Graphics3D::DestroyTransferBuffer(int32_t id) { 96 return PP_FALSE; 97 } 98 99 PP_Bool Graphics3D::GetTransferBuffer(int32_t id, 100 int* shm_handle, 101 uint32_t* shm_size) { 102 return PP_FALSE; 103 } 104 105 gpu::CommandBuffer::State Graphics3D::FlushSyncFast(int32_t put_offset, 106 int32_t last_known_get) { 107 return GetErrorState(); 108 } 109 110 uint32_t Graphics3D::InsertSyncPoint() { 111 NOTREACHED(); 112 return 0; 113 } 114 115 gpu::CommandBuffer* Graphics3D::GetCommandBuffer() { 116 return command_buffer_.get(); 117 } 118 119 gpu::GpuControl* Graphics3D::GetGpuControl() { 120 return command_buffer_.get(); 121 } 122 123 int32 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 133 PPB_Graphics3D_Proxy::PPB_Graphics3D_Proxy(Dispatcher* dispatcher) 134 : InterfaceProxy(dispatcher), 135 callback_factory_(this) { 136 } 137 138 PPB_Graphics3D_Proxy::~PPB_Graphics3D_Proxy() { 139 } 140 141 // static 142 PP_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 186 bool 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) 222 void 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 242 void 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 250 void 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 262 void 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 276 void 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 283 void 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 294 void 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 302 void 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 319 void 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 327 void 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 336 void 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) 344 void 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