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