| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..04ea9fd1582674451f24e339ba1e34760d9b3d62
|
| --- /dev/null
|
| +++ b/gpu/command_buffer/service/in_process_command_buffer.cc
|
| @@ -0,0 +1,702 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "gpu/command_buffer/service/in_process_command_buffer.h"
|
| +
|
| +#include <queue>
|
| +#include <utility>
|
| +
|
| +#include <GLES2/gl2.h>
|
| +#ifndef GL_GLEXT_PROTOTYPES
|
| +#define GL_GLEXT_PROTOTYPES 1
|
| +#endif
|
| +#include <GLES2/gl2ext.h>
|
| +#include <GLES2/gl2extchromium.h>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "base/threading/thread.h"
|
| +#include "gpu/command_buffer/common/id_allocator.h"
|
| +#include "gpu/command_buffer/service/command_buffer_service.h"
|
| +#include "gpu/command_buffer/service/context_group.h"
|
| +#include "gpu/command_buffer/service/gl_context_virtual.h"
|
| +#include "gpu/command_buffer/service/gpu_scheduler.h"
|
| +#include "gpu/command_buffer/service/image_manager.h"
|
| +#include "gpu/command_buffer/service/transfer_buffer_manager.h"
|
| +#include "ui/gfx/size.h"
|
| +#include "ui/gl/gl_context.h"
|
| +#include "ui/gl/gl_image.h"
|
| +#include "ui/gl/gl_share_group.h"
|
| +#include "ui/gl/gl_surface.h"
|
| +
|
| +namespace gpu {
|
| +
|
| +namespace {
|
| +
|
| +static base::LazyInstance<std::set<InProcessCommandBuffer*> >
|
| + g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +static bool g_use_virtualized_gl_context = false;
|
| +static bool g_uses_explicit_scheduling = false;
|
| +
|
| +template <typename T>
|
| +static void RunTaskWithResult(base::Callback<T(void)> task,
|
| + T* result,
|
| + base::WaitableEvent* completion) {
|
| + *result = task.Run();
|
| + completion->Signal();
|
| +}
|
| +
|
| +class GpuInProcessThread
|
| + : public base::Thread,
|
| + public base::RefCountedThreadSafe<GpuInProcessThread> {
|
| + public:
|
| + GpuInProcessThread();
|
| +
|
| + private:
|
| + friend class base::RefCountedThreadSafe<GpuInProcessThread>;
|
| + virtual ~GpuInProcessThread();
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread);
|
| +};
|
| +
|
| +GpuInProcessThread::GpuInProcessThread() : base::Thread("GpuThread") {
|
| + Start();
|
| +}
|
| +
|
| +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 GpuCommandQueue::QueueTask(const base::Closure& task) {
|
| + {
|
| + base::AutoLock lock(tasks_lock_);
|
| + tasks_.push(task);
|
| + }
|
| +
|
| + if (!schedule_callback_.is_null()) {
|
| + schedule_callback_.Run();
|
| + return;
|
| + }
|
| +}
|
| +
|
| +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;
|
| +}
|
| +
|
| +static base::LazyInstance<GpuCommandQueue> g_gpu_queue =
|
| + 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_ =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +SchedulerClientBase::SchedulerClientBase(bool need_thread) {
|
| + base::AutoLock(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(all_clients_lock_.Get());
|
| + all_clients_.Get().erase(this);
|
| +}
|
| +
|
| +bool SchedulerClientBase::HasClients() {
|
| + base::AutoLock(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;
|
| +};
|
| +
|
| +ThreadClient::ThreadClient() : SchedulerClientBase(true) {
|
| + DCHECK(thread_.get());
|
| +}
|
| +
|
| +void ThreadClient::QueueTask(const base::Closure& task) {
|
| + thread_->message_loop()->PostTask(FROM_HERE, task);
|
| +}
|
| +
|
| +// A client that talks to the GpuCommandQueue
|
| +class QueueClient : public SchedulerClientBase {
|
| + public:
|
| + QueueClient();
|
| + virtual void QueueTask(const base::Closure& task) OVERRIDE;
|
| +};
|
| +
|
| +QueueClient::QueueClient() : SchedulerClientBase(false) {
|
| + DCHECK(!thread_.get());
|
| +}
|
| +
|
| +void QueueClient::QueueTask(const base::Closure& task) {
|
| + g_gpu_queue.Get().QueueTask(task);
|
| +}
|
| +
|
| +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) {}
|
| + ~ScopedEvent() { event_->Signal(); }
|
| +
|
| + private:
|
| + base::WaitableEvent* event_;
|
| +};
|
| +
|
| +} // anonyous namespace
|
| +
|
| +InProcessCommandBuffer::InProcessCommandBuffer()
|
| + : context_lost_(false),
|
| + share_group_id_(0),
|
| + last_put_offset_(-1),
|
| + flush_event_(false, false),
|
| + queue_(CreateSchedulerClient()) {}
|
| +
|
| +InProcessCommandBuffer::~InProcessCommandBuffer() {
|
| + Destroy();
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::IsContextLost() {
|
| + if (context_lost_ || !command_buffer_) {
|
| + return true;
|
| + }
|
| + CommandBuffer::State state = GetState();
|
| + return error::IsError(state.error);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::OnResizeView(gfx::Size size, float scale_factor) {
|
| + DCHECK(!surface_->IsOffscreen());
|
| + surface_->Resize(size);
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::MakeCurrent() {
|
| + command_buffer_lock_.AssertAcquired();
|
| +
|
| + if (!context_lost_ && decoder_->MakeCurrent())
|
| + return true;
|
| + DLOG(ERROR) << "Context lost because MakeCurrent failed.";
|
| + command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
|
| + command_buffer_->SetParseError(gpu::error::kLostContext);
|
| + return false;
|
| +}
|
| +
|
| +void InProcessCommandBuffer::PumpCommands() {
|
| + ScopedEvent handle_flush(&flush_event_);
|
| + command_buffer_lock_.AssertAcquired();
|
| +
|
| + if (!MakeCurrent())
|
| + return;
|
| +
|
| + gpu_scheduler_->PutChanged();
|
| + CommandBuffer::State state = command_buffer_->GetState();
|
| + DCHECK((!error::IsError(state.error) && !context_lost_) ||
|
| + (error::IsError(state.error) && context_lost_));
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) {
|
| + command_buffer_lock_.AssertAcquired();
|
| + command_buffer_->SetGetBuffer(transfer_buffer_id);
|
| + return true;
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::Initialize(
|
| + bool is_offscreen,
|
| + bool share_resources,
|
| + gfx::AcceleratedWidget window,
|
| + const gfx::Size& size,
|
| + const char* allowed_extensions,
|
| + const std::vector<int32>& attribs,
|
| + gfx::GpuPreference gpu_preference,
|
| + const base::Closure& context_lost_callback,
|
| + unsigned int share_group_id) {
|
| +
|
| + share_resources_ = share_resources;
|
| + context_lost_callback_ = WrapCallback(context_lost_callback);
|
| + share_group_id_ = share_group_id;
|
| +
|
| + base::WaitableEvent completion(true, false);
|
| + bool result;
|
| + base::Callback<bool(void)> init_task =
|
| + base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread,
|
| + base::Unretained(this),
|
| + is_offscreen,
|
| + window,
|
| + size,
|
| + allowed_extensions,
|
| + attribs,
|
| + gpu_preference);
|
| + QueueTask(
|
| + base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion));
|
| + completion.Wait();
|
| + return result;
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::InitializeOnGpuThread(
|
| + bool is_offscreen,
|
| + gfx::AcceleratedWidget window,
|
| + const gfx::Size& size,
|
| + const char* allowed_extensions,
|
| + const std::vector<int32>& attribs,
|
| + gfx::GpuPreference gpu_preference) {
|
| + // Use one share group for all contexts.
|
| + CR_DEFINE_STATIC_LOCAL(scoped_refptr<gfx::GLShareGroup>, share_group,
|
| + (new gfx::GLShareGroup));
|
| +
|
| + DCHECK(size.width() >= 0 && size.height() >= 0);
|
| +
|
| + TransferBufferManager* manager = new TransferBufferManager();
|
| + transfer_buffer_manager_.reset(manager);
|
| + manager->Initialize();
|
| +
|
| + scoped_ptr<CommandBufferService> command_buffer(
|
| + new CommandBufferService(transfer_buffer_manager_.get()));
|
| + command_buffer->SetPutOffsetChangeCallback(base::Bind(
|
| + &InProcessCommandBuffer::PumpCommands, base::Unretained(this)));
|
| + command_buffer->SetParseErrorCallback(base::Bind(
|
| + &InProcessCommandBuffer::OnContextLost, base::Unretained(this)));
|
| +
|
| + if (!command_buffer->Initialize()) {
|
| + LOG(ERROR) << "Could not initialize command buffer.";
|
| + DestroyOnGpuThread();
|
| + return false;
|
| + }
|
| +
|
| + InProcessCommandBuffer* context_group = NULL;
|
| +
|
| + if (share_resources_ && !g_all_shared_contexts.Get().empty()) {
|
| + DCHECK(share_group_id_);
|
| + for (std::set<InProcessCommandBuffer*>::iterator it =
|
| + g_all_shared_contexts.Get().begin();
|
| + it != g_all_shared_contexts.Get().end();
|
| + ++it) {
|
| + if ((*it)->share_group_id_ == share_group_id_) {
|
| + context_group = *it;
|
| + DCHECK(context_group->share_resources_);
|
| + context_lost_ = context_group->IsContextLost();
|
| + break;
|
| + }
|
| + }
|
| + if (!context_group)
|
| + share_group = new gfx::GLShareGroup;
|
| + }
|
| +
|
| + bool bind_generates_resource = false;
|
| + decoder_.reset(gles2::GLES2Decoder::Create(
|
| + context_group ? context_group->decoder_->GetContextGroup()
|
| + : new gles2::ContextGroup(
|
| + NULL, NULL, NULL, NULL, bind_generates_resource)));
|
| +
|
| + gpu_scheduler_.reset(
|
| + new GpuScheduler(command_buffer.get(), decoder_.get(), decoder_.get()));
|
| + command_buffer->SetGetBufferChangeCallback(base::Bind(
|
| + &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get())));
|
| + command_buffer_ = command_buffer.Pass();
|
| +
|
| + decoder_->set_engine(gpu_scheduler_.get());
|
| +
|
| + if (is_offscreen)
|
| + surface_ = gfx::GLSurface::CreateOffscreenGLSurface(size);
|
| + else
|
| + surface_ = gfx::GLSurface::CreateViewGLSurface(window);
|
| +
|
| + if (!surface_.get()) {
|
| + LOG(ERROR) << "Could not create GLSurface.";
|
| + DestroyOnGpuThread();
|
| + return false;
|
| + }
|
| +
|
| + if (g_use_virtualized_gl_context) {
|
| + context_ = share_group->GetSharedContext();
|
| + if (!context_.get()) {
|
| + context_ = gfx::GLContext::CreateGLContext(
|
| + share_group.get(), surface_.get(), gpu_preference);
|
| + share_group->SetSharedContext(context_.get());
|
| + }
|
| +
|
| + context_ = new GLContextVirtual(
|
| + share_group.get(), context_.get(), decoder_->AsWeakPtr());
|
| + if (context_->Initialize(surface_.get(), gpu_preference)) {
|
| + VLOG(1) << "Created virtual GL context.";
|
| + } else {
|
| + context_ = NULL;
|
| + }
|
| + } else {
|
| + context_ = gfx::GLContext::CreateGLContext(
|
| + share_group.get(), surface_.get(), gpu_preference);
|
| + }
|
| +
|
| + if (!context_.get()) {
|
| + LOG(ERROR) << "Could not create GLContext.";
|
| + DestroyOnGpuThread();
|
| + return false;
|
| + }
|
| +
|
| + if (!context_->MakeCurrent(surface_.get())) {
|
| + LOG(ERROR) << "Could not make context current.";
|
| + DestroyOnGpuThread();
|
| + return false;
|
| + }
|
| +
|
| + gles2::DisallowedFeatures disallowed_features;
|
| + disallowed_features.swap_buffer_complete_callback = true;
|
| + disallowed_features.gpu_memory_manager = true;
|
| + if (!decoder_->Initialize(surface_,
|
| + context_,
|
| + is_offscreen,
|
| + size,
|
| + disallowed_features,
|
| + allowed_extensions,
|
| + attribs)) {
|
| + LOG(ERROR) << "Could not initialize decoder.";
|
| + DestroyOnGpuThread();
|
| + return false;
|
| + }
|
| +
|
| + if (!is_offscreen) {
|
| + decoder_->SetResizeCallback(base::Bind(
|
| + &InProcessCommandBuffer::OnResizeView, base::Unretained(this)));
|
| + }
|
| +
|
| + if (share_resources_) {
|
| + g_all_shared_contexts.Pointer()->insert(this);
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void InProcessCommandBuffer::Destroy() {
|
| + base::WaitableEvent completion(true, false);
|
| + bool result;
|
| + base::Callback<bool(void)> destroy_task = base::Bind(
|
| + &InProcessCommandBuffer::DestroyOnGpuThread, base::Unretained(this));
|
| + QueueTask(
|
| + base::Bind(&RunTaskWithResult<bool>, destroy_task, &result, &completion));
|
| + completion.Wait();
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::DestroyOnGpuThread() {
|
| + command_buffer_.reset();
|
| + // Clean up GL resources if possible.
|
| + bool have_context = context_ && context_->MakeCurrent(surface_);
|
| + if (decoder_) {
|
| + decoder_->Destroy(have_context);
|
| + decoder_.reset();
|
| + }
|
| + context_ = NULL;
|
| + surface_ = NULL;
|
| +
|
| + g_all_shared_contexts.Pointer()->erase(this);
|
| + return true;
|
| +}
|
| +
|
| +unsigned int InProcessCommandBuffer::CreateImageForGpuMemoryBuffer(
|
| + gfx::GpuMemoryBufferHandle buffer,
|
| + gfx::Size size) {
|
| + unsigned int image_id;
|
| + {
|
| + // TODO: ID allocation should go through CommandBuffer
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + gles2::ContextGroup* group = decoder_->GetContextGroup();
|
| + image_id =
|
| + group->GetIdAllocator(gles2::id_namespaces::kImages)->AllocateID();
|
| + }
|
| + base::Closure image_task =
|
| + base::Bind(&InProcessCommandBuffer::CreateImageOnGpuThread,
|
| + base::Unretained(this), buffer, size, image_id);
|
| + QueueTask(image_task);
|
| + return image_id;
|
| +}
|
| +
|
| +void InProcessCommandBuffer::CreateImageOnGpuThread(
|
| + gfx::GpuMemoryBufferHandle buffer,
|
| + gfx::Size size,
|
| + unsigned int image_id) {
|
| + scoped_refptr<gfx::GLImage> gl_image =
|
| + gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer, size);
|
| + decoder_->GetContextGroup()->image_manager()->AddImage(gl_image, image_id);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::RemoveImage(unsigned int image_id) {
|
| + {
|
| + // TODO: ID allocation should go through CommandBuffer
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + gles2::ContextGroup* group = decoder_->GetContextGroup();
|
| + group->GetIdAllocator(gles2::id_namespaces::kImages)->FreeID(image_id);
|
| + }
|
| + base::Closure image_manager_task =
|
| + base::Bind(&InProcessCommandBuffer::RemoveImageOnGpuThread,
|
| + base::Unretained(this),
|
| + image_id);
|
| + QueueTask(image_manager_task);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::RemoveImageOnGpuThread(unsigned int image_id) {
|
| + decoder_->GetContextGroup()->image_manager()->RemoveImage(image_id);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::OnContextLost() {
|
| + if (!context_lost_callback_.is_null())
|
| + context_lost_callback_.Run();
|
| +
|
| + context_lost_ = true;
|
| + if (share_resources_) {
|
| + for (std::set<InProcessCommandBuffer*>::iterator it =
|
| + g_all_shared_contexts.Get().begin();
|
| + it != g_all_shared_contexts.Get().end();
|
| + ++it) {
|
| + (*it)->context_lost_ = true;
|
| + }
|
| + }
|
| +}
|
| +
|
| +CommandBuffer::State InProcessCommandBuffer::GetStateFast() {
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + return last_state_ = command_buffer_->GetState();
|
| +}
|
| +
|
| +CommandBuffer::State InProcessCommandBuffer::GetState() {
|
| + return GetStateFast();
|
| +}
|
| +
|
| +CommandBuffer::State InProcessCommandBuffer::GetLastState() {
|
| + return last_state_;
|
| +}
|
| +
|
| +int32 InProcessCommandBuffer::GetLastToken() { return last_state_.token; }
|
| +
|
| +void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) {
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + command_buffer_->Flush(put_offset);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::Flush(int32 put_offset) {
|
| + if (last_state_.error != gpu::error::kNoError)
|
| + return;
|
| +
|
| + if (last_put_offset_ == put_offset)
|
| + return;
|
| +
|
| + last_put_offset_ = put_offset;
|
| + base::Closure task = base::Bind(&InProcessCommandBuffer::FlushOnGpuThread,
|
| + base::Unretained(this),
|
| + put_offset);
|
| + QueueTask(task);
|
| +}
|
| +
|
| +CommandBuffer::State InProcessCommandBuffer::FlushSync(int32 put_offset,
|
| + int32 last_known_get) {
|
| + if (put_offset == last_known_get || last_state_.error != gpu::error::kNoError)
|
| + return last_state_;
|
| +
|
| + Flush(put_offset);
|
| + GetStateFast();
|
| + while (last_known_get == last_state_.get_offset &&
|
| + last_state_.error == gpu::error::kNoError) {
|
| + flush_event_.Wait();
|
| + GetStateFast();
|
| + }
|
| +
|
| + return last_state_;
|
| +}
|
| +
|
| +void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) {
|
| + if (last_state_.error != gpu::error::kNoError)
|
| + return;
|
| +
|
| + {
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + command_buffer_->SetGetBuffer(shm_id);
|
| + last_put_offset_ = 0;
|
| + }
|
| + GetStateFast();
|
| +}
|
| +
|
| +gpu::Buffer InProcessCommandBuffer::CreateTransferBuffer(size_t size,
|
| + int32* id) {
|
| + base::AutoLock lock(command_buffer_lock_);
|
| + return command_buffer_->CreateTransferBuffer(size, id);
|
| +}
|
| +
|
| +void InProcessCommandBuffer::DestroyTransferBuffer(int32 id) {
|
| + base::Closure task = base::Bind(&CommandBuffer::DestroyTransferBuffer,
|
| + base::Unretained(command_buffer_.get()),
|
| + id);
|
| +
|
| + QueueTask(task);
|
| +}
|
| +
|
| +gpu::Buffer InProcessCommandBuffer::GetTransferBuffer(int32 id) {
|
| + NOTREACHED();
|
| + return gpu::Buffer();
|
| +}
|
| +
|
| +uint32 InProcessCommandBuffer::InsertSyncPoint() {
|
| + NOTREACHED();
|
| + return 0;
|
| +}
|
| +void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point,
|
| + const base::Closure& callback) {
|
| + QueueTask(WrapCallback(callback));
|
| +}
|
| +
|
| +gpu::error::Error InProcessCommandBuffer::GetLastError() {
|
| + return last_state_.error;
|
| +}
|
| +
|
| +bool InProcessCommandBuffer::Initialize() {
|
| + NOTREACHED();
|
| + return false;
|
| +}
|
| +
|
| +void InProcessCommandBuffer::SetGetOffset(int32 get_offset) { NOTREACHED(); }
|
| +
|
| +void InProcessCommandBuffer::SetToken(int32 token) { NOTREACHED(); }
|
| +
|
| +void InProcessCommandBuffer::SetParseError(gpu::error::Error error) {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void InProcessCommandBuffer::SetContextLostReason(
|
| + gpu::error::ContextLostReason reason) {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +static void PostCallback(const scoped_refptr<base::MessageLoopProxy>& loop,
|
| + const base::Closure& callback) {
|
| + if (loop != base::MessageLoopProxy::current())
|
| + loop->PostTask(FROM_HERE, callback);
|
| + else
|
| + callback.Run();
|
| +}
|
| +
|
| +static void RunCallback(scoped_ptr<base::Closure> callback) {
|
| + DCHECK(callback.get());
|
| + callback->Run();
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +base::Closure InProcessCommandBuffer::WrapCallback(
|
| + const base::Closure& callback) {
|
| + // Make sure the callback gets deleted on the target thread by passing
|
| + // ownership.
|
| + scoped_ptr<base::Closure> scoped_callback(new base::Closure(callback));
|
| + base::Closure callback_on_client_thread =
|
| + base::Bind(&RunCallback, base::Passed(&scoped_callback));
|
| + base::Closure wrapped_callback =
|
| + base::Bind(&PostCallback, base::MessageLoopProxy::current(),
|
| + callback);
|
| + return wrapped_callback;
|
| +}
|
| +
|
| +// 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();
|
| +}
|
| +
|
| +} // namespace gpu
|
|
|