// Copyright 2017 The Fuchsia 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 "garnet/bin/ui/sketchy/buffer/mesh_buffer.h"

#include "garnet/bin/ui/sketchy/buffer/shared_buffer_pool.h"
#include "lib/ui/scenic/cpp/commands.h"

namespace {

constexpr vk::DeviceSize kVertexStride = sizeof(float) * 4;
constexpr vk::DeviceSize kIndexStride = sizeof(uint32_t);

constexpr auto kMeshVertexPositionType = fuchsia::ui::gfx::ValueType::kVector2;
constexpr auto kMeshVertexNormalType = fuchsia::ui::gfx::ValueType::kNone;
constexpr auto kMeshVertexTexCoodType = fuchsia::ui::gfx::ValueType::kVector2;
constexpr auto kMeshIndexFormat = fuchsia::ui::gfx::MeshIndexFormat::kUint32;

}  // namespace

namespace sketchy_service {

void MeshBuffer::Prepare(Frame* frame, bool from_scratch,
                         uint32_t delta_vertex_count,
                         uint32_t delta_index_count) {
  from_scratch |= !vertex_buffer_ || !index_buffer_;

  // Multi-buffering for vertex buffer.
  vk::DeviceSize vertex_size = (from_scratch ? 0 : vertex_buffer_->size()) +
                               delta_vertex_count * kVertexStride;
  ReplaceBuffer(frame, vertex_buffer_, vertex_size, !from_scratch);

  // Multi-buffering for index buffer.
  vk::DeviceSize index_size = (from_scratch ? 0 : index_buffer_->size()) +
                              delta_index_count * kIndexStride;
  ReplaceBuffer(frame, index_buffer_, index_size, !from_scratch);

  if (from_scratch) {
    vertex_buffer_->Reset();
    index_buffer_->Reset();
    vertex_count_ = 0;
    index_count_ = 0;
    bbox_ = escher::BoundingBox();
  }
}

std::pair<escher::impl::BufferRange, escher::impl::BufferRange>
MeshBuffer::Reserve(Frame* frame, uint32_t vertex_count, uint32_t index_count,
                    const escher::BoundingBox& bbox) {
  vertex_count_ += vertex_count;
  index_count_ += index_count;
  bbox_.Join(bbox);

  vk::DeviceSize vertex_size = kVertexStride * vertex_count;
  vk::DeviceSize total_vertex_size = vertex_buffer_->size() + vertex_size;
  if (vertex_buffer_->capacity() < total_vertex_size) {
    ReplaceBuffer(frame, vertex_buffer_, total_vertex_size,
                  /* keep_content= */ true);
  }

  vk::DeviceSize index_size = kIndexStride * index_count;
  vk::DeviceSize total_index_size = index_buffer_->size() + index_size;
  if (index_buffer_->capacity() < total_index_size) {
    ReplaceBuffer(frame, index_buffer_, total_index_size,
                  /* keep_content= */ true);
  }

  return {vertex_buffer_->Reserve(vertex_size),
          index_buffer_->Reserve(index_size)};
};

void MeshBuffer::ProvideBuffersToScenicMesh(scenic::Mesh* scenic_mesh) {
  auto bb_min = bbox_.min();
  auto bb_max = bbox_.max();
  float bb_min_arr[] = {bb_min.x, bb_min.y, bb_min.z};
  float bb_max_arr[] = {bb_max.x, bb_max.y, bb_max.z};
  scenic_mesh->BindBuffers(
      index_buffer_->scenic_buffer(), kMeshIndexFormat, /* index_offset= */ 0,
      index_count_, vertex_buffer_->scenic_buffer(),
      scenic::NewMeshVertexFormat(kMeshVertexPositionType,
                                  kMeshVertexNormalType,
                                  kMeshVertexTexCoodType),
      /* vertex_offset= */ 0, vertex_count_, bb_min_arr, bb_max_arr);
}

void MeshBuffer::ReplaceBuffer(Frame* frame, SharedBufferPtr& shared_buffer,
                               vk::DeviceSize capacity_req, bool keep_content) {
  auto shared_buffer_pool = frame->shared_buffer_pool();
  if (!shared_buffer) {
    shared_buffer = shared_buffer_pool->GetBuffer(capacity_req);
    return;
  }

  auto new_buffer = shared_buffer_pool->GetBuffer(capacity_req);
  if (keep_content && shared_buffer->size() > 0) {
    new_buffer->Copy(frame, shared_buffer);
  }
  shared_buffer_pool->ReturnBuffer(std::move(shared_buffer),
                                   frame->DuplicateReleaseFence());
  shared_buffer = std::move(new_buffer);
}

}  // namespace sketchy_service
