1 // Copyright 2013 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 "gpu/command_buffer/service/in_process_command_buffer.h" 6 7 #include <queue> 8 #include <set> 9 #include <utility> 10 11 #include <GLES2/gl2.h> 12 #ifndef GL_GLEXT_PROTOTYPES 13 #define GL_GLEXT_PROTOTYPES 1 14 #endif 15 #include <GLES2/gl2ext.h> 16 #include <GLES2/gl2extchromium.h> 17 18 #include "base/bind.h" 19 #include "base/bind_helpers.h" 20 #include "base/lazy_instance.h" 21 #include "base/logging.h" 22 #include "base/memory/weak_ptr.h" 23 #include "base/message_loop/message_loop_proxy.h" 24 #include "base/sequence_checker.h" 25 #include "base/synchronization/condition_variable.h" 26 #include "base/threading/thread.h" 27 #include "gpu/command_buffer/service/command_buffer_service.h" 28 #include "gpu/command_buffer/service/context_group.h" 29 #include "gpu/command_buffer/service/gl_context_virtual.h" 30 #include "gpu/command_buffer/service/gpu_scheduler.h" 31 #include "gpu/command_buffer/service/image_manager.h" 32 #include "gpu/command_buffer/service/mailbox_manager.h" 33 #include "gpu/command_buffer/service/memory_tracking.h" 34 #include "gpu/command_buffer/service/query_manager.h" 35 #include "gpu/command_buffer/service/transfer_buffer_manager.h" 36 #include "ui/gfx/size.h" 37 #include "ui/gl/gl_context.h" 38 #include "ui/gl/gl_image.h" 39 #include "ui/gl/gl_share_group.h" 40 41 #if defined(OS_ANDROID) 42 #include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h" 43 #include "ui/gl/android/surface_texture.h" 44 #endif 45 46 namespace gpu { 47 48 namespace { 49 50 static InProcessGpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; 51 52 template <typename T> 53 static void RunTaskWithResult(base::Callback<T(void)> task, 54 T* result, 55 base::WaitableEvent* completion) { 56 *result = task.Run(); 57 completion->Signal(); 58 } 59 60 class GpuInProcessThread 61 : public base::Thread, 62 public InProcessCommandBuffer::Service, 63 public base::RefCountedThreadSafe<GpuInProcessThread> { 64 public: 65 GpuInProcessThread(); 66 67 virtual void AddRef() const OVERRIDE { 68 base::RefCountedThreadSafe<GpuInProcessThread>::AddRef(); 69 } 70 virtual void Release() const OVERRIDE { 71 base::RefCountedThreadSafe<GpuInProcessThread>::Release(); 72 } 73 74 virtual void ScheduleTask(const base::Closure& task) OVERRIDE; 75 virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; 76 virtual bool UseVirtualizedGLContexts() OVERRIDE { return false; } 77 virtual scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache() 78 OVERRIDE; 79 80 private: 81 virtual ~GpuInProcessThread(); 82 friend class base::RefCountedThreadSafe<GpuInProcessThread>; 83 84 scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_; 85 DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread); 86 }; 87 88 GpuInProcessThread::GpuInProcessThread() : base::Thread("GpuThread") { 89 Start(); 90 } 91 92 GpuInProcessThread::~GpuInProcessThread() { 93 Stop(); 94 } 95 96 void GpuInProcessThread::ScheduleTask(const base::Closure& task) { 97 message_loop()->PostTask(FROM_HERE, task); 98 } 99 100 void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) { 101 message_loop()->PostDelayedTask( 102 FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); 103 } 104 105 scoped_refptr<gles2::ShaderTranslatorCache> 106 GpuInProcessThread::shader_translator_cache() { 107 if (!shader_translator_cache_.get()) 108 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; 109 return shader_translator_cache_; 110 } 111 112 base::LazyInstance<std::set<InProcessCommandBuffer*> > default_thread_clients_ = 113 LAZY_INSTANCE_INITIALIZER; 114 base::LazyInstance<base::Lock> default_thread_clients_lock_ = 115 LAZY_INSTANCE_INITIALIZER; 116 117 class ScopedEvent { 118 public: 119 ScopedEvent(base::WaitableEvent* event) : event_(event) {} 120 ~ScopedEvent() { event_->Signal(); } 121 122 private: 123 base::WaitableEvent* event_; 124 }; 125 126 class SyncPointManager { 127 public: 128 SyncPointManager(); 129 ~SyncPointManager(); 130 131 uint32 GenerateSyncPoint(); 132 void RetireSyncPoint(uint32 sync_point); 133 134 bool IsSyncPointPassed(uint32 sync_point); 135 void WaitSyncPoint(uint32 sync_point); 136 137 private: 138 // This lock protects access to pending_sync_points_ and next_sync_point_ and 139 // is used with the ConditionVariable to signal when a sync point is retired. 140 base::Lock lock_; 141 std::set<uint32> pending_sync_points_; 142 uint32 next_sync_point_; 143 base::ConditionVariable cond_var_; 144 }; 145 146 SyncPointManager::SyncPointManager() : next_sync_point_(1), cond_var_(&lock_) {} 147 148 SyncPointManager::~SyncPointManager() { 149 DCHECK_EQ(pending_sync_points_.size(), 0U); 150 } 151 152 uint32 SyncPointManager::GenerateSyncPoint() { 153 base::AutoLock lock(lock_); 154 uint32 sync_point = next_sync_point_++; 155 DCHECK_EQ(pending_sync_points_.count(sync_point), 0U); 156 pending_sync_points_.insert(sync_point); 157 return sync_point; 158 } 159 160 void SyncPointManager::RetireSyncPoint(uint32 sync_point) { 161 base::AutoLock lock(lock_); 162 DCHECK(pending_sync_points_.count(sync_point)); 163 pending_sync_points_.erase(sync_point); 164 cond_var_.Broadcast(); 165 } 166 167 bool SyncPointManager::IsSyncPointPassed(uint32 sync_point) { 168 base::AutoLock lock(lock_); 169 return pending_sync_points_.count(sync_point) == 0; 170 } 171 172 void SyncPointManager::WaitSyncPoint(uint32 sync_point) { 173 base::AutoLock lock(lock_); 174 while (pending_sync_points_.count(sync_point)) { 175 cond_var_.Wait(); 176 } 177 } 178 179 base::LazyInstance<SyncPointManager> g_sync_point_manager = 180 LAZY_INSTANCE_INITIALIZER; 181 182 } // anonyous namespace 183 184 InProcessCommandBuffer::Service::Service() {} 185 186 InProcessCommandBuffer::Service::~Service() {} 187 188 scoped_refptr<gles2::MailboxManager> 189 InProcessCommandBuffer::Service::mailbox_manager() { 190 if (!mailbox_manager_.get()) 191 mailbox_manager_ = new gles2::MailboxManager(); 192 return mailbox_manager_; 193 } 194 195 scoped_refptr<InProcessCommandBuffer::Service> 196 InProcessCommandBuffer::GetDefaultService() { 197 base::AutoLock lock(default_thread_clients_lock_.Get()); 198 scoped_refptr<Service> service; 199 if (!default_thread_clients_.Get().empty()) { 200 InProcessCommandBuffer* other = *default_thread_clients_.Get().begin(); 201 service = other->service_; 202 DCHECK(service.get()); 203 } else { 204 service = new GpuInProcessThread; 205 } 206 return service; 207 } 208 209 InProcessCommandBuffer::InProcessCommandBuffer( 210 const scoped_refptr<Service>& service) 211 : context_lost_(false), 212 idle_work_pending_(false), 213 last_put_offset_(-1), 214 flush_event_(false, false), 215 service_(service.get() ? service : GetDefaultService()), 216 gpu_thread_weak_ptr_factory_(this) { 217 if (!service.get()) { 218 base::AutoLock lock(default_thread_clients_lock_.Get()); 219 default_thread_clients_.Get().insert(this); 220 } 221 } 222 223 InProcessCommandBuffer::~InProcessCommandBuffer() { 224 Destroy(); 225 base::AutoLock lock(default_thread_clients_lock_.Get()); 226 default_thread_clients_.Get().erase(this); 227 } 228 229 void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { 230 CheckSequencedThread(); 231 DCHECK(!surface_->IsOffscreen()); 232 surface_->Resize(size); 233 } 234 235 bool InProcessCommandBuffer::MakeCurrent() { 236 CheckSequencedThread(); 237 command_buffer_lock_.AssertAcquired(); 238 239 if (!context_lost_ && decoder_->MakeCurrent()) 240 return true; 241 DLOG(ERROR) << "Context lost because MakeCurrent failed."; 242 command_buffer_->SetContextLostReason(decoder_->GetContextLostReason()); 243 command_buffer_->SetParseError(gpu::error::kLostContext); 244 return false; 245 } 246 247 void InProcessCommandBuffer::PumpCommands() { 248 CheckSequencedThread(); 249 command_buffer_lock_.AssertAcquired(); 250 251 if (!MakeCurrent()) 252 return; 253 254 gpu_scheduler_->PutChanged(); 255 } 256 257 bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) { 258 CheckSequencedThread(); 259 command_buffer_lock_.AssertAcquired(); 260 command_buffer_->SetGetBuffer(transfer_buffer_id); 261 return true; 262 } 263 264 bool InProcessCommandBuffer::Initialize( 265 scoped_refptr<gfx::GLSurface> surface, 266 bool is_offscreen, 267 gfx::AcceleratedWidget window, 268 const gfx::Size& size, 269 const std::vector<int32>& attribs, 270 gfx::GpuPreference gpu_preference, 271 const base::Closure& context_lost_callback, 272 InProcessCommandBuffer* share_group) { 273 DCHECK(!share_group || service_.get() == share_group->service_.get()); 274 context_lost_callback_ = WrapCallback(context_lost_callback); 275 276 if (surface.get()) { 277 // GPU thread must be the same as client thread due to GLSurface not being 278 // thread safe. 279 sequence_checker_.reset(new base::SequenceChecker); 280 surface_ = surface; 281 } 282 283 gpu::Capabilities capabilities; 284 InitializeOnGpuThreadParams params(is_offscreen, 285 window, 286 size, 287 attribs, 288 gpu_preference, 289 &capabilities, 290 share_group); 291 292 base::Callback<bool(void)> init_task = 293 base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread, 294 base::Unretained(this), 295 params); 296 297 base::WaitableEvent completion(true, false); 298 bool result = false; 299 QueueTask( 300 base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion)); 301 completion.Wait(); 302 303 if (result) { 304 capabilities_ = capabilities; 305 capabilities_.map_image = 306 capabilities_.map_image && g_gpu_memory_buffer_factory; 307 } 308 return result; 309 } 310 311 bool InProcessCommandBuffer::InitializeOnGpuThread( 312 const InitializeOnGpuThreadParams& params) { 313 CheckSequencedThread(); 314 gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr(); 315 316 DCHECK(params.size.width() >= 0 && params.size.height() >= 0); 317 318 TransferBufferManager* manager = new TransferBufferManager(); 319 transfer_buffer_manager_.reset(manager); 320 manager->Initialize(); 321 322 scoped_ptr<CommandBufferService> command_buffer( 323 new CommandBufferService(transfer_buffer_manager_.get())); 324 command_buffer->SetPutOffsetChangeCallback(base::Bind( 325 &InProcessCommandBuffer::PumpCommands, gpu_thread_weak_ptr_)); 326 command_buffer->SetParseErrorCallback(base::Bind( 327 &InProcessCommandBuffer::OnContextLost, gpu_thread_weak_ptr_)); 328 329 if (!command_buffer->Initialize()) { 330 LOG(ERROR) << "Could not initialize command buffer."; 331 DestroyOnGpuThread(); 332 return false; 333 } 334 335 gl_share_group_ = params.context_group 336 ? params.context_group->gl_share_group_.get() 337 : new gfx::GLShareGroup; 338 339 #if defined(OS_ANDROID) 340 stream_texture_manager_.reset(new StreamTextureManagerInProcess); 341 #endif 342 343 bool bind_generates_resource = false; 344 decoder_.reset(gles2::GLES2Decoder::Create( 345 params.context_group 346 ? params.context_group->decoder_->GetContextGroup() 347 : new gles2::ContextGroup(service_->mailbox_manager(), 348 NULL, 349 service_->shader_translator_cache(), 350 NULL, 351 bind_generates_resource))); 352 353 gpu_scheduler_.reset( 354 new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get())); 355 command_buffer->SetGetBufferChangeCallback(base::Bind( 356 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); 357 command_buffer_ = command_buffer.Pass(); 358 359 decoder_->set_engine(gpu_scheduler_.get()); 360 361 if (!surface_.get()) { 362 if (params.is_offscreen) 363 surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size); 364 else 365 surface_ = gfx::GLSurface::CreateViewGLSurface(params.window); 366 } 367 368 if (!surface_.get()) { 369 LOG(ERROR) << "Could not create GLSurface."; 370 DestroyOnGpuThread(); 371 return false; 372 } 373 374 if (service_->UseVirtualizedGLContexts() || 375 decoder_->GetContextGroup() 376 ->feature_info() 377 ->workarounds() 378 .use_virtualized_gl_contexts) { 379 context_ = gl_share_group_->GetSharedContext(); 380 if (!context_.get()) { 381 context_ = gfx::GLContext::CreateGLContext( 382 gl_share_group_.get(), surface_.get(), params.gpu_preference); 383 gl_share_group_->SetSharedContext(context_.get()); 384 } 385 386 context_ = new GLContextVirtual( 387 gl_share_group_.get(), context_.get(), decoder_->AsWeakPtr()); 388 if (context_->Initialize(surface_.get(), params.gpu_preference)) { 389 VLOG(1) << "Created virtual GL context."; 390 } else { 391 context_ = NULL; 392 } 393 } else { 394 context_ = gfx::GLContext::CreateGLContext( 395 gl_share_group_.get(), surface_.get(), params.gpu_preference); 396 } 397 398 if (!context_.get()) { 399 LOG(ERROR) << "Could not create GLContext."; 400 DestroyOnGpuThread(); 401 return false; 402 } 403 404 if (!context_->MakeCurrent(surface_.get())) { 405 LOG(ERROR) << "Could not make context current."; 406 DestroyOnGpuThread(); 407 return false; 408 } 409 410 gles2::DisallowedFeatures disallowed_features; 411 disallowed_features.gpu_memory_manager = true; 412 if (!decoder_->Initialize(surface_, 413 context_, 414 params.is_offscreen, 415 params.size, 416 disallowed_features, 417 params.attribs)) { 418 LOG(ERROR) << "Could not initialize decoder."; 419 DestroyOnGpuThread(); 420 return false; 421 } 422 *params.capabilities = decoder_->GetCapabilities(); 423 424 if (!params.is_offscreen) { 425 decoder_->SetResizeCallback(base::Bind( 426 &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_)); 427 } 428 decoder_->SetWaitSyncPointCallback( 429 base::Bind(&InProcessCommandBuffer::WaitSyncPointOnGpuThread, 430 base::Unretained(this))); 431 432 return true; 433 } 434 435 void InProcessCommandBuffer::Destroy() { 436 CheckSequencedThread(); 437 438 base::WaitableEvent completion(true, false); 439 bool result = false; 440 base::Callback<bool(void)> destroy_task = base::Bind( 441 &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this)); 442 QueueTask( 443 base::Bind(&RunTaskWithResult<bool>, destroy_task, &result, &completion)); 444 completion.Wait(); 445 } 446 447 bool InProcessCommandBuffer::DestroyOnGpuThread() { 448 CheckSequencedThread(); 449 gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs(); 450 command_buffer_.reset(); 451 // Clean up GL resources if possible. 452 bool have_context = context_.get() && context_->MakeCurrent(surface_.get()); 453 if (decoder_) { 454 decoder_->Destroy(have_context); 455 decoder_.reset(); 456 } 457 context_ = NULL; 458 surface_ = NULL; 459 gl_share_group_ = NULL; 460 #if defined(OS_ANDROID) 461 stream_texture_manager_.reset(); 462 #endif 463 464 return true; 465 } 466 467 void InProcessCommandBuffer::CheckSequencedThread() { 468 DCHECK(!sequence_checker_ || 469 sequence_checker_->CalledOnValidSequencedThread()); 470 } 471 472 void InProcessCommandBuffer::OnContextLost() { 473 CheckSequencedThread(); 474 if (!context_lost_callback_.is_null()) { 475 context_lost_callback_.Run(); 476 context_lost_callback_.Reset(); 477 } 478 479 context_lost_ = true; 480 } 481 482 CommandBuffer::State InProcessCommandBuffer::GetStateFast() { 483 CheckSequencedThread(); 484 base::AutoLock lock(state_after_last_flush_lock_); 485 if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U) 486 last_state_ = state_after_last_flush_; 487 return last_state_; 488 } 489 490 CommandBuffer::State InProcessCommandBuffer::GetLastState() { 491 CheckSequencedThread(); 492 return last_state_; 493 } 494 495 int32 InProcessCommandBuffer::GetLastToken() { 496 CheckSequencedThread(); 497 GetStateFast(); 498 return last_state_.token; 499 } 500 501 void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { 502 CheckSequencedThread(); 503 ScopedEvent handle_flush(&flush_event_); 504 base::AutoLock lock(command_buffer_lock_); 505 command_buffer_->Flush(put_offset); 506 { 507 // Update state before signaling the flush event. 508 base::AutoLock lock(state_after_last_flush_lock_); 509 state_after_last_flush_ = command_buffer_->GetLastState(); 510 } 511 DCHECK((!error::IsError(state_after_last_flush_.error) && !context_lost_) || 512 (error::IsError(state_after_last_flush_.error) && context_lost_)); 513 514 // If we've processed all pending commands but still have pending queries, 515 // pump idle work until the query is passed. 516 if (put_offset == state_after_last_flush_.get_offset && 517 gpu_scheduler_->HasMoreWork()) { 518 ScheduleIdleWorkOnGpuThread(); 519 } 520 } 521 522 void InProcessCommandBuffer::PerformIdleWork() { 523 CheckSequencedThread(); 524 idle_work_pending_ = false; 525 base::AutoLock lock(command_buffer_lock_); 526 if (MakeCurrent() && gpu_scheduler_->HasMoreWork()) { 527 gpu_scheduler_->PerformIdleWork(); 528 ScheduleIdleWorkOnGpuThread(); 529 } 530 } 531 532 void InProcessCommandBuffer::ScheduleIdleWorkOnGpuThread() { 533 CheckSequencedThread(); 534 if (idle_work_pending_) 535 return; 536 idle_work_pending_ = true; 537 service_->ScheduleIdleWork( 538 base::Bind(&InProcessCommandBuffer::PerformIdleWork, 539 gpu_thread_weak_ptr_)); 540 } 541 542 void InProcessCommandBuffer::Flush(int32 put_offset) { 543 CheckSequencedThread(); 544 if (last_state_.error != gpu::error::kNoError) 545 return; 546 547 if (last_put_offset_ == put_offset) 548 return; 549 550 last_put_offset_ = put_offset; 551 base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread, 552 gpu_thread_weak_ptr_, 553 put_offset); 554 QueueTask(task); 555 } 556 557 void InProcessCommandBuffer::WaitForTokenInRange(int32 start, int32 end) { 558 CheckSequencedThread(); 559 while (!InRange(start, end, GetLastToken()) && 560 last_state_.error == gpu::error::kNoError) 561 flush_event_.Wait(); 562 } 563 564 void InProcessCommandBuffer::WaitForGetOffsetInRange(int32 start, int32 end) { 565 CheckSequencedThread(); 566 567 GetStateFast(); 568 while (!InRange(start, end, last_state_.get_offset) && 569 last_state_.error == gpu::error::kNoError) { 570 flush_event_.Wait(); 571 GetStateFast(); 572 } 573 } 574 575 void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) { 576 CheckSequencedThread(); 577 if (last_state_.error != gpu::error::kNoError) 578 return; 579 580 { 581 base::AutoLock lock(command_buffer_lock_); 582 command_buffer_->SetGetBuffer(shm_id); 583 last_put_offset_ = 0; 584 } 585 { 586 base::AutoLock lock(state_after_last_flush_lock_); 587 state_after_last_flush_ = command_buffer_->GetLastState(); 588 } 589 } 590 591 scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(size_t size, 592 int32* id) { 593 CheckSequencedThread(); 594 base::AutoLock lock(command_buffer_lock_); 595 return command_buffer_->CreateTransferBuffer(size, id); 596 } 597 598 void InProcessCommandBuffer::DestroyTransferBuffer(int32 id) { 599 CheckSequencedThread(); 600 base::Closure task = 601 base::Bind(&InProcessCommandBuffer::DestroyTransferBufferOnGpuThread, 602 base::Unretained(this), 603 id); 604 605 QueueTask(task); 606 } 607 608 void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32 id) { 609 base::AutoLock lock(command_buffer_lock_); 610 command_buffer_->DestroyTransferBuffer(id); 611 } 612 613 gpu::Capabilities InProcessCommandBuffer::GetCapabilities() { 614 return capabilities_; 615 } 616 617 gfx::GpuMemoryBuffer* InProcessCommandBuffer::CreateGpuMemoryBuffer( 618 size_t width, 619 size_t height, 620 unsigned internalformat, 621 unsigned usage, 622 int32* id) { 623 CheckSequencedThread(); 624 625 *id = -1; 626 627 scoped_ptr<gfx::GpuMemoryBuffer> buffer = 628 g_gpu_memory_buffer_factory->AllocateGpuMemoryBuffer( 629 width, height, internalformat, usage); 630 if (!buffer.get()) 631 return NULL; 632 633 static int32 next_id = 1; 634 int32 new_id = next_id++; 635 636 base::Closure task = 637 base::Bind(&InProcessCommandBuffer::RegisterGpuMemoryBufferOnGpuThread, 638 base::Unretained(this), 639 new_id, 640 buffer->GetHandle(), 641 width, 642 height, 643 internalformat); 644 645 QueueTask(task); 646 647 *id = new_id; 648 DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end()); 649 return gpu_memory_buffers_.add(new_id, buffer.Pass()).first->second; 650 } 651 652 void InProcessCommandBuffer::RegisterGpuMemoryBufferOnGpuThread( 653 int32 id, 654 const gfx::GpuMemoryBufferHandle& handle, 655 size_t width, 656 size_t height, 657 unsigned internalformat) { 658 scoped_refptr<gfx::GLImage> image = 659 g_gpu_memory_buffer_factory->CreateImageForGpuMemoryBuffer( 660 handle, gfx::Size(width, height), internalformat); 661 if (!image.get()) 662 return; 663 664 // For Android specific workaround. 665 gles2::ContextGroup* context_group = decoder_->GetContextGroup(); 666 if (context_group->feature_info()->workarounds().release_image_after_use) 667 image->SetReleaseAfterUse(); 668 669 if (decoder_) { 670 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager(); 671 DCHECK(image_manager); 672 image_manager->AddImage(image.get(), id); 673 } 674 } 675 676 void InProcessCommandBuffer::DestroyGpuMemoryBuffer(int32 id) { 677 CheckSequencedThread(); 678 679 base::Closure task = 680 base::Bind(&InProcessCommandBuffer::UnregisterGpuMemoryBufferOnGpuThread, 681 base::Unretained(this), 682 id); 683 684 QueueTask(task); 685 686 gpu_memory_buffers_.erase(id); 687 } 688 689 void InProcessCommandBuffer::UnregisterGpuMemoryBufferOnGpuThread(int32 id) { 690 if (decoder_) { 691 gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager(); 692 DCHECK(image_manager); 693 image_manager->RemoveImage(id); 694 } 695 } 696 697 uint32 InProcessCommandBuffer::InsertSyncPoint() { 698 uint32 sync_point = g_sync_point_manager.Get().GenerateSyncPoint(); 699 QueueTask(base::Bind(&InProcessCommandBuffer::RetireSyncPointOnGpuThread, 700 base::Unretained(this), 701 sync_point)); 702 return sync_point; 703 } 704 705 uint32 InProcessCommandBuffer::InsertFutureSyncPoint() { 706 return g_sync_point_manager.Get().GenerateSyncPoint(); 707 } 708 709 void InProcessCommandBuffer::RetireSyncPoint(uint32 sync_point) { 710 QueueTask(base::Bind(&InProcessCommandBuffer::RetireSyncPointOnGpuThread, 711 base::Unretained(this), 712 sync_point)); 713 } 714 715 void InProcessCommandBuffer::RetireSyncPointOnGpuThread(uint32 sync_point) { 716 gles2::MailboxManager* mailbox_manager = 717 decoder_->GetContextGroup()->mailbox_manager(); 718 if (mailbox_manager->UsesSync()) { 719 bool make_current_success = false; 720 { 721 base::AutoLock lock(command_buffer_lock_); 722 make_current_success = MakeCurrent(); 723 } 724 if (make_current_success) 725 mailbox_manager->PushTextureUpdates(sync_point); 726 } 727 g_sync_point_manager.Get().RetireSyncPoint(sync_point); 728 } 729 730 void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point, 731 const base::Closure& callback) { 732 CheckSequencedThread(); 733 QueueTask(base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, 734 base::Unretained(this), 735 sync_point, 736 WrapCallback(callback))); 737 } 738 739 bool InProcessCommandBuffer::WaitSyncPointOnGpuThread(unsigned sync_point) { 740 g_sync_point_manager.Get().WaitSyncPoint(sync_point); 741 gles2::MailboxManager* mailbox_manager = 742 decoder_->GetContextGroup()->mailbox_manager(); 743 mailbox_manager->PullTextureUpdates(sync_point); 744 return true; 745 } 746 747 void InProcessCommandBuffer::SignalSyncPointOnGpuThread( 748 unsigned sync_point, 749 const base::Closure& callback) { 750 if (g_sync_point_manager.Get().IsSyncPointPassed(sync_point)) { 751 callback.Run(); 752 } else { 753 service_->ScheduleIdleWork( 754 base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread, 755 gpu_thread_weak_ptr_, 756 sync_point, 757 callback)); 758 } 759 } 760 761 void InProcessCommandBuffer::SignalQuery(unsigned query_id, 762 const base::Closure& callback) { 763 CheckSequencedThread(); 764 QueueTask(base::Bind(&InProcessCommandBuffer::SignalQueryOnGpuThread, 765 base::Unretained(this), 766 query_id, 767 WrapCallback(callback))); 768 } 769 770 void InProcessCommandBuffer::SignalQueryOnGpuThread( 771 unsigned query_id, 772 const base::Closure& callback) { 773 gles2::QueryManager* query_manager_ = decoder_->GetQueryManager(); 774 DCHECK(query_manager_); 775 776 gles2::QueryManager::Query* query = query_manager_->GetQuery(query_id); 777 if (!query) 778 callback.Run(); 779 else 780 query->AddCallback(callback); 781 } 782 783 void InProcessCommandBuffer::SetSurfaceVisible(bool visible) {} 784 785 void InProcessCommandBuffer::Echo(const base::Closure& callback) { 786 QueueTask(WrapCallback(callback)); 787 } 788 789 uint32 InProcessCommandBuffer::CreateStreamTexture(uint32 texture_id) { 790 base::WaitableEvent completion(true, false); 791 uint32 stream_id = 0; 792 base::Callback<uint32(void)> task = 793 base::Bind(&InProcessCommandBuffer::CreateStreamTextureOnGpuThread, 794 base::Unretained(this), 795 texture_id); 796 QueueTask( 797 base::Bind(&RunTaskWithResult<uint32>, task, &stream_id, &completion)); 798 completion.Wait(); 799 return stream_id; 800 } 801 802 uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread( 803 uint32 client_texture_id) { 804 #if defined(OS_ANDROID) 805 return stream_texture_manager_->CreateStreamTexture( 806 client_texture_id, decoder_->GetContextGroup()->texture_manager()); 807 #else 808 return 0; 809 #endif 810 } 811 812 gpu::error::Error InProcessCommandBuffer::GetLastError() { 813 CheckSequencedThread(); 814 return last_state_.error; 815 } 816 817 bool InProcessCommandBuffer::Initialize() { 818 NOTREACHED(); 819 return false; 820 } 821 822 namespace { 823 824 void PostCallback(const scoped_refptr<base::MessageLoopProxy>& loop, 825 const base::Closure& callback) { 826 if (!loop->BelongsToCurrentThread()) { 827 loop->PostTask(FROM_HERE, callback); 828 } else { 829 callback.Run(); 830 } 831 } 832 833 void RunOnTargetThread(scoped_ptr<base::Closure> callback) { 834 DCHECK(callback.get()); 835 callback->Run(); 836 } 837 838 } // anonymous namespace 839 840 base::Closure InProcessCommandBuffer::WrapCallback( 841 const base::Closure& callback) { 842 // Make sure the callback gets deleted on the target thread by passing 843 // ownership. 844 scoped_ptr<base::Closure> scoped_callback(new base::Closure(callback)); 845 base::Closure callback_on_client_thread = 846 base::Bind(&RunOnTargetThread, base::Passed(&scoped_callback)); 847 base::Closure wrapped_callback = 848 base::Bind(&PostCallback, base::MessageLoopProxy::current(), 849 callback_on_client_thread); 850 return wrapped_callback; 851 } 852 853 #if defined(OS_ANDROID) 854 scoped_refptr<gfx::SurfaceTexture> 855 InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) { 856 DCHECK(stream_texture_manager_); 857 return stream_texture_manager_->GetSurfaceTexture(stream_id); 858 } 859 #endif 860 861 // static 862 void InProcessCommandBuffer::SetGpuMemoryBufferFactory( 863 InProcessGpuMemoryBufferFactory* factory) { 864 g_gpu_memory_buffer_factory = factory; 865 } 866 867 } // namespace gpu 868