| 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 "content/renderer/renderer_gl_context.h" | |
| 6 | |
| 7 #include "base/debug/trace_event.h" | |
| 8 #include "base/lazy_instance.h" | |
| 9 #include "base/memory/ref_counted.h" | |
| 10 #include "base/memory/scoped_ptr.h" | |
| 11 #include "base/memory/singleton.h" | |
| 12 #include "base/memory/weak_ptr.h" | |
| 13 #include "base/shared_memory.h" | |
| 14 #include "content/common/view_messages.h" | |
| 15 #include "content/renderer/command_buffer_proxy.h" | |
| 16 #include "content/renderer/gpu_channel_host.h" | |
| 17 #include "content/renderer/gpu_video_service_host.h" | |
| 18 #include "content/renderer/media/gles2_video_decode_context.h" | |
| 19 #include "content/renderer/render_thread.h" | |
| 20 #include "content/renderer/render_widget.h" | |
| 21 #include "content/renderer/transport_texture_host.h" | |
| 22 #include "content/renderer/transport_texture_service.h" | |
| 23 #include "googleurl/src/gurl.h" | |
| 24 #include "ipc/ipc_channel_handle.h" | |
| 25 | |
| 26 #if defined(ENABLE_GPU) | |
| 27 #include "gpu/command_buffer/client/gles2_cmd_helper.h" | |
| 28 #include "gpu/command_buffer/client/gles2_implementation.h" | |
| 29 #include "gpu/command_buffer/client/gles2_lib.h" | |
| 30 #include "gpu/command_buffer/common/constants.h" | |
| 31 #include "gpu/GLES2/gles2_command_buffer.h" | |
| 32 #endif // ENABLE_GPU | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 const int32 kCommandBufferSize = 1024 * 1024; | |
| 37 // TODO(kbr): make the transfer buffer size configurable via context | |
| 38 // creation attributes. | |
| 39 const int32 kTransferBufferSize = 1024 * 1024; | |
| 40 | |
| 41 const uint32 kMaxLatchesPerRenderer = 2048; | |
| 42 const uint32 kInvalidLatchId = 0xffffffffu; | |
| 43 | |
| 44 // Singleton used to initialize and terminate the gles2 library. | |
| 45 class GLES2Initializer { | |
| 46 public: | |
| 47 GLES2Initializer() { | |
| 48 gles2::Initialize(); | |
| 49 } | |
| 50 | |
| 51 ~GLES2Initializer() { | |
| 52 gles2::Terminate(); | |
| 53 } | |
| 54 | |
| 55 private: | |
| 56 DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); | |
| 57 }; | |
| 58 | |
| 59 // Shared memory allocator for latches. Creates a block of shared memory for | |
| 60 // each renderer process. | |
| 61 class LatchAllocator { | |
| 62 public: | |
| 63 static LatchAllocator* GetInstance(); | |
| 64 static uint32 size() { return kMaxLatchesPerRenderer*sizeof(uint32); } | |
| 65 static const uint32_t kFreeLatch = 0xffffffffu; | |
| 66 | |
| 67 LatchAllocator(); | |
| 68 ~LatchAllocator(); | |
| 69 | |
| 70 base::SharedMemoryHandle handle() const { return shm_->handle(); } | |
| 71 base::SharedMemory* shared_memory() { return shm_.get(); } | |
| 72 | |
| 73 bool AllocateLatch(uint32* latch_id); | |
| 74 bool FreeLatch(uint32 latch_id); | |
| 75 | |
| 76 private: | |
| 77 friend struct DefaultSingletonTraits<LatchAllocator>; | |
| 78 | |
| 79 scoped_ptr<base::SharedMemory> shm_; | |
| 80 // Pointer to mapped shared memory. | |
| 81 volatile uint32* latches_; | |
| 82 | |
| 83 DISALLOW_COPY_AND_ASSIGN(LatchAllocator); | |
| 84 }; | |
| 85 | |
| 86 //////////////////////////////////////////////////////////////////////////////// | |
| 87 /// LatchAllocator implementation | |
| 88 | |
| 89 LatchAllocator* LatchAllocator::GetInstance() { | |
| 90 return Singleton<LatchAllocator>::get(); | |
| 91 } | |
| 92 | |
| 93 LatchAllocator::LatchAllocator() { | |
| 94 base::SharedMemoryHandle handle; | |
| 95 RenderThread* render_thread = RenderThread::current(); | |
| 96 if (!render_thread->Send( | |
| 97 new ViewHostMsg_AllocateSharedMemoryBuffer(size(), &handle))) { | |
| 98 NOTREACHED() << "failed to send sync IPC"; | |
| 99 } | |
| 100 | |
| 101 if (!base::SharedMemory::IsHandleValid(handle)) { | |
| 102 NOTREACHED() << "failed to create shared memory"; | |
| 103 } | |
| 104 | |
| 105 // Handle is closed by the SharedMemory object below. This stops | |
| 106 // base::FileDescriptor from closing it as well. | |
| 107 #if defined(OS_POSIX) | |
| 108 handle.auto_close = false; | |
| 109 #endif | |
| 110 | |
| 111 shm_.reset(new base::SharedMemory(handle, false)); | |
| 112 if (!shm_->Map(size())) { | |
| 113 NOTREACHED() << "failed to map shared memory"; | |
| 114 } | |
| 115 | |
| 116 latches_ = static_cast<uint32*>(shm_->memory()); | |
| 117 // Mark all latches as unallocated. | |
| 118 for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) | |
| 119 latches_[i] = kFreeLatch; | |
| 120 } | |
| 121 | |
| 122 LatchAllocator::~LatchAllocator() { | |
| 123 } | |
| 124 | |
| 125 bool LatchAllocator::AllocateLatch(uint32* latch_id) { | |
| 126 for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) { | |
| 127 if (latches_[i] == kFreeLatch) { | |
| 128 // mark latch as taken and blocked. | |
| 129 // 0 means waiter will block, 1 means waiter will pass. | |
| 130 latches_[i] = 0; | |
| 131 *latch_id = i; | |
| 132 return true; | |
| 133 } | |
| 134 } | |
| 135 return false; | |
| 136 } | |
| 137 | |
| 138 bool LatchAllocator::FreeLatch(uint32 latch_id) { | |
| 139 if (latch_id < kMaxLatchesPerRenderer && latches_[latch_id] != kFreeLatch) { | |
| 140 latches_[latch_id] = kFreeLatch; | |
| 141 return true; | |
| 142 } | |
| 143 return false; | |
| 144 } | |
| 145 | |
| 146 //////////////////////////////////////////////////////////////////////////////// | |
| 147 | |
| 148 static base::LazyInstance<GLES2Initializer> g_gles2_initializer( | |
| 149 base::LINKER_INITIALIZED); | |
| 150 | |
| 151 } // namespace anonymous | |
| 152 | |
| 153 RendererGLContext::~RendererGLContext() { | |
| 154 Destroy(); | |
| 155 } | |
| 156 | |
| 157 RendererGLContext* RendererGLContext::CreateViewContext( | |
| 158 GpuChannelHost* channel, | |
| 159 gfx::PluginWindowHandle render_surface, | |
| 160 int render_view_id, | |
| 161 const char* allowed_extensions, | |
| 162 const int32* attrib_list, | |
| 163 const GURL& active_url) { | |
| 164 #if defined(ENABLE_GPU) | |
| 165 scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, NULL)); | |
| 166 if (!context->Initialize( | |
| 167 true, | |
| 168 render_surface, | |
| 169 render_view_id, | |
| 170 gfx::Size(), | |
| 171 allowed_extensions, | |
| 172 attrib_list, | |
| 173 active_url)) | |
| 174 return NULL; | |
| 175 | |
| 176 return context.release(); | |
| 177 #else | |
| 178 return NULL; | |
| 179 #endif | |
| 180 } | |
| 181 | |
| 182 #if defined(OS_MACOSX) | |
| 183 void RendererGLContext::ResizeOnscreen(const gfx::Size& size) { | |
| 184 DCHECK(size.width() > 0 && size.height() > 0); | |
| 185 size_ = size; | |
| 186 command_buffer_->SetWindowSize(size); | |
| 187 } | |
| 188 #endif | |
| 189 | |
| 190 RendererGLContext* RendererGLContext::CreateOffscreenContext( | |
| 191 GpuChannelHost* channel, | |
| 192 RendererGLContext* parent, | |
| 193 const gfx::Size& size, | |
| 194 const char* allowed_extensions, | |
| 195 const int32* attrib_list, | |
| 196 const GURL& active_url) { | |
| 197 #if defined(ENABLE_GPU) | |
| 198 scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, parent)); | |
| 199 if (!context->Initialize( | |
| 200 false, | |
| 201 gfx::kNullPluginWindow, | |
| 202 0, | |
| 203 size, | |
| 204 allowed_extensions, | |
| 205 attrib_list, | |
| 206 active_url)) | |
| 207 return NULL; | |
| 208 | |
| 209 return context.release(); | |
| 210 #else | |
| 211 return NULL; | |
| 212 #endif | |
| 213 } | |
| 214 | |
| 215 void RendererGLContext::ResizeOffscreen(const gfx::Size& size) { | |
| 216 DCHECK(size.width() > 0 && size.height() > 0); | |
| 217 if (size_ != size) { | |
| 218 command_buffer_->ResizeOffscreenFrameBuffer(size); | |
| 219 size_ = size; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 uint32 RendererGLContext::GetParentTextureId() { | |
| 224 return parent_texture_id_; | |
| 225 } | |
| 226 | |
| 227 uint32 RendererGLContext::CreateParentTexture(const gfx::Size& size) { | |
| 228 // Allocate a texture ID with respect to the parent. | |
| 229 if (parent_.get()) { | |
| 230 if (!MakeCurrent(parent_.get())) | |
| 231 return 0; | |
| 232 uint32 texture_id = parent_->gles2_implementation_->MakeTextureId(); | |
| 233 parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id); | |
| 234 parent_->gles2_implementation_->TexParameteri( | |
| 235 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 236 parent_->gles2_implementation_->TexParameteri( | |
| 237 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 238 parent_->gles2_implementation_->TexParameteri( | |
| 239 GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 240 parent_->gles2_implementation_->TexParameteri( | |
| 241 GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 242 | |
| 243 parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D, | |
| 244 0, // mip level | |
| 245 GL_RGBA, | |
| 246 size.width(), | |
| 247 size.height(), | |
| 248 0, // border | |
| 249 GL_RGBA, | |
| 250 GL_UNSIGNED_BYTE, | |
| 251 NULL); | |
| 252 // Make sure that the parent texture's storage is allocated before we let | |
| 253 // the caller attempt to use it. | |
| 254 int32 token = parent_->gles2_helper_->InsertToken(); | |
| 255 parent_->gles2_helper_->WaitForToken(token); | |
| 256 return texture_id; | |
| 257 } | |
| 258 return 0; | |
| 259 } | |
| 260 | |
| 261 void RendererGLContext::DeleteParentTexture(uint32 texture) { | |
| 262 if (parent_.get()) { | |
| 263 if (!MakeCurrent(parent_.get())) | |
| 264 return; | |
| 265 parent_->gles2_implementation_->DeleteTextures(1, &texture); | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 void RendererGLContext::SetSwapBuffersCallback(Callback0::Type* callback) { | |
| 270 swap_buffers_callback_.reset(callback); | |
| 271 } | |
| 272 | |
| 273 void RendererGLContext::SetContextLostCallback(Callback0::Type* callback) { | |
| 274 context_lost_callback_.reset(callback); | |
| 275 } | |
| 276 | |
| 277 bool RendererGLContext::MakeCurrent(RendererGLContext* context) { | |
| 278 if (context) { | |
| 279 gles2::SetGLContext(context->gles2_implementation_); | |
| 280 | |
| 281 // Don't request latest error status from service. Just use the locally | |
| 282 // cached information from the last flush. | |
| 283 // TODO(apatrick): I'm not sure if this should actually change the | |
| 284 // current context if it fails. For now it gets changed even if it fails | |
| 285 // because making GL calls with a NULL context crashes. | |
| 286 if (context->command_buffer_->GetLastState().error != gpu::error::kNoError) | |
| 287 return false; | |
| 288 } else { | |
| 289 gles2::SetGLContext(NULL); | |
| 290 } | |
| 291 | |
| 292 return true; | |
| 293 } | |
| 294 | |
| 295 bool RendererGLContext::SwapBuffers() { | |
| 296 TRACE_EVENT1("gpu", "RendererGLContext::SwapBuffers", "frame", frame_number_); | |
| 297 frame_number_++; | |
| 298 | |
| 299 // Don't request latest error status from service. Just use the locally cached | |
| 300 // information from the last flush. | |
| 301 if (command_buffer_->GetLastState().error != gpu::error::kNoError) | |
| 302 return false; | |
| 303 | |
| 304 gles2_implementation_->SwapBuffers(); | |
| 305 return true; | |
| 306 } | |
| 307 | |
| 308 media::VideoDecodeEngine* RendererGLContext::CreateVideoDecodeEngine() { | |
| 309 return channel_->gpu_video_service_host()->CreateVideoDecoder( | |
| 310 command_buffer_->route_id()); | |
| 311 } | |
| 312 | |
| 313 media::VideoDecodeContext* RendererGLContext::CreateVideoDecodeContext( | |
| 314 MessageLoop* message_loop, bool hardware_decoder) { | |
| 315 return new Gles2VideoDecodeContext(message_loop, hardware_decoder, this); | |
| 316 } | |
| 317 | |
| 318 scoped_refptr<TransportTextureHost> | |
| 319 RendererGLContext::CreateTransportTextureHost() { | |
| 320 return channel_->transport_texture_service()->CreateTransportTextureHost( | |
| 321 this, command_buffer_->route_id()); | |
| 322 } | |
| 323 | |
| 324 RendererGLContext::Error RendererGLContext::GetError() { | |
| 325 gpu::CommandBuffer::State state = command_buffer_->GetState(); | |
| 326 if (state.error == gpu::error::kNoError) { | |
| 327 Error old_error = last_error_; | |
| 328 last_error_ = SUCCESS; | |
| 329 return old_error; | |
| 330 } else { | |
| 331 // All command buffer errors are unrecoverable. The error is treated as a | |
| 332 // lost context: destroy the context and create another one. | |
| 333 return CONTEXT_LOST; | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 bool RendererGLContext::IsCommandBufferContextLost() { | |
| 338 gpu::CommandBuffer::State state = command_buffer_->GetLastState(); | |
| 339 return state.error == gpu::error::kLostContext; | |
| 340 } | |
| 341 | |
| 342 CommandBufferProxy* RendererGLContext::GetCommandBufferProxy() { | |
| 343 return command_buffer_; | |
| 344 } | |
| 345 | |
| 346 // TODO(gman): Remove This | |
| 347 void RendererGLContext::DisableShaderTranslation() { | |
| 348 gles2_implementation_->CommandBufferEnableCHROMIUM( | |
| 349 PEPPER3D_SKIP_GLSL_TRANSLATION); | |
| 350 } | |
| 351 | |
| 352 gpu::gles2::GLES2Implementation* RendererGLContext::GetImplementation() { | |
| 353 return gles2_implementation_; | |
| 354 } | |
| 355 | |
| 356 RendererGLContext::RendererGLContext(GpuChannelHost* channel, | |
| 357 RendererGLContext* parent) | |
| 358 : channel_(channel), | |
| 359 parent_(parent ? | |
| 360 parent->AsWeakPtr() : base::WeakPtr<RendererGLContext>()), | |
| 361 parent_texture_id_(0), | |
| 362 child_to_parent_latch_(kInvalidLatchId), | |
| 363 parent_to_child_latch_(kInvalidLatchId), | |
| 364 latch_transfer_buffer_id_(-1), | |
| 365 command_buffer_(NULL), | |
| 366 gles2_helper_(NULL), | |
| 367 transfer_buffer_id_(-1), | |
| 368 gles2_implementation_(NULL), | |
| 369 last_error_(SUCCESS), | |
| 370 frame_number_(0) { | |
| 371 DCHECK(channel); | |
| 372 } | |
| 373 | |
| 374 bool RendererGLContext::Initialize(bool onscreen, | |
| 375 gfx::PluginWindowHandle render_surface, | |
| 376 int render_view_id, | |
| 377 const gfx::Size& size, | |
| 378 const char* allowed_extensions, | |
| 379 const int32* attrib_list, | |
| 380 const GURL& active_url) { | |
| 381 DCHECK(size.width() >= 0 && size.height() >= 0); | |
| 382 TRACE_EVENT2("gpu", "RendererGLContext::Initialize", | |
| 383 "on_screen", onscreen, "num_pixels", size.GetArea()); | |
| 384 | |
| 385 if (channel_->state() != GpuChannelHost::kConnected) | |
| 386 return false; | |
| 387 | |
| 388 // Ensure the gles2 library is initialized first in a thread safe way. | |
| 389 g_gles2_initializer.Get(); | |
| 390 | |
| 391 // Allocate a frame buffer ID with respect to the parent. | |
| 392 if (parent_.get()) { | |
| 393 // Flush any remaining commands in the parent context to make sure the | |
| 394 // texture id accounting stays consistent. | |
| 395 int32 token = parent_->gles2_helper_->InsertToken(); | |
| 396 parent_->gles2_helper_->WaitForToken(token); | |
| 397 parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId(); | |
| 398 } | |
| 399 | |
| 400 std::vector<int32> attribs; | |
| 401 while (attrib_list) { | |
| 402 int32 attrib = *attrib_list++; | |
| 403 switch (attrib) { | |
| 404 // Known attributes | |
| 405 case ALPHA_SIZE: | |
| 406 case BLUE_SIZE: | |
| 407 case GREEN_SIZE: | |
| 408 case RED_SIZE: | |
| 409 case DEPTH_SIZE: | |
| 410 case STENCIL_SIZE: | |
| 411 case SAMPLES: | |
| 412 case SAMPLE_BUFFERS: | |
| 413 attribs.push_back(attrib); | |
| 414 attribs.push_back(*attrib_list++); | |
| 415 break; | |
| 416 case NONE: | |
| 417 attribs.push_back(attrib); | |
| 418 attrib_list = NULL; | |
| 419 break; | |
| 420 default: | |
| 421 last_error_ = BAD_ATTRIBUTE; | |
| 422 attribs.push_back(NONE); | |
| 423 attrib_list = NULL; | |
| 424 break; | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 // Create a proxy to a command buffer in the GPU process. | |
| 429 if (onscreen) { | |
| 430 if (render_surface == gfx::kNullPluginWindow) { | |
| 431 LOG(ERROR) << "Invalid surface handle for onscreen context."; | |
| 432 command_buffer_ = NULL; | |
| 433 } else { | |
| 434 command_buffer_ = channel_->CreateViewCommandBuffer( | |
| 435 render_surface, | |
| 436 render_view_id, | |
| 437 allowed_extensions, | |
| 438 attribs, | |
| 439 active_url); | |
| 440 } | |
| 441 } else { | |
| 442 CommandBufferProxy* parent_command_buffer = | |
| 443 parent_.get() ? parent_->command_buffer_ : NULL; | |
| 444 command_buffer_ = channel_->CreateOffscreenCommandBuffer( | |
| 445 parent_command_buffer, | |
| 446 size, | |
| 447 allowed_extensions, | |
| 448 attribs, | |
| 449 parent_texture_id_, | |
| 450 active_url); | |
| 451 } | |
| 452 if (!command_buffer_) { | |
| 453 Destroy(); | |
| 454 return false; | |
| 455 } | |
| 456 | |
| 457 // Initiaize the command buffer. | |
| 458 if (!command_buffer_->Initialize(kCommandBufferSize)) { | |
| 459 Destroy(); | |
| 460 return false; | |
| 461 } | |
| 462 | |
| 463 command_buffer_->SetSwapBuffersCallback( | |
| 464 NewCallback(this, &RendererGLContext::OnSwapBuffers)); | |
| 465 | |
| 466 command_buffer_->SetChannelErrorCallback( | |
| 467 NewCallback(this, &RendererGLContext::OnContextLost)); | |
| 468 | |
| 469 // Create the GLES2 helper, which writes the command buffer protocol. | |
| 470 gles2_helper_ = new gpu::gles2::GLES2CmdHelper(command_buffer_); | |
| 471 if (!gles2_helper_->Initialize(kCommandBufferSize)) { | |
| 472 Destroy(); | |
| 473 return false; | |
| 474 } | |
| 475 | |
| 476 // Create a transfer buffer used to copy resources between the renderer | |
| 477 // process and the GPU process. | |
| 478 transfer_buffer_id_ = | |
| 479 command_buffer_->CreateTransferBuffer(kTransferBufferSize, | |
| 480 gpu::kCommandBufferSharedMemoryId); | |
| 481 if (transfer_buffer_id_ < 0) { | |
| 482 Destroy(); | |
| 483 return false; | |
| 484 } | |
| 485 | |
| 486 // Map the buffer into the renderer process's address space. | |
| 487 gpu::Buffer transfer_buffer = | |
| 488 command_buffer_->GetTransferBuffer(transfer_buffer_id_); | |
| 489 if (!transfer_buffer.ptr) { | |
| 490 Destroy(); | |
| 491 return false; | |
| 492 } | |
| 493 | |
| 494 // Register transfer buffer so that the context can access latches. | |
| 495 LatchAllocator* latch_shm = LatchAllocator::GetInstance(); | |
| 496 latch_transfer_buffer_id_ = command_buffer_->RegisterTransferBuffer( | |
| 497 latch_shm->shared_memory(), LatchAllocator::size(), | |
| 498 gpu::kLatchSharedMemoryId); | |
| 499 if (latch_transfer_buffer_id_ != gpu::kLatchSharedMemoryId) { | |
| 500 Destroy(); | |
| 501 return false; | |
| 502 } | |
| 503 | |
| 504 // If this is a child context, setup latches for synchronization between child | |
| 505 // and parent. | |
| 506 if (parent_.get()) { | |
| 507 if (!CreateLatch(&child_to_parent_latch_) || | |
| 508 !CreateLatch(&parent_to_child_latch_)) { | |
| 509 Destroy(); | |
| 510 return false; | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 // Create the object exposing the OpenGL API. | |
| 515 gles2_implementation_ = new gpu::gles2::GLES2Implementation( | |
| 516 gles2_helper_, | |
| 517 transfer_buffer.size, | |
| 518 transfer_buffer.ptr, | |
| 519 transfer_buffer_id_, | |
| 520 false); | |
| 521 | |
| 522 size_ = size; | |
| 523 | |
| 524 return true; | |
| 525 } | |
| 526 | |
| 527 void RendererGLContext::Destroy() { | |
| 528 if (parent_.get() && parent_texture_id_ != 0) { | |
| 529 parent_->gles2_implementation_->FreeTextureId(parent_texture_id_); | |
| 530 parent_texture_id_ = 0; | |
| 531 } | |
| 532 | |
| 533 delete gles2_implementation_; | |
| 534 gles2_implementation_ = NULL; | |
| 535 | |
| 536 if (child_to_parent_latch_ != kInvalidLatchId) { | |
| 537 DestroyLatch(child_to_parent_latch_); | |
| 538 child_to_parent_latch_ = kInvalidLatchId; | |
| 539 } | |
| 540 if (parent_to_child_latch_ != kInvalidLatchId) { | |
| 541 DestroyLatch(parent_to_child_latch_); | |
| 542 parent_to_child_latch_ = kInvalidLatchId; | |
| 543 } | |
| 544 if (command_buffer_ && latch_transfer_buffer_id_ != -1) { | |
| 545 command_buffer_->DestroyTransferBuffer(latch_transfer_buffer_id_); | |
| 546 latch_transfer_buffer_id_ = -1; | |
| 547 } | |
| 548 | |
| 549 if (command_buffer_ && transfer_buffer_id_ != -1) { | |
| 550 command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); | |
| 551 transfer_buffer_id_ = -1; | |
| 552 } | |
| 553 | |
| 554 delete gles2_helper_; | |
| 555 gles2_helper_ = NULL; | |
| 556 | |
| 557 if (channel_ && command_buffer_) { | |
| 558 channel_->DestroyCommandBuffer(command_buffer_); | |
| 559 command_buffer_ = NULL; | |
| 560 } | |
| 561 | |
| 562 channel_ = NULL; | |
| 563 } | |
| 564 | |
| 565 void RendererGLContext::OnSwapBuffers() { | |
| 566 if (swap_buffers_callback_.get()) | |
| 567 swap_buffers_callback_->Run(); | |
| 568 } | |
| 569 | |
| 570 void RendererGLContext::OnContextLost() { | |
| 571 if (context_lost_callback_.get()) | |
| 572 context_lost_callback_->Run(); | |
| 573 } | |
| 574 | |
| 575 bool RendererGLContext::CreateLatch(uint32* ret_latch) { | |
| 576 return LatchAllocator::GetInstance()->AllocateLatch(ret_latch); | |
| 577 } | |
| 578 | |
| 579 bool RendererGLContext::DestroyLatch(uint32 latch) { | |
| 580 return LatchAllocator::GetInstance()->FreeLatch(latch); | |
| 581 } | |
| 582 | |
| 583 bool RendererGLContext::GetParentToChildLatch(uint32* parent_to_child_latch) { | |
| 584 if (parent_.get()) { | |
| 585 *parent_to_child_latch = parent_to_child_latch_; | |
| 586 return true; | |
| 587 } | |
| 588 return false; | |
| 589 } | |
| 590 | |
| 591 bool RendererGLContext::GetChildToParentLatch(uint32* child_to_parent_latch) { | |
| 592 if (parent_.get()) { | |
| 593 *child_to_parent_latch = child_to_parent_latch_; | |
| 594 return true; | |
| 595 } | |
| 596 return false; | |
| 597 } | |
| OLD | NEW |