Index: gpu/command_buffer/service/in_process_command_buffer.cc |
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc |
index a1d7ca45ed5261ebd78fc64c981af42c379435f3..7f160173bcee62c7250659f8d7cddd02e6371290 100644 |
--- a/gpu/command_buffer/service/in_process_command_buffer.cc |
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc |
@@ -43,8 +43,6 @@ namespace gpu { |
namespace { |
-static bool g_use_virtualized_gl_context = false; |
-static bool g_uses_explicit_scheduling = false; |
static GpuMemoryBufferFactory* g_gpu_memory_buffer_factory = NULL; |
template <typename T> |
@@ -57,13 +55,25 @@ static void RunTaskWithResult(base::Callback<T(void)> task, |
class GpuInProcessThread |
: public base::Thread, |
+ public InProcessCommandBuffer::Service, |
public base::RefCountedThreadSafe<GpuInProcessThread> { |
public: |
GpuInProcessThread(); |
+ virtual void AddRef() const OVERRIDE { |
+ base::RefCountedThreadSafe<GpuInProcessThread>::AddRef(); |
+ } |
+ virtual void Release() const OVERRIDE { |
+ base::RefCountedThreadSafe<GpuInProcessThread>::Release(); |
+ } |
+ |
+ virtual void ScheduleTask(const base::Closure& task) OVERRIDE; |
+ virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; |
+ virtual bool UseVirtualizedGLContexts() OVERRIDE { return false; } |
+ |
private: |
- friend class base::RefCountedThreadSafe<GpuInProcessThread>; |
virtual ~GpuInProcessThread(); |
+ friend class base::RefCountedThreadSafe<GpuInProcessThread>; |
DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread); |
}; |
@@ -76,165 +86,20 @@ GpuInProcessThread::~GpuInProcessThread() { |
Stop(); |
} |
-// Used with explicit scheduling when there is no dedicated GPU thread. |
-class GpuCommandQueue { |
- public: |
- GpuCommandQueue(); |
- ~GpuCommandQueue(); |
- |
- void QueueTask(const base::Closure& task); |
- void RunTasks(); |
- void SetScheduleCallback(const base::Closure& callback); |
- |
- private: |
- base::Lock tasks_lock_; |
- std::queue<base::Closure> tasks_; |
- base::Closure schedule_callback_; |
- |
- DISALLOW_COPY_AND_ASSIGN(GpuCommandQueue); |
-}; |
- |
-GpuCommandQueue::GpuCommandQueue() {} |
- |
-GpuCommandQueue::~GpuCommandQueue() { |
- base::AutoLock lock(tasks_lock_); |
- DCHECK(tasks_.empty()); |
+void GpuInProcessThread::ScheduleTask(const base::Closure& task) { |
+ message_loop()->PostTask(FROM_HERE, task); |
} |
-void GpuCommandQueue::QueueTask(const base::Closure& task) { |
- { |
- base::AutoLock lock(tasks_lock_); |
- tasks_.push(task); |
- } |
- |
- DCHECK(!schedule_callback_.is_null()); |
- schedule_callback_.Run(); |
-} |
- |
-void GpuCommandQueue::RunTasks() { |
- size_t num_tasks; |
- { |
- base::AutoLock lock(tasks_lock_); |
- num_tasks = tasks_.size(); |
- } |
- |
- while (num_tasks) { |
- base::Closure task; |
- { |
- base::AutoLock lock(tasks_lock_); |
- task = tasks_.front(); |
- tasks_.pop(); |
- num_tasks = tasks_.size(); |
- } |
- |
- task.Run(); |
- } |
-} |
- |
-void GpuCommandQueue::SetScheduleCallback(const base::Closure& callback) { |
- DCHECK(schedule_callback_.is_null()); |
- schedule_callback_ = callback; |
+void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) { |
+ message_loop()->PostDelayedTask( |
+ FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); |
} |
-static base::LazyInstance<GpuCommandQueue> g_gpu_queue = |
+base::LazyInstance<std::set<InProcessCommandBuffer*> > default_thread_clients_ = |
LAZY_INSTANCE_INITIALIZER; |
- |
-class SchedulerClientBase : public InProcessCommandBuffer::SchedulerClient { |
- public: |
- explicit SchedulerClientBase(bool need_thread); |
- virtual ~SchedulerClientBase(); |
- |
- static bool HasClients(); |
- |
- protected: |
- scoped_refptr<GpuInProcessThread> thread_; |
- |
- private: |
- static base::LazyInstance<std::set<SchedulerClientBase*> > all_clients_; |
- static base::LazyInstance<base::Lock> all_clients_lock_; |
-}; |
- |
-base::LazyInstance<std::set<SchedulerClientBase*> > |
- SchedulerClientBase::all_clients_ = LAZY_INSTANCE_INITIALIZER; |
-base::LazyInstance<base::Lock> SchedulerClientBase::all_clients_lock_ = |
+base::LazyInstance<base::Lock> default_thread_clients_lock_ = |
LAZY_INSTANCE_INITIALIZER; |
-SchedulerClientBase::SchedulerClientBase(bool need_thread) { |
- base::AutoLock lock(all_clients_lock_.Get()); |
- if (need_thread) { |
- if (!all_clients_.Get().empty()) { |
- SchedulerClientBase* other = *all_clients_.Get().begin(); |
- thread_ = other->thread_; |
- DCHECK(thread_.get()); |
- } else { |
- thread_ = new GpuInProcessThread; |
- } |
- } |
- all_clients_.Get().insert(this); |
-} |
- |
-SchedulerClientBase::~SchedulerClientBase() { |
- base::AutoLock lock(all_clients_lock_.Get()); |
- all_clients_.Get().erase(this); |
-} |
- |
-bool SchedulerClientBase::HasClients() { |
- base::AutoLock lock(all_clients_lock_.Get()); |
- return !all_clients_.Get().empty(); |
-} |
- |
-// A client that talks to the GPU thread |
-class ThreadClient : public SchedulerClientBase { |
- public: |
- ThreadClient(); |
- virtual void QueueTask(const base::Closure& task) OVERRIDE; |
- virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; |
-}; |
- |
-ThreadClient::ThreadClient() : SchedulerClientBase(true) { |
- DCHECK(thread_.get()); |
-} |
- |
-void ThreadClient::QueueTask(const base::Closure& task) { |
- thread_->message_loop()->PostTask(FROM_HERE, task); |
-} |
- |
-void ThreadClient::ScheduleIdleWork(const base::Closure& callback) { |
- thread_->message_loop()->PostDelayedTask( |
- FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); |
-} |
- |
-// A client that talks to the GpuCommandQueue |
-class QueueClient : public SchedulerClientBase { |
- public: |
- QueueClient(); |
- virtual void QueueTask(const base::Closure& task) OVERRIDE; |
- virtual void ScheduleIdleWork(const base::Closure& callback) OVERRIDE; |
-}; |
- |
-QueueClient::QueueClient() : SchedulerClientBase(false) { |
- DCHECK(!thread_.get()); |
-} |
- |
-void QueueClient::QueueTask(const base::Closure& task) { |
- g_gpu_queue.Get().QueueTask(task); |
-} |
- |
-void QueueClient::ScheduleIdleWork(const base::Closure& callback) { |
- // TODO(sievers): Should this do anything? |
-} |
- |
-static scoped_ptr<InProcessCommandBuffer::SchedulerClient> |
-CreateSchedulerClient() { |
- scoped_ptr<InProcessCommandBuffer::SchedulerClient> client; |
- if (g_uses_explicit_scheduling) |
- client.reset(new QueueClient); |
- else |
- client.reset(new ThreadClient); |
- |
- return client.Pass(); |
-} |
- |
class ScopedEvent { |
public: |
ScopedEvent(base::WaitableEvent* event) : event_(event) {} |
@@ -246,15 +111,41 @@ class ScopedEvent { |
} // anonyous namespace |
-InProcessCommandBuffer::InProcessCommandBuffer() |
+InProcessCommandBuffer::Service::Service() {} |
+ |
+InProcessCommandBuffer::Service::~Service() {} |
+ |
+scoped_refptr<InProcessCommandBuffer::Service> |
+InProcessCommandBuffer::GetDefaultService() { |
+ base::AutoLock lock(default_thread_clients_lock_.Get()); |
+ scoped_refptr<Service> service; |
+ if (!default_thread_clients_.Get().empty()) { |
+ InProcessCommandBuffer* other = *default_thread_clients_.Get().begin(); |
+ service = other->service_; |
+ DCHECK(service.get()); |
+ } else { |
+ service = new GpuInProcessThread; |
+ } |
+ return service; |
+} |
+ |
+InProcessCommandBuffer::InProcessCommandBuffer( |
+ const scoped_refptr<Service>& service) |
: context_lost_(false), |
last_put_offset_(-1), |
flush_event_(false, false), |
- queue_(CreateSchedulerClient()), |
- gpu_thread_weak_ptr_factory_(this) {} |
+ service_(service.get() ? service : GetDefaultService()), |
+ gpu_thread_weak_ptr_factory_(this) { |
+ if (!service) { |
+ base::AutoLock lock(default_thread_clients_lock_.Get()); |
+ default_thread_clients_.Get().insert(this); |
+ } |
+} |
InProcessCommandBuffer::~InProcessCommandBuffer() { |
Destroy(); |
+ base::AutoLock lock(default_thread_clients_lock_.Get()); |
+ default_thread_clients_.Get().erase(this); |
} |
void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) { |
@@ -301,7 +192,7 @@ bool InProcessCommandBuffer::Initialize( |
gfx::GpuPreference gpu_preference, |
const base::Closure& context_lost_callback, |
InProcessCommandBuffer* share_group) { |
- |
+ DCHECK(!share_group || service_ == share_group->service_); |
context_lost_callback_ = WrapCallback(context_lost_callback); |
if (surface) { |
@@ -398,7 +289,7 @@ bool InProcessCommandBuffer::InitializeOnGpuThread( |
return false; |
} |
- if (g_use_virtualized_gl_context) { |
+ if (service_->UseVirtualizedGLContexts()) { |
context_ = gl_share_group_->GetSharedContext(); |
if (!context_.get()) { |
context_ = gfx::GLContext::CreateGLContext( |
@@ -548,7 +439,7 @@ void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) { |
// pump idle work until the query is passed. |
if (put_offset == state_after_last_flush_.get_offset && |
gpu_scheduler_->HasMoreWork()) { |
- queue_->ScheduleIdleWork( |
+ service_->ScheduleIdleWork( |
base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork, |
gpu_thread_weak_ptr_)); |
} |
@@ -559,7 +450,7 @@ void InProcessCommandBuffer::ScheduleMoreIdleWork() { |
base::AutoLock lock(command_buffer_lock_); |
if (gpu_scheduler_->HasMoreWork()) { |
gpu_scheduler_->PerformIdleWork(); |
- queue_->ScheduleIdleWork( |
+ service_->ScheduleIdleWork( |
base::Bind(&InProcessCommandBuffer::ScheduleMoreIdleWork, |
gpu_thread_weak_ptr_)); |
} |
@@ -782,25 +673,6 @@ InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) { |
#endif |
// static |
-void InProcessCommandBuffer::EnableVirtualizedContext() { |
- g_use_virtualized_gl_context = true; |
-} |
- |
-// static |
-void InProcessCommandBuffer::SetScheduleCallback( |
- const base::Closure& callback) { |
- DCHECK(!g_uses_explicit_scheduling); |
- DCHECK(!SchedulerClientBase::HasClients()); |
- g_uses_explicit_scheduling = true; |
- g_gpu_queue.Get().SetScheduleCallback(callback); |
-} |
- |
-// static |
-void InProcessCommandBuffer::ProcessGpuWorkOnCurrentThread() { |
- g_gpu_queue.Get().RunTasks(); |
-} |
- |
-// static |
void InProcessCommandBuffer::SetGpuMemoryBufferFactory( |
GpuMemoryBufferFactory* factory) { |
g_gpu_memory_buffer_factory = factory; |