// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/client/implementation_base.h"

#include <algorithm>

#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"
#include "gpu/command_buffer/client/gpu_control.h"
#include "gpu/command_buffer/client/mapped_memory.h"
#include "gpu/command_buffer/client/query_tracker.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/common/sync_token.h"

namespace gpu {

const uint32_t ImplementationBase::kMaxSizeOfSimpleResult;
const uint32_t ImplementationBase::kStartingOffset;

ImplementationBase::ImplementationBase(CommandBufferHelper* helper,
                                       TransferBufferInterface* transfer_buffer,
                                       GpuControl* gpu_control)
    : transfer_buffer_(transfer_buffer),
      gpu_control_(gpu_control),
      capabilities_(gpu_control->GetCapabilities()),
      helper_(helper) {}

ImplementationBase::~ImplementationBase() {
  // The gpu_control_ outlives this class, so clear the client on it before we
  // self-destruct.
  gpu_control_->SetGpuControlClient(nullptr);
}

void ImplementationBase::FreeUnusedSharedMemory() {
  mapped_memory_->FreeUnused();
}

void ImplementationBase::FreeEverything() {
  query_tracker_->Shrink(helper_);
  FreeUnusedSharedMemory();
  transfer_buffer_->Free();
  helper_->FreeRingBuffer();
}

void ImplementationBase::SetLostContextCallback(base::OnceClosure callback) {
  lost_context_callback_ = std::move(callback);
}

void ImplementationBase::FlushPendingWork() {
  gpu_control_->FlushPendingWork();
}

void ImplementationBase::SignalSyncToken(const SyncToken& sync_token,
                                         base::OnceClosure callback) {
  SyncToken verified_sync_token;
  if (sync_token.HasData() &&
      GetVerifiedSyncTokenForIPC(sync_token, &verified_sync_token)) {
    // We can only send verified sync tokens across IPC.
    gpu_control_->SignalSyncToken(
        verified_sync_token,
        base::BindOnce(&ImplementationBase::RunIfContextNotLost,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  } else {
    // Invalid sync token, just call the callback immediately.
    std::move(callback).Run();
  }
}

// This may be called from any thread. It's safe to access gpu_control_ without
// the lock because it is const.
bool ImplementationBase::IsSyncTokenSignaled(const SyncToken& sync_token) {
  // Check that the sync token belongs to this context.
  DCHECK_EQ(gpu_control_->GetNamespaceID(), sync_token.namespace_id());
  DCHECK_EQ(gpu_control_->GetCommandBufferID(), sync_token.command_buffer_id());
  return gpu_control_->IsFenceSyncReleased(sync_token.release_count());
}

void ImplementationBase::GenSyncToken(GLbyte* sync_token) {
  if (!sync_token) {
    SetGLError(GL_INVALID_VALUE, "glGenSyncTokenCHROMIUM", "empty sync_token");
    return;
  }

  uint64_t fence_sync = helper_->InsertFenceSync(
      [this]() { return gpu_control_->GenerateFenceSyncRelease(); });
  helper_->CommandBufferHelper::OrderingBarrier();
  gpu_control_->EnsureWorkVisible();

  // Copy the data over after setting the data to ensure alignment.
  SyncToken sync_token_data(gpu_control_->GetNamespaceID(),
                            gpu_control_->GetCommandBufferID(), fence_sync);
  sync_token_data.SetVerifyFlush();
  UNSAFE_TODO(memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)));
}

void ImplementationBase::GenUnverifiedSyncToken(GLbyte* sync_token) {
  if (!sync_token) {
    SetGLError(GL_INVALID_VALUE, "glGenUnverifiedSyncTokenCHROMIUM",
               "empty sync_token");
    return;
  }

  uint64_t fence_sync = helper_->InsertFenceSync(
      [this]() { return gpu_control_->GenerateFenceSyncRelease(); });
  helper_->CommandBufferHelper::OrderingBarrier();

  // Copy the data over after setting the data to ensure alignment.
  SyncToken sync_token_data(gpu_control_->GetNamespaceID(),
                            gpu_control_->GetCommandBufferID(), fence_sync);
  UNSAFE_TODO(memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)));
}

void ImplementationBase::VerifySyncTokens(GLbyte** sync_tokens, GLsizei count) {
  bool requires_synchronization = false;
  for (GLsizei i = 0; i < count; ++i) {
    if (UNSAFE_TODO(sync_tokens[i])) {
      SyncToken sync_token;
      UNSAFE_TODO(memcpy(&sync_token, sync_tokens[i], sizeof(sync_token)));

      if (sync_token.HasData() && !sync_token.verified_flush()) {
        if (!GetVerifiedSyncTokenForIPC(sync_token, &sync_token)) {
          SetGLError(GL_INVALID_VALUE, "glVerifySyncTokensCHROMIUM",
                     "Cannot verify sync token using this context.");
          return;
        }
        requires_synchronization = true;
        DCHECK(sync_token.verified_flush());
      }

      // Set verify bit on empty sync tokens too.
      sync_token.SetVerifyFlush();

      UNSAFE_TODO(memcpy(sync_tokens[i], &sync_token, sizeof(sync_token)));
    }
  }

  // Ensure all the fence syncs are visible on GPU service.
  if (requires_synchronization)
    gpu_control_->EnsureWorkVisible();
}

void ImplementationBase::WaitSyncToken(const GLbyte* sync_token_data) {
  if (!sync_token_data)
    return;

  // Copy the data over before data access to ensure alignment.
  SyncToken sync_token, verified_sync_token;
  UNSAFE_TODO(memcpy(&sync_token, sync_token_data, sizeof(SyncToken)));

  if (!sync_token.HasData())
    return;

  if (!GetVerifiedSyncTokenForIPC(sync_token, &verified_sync_token)) {
    SetGLError(GL_INVALID_VALUE, "glWaitSyncTokenCHROMIUM",
               "Cannot wait on sync_token which has not been verified");
    return;
  }

  // Enqueue sync token in flush after inserting command so that it's not
  // included in an automatic flush.
  gpu_control_->WaitSyncToken(verified_sync_token);
}

void ImplementationBase::SignalQuery(uint32_t query,
                                     base::OnceClosure callback) {
  // Flush previously entered commands to ensure ordering with any
  // glBeginQueryEXT() calls that may have been put into the context.
  IssueShallowFlush();
  gpu_control_->SignalQuery(
      query,
      base::BindOnce(&ImplementationBase::RunIfContextNotLost,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void ImplementationBase::GetGpuFence(
    uint32_t gpu_fence_id,
    base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
  // This ShallowFlush is required to ensure that the GetGpuFence
  // call is processed after the preceding CreateGpuFenceCHROMIUM call.
  IssueShallowFlush();
  gpu_control_->GetGpuFence(gpu_fence_id, std::move(callback));
}

bool ImplementationBase::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  using base::trace_event::MemoryAllocatorDump;
  using base::trace_event::MemoryDumpLevelOfDetail;

  // Dump owned MappedMemoryManager memory as well.
  mapped_memory_->OnMemoryDump(args, pmd);

  if (!transfer_buffer_->HaveBuffer())
    return true;

  const uint64_t tracing_process_id =
      base::trace_event::MemoryDumpManager::GetInstance()
          ->GetTracingProcessId();

  MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(base::StringPrintf(
      "gpu/transfer_buffer_memory/buffer_0x%x", transfer_buffer_->GetShmId()));
  dump->AddScalar(MemoryAllocatorDump::kNameSize,
                  MemoryAllocatorDump::kUnitsBytes,
                  transfer_buffer_->GetSize());

  if (args.level_of_detail != MemoryDumpLevelOfDetail::kBackground) {
    dump->AddScalar("free_size", MemoryAllocatorDump::kUnitsBytes,
                    transfer_buffer_->GetFragmentedFreeSize());
    auto shared_memory_guid = transfer_buffer_->shared_memory_guid();
    const int kImportance = 2;
    if (!shared_memory_guid.is_empty()) {
      pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
                                           kImportance);
    } else {
      auto guid = GetBufferGUIDForTracing(tracing_process_id,
                                          transfer_buffer_->GetShmId());
      pmd->CreateSharedGlobalAllocatorDump(guid);
      pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
    }
  }

  return true;
}

gpu::ContextResult ImplementationBase::Initialize(
    const SharedMemoryLimits& limits) {
  TRACE_EVENT0("gpu", "ImplementationBase::Initialize");
  DCHECK_GE(limits.start_transfer_buffer_size, limits.min_transfer_buffer_size);
  DCHECK_LE(limits.start_transfer_buffer_size, limits.max_transfer_buffer_size);
  DCHECK_GE(limits.min_transfer_buffer_size, kStartingOffset);

  gpu_control_->SetGpuControlClient(this);

  if (!transfer_buffer_->Initialize(
          limits.start_transfer_buffer_size, kStartingOffset,
          limits.min_transfer_buffer_size, limits.max_transfer_buffer_size,
          kAlignment)) {
    // TransferBuffer::Initialize doesn't fail for transient reasons such as if
    // the context was lost. See http://crrev.com/c/720269
    LOG(ERROR) << "ContextResult::kFatalFailure: "
               << "TransferBuffer::Initialize() failed";
    return gpu::ContextResult::kFatalFailure;
  }

  mapped_memory_ = std::make_unique<MappedMemoryManager>(
      helper_, limits.mapped_memory_reclaim_limit);
  mapped_memory_->set_chunk_size_multiple(limits.mapped_memory_chunk_size);
  query_tracker_ = std::make_unique<gles2::QueryTracker>(mapped_memory_.get());

  return gpu::ContextResult::kSuccess;
}

bool ImplementationBase::WaitForCmd() {
  TRACE_EVENT0("gpu", "ImplementationBase::WaitForCmd");
  return helper_->Finish();
}

int32_t ImplementationBase::GetResultShmId() {
  return transfer_buffer_->GetShmId();
}

bool ImplementationBase::GetBucketContents(uint32_t bucket_id,
                                           std::vector<int8_t>* data) {
  TRACE_EVENT0("gpu", "ImplementationBase::GetBucketContents");
  DCHECK(data);
  const uint32_t kStartSize = 32 * 1024;
  ScopedTransferBufferPtr buffer(kStartSize, helper_, transfer_buffer_);
  if (!buffer.valid()) {
    return false;
  }
  uint32_t size = 0;
  {
    // The Result pointer must be scoped to this block because it can be
    // invalidated below if resizing the ScopedTransferBufferPtr causes the
    // transfer buffer to be reallocated.
    typedef cmd::GetBucketStart::Result Result;
    auto result = GetResultAs<Result>();
    if (!result) {
      return false;
    }
    *result = 0;
    helper_->GetBucketStart(bucket_id, GetResultShmId(), result.offset(),
                            buffer.size(), buffer.shm_id(), buffer.offset());
    WaitForCmd();
    size = *result;
  }
  data->resize(size);
  if (size > 0u) {
    uint32_t offset = 0;
    while (size) {
      if (!buffer.valid()) {
        buffer.Reset(size);
        if (!buffer.valid()) {
          return false;
        }
        helper_->GetBucketData(bucket_id, offset, buffer.size(),
                               buffer.shm_id(), buffer.offset());
        if (!WaitForCmd()) {
          data->clear();
          return false;
        }
      }
      uint32_t size_to_copy = std::min(size, buffer.size());
      UNSAFE_TODO(memcpy(&(*data)[offset], buffer.address(), size_to_copy));
      offset += size_to_copy;
      size -= size_to_copy;
      buffer.Release();
    }
    // Free the bucket. This is not required but it does free up the memory.
    // and we don't have to wait for the result so from the client's perspective
    // it's cheap.
    helper_->SetBucketSize(bucket_id, 0);
  }
  return true;
}

void ImplementationBase::SetBucketContents(uint32_t bucket_id,
                                           const void* data,
                                           uint32_t size) {
  DCHECK(data);
  helper_->SetBucketSize(bucket_id, size);
  if (size > 0u) {
    uint32_t offset = 0;
    while (size) {
      ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
      if (!buffer.valid()) {
        return;
      }
      UNSAFE_TODO(memcpy(buffer.address(),
                         static_cast<const int8_t*>(data) + offset,
                         buffer.size()));
      helper_->SetBucketData(bucket_id, offset, buffer.size(), buffer.shm_id(),
                             buffer.offset());
      offset += buffer.size();
      size -= buffer.size();
    }
  }
}

void ImplementationBase::SetBucketAsCString(uint32_t bucket_id,
                                            const char* str) {
  // NOTE: strings are passed NULL terminated. That means the empty
  // string will have a size of 1 and no-string will have a size of 0
  if (str) {
    base::CheckedNumeric<uint32_t> len = strlen(str);
    len += 1;
    SetBucketContents(bucket_id, str, len.ValueOrDefault(0));
  } else {
    helper_->SetBucketSize(bucket_id, 0);
  }
}

bool ImplementationBase::GetBucketAsString(uint32_t bucket_id,
                                           std::string* str) {
  DCHECK(str);
  std::vector<int8_t> data;
  // NOTE: strings are passed NULL terminated. That means the empty
  // string will have a size of 1 and no-string will have a size of 0
  if (!GetBucketContents(bucket_id, &data)) {
    return false;
  }
  if (data.empty()) {
    return false;
  }
  str->assign(&data[0], UNSAFE_TODO(&data[0] + data.size() - 1));
  return true;
}

void ImplementationBase::SetBucketAsString(uint32_t bucket_id,
                                           const std::string& str) {
  // NOTE: strings are passed NULL terminated. That means the empty
  // string will have a size of 1 and no-string will have a size of 0
  base::CheckedNumeric<uint32_t> len = str.size();
  len += 1;
  SetBucketContents(bucket_id, str.c_str(), len.ValueOrDefault(0));
}

bool ImplementationBase::GetVerifiedSyncTokenForIPC(
    const SyncToken& sync_token,
    SyncToken* verified_sync_token) {
  DCHECK(sync_token.HasData());
  DCHECK(verified_sync_token);

  if (!sync_token.verified_flush() &&
      !gpu_control_->CanWaitUnverifiedSyncToken(sync_token))
    return false;

  *verified_sync_token = sync_token;
  verified_sync_token->SetVerifyFlush();
  return true;
}

void ImplementationBase::RunIfContextNotLost(base::OnceClosure callback) {
  if (!lost_context_callback_run_) {
    std::move(callback).Run();
  }
}

}  // namespace gpu
