// Copyright 2017 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/client_transfer_cache.h"

namespace gpu {

ClientTransferCache::ClientTransferCache(Client* client) : client_(client) {}

ClientTransferCache::~ClientTransferCache() = default;

void* ClientTransferCache::MapEntry(MappedMemoryManager* mapped_memory,
                                    uint32_t size) {
  DCHECK(!mapped_ptr_);
  DCHECK(!transfer_buffer_ptr_);
  mapped_ptr_.emplace(size, client_->cmd_buffer_helper(), mapped_memory);
  if (!mapped_ptr_->valid()) {
    mapped_ptr_ = absl::nullopt;
    return nullptr;
  }
  return mapped_ptr_->address();
}

void* ClientTransferCache::MapTransferBufferEntry(
    TransferBufferInterface* transfer_buffer,
    uint32_t size) {
  DCHECK(!mapped_ptr_);
  DCHECK(!transfer_buffer_ptr_);
  transfer_buffer_ptr_.emplace(size, client_->cmd_buffer_helper(),
                               transfer_buffer);
  if (!transfer_buffer_ptr_->valid()) {
    transfer_buffer_ptr_ = absl::nullopt;
    return nullptr;
  }
  return transfer_buffer_ptr_->address();
}

void ClientTransferCache::UnmapAndCreateEntry(uint32_t type, uint32_t id) {
  EntryKey key(type, id);

  base::AutoLock hold(lock_);
  auto handle = CreateDiscardableHandle(key);
  if (!handle.IsValid()) {
    // Release any data pointers. Keeping these alive longer can lead to issues
    // with transfer buffer reallocation.
    mapped_ptr_ = absl::nullopt;
    transfer_buffer_ptr_ = absl::nullopt;
    return;
  }

  if (mapped_ptr_) {
    DCHECK(!transfer_buffer_ptr_);
    client_->IssueCreateTransferCacheEntry(
        type, id, handle.shm_id(), handle.byte_offset(), mapped_ptr_->shm_id(),
        mapped_ptr_->offset(), mapped_ptr_->size());
    mapped_ptr_ = absl::nullopt;
  } else {
    DCHECK(!mapped_ptr_);
    client_->IssueCreateTransferCacheEntry(
        type, id, handle.shm_id(), handle.byte_offset(),
        transfer_buffer_ptr_->shm_id(), transfer_buffer_ptr_->offset(),
        transfer_buffer_ptr_->size());
    transfer_buffer_ptr_ = absl::nullopt;
  }
}

void ClientTransferCache::AddTransferCacheEntry(uint32_t type,
                                                uint32_t id,
                                                uint32_t shm_id,
                                                uint32_t shm_offset,
                                                uint32_t size) {
  DCHECK(!mapped_ptr_);
  EntryKey key(type, id);

  base::AutoLock hold(lock_);
  auto handle = CreateDiscardableHandle(key);
  if (!handle.IsValid())
    return;

  client_->IssueCreateTransferCacheEntry(type, id, handle.shm_id(),
                                         handle.byte_offset(), shm_id,
                                         shm_offset, size);
}

void ClientTransferCache::StartTransferCacheEntry(
    uint32_t type,
    uint32_t id,
    base::OnceCallback<void(ClientDiscardableHandle)> create_entry_cb) {
  DCHECK(!mapped_ptr_);
  EntryKey key(type, id);

  base::AutoLock hold(lock_);
  auto handle = CreateDiscardableHandle(key);
  if (!handle.IsValid())
    return;

  // Call |create_entry_cb| while |lock_| is held so that in case another thread
  // tries to lock the cache entry later, it can assume that the creation of the
  // service-side cache entry has been triggered.
  std::move(create_entry_cb).Run(handle);
}

ClientDiscardableHandle ClientTransferCache::CreateDiscardableHandle(
    const EntryKey& key) {
  lock_.AssertAcquired();

  ClientDiscardableHandle::Id discardable_handle_id =
      discardable_manager_.CreateHandle(client_->command_buffer());
  if (discardable_handle_id.is_null())
    return ClientDiscardableHandle();

  // We must have a valid handle here, since the id was generated above and
  // should be in locked state.
  ClientDiscardableHandle handle =
      discardable_manager_.GetHandle(discardable_handle_id);

  // Store the mapping from the given namespace/discardable_handle_id to the
  // transfer cache discardable_handle_id.
  DCHECK(FindDiscardableHandleId(key).is_null());
  discardable_handle_id_map_.emplace(key, discardable_handle_id);
  return handle;
}

bool ClientTransferCache::LockEntry(uint32_t type, uint32_t id) {
  EntryKey key(type, id);

  base::AutoLock hold(lock_);
  auto discardable_handle_id = FindDiscardableHandleId(key);
  if (discardable_handle_id.is_null())
    return false;

  if (discardable_manager_.LockHandle(discardable_handle_id))
    return true;

  // Could not lock. Entry is already deleted service side.
  discardable_handle_id_map_.erase(key);
  return false;
}

void ClientTransferCache::UnlockEntries(
    const std::vector<std::pair<uint32_t, uint32_t>>& entries) {
  base::AutoLock hold(lock_);
  for (const auto& entry : entries) {
    DCHECK(!FindDiscardableHandleId(entry).is_null());
    client_->IssueUnlockTransferCacheEntry(entry.first, entry.second);
  }
}

void ClientTransferCache::DeleteEntry(uint32_t type, uint32_t id) {
  EntryKey key(type, id);
  base::AutoLock hold(lock_);
  auto discardable_handle_id = FindDiscardableHandleId(key);
  if (discardable_handle_id.is_null())
    return;

  discardable_manager_.FreeHandle(discardable_handle_id);
  client_->IssueDeleteTransferCacheEntry(type, id);
  discardable_handle_id_map_.erase(key);
}

ClientDiscardableHandle::Id ClientTransferCache::FindDiscardableHandleId(
    const EntryKey& key) {
  lock_.AssertAcquired();
  auto id_map_it = discardable_handle_id_map_.find(key);
  if (id_map_it == discardable_handle_id_map_.end())
    return ClientDiscardableHandle::Id();
  return id_map_it->second;
}

}  // namespace gpu
