| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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_context_3d_proxy.h" | |
| 6 | |
| 7 #include "base/hash_tables.h" | |
| 8 #include "gpu/command_buffer/client/gles2_cmd_helper.h" | |
| 9 #include "gpu/command_buffer/client/gles2_implementation.h" | |
| 10 #include "ppapi/c/pp_errors.h" | |
| 11 #include "ppapi/c/pp_resource.h" | |
| 12 #include "ppapi/c/dev/ppb_context_3d_dev.h" | |
| 13 #include "ppapi/c/dev/ppb_context_3d_trusted_dev.h" | |
| 14 #include "ppapi/proxy/enter_proxy.h" | |
| 15 #include "ppapi/proxy/plugin_dispatcher.h" | |
| 16 #include "ppapi/proxy/ppapi_messages.h" | |
| 17 #include "ppapi/proxy/ppb_surface_3d_proxy.h" | |
| 18 #include "ppapi/thunk/enter.h" | |
| 19 #include "ppapi/thunk/resource_creation_api.h" | |
| 20 #include "ppapi/thunk/thunk.h" | |
| 21 | |
| 22 using ppapi::thunk::EnterFunctionNoLock; | |
| 23 using ppapi::thunk::EnterResourceNoLock; | |
| 24 using ppapi::thunk::PPB_Context3D_API; | |
| 25 using ppapi::thunk::PPB_Surface3D_API; | |
| 26 using ppapi::thunk::ResourceCreationAPI; | |
| 27 | |
| 28 namespace ppapi { | |
| 29 namespace proxy { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 base::SharedMemoryHandle TransportSHMHandleFromInt(Dispatcher* dispatcher, | |
| 34 int shm_handle) { | |
| 35 // TODO(piman): Change trusted interface to return a PP_FileHandle, those | |
| 36 // casts are ugly. | |
| 37 base::PlatformFile source = | |
| 38 #if defined(OS_WIN) | |
| 39 reinterpret_cast<HANDLE>(static_cast<intptr_t>(shm_handle)); | |
| 40 #elif defined(OS_POSIX) | |
| 41 shm_handle; | |
| 42 #else | |
| 43 #error Not implemented. | |
| 44 #endif | |
| 45 // Don't close the handle, it doesn't belong to us. | |
| 46 return dispatcher->ShareHandleWithRemote(source, false); | |
| 47 } | |
| 48 | |
| 49 PP_Context3DTrustedState GetErrorState() { | |
| 50 PP_Context3DTrustedState error_state = { 0 }; | |
| 51 error_state.error = kGenericError; | |
| 52 return error_state; | |
| 53 } | |
| 54 | |
| 55 gpu::CommandBuffer::State GPUStateFromPPState( | |
| 56 const PP_Context3DTrustedState& s) { | |
| 57 gpu::CommandBuffer::State state; | |
| 58 state.num_entries = s.num_entries; | |
| 59 state.get_offset = s.get_offset; | |
| 60 state.put_offset = s.put_offset; | |
| 61 state.token = s.token; | |
| 62 state.error = static_cast<gpu::error::Error>(s.error); | |
| 63 state.generation = s.generation; | |
| 64 return state; | |
| 65 } | |
| 66 | |
| 67 // Size of the transfer buffer. | |
| 68 const int32 kCommandBufferSize = 1024 * 1024; | |
| 69 const int32 kTransferBufferSize = 1024 * 1024; | |
| 70 | |
| 71 } // namespace | |
| 72 | |
| 73 class PepperCommandBuffer : public gpu::CommandBuffer { | |
| 74 public: | |
| 75 PepperCommandBuffer(const HostResource& resource, | |
| 76 PluginDispatcher* dispatcher); | |
| 77 virtual ~PepperCommandBuffer(); | |
| 78 | |
| 79 // CommandBuffer implementation: | |
| 80 virtual bool Initialize(int32 size); | |
| 81 virtual bool Initialize(base::SharedMemory* buffer, int32 size); | |
| 82 virtual gpu::Buffer GetRingBuffer(); | |
| 83 virtual State GetState(); | |
| 84 virtual State GetLastState(); | |
| 85 virtual void Flush(int32 put_offset); | |
| 86 virtual State FlushSync(int32 put_offset, int32 last_known_get); | |
| 87 virtual void SetGetOffset(int32 get_offset); | |
| 88 virtual int32 CreateTransferBuffer(size_t size, int32 id_request); | |
| 89 virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory, | |
| 90 size_t size, | |
| 91 int32 id_request); | |
| 92 virtual void DestroyTransferBuffer(int32 id); | |
| 93 virtual gpu::Buffer GetTransferBuffer(int32 handle); | |
| 94 virtual void SetToken(int32 token); | |
| 95 virtual void SetParseError(gpu::error::Error error); | |
| 96 virtual void SetContextLostReason(gpu::error::ContextLostReason reason); | |
| 97 | |
| 98 private: | |
| 99 bool Send(IPC::Message* msg); | |
| 100 void UpdateState(const gpu::CommandBuffer::State& state); | |
| 101 | |
| 102 int32 num_entries_; | |
| 103 scoped_ptr<base::SharedMemory> ring_buffer_; | |
| 104 | |
| 105 typedef base::hash_map<int32, gpu::Buffer> TransferBufferMap; | |
| 106 TransferBufferMap transfer_buffers_; | |
| 107 | |
| 108 State last_state_; | |
| 109 | |
| 110 HostResource resource_; | |
| 111 PluginDispatcher* dispatcher_; | |
| 112 | |
| 113 DISALLOW_COPY_AND_ASSIGN(PepperCommandBuffer); | |
| 114 }; | |
| 115 | |
| 116 PepperCommandBuffer::PepperCommandBuffer( | |
| 117 const HostResource& resource, | |
| 118 PluginDispatcher* dispatcher) | |
| 119 : num_entries_(0), | |
| 120 resource_(resource), | |
| 121 dispatcher_(dispatcher) { | |
| 122 } | |
| 123 | |
| 124 PepperCommandBuffer::~PepperCommandBuffer() { | |
| 125 // Delete all the locally cached shared memory objects, closing the handle | |
| 126 // in this process. | |
| 127 for (TransferBufferMap::iterator it = transfer_buffers_.begin(); | |
| 128 it != transfer_buffers_.end(); | |
| 129 ++it) { | |
| 130 delete it->second.shared_memory; | |
| 131 it->second.shared_memory = NULL; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 bool PepperCommandBuffer::Initialize(int32 size) { | |
| 136 DCHECK(!ring_buffer_.get()); | |
| 137 | |
| 138 // Initialize the service. Assuming we are sandboxed, the GPU | |
| 139 // process is responsible for duplicating the handle. This might not be true | |
| 140 // for NaCl. | |
| 141 base::SharedMemoryHandle handle; | |
| 142 if (Send(new PpapiHostMsg_PPBContext3D_Initialize( | |
| 143 API_ID_PPB_CONTEXT_3D, resource_, size, &handle)) && | |
| 144 base::SharedMemory::IsHandleValid(handle)) { | |
| 145 ring_buffer_.reset(new base::SharedMemory(handle, false)); | |
| 146 if (ring_buffer_->Map(size)) { | |
| 147 num_entries_ = size / sizeof(gpu::CommandBufferEntry); | |
| 148 return true; | |
| 149 } | |
| 150 | |
| 151 ring_buffer_.reset(); | |
| 152 } | |
| 153 | |
| 154 return false; | |
| 155 } | |
| 156 | |
| 157 bool PepperCommandBuffer::Initialize(base::SharedMemory* buffer, int32 size) { | |
| 158 // Not implemented in proxy. | |
| 159 NOTREACHED(); | |
| 160 return false; | |
| 161 } | |
| 162 | |
| 163 gpu::Buffer PepperCommandBuffer::GetRingBuffer() { | |
| 164 // Return locally cached ring buffer. | |
| 165 gpu::Buffer buffer; | |
| 166 buffer.ptr = ring_buffer_->memory(); | |
| 167 buffer.size = num_entries_ * sizeof(gpu::CommandBufferEntry); | |
| 168 buffer.shared_memory = ring_buffer_.get(); | |
| 169 return buffer; | |
| 170 } | |
| 171 | |
| 172 gpu::CommandBuffer::State PepperCommandBuffer::GetState() { | |
| 173 // Send will flag state with lost context if IPC fails. | |
| 174 if (last_state_.error == gpu::error::kNoError) { | |
| 175 gpu::CommandBuffer::State state; | |
| 176 if (Send(new PpapiHostMsg_PPBContext3D_GetState( | |
| 177 API_ID_PPB_CONTEXT_3D, resource_, &state))) | |
| 178 UpdateState(state); | |
| 179 } | |
| 180 | |
| 181 return last_state_; | |
| 182 } | |
| 183 | |
| 184 gpu::CommandBuffer::State PepperCommandBuffer::GetLastState() { | |
| 185 return last_state_; | |
| 186 } | |
| 187 | |
| 188 void PepperCommandBuffer::Flush(int32 put_offset) { | |
| 189 if (last_state_.error != gpu::error::kNoError) | |
| 190 return; | |
| 191 | |
| 192 IPC::Message* message = new PpapiHostMsg_PPBContext3D_AsyncFlush( | |
| 193 API_ID_PPB_CONTEXT_3D, resource_, put_offset); | |
| 194 | |
| 195 // Do not let a synchronous flush hold up this message. If this handler is | |
| 196 // deferred until after the synchronous flush completes, it will overwrite the | |
| 197 // cached last_state_ with out-of-date data. | |
| 198 message->set_unblock(true); | |
| 199 Send(message); | |
| 200 } | |
| 201 | |
| 202 gpu::CommandBuffer::State PepperCommandBuffer::FlushSync( | |
| 203 int32 put_offset, int32 last_known_get) { | |
| 204 if (last_known_get == last_state_.get_offset) { | |
| 205 // Send will flag state with lost context if IPC fails. | |
| 206 if (last_state_.error == gpu::error::kNoError) { | |
| 207 gpu::CommandBuffer::State state; | |
| 208 if (Send(new PpapiHostMsg_PPBContext3D_Flush( | |
| 209 API_ID_PPB_CONTEXT_3D, resource_, put_offset, | |
| 210 last_known_get, &state))) | |
| 211 UpdateState(state); | |
| 212 } | |
| 213 } else { | |
| 214 Flush(put_offset); | |
| 215 } | |
| 216 | |
| 217 return last_state_; | |
| 218 } | |
| 219 | |
| 220 void PepperCommandBuffer::SetGetOffset(int32 get_offset) { | |
| 221 // Not implemented in proxy. | |
| 222 NOTREACHED(); | |
| 223 } | |
| 224 | |
| 225 int32 PepperCommandBuffer::CreateTransferBuffer(size_t size, int32 id_request) { | |
| 226 if (last_state_.error == gpu::error::kNoError) { | |
| 227 int32 id; | |
| 228 if (Send(new PpapiHostMsg_PPBContext3D_CreateTransferBuffer( | |
| 229 API_ID_PPB_CONTEXT_3D, resource_, size, &id))) { | |
| 230 return id; | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 return -1; | |
| 235 } | |
| 236 | |
| 237 int32 PepperCommandBuffer::RegisterTransferBuffer( | |
| 238 base::SharedMemory* shared_memory, | |
| 239 size_t size, | |
| 240 int32 id_request) { | |
| 241 // Not implemented in proxy. | |
| 242 NOTREACHED(); | |
| 243 return -1; | |
| 244 } | |
| 245 | |
| 246 void PepperCommandBuffer::DestroyTransferBuffer(int32 id) { | |
| 247 if (last_state_.error != gpu::error::kNoError) | |
| 248 return; | |
| 249 | |
| 250 // Remove the transfer buffer from the client side4 cache. | |
| 251 TransferBufferMap::iterator it = transfer_buffers_.find(id); | |
| 252 DCHECK(it != transfer_buffers_.end()); | |
| 253 | |
| 254 // Delete the shared memory object, closing the handle in this process. | |
| 255 delete it->second.shared_memory; | |
| 256 | |
| 257 transfer_buffers_.erase(it); | |
| 258 | |
| 259 Send(new PpapiHostMsg_PPBContext3D_DestroyTransferBuffer( | |
| 260 API_ID_PPB_CONTEXT_3D, resource_, id)); | |
| 261 } | |
| 262 | |
| 263 gpu::Buffer PepperCommandBuffer::GetTransferBuffer(int32 id) { | |
| 264 if (last_state_.error != gpu::error::kNoError) | |
| 265 return gpu::Buffer(); | |
| 266 | |
| 267 // Check local cache to see if there is already a client side shared memory | |
| 268 // object for this id. | |
| 269 TransferBufferMap::iterator it = transfer_buffers_.find(id); | |
| 270 if (it != transfer_buffers_.end()) { | |
| 271 return it->second; | |
| 272 } | |
| 273 | |
| 274 // Assuming we are in the renderer process, the service is responsible for | |
| 275 // duplicating the handle. This might not be true for NaCl. | |
| 276 base::SharedMemoryHandle handle; | |
| 277 uint32 size; | |
| 278 if (!Send(new PpapiHostMsg_PPBContext3D_GetTransferBuffer( | |
| 279 API_ID_PPB_CONTEXT_3D, resource_, id, &handle, &size))) { | |
| 280 return gpu::Buffer(); | |
| 281 } | |
| 282 | |
| 283 // Cache the transfer buffer shared memory object client side. | |
| 284 scoped_ptr<base::SharedMemory> shared_memory( | |
| 285 new base::SharedMemory(handle, false)); | |
| 286 | |
| 287 // Map the shared memory on demand. | |
| 288 if (!shared_memory->memory()) { | |
| 289 if (!shared_memory->Map(size)) { | |
| 290 return gpu::Buffer(); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 gpu::Buffer buffer; | |
| 295 buffer.ptr = shared_memory->memory(); | |
| 296 buffer.size = size; | |
| 297 buffer.shared_memory = shared_memory.release(); | |
| 298 transfer_buffers_[id] = buffer; | |
| 299 | |
| 300 return buffer; | |
| 301 } | |
| 302 | |
| 303 void PepperCommandBuffer::SetToken(int32 token) { | |
| 304 NOTREACHED(); | |
| 305 } | |
| 306 | |
| 307 void PepperCommandBuffer::SetParseError(gpu::error::Error error) { | |
| 308 NOTREACHED(); | |
| 309 } | |
| 310 | |
| 311 void PepperCommandBuffer::SetContextLostReason( | |
| 312 gpu::error::ContextLostReason reason) { | |
| 313 NOTREACHED(); | |
| 314 } | |
| 315 | |
| 316 bool PepperCommandBuffer::Send(IPC::Message* msg) { | |
| 317 DCHECK(last_state_.error == gpu::error::kNoError); | |
| 318 | |
| 319 if (dispatcher_->Send(msg)) | |
| 320 return true; | |
| 321 | |
| 322 last_state_.error = gpu::error::kLostContext; | |
| 323 return false; | |
| 324 } | |
| 325 | |
| 326 void PepperCommandBuffer::UpdateState(const gpu::CommandBuffer::State& state) { | |
| 327 // Handle wraparound. It works as long as we don't have more than 2B state | |
| 328 // updates in flight across which reordering occurs. | |
| 329 if (state.generation - last_state_.generation < 0x80000000U) | |
| 330 last_state_ = state; | |
| 331 } | |
| 332 | |
| 333 // Context3D ------------------------------------------------------------------- | |
| 334 | |
| 335 Context3D::Context3D(const HostResource& resource) | |
| 336 : Resource(resource), | |
| 337 draw_(NULL), | |
| 338 read_(NULL), | |
| 339 transfer_buffer_id_(0) { | |
| 340 } | |
| 341 | |
| 342 Context3D::~Context3D() { | |
| 343 if (draw_) | |
| 344 draw_->set_context(NULL); | |
| 345 } | |
| 346 | |
| 347 PPB_Context3D_API* Context3D::AsPPB_Context3D_API() { | |
| 348 return this; | |
| 349 } | |
| 350 | |
| 351 bool Context3D::CreateImplementation() { | |
| 352 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(this); | |
| 353 if (!dispatcher) | |
| 354 return false; | |
| 355 | |
| 356 command_buffer_.reset(new PepperCommandBuffer(host_resource(), dispatcher)); | |
| 357 | |
| 358 if (!command_buffer_->Initialize(kCommandBufferSize)) | |
| 359 return false; | |
| 360 | |
| 361 helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); | |
| 362 if (!helper_->Initialize(kCommandBufferSize)) | |
| 363 return false; | |
| 364 | |
| 365 transfer_buffer_id_ = | |
| 366 command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1); | |
| 367 if (transfer_buffer_id_ < 0) | |
| 368 return false; | |
| 369 | |
| 370 gpu::Buffer transfer_buffer = | |
| 371 command_buffer_->GetTransferBuffer(transfer_buffer_id_); | |
| 372 if (!transfer_buffer.ptr) | |
| 373 return false; | |
| 374 | |
| 375 gles2_impl_.reset(new gpu::gles2::GLES2Implementation( | |
| 376 helper_.get(), | |
| 377 transfer_buffer.size, | |
| 378 transfer_buffer.ptr, | |
| 379 transfer_buffer_id_, | |
| 380 false, | |
| 381 true)); | |
| 382 | |
| 383 return true; | |
| 384 } | |
| 385 | |
| 386 int32_t Context3D::GetAttrib(int32_t attribute, int32_t* value) { | |
| 387 // TODO(alokp): Implement me. | |
| 388 return 0; | |
| 389 } | |
| 390 | |
| 391 int32_t Context3D::BindSurfaces(PP_Resource pp_draw, PP_Resource pp_read) { | |
| 392 // TODO(alokp): Support separate draw-read surfaces. | |
| 393 DCHECK_EQ(pp_draw, pp_read); | |
| 394 if (pp_draw != pp_read) | |
| 395 return PP_ERROR_BADARGUMENT; | |
| 396 | |
| 397 EnterResourceNoLock<PPB_Surface3D_API> enter_draw(pp_draw, false); | |
| 398 EnterResourceNoLock<PPB_Surface3D_API> enter_read(pp_read, false); | |
| 399 Surface3D* draw_surface = enter_draw.succeeded() ? | |
| 400 static_cast<Surface3D*>(enter_draw.object()) : NULL; | |
| 401 Surface3D* read_surface = enter_read.succeeded() ? | |
| 402 static_cast<Surface3D*>(enter_read.object()) : NULL; | |
| 403 | |
| 404 if (pp_draw && !draw_surface) | |
| 405 return PP_ERROR_BADRESOURCE; | |
| 406 if (pp_read && !read_surface) | |
| 407 return PP_ERROR_BADRESOURCE; | |
| 408 HostResource host_draw = | |
| 409 draw_surface ? draw_surface->host_resource() : HostResource(); | |
| 410 HostResource host_read = | |
| 411 read_surface ? read_surface->host_resource() : HostResource(); | |
| 412 | |
| 413 int32_t result; | |
| 414 PluginDispatcher::GetForResource(this)->Send( | |
| 415 new PpapiHostMsg_PPBContext3D_BindSurfaces( | |
| 416 API_ID_PPB_CONTEXT_3D, | |
| 417 host_resource(), host_draw, host_read, &result)); | |
| 418 if (result != PP_OK) | |
| 419 return result; | |
| 420 | |
| 421 if (draw_surface != draw_) { | |
| 422 if (draw_) | |
| 423 draw_->set_context(NULL); | |
| 424 if (draw_surface) { | |
| 425 draw_surface->set_context(this); | |
| 426 // Resize the backing texture to the size of the instance when it is | |
| 427 // bound. | |
| 428 // TODO(alokp): This should be the responsibility of plugins. | |
| 429 InstanceData* data = | |
| 430 PluginDispatcher::GetForResource(this)->GetInstanceData( | |
| 431 pp_instance()); | |
| 432 gles2_impl()->ResizeCHROMIUM(data->position.size.width, | |
| 433 data->position.size.height); | |
| 434 } | |
| 435 draw_ = draw_surface; | |
| 436 } | |
| 437 read_ = read_surface; | |
| 438 return PP_OK; | |
| 439 } | |
| 440 | |
| 441 int32_t Context3D::GetBoundSurfaces(PP_Resource* draw, PP_Resource* read) { | |
| 442 *draw = draw_ ? draw_->pp_resource() : 0; | |
| 443 *read = read_ ? read_->pp_resource() : 0; | |
| 444 return PP_OK; | |
| 445 } | |
| 446 | |
| 447 PP_Bool Context3D::InitializeTrusted(int32_t size) { | |
| 448 // Trusted interface not implemented in the proxy. | |
| 449 return PP_FALSE; | |
| 450 } | |
| 451 | |
| 452 PP_Bool Context3D::GetRingBuffer(int* shm_handle, | |
| 453 uint32_t* shm_size) { | |
| 454 // Trusted interface not implemented in the proxy. | |
| 455 return PP_FALSE; | |
| 456 } | |
| 457 | |
| 458 PP_Context3DTrustedState Context3D::GetState() { | |
| 459 // Trusted interface not implemented in the proxy. | |
| 460 return GetErrorState(); | |
| 461 } | |
| 462 | |
| 463 PP_Bool Context3D::Flush(int32_t put_offset) { | |
| 464 // Trusted interface not implemented in the proxy. | |
| 465 return PP_FALSE; | |
| 466 } | |
| 467 | |
| 468 PP_Context3DTrustedState Context3D::FlushSync(int32_t put_offset) { | |
| 469 // Trusted interface not implemented in the proxy. | |
| 470 return GetErrorState(); | |
| 471 } | |
| 472 | |
| 473 int32_t Context3D::CreateTransferBuffer(uint32_t size) { | |
| 474 // Trusted interface not implemented in the proxy. | |
| 475 return 0; | |
| 476 } | |
| 477 | |
| 478 PP_Bool Context3D::DestroyTransferBuffer(int32_t id) { | |
| 479 // Trusted interface not implemented in the proxy. | |
| 480 return PP_FALSE; | |
| 481 } | |
| 482 | |
| 483 PP_Bool Context3D::GetTransferBuffer(int32_t id, | |
| 484 int* shm_handle, | |
| 485 uint32_t* shm_size) { | |
| 486 // Trusted interface not implemented in the proxy. | |
| 487 return PP_FALSE; | |
| 488 } | |
| 489 | |
| 490 PP_Context3DTrustedState Context3D::FlushSyncFast(int32_t put_offset, | |
| 491 int32_t last_known_get) { | |
| 492 // Trusted interface not implemented in the proxy. | |
| 493 return GetErrorState(); | |
| 494 } | |
| 495 | |
| 496 void* Context3D::MapTexSubImage2DCHROMIUM(GLenum target, | |
| 497 GLint level, | |
| 498 GLint xoffset, | |
| 499 GLint yoffset, | |
| 500 GLsizei width, | |
| 501 GLsizei height, | |
| 502 GLenum format, | |
| 503 GLenum type, | |
| 504 GLenum access) { | |
| 505 return gles2_impl_->MapTexSubImage2DCHROMIUM( | |
| 506 target, level, xoffset, yoffset, width, height, format, type, access); | |
| 507 } | |
| 508 | |
| 509 void Context3D::UnmapTexSubImage2DCHROMIUM(const void* mem) { | |
| 510 gles2_impl_->UnmapTexSubImage2DCHROMIUM(mem); | |
| 511 } | |
| 512 | |
| 513 gpu::gles2::GLES2Implementation* Context3D::GetGLES2Impl() { | |
| 514 return gles2_impl(); | |
| 515 } | |
| 516 | |
| 517 // PPB_Context3D_Proxy --------------------------------------------------------- | |
| 518 | |
| 519 PPB_Context3D_Proxy::PPB_Context3D_Proxy(Dispatcher* dispatcher) | |
| 520 : InterfaceProxy(dispatcher) { | |
| 521 } | |
| 522 | |
| 523 PPB_Context3D_Proxy::~PPB_Context3D_Proxy() { | |
| 524 } | |
| 525 | |
| 526 // static | |
| 527 PP_Resource PPB_Context3D_Proxy::Create(PP_Instance instance, | |
| 528 PP_Config3D_Dev config, | |
| 529 PP_Resource share_context, | |
| 530 const int32_t* attrib_list) { | |
| 531 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | |
| 532 if (!dispatcher) | |
| 533 return PP_ERROR_BADARGUMENT; | |
| 534 | |
| 535 // TODO(alokp): Support shared context. | |
| 536 DCHECK_EQ(0, share_context); | |
| 537 if (share_context != 0) | |
| 538 return 0; | |
| 539 | |
| 540 std::vector<int32_t> attribs; | |
| 541 if (attrib_list) { | |
| 542 for (const int32_t* attr = attrib_list; attr; ++attr) | |
| 543 attribs.push_back(*attr); | |
| 544 } else { | |
| 545 attribs.push_back(0); | |
| 546 } | |
| 547 | |
| 548 HostResource result; | |
| 549 dispatcher->Send(new PpapiHostMsg_PPBContext3D_Create( | |
| 550 API_ID_PPB_CONTEXT_3D, instance, config, attribs, &result)); | |
| 551 | |
| 552 if (result.is_null()) | |
| 553 return 0; | |
| 554 scoped_refptr<Context3D> context_3d(new Context3D(result)); | |
| 555 if (!context_3d->CreateImplementation()) | |
| 556 return 0; | |
| 557 return context_3d->GetReference(); | |
| 558 } | |
| 559 | |
| 560 bool PPB_Context3D_Proxy::OnMessageReceived(const IPC::Message& msg) { | |
| 561 bool handled = true; | |
| 562 IPC_BEGIN_MESSAGE_MAP(PPB_Context3D_Proxy, msg) | |
| 563 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Create, | |
| 564 OnMsgCreate) | |
| 565 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_BindSurfaces, | |
| 566 OnMsgBindSurfaces) | |
| 567 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Initialize, | |
| 568 OnMsgInitialize) | |
| 569 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_GetState, | |
| 570 OnMsgGetState) | |
| 571 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_Flush, | |
| 572 OnMsgFlush) | |
| 573 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_AsyncFlush, | |
| 574 OnMsgAsyncFlush) | |
| 575 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_CreateTransferBuffer, | |
| 576 OnMsgCreateTransferBuffer) | |
| 577 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_DestroyTransferBuffer, | |
| 578 OnMsgDestroyTransferBuffer) | |
| 579 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBContext3D_GetTransferBuffer, | |
| 580 OnMsgGetTransferBuffer) | |
| 581 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 582 | |
| 583 IPC_END_MESSAGE_MAP() | |
| 584 // FIXME(brettw) handle bad messages! | |
| 585 return handled; | |
| 586 } | |
| 587 | |
| 588 void PPB_Context3D_Proxy::OnMsgCreate(PP_Instance instance, | |
| 589 PP_Config3D_Dev config, | |
| 590 const std::vector<int32_t>& attribs, | |
| 591 HostResource* result) { | |
| 592 if (attribs.empty() || attribs.back() != 0) | |
| 593 return; // Bad message. | |
| 594 thunk::EnterResourceCreation enter(instance); | |
| 595 if (enter.succeeded()) { | |
| 596 result->SetHostResource( | |
| 597 instance, | |
| 598 enter.functions()->CreateContext3DRaw(instance, config, 0, | |
| 599 &attribs.front())); | |
| 600 } | |
| 601 } | |
| 602 | |
| 603 void PPB_Context3D_Proxy::OnMsgBindSurfaces(const HostResource& context, | |
| 604 const HostResource& draw, | |
| 605 const HostResource& read, | |
| 606 int32_t* result) { | |
| 607 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 608 if (enter.succeeded()) { | |
| 609 *result = enter.object()->BindSurfaces(draw.host_resource(), | |
| 610 read.host_resource()); | |
| 611 } else { | |
| 612 *result = PP_ERROR_BADRESOURCE; | |
| 613 } | |
| 614 } | |
| 615 | |
| 616 void PPB_Context3D_Proxy::OnMsgInitialize( | |
| 617 const HostResource& context, | |
| 618 int32 size, | |
| 619 base::SharedMemoryHandle* ring_buffer) { | |
| 620 *ring_buffer = base::SharedMemory::NULLHandle(); | |
| 621 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 622 if (enter.failed()) | |
| 623 return; | |
| 624 | |
| 625 if (!enter.object()->InitializeTrusted(size)) | |
| 626 return; | |
| 627 | |
| 628 int shm_handle; | |
| 629 uint32_t shm_size; | |
| 630 if (!enter.object()->GetRingBuffer(&shm_handle, &shm_size)) | |
| 631 return; | |
| 632 *ring_buffer = TransportSHMHandleFromInt(dispatcher(), shm_handle); | |
| 633 } | |
| 634 | |
| 635 void PPB_Context3D_Proxy::OnMsgGetState(const HostResource& context, | |
| 636 gpu::CommandBuffer::State* state) { | |
| 637 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 638 if (enter.failed()) | |
| 639 return; | |
| 640 PP_Context3DTrustedState pp_state = enter.object()->GetState(); | |
| 641 *state = GPUStateFromPPState(pp_state); | |
| 642 } | |
| 643 | |
| 644 void PPB_Context3D_Proxy::OnMsgFlush(const HostResource& context, | |
| 645 int32 put_offset, | |
| 646 int32 last_known_get, | |
| 647 gpu::CommandBuffer::State* state) { | |
| 648 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 649 if (enter.failed()) | |
| 650 return; | |
| 651 PP_Context3DTrustedState pp_state = enter.object()->FlushSyncFast( | |
| 652 put_offset, last_known_get); | |
| 653 *state = GPUStateFromPPState(pp_state); | |
| 654 } | |
| 655 | |
| 656 void PPB_Context3D_Proxy::OnMsgAsyncFlush(const HostResource& context, | |
| 657 int32 put_offset) { | |
| 658 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 659 if (enter.succeeded()) | |
| 660 enter.object()->Flush(put_offset); | |
| 661 } | |
| 662 | |
| 663 void PPB_Context3D_Proxy::OnMsgCreateTransferBuffer( | |
| 664 const HostResource& context, | |
| 665 int32 size, | |
| 666 int32* id) { | |
| 667 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 668 if (enter.succeeded()) | |
| 669 *id = enter.object()->CreateTransferBuffer(size); | |
| 670 else | |
| 671 *id = 0; | |
| 672 } | |
| 673 | |
| 674 void PPB_Context3D_Proxy::OnMsgDestroyTransferBuffer( | |
| 675 const HostResource& context, | |
| 676 int32 id) { | |
| 677 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 678 if (enter.succeeded()) | |
| 679 enter.object()->DestroyTransferBuffer(id); | |
| 680 } | |
| 681 | |
| 682 void PPB_Context3D_Proxy::OnMsgGetTransferBuffer( | |
| 683 const HostResource& context, | |
| 684 int32 id, | |
| 685 base::SharedMemoryHandle* transfer_buffer, | |
| 686 uint32* size) { | |
| 687 *transfer_buffer = base::SharedMemory::NULLHandle(); | |
| 688 *size = 0; | |
| 689 | |
| 690 EnterHostFromHostResource<PPB_Context3D_API> enter(context); | |
| 691 int shm_handle = 0; | |
| 692 uint32_t shm_size = 0; | |
| 693 if (enter.succeeded() && | |
| 694 enter.object()->GetTransferBuffer(id, &shm_handle, &shm_size)) { | |
| 695 *transfer_buffer = TransportSHMHandleFromInt(dispatcher(), shm_handle); | |
| 696 *size = shm_size; | |
| 697 } | |
| 698 } | |
| 699 | |
| 700 } // namespace proxy | |
| 701 } // namespace ppapi | |
| OLD | NEW |