// Copyright (c) 2017 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/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
