// 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 "ppapi/proxy/ppapi_command_buffer_proxy.h"

#include <utility>

#include "base/numerics/safe_conversions.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/api_id.h"
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/proxy_lock.h"

namespace ppapi {
namespace proxy {

PpapiCommandBufferProxy::PpapiCommandBufferProxy(
    const ppapi::HostResource& resource,
    InstanceData::FlushInfo* flush_info,
    LockedSender* sender,
    const gpu::Capabilities& capabilities,
    SerializedHandle shared_state,
    gpu::CommandBufferId command_buffer_id)
    : command_buffer_id_(command_buffer_id),
      capabilities_(capabilities),
      resource_(resource),
      flush_info_(flush_info),
      sender_(sender),
      next_fence_sync_release_(1),
      pending_fence_sync_release_(0),
      flushed_fence_sync_release_(0),
      validated_fence_sync_release_(0) {
  base::UnsafeSharedMemoryRegion shmem_region =
      base::UnsafeSharedMemoryRegion::Deserialize(
          shared_state.TakeSharedMemoryRegion());
  shared_state_mapping_ = shmem_region.Map();
}

PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
  // gpu::Buffers are no longer referenced, allowing shared memory objects to be
  // deleted, closing the handle in this process.
}

gpu::CommandBuffer::State PpapiCommandBufferProxy::GetLastState() {
  ppapi::ProxyLock::AssertAcquiredDebugOnly();
  TryUpdateState();
  return last_state_;
}

void PpapiCommandBufferProxy::Flush(int32_t put_offset) {
  if (last_state_.error != gpu::error::kNoError)
    return;

  OrderingBarrier(put_offset);
  FlushInternal();
}

void PpapiCommandBufferProxy::OrderingBarrier(int32_t put_offset) {
  if (last_state_.error != gpu::error::kNoError)
    return;

  if (flush_info_->flush_pending && flush_info_->resource != resource_) {
    FlushInternal();
  }

  flush_info_->flush_pending = true;
  flush_info_->resource = resource_;
  flush_info_->put_offset = put_offset;
  pending_fence_sync_release_ = next_fence_sync_release_ - 1;
}

gpu::CommandBuffer::State PpapiCommandBufferProxy::WaitForTokenInRange(
    int32_t start,
    int32_t end) {
  TryUpdateState();
  if (!InRange(start, end, last_state_.token) &&
      last_state_.error == gpu::error::kNoError) {
    bool success = false;
    gpu::CommandBuffer::State state;
    if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForTokenInRange(
            ppapi::API_ID_PPB_GRAPHICS_3D, resource_, start, end, &state,
            &success)))
      UpdateState(state, success);
  }
  DCHECK(InRange(start, end, last_state_.token) ||
         last_state_.error != gpu::error::kNoError);
  return last_state_;
}

gpu::CommandBuffer::State PpapiCommandBufferProxy::WaitForGetOffsetInRange(
    uint32_t set_get_buffer_count,
    int32_t start,
    int32_t end) {
  TryUpdateState();
  if (((set_get_buffer_count != last_state_.set_get_buffer_count) ||
       !InRange(start, end, last_state_.get_offset)) &&
      last_state_.error == gpu::error::kNoError) {
    bool success = false;
    gpu::CommandBuffer::State state;
    if (Send(new PpapiHostMsg_PPBGraphics3D_WaitForGetOffsetInRange(
            ppapi::API_ID_PPB_GRAPHICS_3D, resource_, set_get_buffer_count,
            start, end, &state, &success)))
      UpdateState(state, success);
  }
  DCHECK(((set_get_buffer_count == last_state_.set_get_buffer_count) &&
          InRange(start, end, last_state_.get_offset)) ||
         last_state_.error != gpu::error::kNoError);
  return last_state_;
}

void PpapiCommandBufferProxy::SetGetBuffer(int32_t transfer_buffer_id) {
  if (last_state_.error == gpu::error::kNoError) {
    Send(new PpapiHostMsg_PPBGraphics3D_SetGetBuffer(
        ppapi::API_ID_PPB_GRAPHICS_3D, resource_, transfer_buffer_id));
  }
}

scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
    uint32_t size,
    int32_t* id) {
  *id = -1;

  if (last_state_.error != gpu::error::kNoError)
    return NULL;

  // Assuming we are in the renderer process, the service is responsible for
  // duplicating the handle. This might not be true for NaCl.
  ppapi::proxy::SerializedHandle handle(
      ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION);
  if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
          ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id, &handle))) {
    if (last_state_.error == gpu::error::kNoError)
      last_state_.error = gpu::error::kLostContext;
    return NULL;
  }

  if (*id <= 0 || !handle.is_shmem_region()) {
    if (last_state_.error == gpu::error::kNoError)
      last_state_.error = gpu::error::kOutOfBounds;
    return NULL;
  }

  base::UnsafeSharedMemoryRegion shared_memory_region =
      base::UnsafeSharedMemoryRegion::Deserialize(
          handle.TakeSharedMemoryRegion());

  base::WritableSharedMemoryMapping shared_memory_mapping =
      shared_memory_region.Map();
  if (!shared_memory_mapping.IsValid() ||
      (shared_memory_mapping.size() > UINT32_MAX)) {
    if (last_state_.error == gpu::error::kNoError)
      last_state_.error = gpu::error::kOutOfBounds;
    *id = -1;
    return NULL;
  }

  return gpu::MakeBufferFromSharedMemory(std::move(shared_memory_region),
                                         std::move(shared_memory_mapping));
}

void PpapiCommandBufferProxy::DestroyTransferBuffer(int32_t id) {
  if (last_state_.error != gpu::error::kNoError)
    return;

  if (flush_info_->flush_pending)
    FlushInternal();

  Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
      ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
}

void PpapiCommandBufferProxy::SetLock(base::Lock*) {
  NOTREACHED();
}

void PpapiCommandBufferProxy::EnsureWorkVisible() {
  if (last_state_.error != gpu::error::kNoError)
    return;

  if (flush_info_->flush_pending)
    FlushInternal();
  DCHECK_GE(flushed_fence_sync_release_, validated_fence_sync_release_);
  Send(new PpapiHostMsg_PPBGraphics3D_EnsureWorkVisible(
      ppapi::API_ID_PPB_GRAPHICS_3D, resource_));
  validated_fence_sync_release_ = flushed_fence_sync_release_;
}

gpu::CommandBufferNamespace PpapiCommandBufferProxy::GetNamespaceID() const {
  return gpu::CommandBufferNamespace::GPU_IO;
}

gpu::CommandBufferId PpapiCommandBufferProxy::GetCommandBufferID() const {
  return command_buffer_id_;
}

void PpapiCommandBufferProxy::FlushPendingWork() {
  if (last_state_.error != gpu::error::kNoError)
    return;
  if (flush_info_->flush_pending)
    FlushInternal();
}

uint64_t PpapiCommandBufferProxy::GenerateFenceSyncRelease() {
  return next_fence_sync_release_++;
}

bool PpapiCommandBufferProxy::IsFenceSyncReleased(uint64_t release) {
  NOTREACHED();
  return false;
}

void PpapiCommandBufferProxy::SignalSyncToken(const gpu::SyncToken& sync_token,
                                              base::OnceClosure callback) {
  NOTREACHED();
}

// Pepper plugin does not expose or call WaitSyncTokenCHROMIUM.
void PpapiCommandBufferProxy::WaitSyncToken(const gpu::SyncToken& sync_token) {
  NOTREACHED();
}

bool PpapiCommandBufferProxy::CanWaitUnverifiedSyncToken(
    const gpu::SyncToken& sync_token) {
  NOTREACHED();
  return false;
}

void PpapiCommandBufferProxy::SignalQuery(uint32_t query,
                                          base::OnceClosure callback) {
  NOTREACHED();
}

void PpapiCommandBufferProxy::CreateGpuFence(uint32_t gpu_fence_id,
                                             ClientGpuFence source) {
  NOTREACHED();
}

void PpapiCommandBufferProxy::GetGpuFence(
    uint32_t gpu_fence_id,
    base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
  NOTREACHED();
}

void PpapiCommandBufferProxy::SetGpuControlClient(gpu::GpuControlClient*) {
  // TODO(piman): The lost context callback skips past here and goes directly
  // to the plugin instance. Make it more uniform and use the GpuControlClient.
}

const gpu::Capabilities& PpapiCommandBufferProxy::GetCapabilities() const {
  return capabilities_;
}

int32_t PpapiCommandBufferProxy::CreateImage(ClientBuffer buffer,
                                             size_t width,
                                             size_t height) {
  NOTREACHED();
  return -1;
}

void PpapiCommandBufferProxy::DestroyImage(int32_t id) {
  NOTREACHED();
}

bool PpapiCommandBufferProxy::Send(IPC::Message* msg) {
  DCHECK(last_state_.error == gpu::error::kNoError);

  // We need to hold the Pepper proxy lock for sync IPC, because the GPU command
  // buffer may use a sync IPC with another lock held which could lead to lock
  // and deadlock if we dropped the proxy lock here.
  // http://crbug.com/418651
  if (sender_->SendAndStayLocked(msg))
    return true;

  last_state_.error = gpu::error::kLostContext;
  return false;
}

void PpapiCommandBufferProxy::UpdateState(
    const gpu::CommandBuffer::State& state,
    bool success) {
  // Handle wraparound. It works as long as we don't have more than 2B state
  // updates in flight across which reordering occurs.
  if (success) {
    if (state.generation - last_state_.generation < 0x80000000U) {
      last_state_ = state;
    }
  } else {
    last_state_.error = gpu::error::kLostContext;
    ++last_state_.generation;
  }
}

void PpapiCommandBufferProxy::TryUpdateState() {
  if (last_state_.error == gpu::error::kNoError)
    shared_state()->Read(&last_state_);
}

gpu::CommandBufferSharedState* PpapiCommandBufferProxy::shared_state() const {
  return reinterpret_cast<gpu::CommandBufferSharedState*>(
      shared_state_mapping_.memory());
}

void PpapiCommandBufferProxy::FlushInternal() {
  DCHECK(last_state_.error == gpu::error::kNoError);

  DCHECK(flush_info_->flush_pending);
  DCHECK_GE(pending_fence_sync_release_, flushed_fence_sync_release_);

  IPC::Message* message = new PpapiHostMsg_PPBGraphics3D_AsyncFlush(
      ppapi::API_ID_PPB_GRAPHICS_3D, flush_info_->resource,
      flush_info_->put_offset);

  // Do not let a synchronous flush hold up this message. If this handler is
  // deferred until after the synchronous flush completes, it will overwrite the
  // cached last_state_ with out-of-date data.
  message->set_unblock(true);
  Send(message);

  flush_info_->flush_pending = false;
  flush_info_->resource.SetHostResource(0, 0);
  flushed_fence_sync_release_ = pending_fence_sync_release_;
}

}  // namespace proxy
}  // namespace ppapi
