/*
 * Copyright 2020 Google LLC
 *
 */

/*
 * Copyright (c) 2020, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include "frame_outs.h"
#include <assert.h>
#include "d3dx12.h"

#if defined(_DEBUG)
inline void SetName(ID3D12Object* pObject, LPCWSTR name) { pObject->SetName(name); }
inline void SetNameIndexed(ID3D12Object* pObject, LPCWSTR name, UINT index) {
  WCHAR fullName[50];
  if (swprintf_s(fullName, L"%s[%u]", name, index) > 0) {
    pObject->SetName(fullName);
  }
}

#define NAME_D3D12_OBJECT(x) SetName(x.Get(), L#x)
#define NAME_D3D12_OBJECT_INDEXED(x, n) SetNameIndexed(x[n].Get(), L#x, n)
#else
#define NAME_D3D12_OBJECT(x)
#define NAME_D3D12_OBJECT_INDEXED(x, n)
#endif

OutBufferWrapper::~OutBufferWrapper() {
  if (storage_ && buffer_) {
    XB_LOGD << "Release OutBuffer " << buffer_;
    storage_->Push(buffer_);
  }
}

void OutBufferWrapper::ReleaseRented() {
  if (storage_ && buffer_) {
    storage_->ReleaseRentedBuffer(buffer_);
  }
}

OutBufferStorage::OutBufferStorage(int queue_size, ID3D12Device* dx12_device)
    : storage_(queue_size), queue_free_(queue_size), queue_size_(queue_size), dx12_device_(dx12_device) {
  for (int i = 0; i < queue_size_; i++) {
    OutBuffer& item = storage_[i];
    item.shown = 0;
    queue_free_.Push(&item);
  }
}

void OutBufferStorage::Push(OutBuffer* frame) { queue_free_.Push(frame); }

std::shared_ptr<OutBufferWrapper> OutBufferStorage::GetFreeBuffer(uint32_t width, uint32_t height,
                                                                  frame_buffer_type fb_type, size_t buffer_size,
                                                                  uint32_t flags) {
  HRESULT hr;
  int has_errors = 0;
  queue_free_.DoForAll(1, [&](OutBuffer* buffer) {
    if (flags & CBUFTEXTURE) {
      if (buffer->renderWidth != width || buffer->renderHeight != height || buffer->fb_type != fb_type) {
        for (int i = 0; i < 3; i++) {
          const int subsampling = i > 0;
          const int _width = (fb_type == fbt10x3) ? (((width + subsampling) >> subsampling) + 2) / 3
                                                  : ((width + subsampling) >> subsampling);
          const int _height = (height + subsampling) >> subsampling;

          // Create interop resources
          D3D12_RESOURCE_DESC textureDesc = {};
          textureDesc.MipLevels = 1;
          textureDesc.Format = (fb_type == fbt10bit)
                                   ? DXGI_FORMAT_R16_UNORM
                                   : ((fb_type == fbt8bit) ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R10G10B10A2_UNORM);
          textureDesc.Width = _width;
          textureDesc.Height = _height;
          textureDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
          textureDesc.DepthOrArraySize = 1;
          textureDesc.SampleDesc.Count = 1;
          textureDesc.SampleDesc.Quality = 0;
          textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
          textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
          hr = dx12_device_->CreateCommittedResource(
              &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_SHARED, &textureDesc,
              D3D12_RESOURCE_STATE_COPY_DEST, 0,
              IID_PPV_ARGS(&buffer->d3d12textures[i]));
          if (FAILED(hr)) {
            has_errors = 1;
            return 0;
          }
          NAME_D3D12_OBJECT_INDEXED(buffer->d3d12textures, i);
        }
        buffer->renderWidth = width;
        buffer->renderHeight = height;
        buffer->fb_type = fb_type;
      }
    }
    if (flags & CBUFREADBACK) {
      if (buffer->buffer_size < buffer_size) {
        // Create readback buffer (if any)
        const D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_READBACK;
        const D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COPY_DEST;
        D3D12_HEAP_PROPERTIES heapProp;
        heapProp.Type = heapType;
        heapProp.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;  //
        heapProp.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
        heapProp.CreationNodeMask = 0;
        heapProp.VisibleNodeMask = 0;

        const D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
        hr = dx12_device_->CreateCommittedResource(&heapProp, D3D12_HEAP_FLAG_NONE,
                                                   &CD3DX12_RESOURCE_DESC::Buffer(buffer_size, flags), state, NULL,
                                                   IID_PPV_ARGS(&buffer->d3d12buffer));

        if (SUCCEEDED(hr)) {
          hr = buffer->d3d12buffer->Map(0, NULL, &buffer->pMem);
          if (FAILED(hr)) {
            has_errors = 1;
            return 0;
          }
          buffer->d3d12buffer->Unmap(0, 0);
        }
        buffer->buffer_size = buffer_size;
      }
    }
    return 1;
  });
  if (has_errors) {
    XB_LOGE << "Failed to allocate output buffers.";
    queue_free_.DoForAll(1, [&](OutBuffer* buffer) {
      buffer->Reset();
      return 1;
    });
    return 0;
  }
  OutBuffer* buffer = queue_free_.Pull();
  if (!(flags & CBUFREADBACK)) {
    buffer->d3d12buffer.Reset();
    buffer->pMem = 0;
  }
  std::unique_lock<std::mutex> lock(cs_);
  OutBufferWrapper* bf = new (std::nothrow) OutBufferWrapper(buffer, this);
  if (!bf) return 0;
  std::shared_ptr<OutBufferWrapper> retbuf = std::shared_ptr<OutBufferWrapper>(bf);
  rented_.push_back(retbuf);
  return retbuf;
}

std::shared_ptr<OutBufferWrapper> OutBufferStorage::ReleaseRentedBuffer(void* ptr) {
  std::unique_lock<std::mutex> lock(cs_);
  for (auto iter = rented_.begin(); iter != rented_.end(); iter++) {
    if ((*iter)->Buffer() == ptr) {
      XB_LOGD << "ReleaseRentedBuffer " << ptr;
      std::shared_ptr<OutBufferWrapper> buff = *iter;
      rented_.erase(iter);
      return buff;
    }
  }
  assert(0 && "buffer not found");
  return 0;
}

std::shared_ptr<OutBufferWrapper> OutBufferStorage::FindRentedBuffer(void* ptr) {
  std::unique_lock<std::mutex> lock(cs_);
  for (auto iter = rented_.begin(); iter != rented_.end(); iter++) {
    if ((*iter)->Buffer() == ptr) {
      std::shared_ptr<OutBufferWrapper> buff = *iter;
      return buff;
    }
  }
  assert(0 && "buffer not found");
  return 0;
}
