// 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 "components/mus/gles2/command_buffer_driver.h"

#include <stddef.h>
#include <utility>

#include "base/bind.h"
#include "base/memory/shared_memory.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/mus/gles2/gl_surface_adapter.h"
#include "components/mus/gles2/gpu_memory_tracker.h"
#include "components/mus/gles2/gpu_state.h"
#include "components/mus/gles2/mojo_buffer_backing.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/command_executor.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/query_manager.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/transfer_buffer_manager.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/platform_handle/platform_handle_functions.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/vsync_provider.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_shared_memory.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"

#if defined(USE_OZONE)
#include "ui/gl/gl_image_ozone_native_pixmap.h"
#endif

namespace mus {

namespace {

// The first time polling a fence, delay some extra time to allow other
// stubs to process some work, or else the timing of the fences could
// allow a pattern of alternating fast and slow frames to occur.
const int64_t kHandleMoreWorkPeriodMs = 2;
const int64_t kHandleMoreWorkPeriodBusyMs = 1;

// Prevents idle work from being starved.
const int64_t kMaxTimeSinceIdleMs = 10;

}  // namespace

CommandBufferDriver::Client::~Client() {}

CommandBufferDriver::CommandBufferDriver(
    gpu::CommandBufferNamespace command_buffer_namespace,
    gpu::CommandBufferId command_buffer_id,
    gfx::AcceleratedWidget widget,
    scoped_refptr<GpuState> gpu_state)
    : command_buffer_namespace_(command_buffer_namespace),
      command_buffer_id_(command_buffer_id),
      widget_(widget),
      client_(nullptr),
      gpu_state_(gpu_state),
      previous_processed_num_(0),
      weak_factory_(this) {
  DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(),
            gpu_state_->command_buffer_task_runner()->task_runner());
}

CommandBufferDriver::~CommandBufferDriver() {
  DCHECK(CalledOnValidThread());
  DestroyDecoder();
}

bool CommandBufferDriver::Initialize(
    mojo::ScopedSharedBufferHandle shared_state,
    mojo::Array<int32_t> attribs) {
  DCHECK(CalledOnValidThread());
  gpu::gles2::ContextCreationAttribHelper attrib_helper;
  if (!attrib_helper.Parse(attribs.storage()))
    return false;

  const bool offscreen = widget_ == gfx::kNullAcceleratedWidget;
  if (offscreen) {
    surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size(0, 0));
  } else {
#if defined(USE_OZONE)
    scoped_refptr<gfx::GLSurface> underlying_surface =
        gl::init::CreateSurfacelessViewGLSurface(widget_);
    if (!underlying_surface)
      underlying_surface = gl::init::CreateViewGLSurface(widget_);
#else
    scoped_refptr<gfx::GLSurface> underlying_surface =
        gl::init::CreateViewGLSurface(widget_);
#endif
    scoped_refptr<GLSurfaceAdapterMus> surface_adapter =
        new GLSurfaceAdapterMus(underlying_surface);
    surface_adapter->SetGpuCompletedSwapBuffersCallback(
        base::Bind(&CommandBufferDriver::OnGpuCompletedSwapBuffers,
                   weak_factory_.GetWeakPtr()));
    surface_ = surface_adapter;

    gfx::VSyncProvider* vsync_provider =
        surface_ ? surface_->GetVSyncProvider() : nullptr;
    if (vsync_provider) {
      vsync_provider->GetVSyncParameters(
          base::Bind(&CommandBufferDriver::OnUpdateVSyncParameters,
                     weak_factory_.GetWeakPtr()));
    }
  }

  if (!surface_.get())
    return false;

  // TODO(piman): virtual contexts, gpu preference.
  context_ = gl::init::CreateGLContext(
      gpu_state_->share_group(), surface_.get(), gfx::PreferIntegratedGpu);
  if (!context_.get())
    return false;

  if (!context_->MakeCurrent(surface_.get()))
    return false;

  // TODO(piman): ShaderTranslatorCache is currently per-ContextGroup but
  // only needs to be per-thread.
  const bool bind_generates_resource = attrib_helper.bind_generates_resource;
  scoped_refptr<gpu::gles2::FeatureInfo> feature_info =
      new gpu::gles2::FeatureInfo(gpu_state_->gpu_driver_bug_workarounds());
  scoped_refptr<gpu::gles2::ContextGroup> context_group =
      new gpu::gles2::ContextGroup(
          gpu_state_->gpu_preferences(), gpu_state_->mailbox_manager(),
          new GpuMemoryTracker,
          new gpu::gles2::ShaderTranslatorCache(gpu_state_->gpu_preferences()),
          new gpu::gles2::FramebufferCompletenessCache, feature_info,
          bind_generates_resource);

  command_buffer_.reset(
      new gpu::CommandBufferService(context_group->transfer_buffer_manager()));

  decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group.get()));
  executor_.reset(new gpu::CommandExecutor(command_buffer_.get(),
                                           decoder_.get(), decoder_.get()));
  sync_point_order_data_ = gpu::SyncPointOrderData::Create();
  sync_point_client_ = gpu_state_->sync_point_manager()->CreateSyncPointClient(
      sync_point_order_data_, GetNamespaceID(), command_buffer_id_);
  decoder_->set_engine(executor_.get());
  decoder_->SetFenceSyncReleaseCallback(base::Bind(
      &CommandBufferDriver::OnFenceSyncRelease, base::Unretained(this)));
  decoder_->SetWaitFenceSyncCallback(base::Bind(
      &CommandBufferDriver::OnWaitFenceSync, base::Unretained(this)));

  gpu::gles2::DisallowedFeatures disallowed_features;

  std::vector<int32_t> attrib_vector;
  attrib_helper.Serialize(&attrib_vector);
  if (!decoder_->Initialize(surface_, context_, offscreen, gfx::Size(1, 1),
                            disallowed_features, attrib_vector))
    return false;

  command_buffer_->SetPutOffsetChangeCallback(base::Bind(
      &gpu::CommandExecutor::PutChanged, base::Unretained(executor_.get())));
  command_buffer_->SetGetBufferChangeCallback(base::Bind(
      &gpu::CommandExecutor::SetGetBuffer, base::Unretained(executor_.get())));
  command_buffer_->SetParseErrorCallback(
      base::Bind(&CommandBufferDriver::OnParseError, base::Unretained(this)));

  // TODO(piman): other callbacks

  const size_t kSize = sizeof(gpu::CommandBufferSharedState);
  std::unique_ptr<gpu::BufferBacking> backing(
      MojoBufferBacking::Create(std::move(shared_state), kSize));
  if (!backing)
    return false;

  command_buffer_->SetSharedStateBuffer(std::move(backing));
  gpu_state_->driver_manager()->AddDriver(this);
  return true;
}

void CommandBufferDriver::SetGetBuffer(int32_t buffer) {
  DCHECK(CalledOnValidThread());
  command_buffer_->SetGetBuffer(buffer);
}

void CommandBufferDriver::Flush(int32_t put_offset) {
  DCHECK(CalledOnValidThread());
  if (!MakeCurrent())
    return;

  command_buffer_->Flush(put_offset);
  ProcessPendingAndIdleWork();
}

void CommandBufferDriver::RegisterTransferBuffer(
    int32_t id,
    mojo::ScopedSharedBufferHandle transfer_buffer,
    uint32_t size) {
  DCHECK(CalledOnValidThread());
  // Take ownership of the memory and map it into this process.
  // This validates the size.
  std::unique_ptr<gpu::BufferBacking> backing(
      MojoBufferBacking::Create(std::move(transfer_buffer), size));
  if (!backing) {
    DVLOG(0) << "Failed to map shared memory.";
    return;
  }
  command_buffer_->RegisterTransferBuffer(id, std::move(backing));
}

void CommandBufferDriver::DestroyTransferBuffer(int32_t id) {
  DCHECK(CalledOnValidThread());
  command_buffer_->DestroyTransferBuffer(id);
}

void CommandBufferDriver::CreateImage(int32_t id,
                                      mojo::ScopedHandle memory_handle,
                                      int32_t type,
                                      mojo::SizePtr size,
                                      int32_t format,
                                      int32_t internal_format) {
  DCHECK(CalledOnValidThread());
  if (!MakeCurrent())
    return;

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

  gfx::BufferFormat gpu_format = static_cast<gfx::BufferFormat>(format);
  if (!gpu::IsGpuMemoryBufferFormatSupported(gpu_format,
                                             decoder_->GetCapabilities())) {
    LOG(ERROR) << "Format is not supported.";
    return;
  }

  gfx::Size gfx_size = size.To<gfx::Size>();
  if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(gfx_size, gpu_format)) {
    LOG(ERROR) << "Invalid image size for format.";
    return;
  }

  if (!gpu::IsImageFormatCompatibleWithGpuMemoryBufferFormat(internal_format,
                                                             gpu_format)) {
    LOG(ERROR) << "Incompatible image format.";
    return;
  }

  if (type != gfx::SHARED_MEMORY_BUFFER) {
    NOTIMPLEMENTED();
    return;
  }

  MojoPlatformHandle platform_handle;
  MojoResult extract_result = MojoExtractPlatformHandle(
      memory_handle.release().value(), &platform_handle);
  if (extract_result != MOJO_RESULT_OK) {
    NOTREACHED();
    return;
  }

#if defined(OS_WIN)
  base::SharedMemoryHandle handle(platform_handle, base::GetCurrentProcId());
#else
  base::FileDescriptor handle(platform_handle, false);
#endif

  scoped_refptr<gl::GLImageSharedMemory> image =
      new gl::GLImageSharedMemory(gfx_size, internal_format);
  // TODO(jam): also need a mojo enum for this enum
  if (!image->Initialize(
          handle, gfx::GpuMemoryBufferId(id), gpu_format, 0,
          gfx::RowSizeForBufferFormat(gfx_size.width(), gpu_format, 0))) {
    NOTREACHED();
    return;
  }

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

// TODO(rjkroege): It is conceivable that this code belongs in
// ozone_gpu_memory_buffer.cc
void CommandBufferDriver::CreateImageNativeOzone(int32_t id,
                                                 int32_t type,
                                                 gfx::Size size,
                                                 gfx::BufferFormat format,
                                                 uint32_t internal_format,
                                                 ui::NativePixmap* pixmap) {
#if defined(USE_OZONE)
  gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
  if (image_manager->LookupImage(id)) {
    LOG(ERROR) << "Image already exists with same ID.";
    return;
  }

  scoped_refptr<gfx::GLImageOzoneNativePixmap> image =
      new gfx::GLImageOzoneNativePixmap(size, internal_format);
  if (!image->Initialize(pixmap, format)) {
    NOTREACHED();
    return;
  }

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

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

bool CommandBufferDriver::IsScheduled() const {
  DCHECK(CalledOnValidThread());
  DCHECK(executor_);
  return executor_->scheduled();
}

bool CommandBufferDriver::HasUnprocessedCommands() const {
  DCHECK(CalledOnValidThread());
  if (command_buffer_) {
    gpu::CommandBuffer::State state = GetLastState();
    return command_buffer_->GetPutOffset() != state.get_offset &&
        !gpu::error::IsError(state.error);
  }
  return false;
}

gpu::Capabilities CommandBufferDriver::GetCapabilities() const {
  DCHECK(CalledOnValidThread());
  return decoder_->GetCapabilities();
}

gpu::CommandBuffer::State CommandBufferDriver::GetLastState() const {
  DCHECK(CalledOnValidThread());
  return command_buffer_->GetLastState();
}

uint32_t CommandBufferDriver::GetUnprocessedOrderNum() const {
  DCHECK(CalledOnValidThread());
  return sync_point_order_data_->unprocessed_order_num();
}

uint32_t CommandBufferDriver::GetProcessedOrderNum() const {
  DCHECK(CalledOnValidThread());
  return sync_point_order_data_->processed_order_num();
}

bool CommandBufferDriver::MakeCurrent() {
  DCHECK(CalledOnValidThread());
  if (!decoder_)
    return false;
  if (decoder_->MakeCurrent())
    return true;
  DLOG(ERROR) << "Context lost because MakeCurrent failed.";
  gpu::error::ContextLostReason reason =
      static_cast<gpu::error::ContextLostReason>(
          decoder_->GetContextLostReason());
  command_buffer_->SetContextLostReason(reason);
  command_buffer_->SetParseError(gpu::error::kLostContext);
  OnContextLost(reason);
  return false;
}

void CommandBufferDriver::ProcessPendingAndIdleWork() {
  DCHECK(CalledOnValidThread());
  executor_->ProcessPendingQueries();
  ScheduleDelayedWork(
      base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodMs));
}

void CommandBufferDriver::ScheduleDelayedWork(base::TimeDelta delay) {
  DCHECK(CalledOnValidThread());
  const bool has_more_work =
      executor_->HasPendingQueries() || executor_->HasMoreIdleWork();
  if (!has_more_work) {
    last_idle_time_ = base::TimeTicks();
    return;
  }

  const base::TimeTicks current_time = base::TimeTicks::Now();
  // |process_delayed_work_time_| is set if processing of delayed work is
  // already scheduled. Just update the time if already scheduled.
  if (!process_delayed_work_time_.is_null()) {
    process_delayed_work_time_ = current_time + delay;
    return;
  }

  // Idle when no messages are processed between now and when PollWork is
  // called.
  previous_processed_num_ =
      gpu_state_->driver_manager()->GetProcessedOrderNum();

  if (last_idle_time_.is_null())
    last_idle_time_ = current_time;

    // scheduled() returns true after passing all unschedule fences and this is
    // when we can start performing idle work. Idle work is done synchronously
    // so we can set delay to 0 and instead poll for more work at the rate idle
    // work is performed. This also ensures that idle work is done as
    // efficiently as possible without any unnecessary delays.
  if (executor_->scheduled() && executor_->HasMoreIdleWork())
    delay = base::TimeDelta();

  process_delayed_work_time_ = current_time + delay;
  gpu_state_->command_buffer_task_runner()->task_runner()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&CommandBufferDriver::PollWork, weak_factory_.GetWeakPtr()),
      delay);
}

void CommandBufferDriver::PollWork() {
  DCHECK(CalledOnValidThread());
  // Post another delayed task if we have not yet reached the time at which
  // we should process delayed work.
  base::TimeTicks current_time = base::TimeTicks::Now();
  DCHECK(!process_delayed_work_time_.is_null());
  if (process_delayed_work_time_ > current_time) {
    gpu_state_->command_buffer_task_runner()->task_runner()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&CommandBufferDriver::PollWork, weak_factory_.GetWeakPtr()),
      process_delayed_work_time_ - current_time);
    return;
  }
  process_delayed_work_time_ = base::TimeTicks();
  PerformWork();
}

void CommandBufferDriver::PerformWork() {
  DCHECK(CalledOnValidThread());
  if (!MakeCurrent())
    return;

  if (executor_) {
    const uint32_t current_unprocessed_num =
        gpu_state_->driver_manager()->GetUnprocessedOrderNum();
    // We're idle when no messages were processed or scheduled.
    bool is_idle = (previous_processed_num_ == current_unprocessed_num);
    if (!is_idle && !last_idle_time_.is_null()) {
      base::TimeDelta time_since_idle =
          base::TimeTicks::Now() - last_idle_time_;
      base::TimeDelta max_time_since_idle =
          base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs);
      // Force idle when it's been too long since last time we were idle.
      if (time_since_idle > max_time_since_idle)
        is_idle = true;
    }

    if (is_idle) {
      last_idle_time_ = base::TimeTicks::Now();
      executor_->PerformIdleWork();
    }
    executor_->ProcessPendingQueries();
  }

  ScheduleDelayedWork(
      base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodBusyMs));
}

void CommandBufferDriver::DestroyDecoder() {
  DCHECK(CalledOnValidThread());
  if (decoder_) {
    gpu_state_->driver_manager()->RemoveDriver(this);
    bool have_context = decoder_->MakeCurrent();
    decoder_->Destroy(have_context);
    decoder_.reset();
  }
}

void CommandBufferDriver::OnUpdateVSyncParameters(
    const base::TimeTicks timebase,
    const base::TimeDelta interval) {
  DCHECK(CalledOnValidThread());
  if (client_) {
    client_->UpdateVSyncParameters(timebase.ToInternalValue(),
                                   interval.ToInternalValue());
  }
}

void CommandBufferDriver::OnFenceSyncRelease(uint64_t release) {
  DCHECK(CalledOnValidThread());
  if (!sync_point_client_->client_state()->IsFenceSyncReleased(release))
    sync_point_client_->ReleaseFenceSync(release);
}

bool CommandBufferDriver::OnWaitFenceSync(
    gpu::CommandBufferNamespace namespace_id,
    gpu::CommandBufferId command_buffer_id,
    uint64_t release) {
  DCHECK(CalledOnValidThread());
  DCHECK(IsScheduled());
  gpu::SyncPointManager* sync_point_manager = gpu_state_->sync_point_manager();
  DCHECK(sync_point_manager);

  scoped_refptr<gpu::SyncPointClientState> release_state =
      sync_point_manager->GetSyncPointClientState(namespace_id,
                                                  command_buffer_id);

  if (!release_state)
    return true;

  executor_->SetScheduled(false);
  sync_point_client_->Wait(release_state.get(), release,
                           base::Bind(&gpu::CommandExecutor::SetScheduled,
                                      executor_->AsWeakPtr(), true));
  return executor_->scheduled();
}

void CommandBufferDriver::OnParseError() {
  DCHECK(CalledOnValidThread());
  gpu::CommandBuffer::State state = GetLastState();
  OnContextLost(state.context_lost_reason);
}

void CommandBufferDriver::OnContextLost(uint32_t reason) {
  DCHECK(CalledOnValidThread());
  if (client_)
    client_->DidLoseContext(reason);
}

void CommandBufferDriver::SignalQuery(uint32_t query_id,
                                      const base::Closure& callback) {
  DCHECK(CalledOnValidThread());

  gpu::gles2::QueryManager* query_manager = decoder_->GetQueryManager();
  gpu::gles2::QueryManager::Query* query = query_manager->GetQuery(query_id);
  if (query)
    query->AddCallback(callback);
  else
    callback.Run();
}

void CommandBufferDriver::OnGpuCompletedSwapBuffers(gfx::SwapResult result) {
  DCHECK(CalledOnValidThread());
  if (client_) {
    client_->OnGpuCompletedSwapBuffers(result);
  }
}

}  // namespace mus
