// Copyright 2013 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 <set>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.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/sequence_checker.h"
#include "base/synchronization/condition_variable.h"
#include "base/threading/thread.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.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/gpu_switches.h"
#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/mailbox_manager_sync.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/query_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"

#if defined(OS_ANDROID)
#include "gpu/command_buffer/service/stream_texture_manager_in_process_android.h"
#include "ui/gl/android/surface_texture.h"
#endif

namespace gpu {

namespace {

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 InProcessCommandBuffer::Service,
      public base::RefCountedThreadSafe<GpuInProcessThread> {
 public:
  GpuInProcessThread();

  void AddRef() const override {
    base::RefCountedThreadSafe<GpuInProcessThread>::AddRef();
  }
  void Release() const override {
    base::RefCountedThreadSafe<GpuInProcessThread>::Release();
  }

  void ScheduleTask(const base::Closure& task) override;
  void ScheduleIdleWork(const base::Closure& callback) override;
  bool UseVirtualizedGLContexts() override { return false; }
  scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache()
      override;

 private:
  ~GpuInProcessThread() override;
  friend class base::RefCountedThreadSafe<GpuInProcessThread>;

  scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_;
  DISALLOW_COPY_AND_ASSIGN(GpuInProcessThread);
};

GpuInProcessThread::GpuInProcessThread() : base::Thread("GpuThread") {
  Start();
}

GpuInProcessThread::~GpuInProcessThread() {
  Stop();
}

void GpuInProcessThread::ScheduleTask(const base::Closure& task) {
  message_loop()->PostTask(FROM_HERE, task);
}

void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) {
  message_loop()->PostDelayedTask(
      FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5));
}

scoped_refptr<gles2::ShaderTranslatorCache>
GpuInProcessThread::shader_translator_cache() {
  if (!shader_translator_cache_.get())
    shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
  return shader_translator_cache_;
}

base::LazyInstance<std::set<InProcessCommandBuffer*> > default_thread_clients_ =
    LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<base::Lock> default_thread_clients_lock_ =
    LAZY_INSTANCE_INITIALIZER;

class ScopedEvent {
 public:
  ScopedEvent(base::WaitableEvent* event) : event_(event) {}
  ~ScopedEvent() { event_->Signal(); }

 private:
  base::WaitableEvent* event_;
};

class SyncPointManager {
 public:
  SyncPointManager();
  ~SyncPointManager();

  uint32 GenerateSyncPoint();
  void RetireSyncPoint(uint32 sync_point);

  bool IsSyncPointPassed(uint32 sync_point);
  void WaitSyncPoint(uint32 sync_point);

private:
  // This lock protects access to pending_sync_points_ and next_sync_point_ and
  // is used with the ConditionVariable to signal when a sync point is retired.
  base::Lock lock_;
  std::set<uint32> pending_sync_points_;
  uint32 next_sync_point_;
  base::ConditionVariable cond_var_;
};

SyncPointManager::SyncPointManager() : next_sync_point_(1), cond_var_(&lock_) {}

SyncPointManager::~SyncPointManager() {
  DCHECK_EQ(pending_sync_points_.size(), 0U);
}

uint32 SyncPointManager::GenerateSyncPoint() {
  base::AutoLock lock(lock_);
  uint32 sync_point = next_sync_point_++;
  DCHECK_EQ(pending_sync_points_.count(sync_point), 0U);
  pending_sync_points_.insert(sync_point);
  return sync_point;
}

void SyncPointManager::RetireSyncPoint(uint32 sync_point) {
  base::AutoLock lock(lock_);
  DCHECK(pending_sync_points_.count(sync_point));
  pending_sync_points_.erase(sync_point);
  cond_var_.Broadcast();
}

bool SyncPointManager::IsSyncPointPassed(uint32 sync_point) {
  base::AutoLock lock(lock_);
  return pending_sync_points_.count(sync_point) == 0;
}

void SyncPointManager::WaitSyncPoint(uint32 sync_point) {
  base::AutoLock lock(lock_);
  while (pending_sync_points_.count(sync_point)) {
    cond_var_.Wait();
  }
}

base::LazyInstance<SyncPointManager> g_sync_point_manager =
    LAZY_INSTANCE_INITIALIZER;

}  // anonyous namespace

InProcessCommandBuffer::Service::Service() {}

InProcessCommandBuffer::Service::~Service() {}

scoped_refptr<gles2::MailboxManager>
InProcessCommandBuffer::Service::mailbox_manager() {
  if (!mailbox_manager_.get()) {
    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kEnableThreadedTextureMailboxes)) {
      mailbox_manager_ = new gles2::MailboxManagerSync();
    } else {
      mailbox_manager_ = new gles2::MailboxManagerImpl();
    }
  }
  return mailbox_manager_;
}

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),
      idle_work_pending_(false),
      image_factory_(nullptr),
      last_put_offset_(-1),
      gpu_memory_buffer_manager_(nullptr),
      flush_event_(false, false),
      service_(service.get() ? service : GetDefaultService()),
      gpu_thread_weak_ptr_factory_(this) {
  if (!service.get()) {
    base::AutoLock lock(default_thread_clients_lock_.Get());
    default_thread_clients_.Get().insert(this);
  }
  next_image_id_.GetNext();
}

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) {
  CheckSequencedThread();
  DCHECK(!surface_->IsOffscreen());
  surface_->Resize(size);
}

bool InProcessCommandBuffer::MakeCurrent() {
  CheckSequencedThread();
  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() {
  CheckSequencedThread();
  command_buffer_lock_.AssertAcquired();

  if (!MakeCurrent())
    return;

  gpu_scheduler_->PutChanged();
}

bool InProcessCommandBuffer::GetBufferChanged(int32 transfer_buffer_id) {
  CheckSequencedThread();
  command_buffer_lock_.AssertAcquired();
  command_buffer_->SetGetBuffer(transfer_buffer_id);
  return true;
}

bool InProcessCommandBuffer::Initialize(
    scoped_refptr<gfx::GLSurface> surface,
    bool is_offscreen,
    gfx::AcceleratedWidget window,
    const gfx::Size& size,
    const std::vector<int32>& attribs,
    gfx::GpuPreference gpu_preference,
    const base::Closure& context_lost_callback,
    InProcessCommandBuffer* share_group,
    GpuMemoryBufferManager* gpu_memory_buffer_manager,
    ImageFactory* image_factory) {
  DCHECK(!share_group || service_.get() == share_group->service_.get());
  context_lost_callback_ = WrapCallback(context_lost_callback);

  if (surface.get()) {
    // GPU thread must be the same as client thread due to GLSurface not being
    // thread safe.
    sequence_checker_.reset(new base::SequenceChecker);
    surface_ = surface;
  }

  gpu::Capabilities capabilities;
  InitializeOnGpuThreadParams params(is_offscreen,
                                     window,
                                     size,
                                     attribs,
                                     gpu_preference,
                                     &capabilities,
                                     share_group,
                                     image_factory);

  base::Callback<bool(void)> init_task =
      base::Bind(&InProcessCommandBuffer::InitializeOnGpuThread,
                 base::Unretained(this),
                 params);

  base::WaitableEvent completion(true, false);
  bool result = false;
  QueueTask(
      base::Bind(&RunTaskWithResult<bool>, init_task, &result, &completion));
  completion.Wait();

  gpu_memory_buffer_manager_ = gpu_memory_buffer_manager;

  if (result) {
    capabilities_ = capabilities;
    capabilities_.image = capabilities_.image && gpu_memory_buffer_manager_;
  }

  return result;
}

bool InProcessCommandBuffer::InitializeOnGpuThread(
    const InitializeOnGpuThreadParams& params) {
  CheckSequencedThread();
  gpu_thread_weak_ptr_ = gpu_thread_weak_ptr_factory_.GetWeakPtr();

  DCHECK(params.size.width() >= 0 && params.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, gpu_thread_weak_ptr_));
  command_buffer->SetParseErrorCallback(base::Bind(
      &InProcessCommandBuffer::OnContextLost, gpu_thread_weak_ptr_));

  if (!command_buffer->Initialize()) {
    LOG(ERROR) << "Could not initialize command buffer.";
    DestroyOnGpuThread();
    return false;
  }

  gl_share_group_ = params.context_group
                        ? params.context_group->gl_share_group_.get()
                        : new gfx::GLShareGroup;

#if defined(OS_ANDROID)
  stream_texture_manager_.reset(new StreamTextureManagerInProcess);
#endif

  bool bind_generates_resource = false;
  decoder_.reset(gles2::GLES2Decoder::Create(
      params.context_group
          ? params.context_group->decoder_->GetContextGroup()
          : new gles2::ContextGroup(service_->mailbox_manager(),
                                    NULL,
                                    service_->shader_translator_cache(),
                                    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 (!surface_.get()) {
    if (params.is_offscreen)
      surface_ = gfx::GLSurface::CreateOffscreenGLSurface(params.size);
    else
      surface_ = gfx::GLSurface::CreateViewGLSurface(params.window);
  }

  if (!surface_.get()) {
    LOG(ERROR) << "Could not create GLSurface.";
    DestroyOnGpuThread();
    return false;
  }

  if (service_->UseVirtualizedGLContexts()) {
    context_ = gl_share_group_->GetSharedContext();
    if (!context_.get()) {
      context_ = gfx::GLContext::CreateGLContext(
          gl_share_group_.get(), surface_.get(), params.gpu_preference);
      gl_share_group_->SetSharedContext(context_.get());
    }

    context_ = new GLContextVirtual(
        gl_share_group_.get(), context_.get(), decoder_->AsWeakPtr());
    if (context_->Initialize(surface_.get(), params.gpu_preference)) {
      VLOG(1) << "Created virtual GL context.";
    } else {
      context_ = NULL;
    }
  } else {
    context_ = gfx::GLContext::CreateGLContext(
        gl_share_group_.get(), surface_.get(), params.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.gpu_memory_manager = true;
  if (!decoder_->Initialize(surface_,
                            context_,
                            params.is_offscreen,
                            params.size,
                            disallowed_features,
                            params.attribs)) {
    LOG(ERROR) << "Could not initialize decoder.";
    DestroyOnGpuThread();
    return false;
  }
  *params.capabilities = decoder_->GetCapabilities();

  if (!params.is_offscreen) {
    decoder_->SetResizeCallback(base::Bind(
        &InProcessCommandBuffer::OnResizeView, gpu_thread_weak_ptr_));
  }
  decoder_->SetWaitSyncPointCallback(
      base::Bind(&InProcessCommandBuffer::WaitSyncPointOnGpuThread,
                 base::Unretained(this)));

  image_factory_ = params.image_factory;
  params.capabilities->image = params.capabilities->image && image_factory_;

  return true;
}

void InProcessCommandBuffer::Destroy() {
  CheckSequencedThread();

  base::WaitableEvent completion(true, false);
  bool result = false;
  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() {
  CheckSequencedThread();
  gpu_thread_weak_ptr_factory_.InvalidateWeakPtrs();
  command_buffer_.reset();
  // Clean up GL resources if possible.
  bool have_context = context_.get() && context_->MakeCurrent(surface_.get());
  if (decoder_) {
    decoder_->Destroy(have_context);
    decoder_.reset();
  }
  context_ = NULL;
  surface_ = NULL;
  gl_share_group_ = NULL;
#if defined(OS_ANDROID)
  stream_texture_manager_.reset();
#endif

  return true;
}

void InProcessCommandBuffer::CheckSequencedThread() {
  DCHECK(!sequence_checker_ ||
         sequence_checker_->CalledOnValidSequencedThread());
}

void InProcessCommandBuffer::OnContextLost() {
  CheckSequencedThread();
  if (!context_lost_callback_.is_null()) {
    context_lost_callback_.Run();
    context_lost_callback_.Reset();
  }

  context_lost_ = true;
}

CommandBuffer::State InProcessCommandBuffer::GetStateFast() {
  CheckSequencedThread();
  base::AutoLock lock(state_after_last_flush_lock_);
  if (state_after_last_flush_.generation - last_state_.generation < 0x80000000U)
    last_state_ = state_after_last_flush_;
  return last_state_;
}

CommandBuffer::State InProcessCommandBuffer::GetLastState() {
  CheckSequencedThread();
  return last_state_;
}

int32 InProcessCommandBuffer::GetLastToken() {
  CheckSequencedThread();
  GetStateFast();
  return last_state_.token;
}

void InProcessCommandBuffer::FlushOnGpuThread(int32 put_offset) {
  CheckSequencedThread();
  ScopedEvent handle_flush(&flush_event_);
  base::AutoLock lock(command_buffer_lock_);
  command_buffer_->Flush(put_offset);
  {
    // Update state before signaling the flush event.
    base::AutoLock lock(state_after_last_flush_lock_);
    state_after_last_flush_ = command_buffer_->GetLastState();
  }
  DCHECK((!error::IsError(state_after_last_flush_.error) && !context_lost_) ||
         (error::IsError(state_after_last_flush_.error) && context_lost_));

  // If we've processed all pending commands but still have pending queries,
  // pump idle work until the query is passed.
  if (put_offset == state_after_last_flush_.get_offset &&
      gpu_scheduler_->HasMoreWork()) {
    ScheduleIdleWorkOnGpuThread();
  }
}

void InProcessCommandBuffer::PerformIdleWork() {
  CheckSequencedThread();
  idle_work_pending_ = false;
  base::AutoLock lock(command_buffer_lock_);
  if (MakeCurrent() && gpu_scheduler_->HasMoreWork()) {
    gpu_scheduler_->PerformIdleWork();
    ScheduleIdleWorkOnGpuThread();
  }
}

void InProcessCommandBuffer::ScheduleIdleWorkOnGpuThread() {
  CheckSequencedThread();
  if (idle_work_pending_)
    return;
  idle_work_pending_ = true;
  service_->ScheduleIdleWork(
      base::Bind(&InProcessCommandBuffer::PerformIdleWork,
                 gpu_thread_weak_ptr_));
}

void InProcessCommandBuffer::Flush(int32 put_offset) {
  CheckSequencedThread();
  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,
                                  gpu_thread_weak_ptr_,
                                  put_offset);
  QueueTask(task);
}

void InProcessCommandBuffer::WaitForTokenInRange(int32 start, int32 end) {
  CheckSequencedThread();
  while (!InRange(start, end, GetLastToken()) &&
         last_state_.error == gpu::error::kNoError)
    flush_event_.Wait();
}

void InProcessCommandBuffer::WaitForGetOffsetInRange(int32 start, int32 end) {
  CheckSequencedThread();

  GetStateFast();
  while (!InRange(start, end, last_state_.get_offset) &&
         last_state_.error == gpu::error::kNoError) {
    flush_event_.Wait();
    GetStateFast();
  }
}

void InProcessCommandBuffer::SetGetBuffer(int32 shm_id) {
  CheckSequencedThread();
  if (last_state_.error != gpu::error::kNoError)
    return;

  {
    base::AutoLock lock(command_buffer_lock_);
    command_buffer_->SetGetBuffer(shm_id);
    last_put_offset_ = 0;
  }
  {
    base::AutoLock lock(state_after_last_flush_lock_);
    state_after_last_flush_ = command_buffer_->GetLastState();
  }
}

scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(size_t size,
                                                                   int32* id) {
  CheckSequencedThread();
  base::AutoLock lock(command_buffer_lock_);
  return command_buffer_->CreateTransferBuffer(size, id);
}

void InProcessCommandBuffer::DestroyTransferBuffer(int32 id) {
  CheckSequencedThread();
  base::Closure task =
      base::Bind(&InProcessCommandBuffer::DestroyTransferBufferOnGpuThread,
                 base::Unretained(this),
                 id);

  QueueTask(task);
}

void InProcessCommandBuffer::DestroyTransferBufferOnGpuThread(int32 id) {
  base::AutoLock lock(command_buffer_lock_);
  command_buffer_->DestroyTransferBuffer(id);
}

gpu::Capabilities InProcessCommandBuffer::GetCapabilities() {
  return capabilities_;
}

int32 InProcessCommandBuffer::CreateImage(ClientBuffer buffer,
                                          size_t width,
                                          size_t height,
                                          unsigned internalformat) {
  CheckSequencedThread();

  DCHECK(gpu_memory_buffer_manager_);
  gfx::GpuMemoryBuffer* gpu_memory_buffer =
      gpu_memory_buffer_manager_->GpuMemoryBufferFromClientBuffer(buffer);
  DCHECK(gpu_memory_buffer);

  int32 new_id = next_image_id_.GetNext();

  DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
      internalformat, gpu_memory_buffer->GetFormat()));
  QueueTask(base::Bind(&InProcessCommandBuffer::CreateImageOnGpuThread,
                       base::Unretained(this),
                       new_id,
                       gpu_memory_buffer->GetHandle(),
                       gfx::Size(width, height),
                       gpu_memory_buffer->GetFormat(),
                       internalformat));
  return new_id;
}

void InProcessCommandBuffer::CreateImageOnGpuThread(
    int32 id,
    const gfx::GpuMemoryBufferHandle& handle,
    const gfx::Size& size,
    gfx::GpuMemoryBuffer::Format format,
    uint32 internalformat) {
  if (!decoder_)
    return;

  gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
  DCHECK(image_manager);
  if (image_manager->LookupImage(id)) {
    LOG(ERROR) << "Image already exists with same ID.";
    return;
  }

  // Note: this assumes that client ID is always 0.
  const int kClientId = 0;

  DCHECK(image_factory_);
  scoped_refptr<gfx::GLImage> image =
      image_factory_->CreateImageForGpuMemoryBuffer(
          handle, size, format, internalformat, kClientId);
  if (!image.get())
    return;

  image_manager->AddImage(image.get(), id);
}

void InProcessCommandBuffer::DestroyImage(int32 id) {
  CheckSequencedThread();

  QueueTask(base::Bind(&InProcessCommandBuffer::DestroyImageOnGpuThread,
                       base::Unretained(this),
                       id));
}

void InProcessCommandBuffer::DestroyImageOnGpuThread(int32 id) {
  if (!decoder_)
    return;

  gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
  DCHECK(image_manager);
  if (!image_manager->LookupImage(id)) {
    LOG(ERROR) << "Image with ID doesn't exist.";
    return;
  }

  image_manager->RemoveImage(id);
}

int32 InProcessCommandBuffer::CreateGpuMemoryBufferImage(
    size_t width,
    size_t height,
    unsigned internalformat,
    unsigned usage) {
  CheckSequencedThread();

  DCHECK(gpu_memory_buffer_manager_);
  scoped_ptr<gfx::GpuMemoryBuffer> buffer(
      gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
          gfx::Size(width, height),
          gpu::ImageFactory::ImageFormatToGpuMemoryBufferFormat(internalformat),
          gpu::ImageFactory::ImageUsageToGpuMemoryBufferUsage(usage)));
  if (!buffer)
    return -1;

  return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
}

uint32 InProcessCommandBuffer::InsertSyncPoint() {
  uint32 sync_point = g_sync_point_manager.Get().GenerateSyncPoint();
  QueueTask(base::Bind(&InProcessCommandBuffer::RetireSyncPointOnGpuThread,
                       base::Unretained(this),
                       sync_point));
  return sync_point;
}

uint32 InProcessCommandBuffer::InsertFutureSyncPoint() {
  return g_sync_point_manager.Get().GenerateSyncPoint();
}

void InProcessCommandBuffer::RetireSyncPoint(uint32 sync_point) {
  QueueTask(base::Bind(&InProcessCommandBuffer::RetireSyncPointOnGpuThread,
                       base::Unretained(this),
                       sync_point));
}

void InProcessCommandBuffer::RetireSyncPointOnGpuThread(uint32 sync_point) {
  gles2::MailboxManager* mailbox_manager =
      decoder_->GetContextGroup()->mailbox_manager();
  if (mailbox_manager->UsesSync()) {
    bool make_current_success = false;
    {
      base::AutoLock lock(command_buffer_lock_);
      make_current_success = MakeCurrent();
    }
    if (make_current_success)
      mailbox_manager->PushTextureUpdates(sync_point);
  }
  g_sync_point_manager.Get().RetireSyncPoint(sync_point);
}

void InProcessCommandBuffer::SignalSyncPoint(unsigned sync_point,
                                             const base::Closure& callback) {
  CheckSequencedThread();
  QueueTask(base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread,
                       base::Unretained(this),
                       sync_point,
                       WrapCallback(callback)));
}

bool InProcessCommandBuffer::WaitSyncPointOnGpuThread(unsigned sync_point) {
  g_sync_point_manager.Get().WaitSyncPoint(sync_point);
  gles2::MailboxManager* mailbox_manager =
      decoder_->GetContextGroup()->mailbox_manager();
  mailbox_manager->PullTextureUpdates(sync_point);
  return true;
}

void InProcessCommandBuffer::SignalSyncPointOnGpuThread(
    unsigned sync_point,
    const base::Closure& callback) {
  if (g_sync_point_manager.Get().IsSyncPointPassed(sync_point)) {
    callback.Run();
  } else {
    service_->ScheduleIdleWork(
        base::Bind(&InProcessCommandBuffer::SignalSyncPointOnGpuThread,
                   gpu_thread_weak_ptr_,
                   sync_point,
                   callback));
  }
}

void InProcessCommandBuffer::SignalQuery(unsigned query_id,
                                         const base::Closure& callback) {
  CheckSequencedThread();
  QueueTask(base::Bind(&InProcessCommandBuffer::SignalQueryOnGpuThread,
                       base::Unretained(this),
                       query_id,
                       WrapCallback(callback)));
}

void InProcessCommandBuffer::SignalQueryOnGpuThread(
    unsigned query_id,
    const base::Closure& callback) {
  gles2::QueryManager* query_manager_ = decoder_->GetQueryManager();
  DCHECK(query_manager_);

  gles2::QueryManager::Query* query = query_manager_->GetQuery(query_id);
  if (!query)
    callback.Run();
  else
    query->AddCallback(callback);
}

void InProcessCommandBuffer::SetSurfaceVisible(bool visible) {}

uint32 InProcessCommandBuffer::CreateStreamTexture(uint32 texture_id) {
  base::WaitableEvent completion(true, false);
  uint32 stream_id = 0;
  base::Callback<uint32(void)> task =
      base::Bind(&InProcessCommandBuffer::CreateStreamTextureOnGpuThread,
                 base::Unretained(this),
                 texture_id);
  QueueTask(
      base::Bind(&RunTaskWithResult<uint32>, task, &stream_id, &completion));
  completion.Wait();
  return stream_id;
}

uint32 InProcessCommandBuffer::CreateStreamTextureOnGpuThread(
    uint32 client_texture_id) {
#if defined(OS_ANDROID)
  return stream_texture_manager_->CreateStreamTexture(
      client_texture_id, decoder_->GetContextGroup()->texture_manager());
#else
  return 0;
#endif
}

gpu::error::Error InProcessCommandBuffer::GetLastError() {
  CheckSequencedThread();
  return last_state_.error;
}

bool InProcessCommandBuffer::Initialize() {
  NOTREACHED();
  return false;
}

namespace {

void PostCallback(const scoped_refptr<base::MessageLoopProxy>& loop,
                         const base::Closure& callback) {
  // The loop.get() check is to support using InProcessCommandBuffer on a thread
  // without a message loop.
  if (loop.get() && !loop->BelongsToCurrentThread()) {
    loop->PostTask(FROM_HERE, callback);
  } else {
    callback.Run();
  }
}

void RunOnTargetThread(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(&RunOnTargetThread, base::Passed(&scoped_callback));
  base::Closure wrapped_callback =
      base::Bind(&PostCallback, base::MessageLoopProxy::current(),
                 callback_on_client_thread);
  return wrapped_callback;
}

#if defined(OS_ANDROID)
scoped_refptr<gfx::SurfaceTexture>
InProcessCommandBuffer::GetSurfaceTexture(uint32 stream_id) {
  DCHECK(stream_texture_manager_);
  return stream_texture_manager_->GetSurfaceTexture(stream_id);
}
#endif

}  // namespace gpu
