// Copyright 2018 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 "lib/escher/paper/paper_draw_call_factory.h"

#include <glm/gtc/matrix_access.hpp>

#include "lib/escher/escher.h"
#include "lib/escher/paper/paper_material.h"
#include "lib/escher/paper/paper_render_funcs.h"
#include "lib/escher/paper/paper_render_queue.h"
#include "lib/escher/paper/paper_render_queue_flags.h"
#include "lib/escher/paper/paper_scene.h"
#include "lib/escher/paper/paper_shader_structs.h"
#include "lib/escher/paper/paper_shape_cache.h"
#include "lib/escher/paper/paper_transform_stack.h"
#include "lib/escher/renderer/frame.h"
#include "lib/escher/renderer/render_queue_item.h"
#include "lib/escher/shape/mesh.h"
#include "lib/escher/util/hasher.h"
#include "lib/escher/util/trace_macros.h"

namespace escher {

namespace {

// Default 1x1 texture for Materials that have no texture.  See header file
// |white_texture_| comment.
TexturePtr CreateWhiteTexture(Escher* escher) {
  FXL_DCHECK(escher);
  uint8_t channels[4];
  channels[0] = channels[1] = channels[2] = channels[3] = 255;
  auto image = escher->NewRgbaImage(1, 1, channels);
  return escher->NewTexture(std::move(image), vk::Filter::eNearest);
}

}  // anonymous namespace

PaperDrawCallFactory::PaperDrawCallFactory(EscherWeakPtr weak_escher,
                                           const PaperRendererConfig& config)
    : white_texture_(CreateWhiteTexture(weak_escher.get())) {}

PaperDrawCallFactory::~PaperDrawCallFactory() { FXL_DCHECK(!frame_); }

void PaperDrawCallFactory::DrawCircle(float radius,
                                      const PaperMaterial& material,
                                      PaperDrawableFlags flags) {
  FXL_DCHECK(frame_);

  // We aim to improve cache hit rate by using a circle of radius 1.  This
  // requires us to push a new transform.

  const bool scale_radius = (radius != 1.f);
  const auto& transform = scale_radius ? transform_stack_->PushScale(radius)
                                       : transform_stack_->Top();
  const auto& entry = shape_cache_->GetCircleMesh(
      1.f, transform.clip_planes.data(), transform.clip_planes.size());

  EnqueueDrawCalls(entry, material, flags);

  if (scale_radius)
    transform_stack_->Pop();
}

void PaperDrawCallFactory::DrawRect(vec2 min, vec2 max,
                                    const PaperMaterial& material,
                                    PaperDrawableFlags flags) {
  FXL_DCHECK(frame_);

  const auto& transform = transform_stack_->Top();
  const auto& entry = shape_cache_->GetRectMesh(
      min, max, transform.clip_planes.data(), transform.clip_planes.size());
  EnqueueDrawCalls(entry, material, flags);
}

void PaperDrawCallFactory::DrawRoundedRect(const RoundedRectSpec& spec,
                                           const PaperMaterial& material,
                                           PaperDrawableFlags flags) {
  FXL_DCHECK(frame_);

  const auto& transform = transform_stack_->Top();
  const auto& entry = shape_cache_->GetRoundedRectMesh(
      spec, transform.clip_planes.data(), transform.clip_planes.size());
  EnqueueDrawCalls(entry, material, flags);
}

void PaperDrawCallFactory::EnqueueDrawCalls(
    const PaperShapeCacheEntry& cache_entry, const PaperMaterial& material,
    PaperDrawableFlags drawable_flags) {
  FXL_DCHECK(frame_);
  if (!cache_entry)
    return;

  TRACE_DURATION("gfx", "PaperDrawCallFactory::EnqueueDrawCalls");

  auto* mesh = cache_entry.mesh.get();
  const auto& texture =
      material.texture() ? material.texture() : white_texture_;
  const auto& transform = transform_stack_->Top();
  const uint32_t num_indices = cache_entry.num_indices;
  const uint32_t num_shadow_volume_indices =
      cache_entry.num_shadow_volume_indices;

  Hash pipeline_hash;
  Hash mesh_hash;

  // Only the program goes into the pipeline hash.  If we also wanted e.g. some
  // objects to be stencil-tested and others not, this info would be included.
  {
    Hasher h;
    // TODO(ES-150): add this back in some way, with a more abstract pipeline
    // identifier instead of the actual program uid (which can change from pass
    // to pass). h.u64(shadow_volume_program_->uid());
    pipeline_hash = h.value();
  }

  // The object-hash is used to look up an existing MeshData for this
  // Mesh/Material pair, and is also used as part of the sort-key below.
  // We don't need to take opacity into account because separate RenderQueues
  // are used for opaque vs. translucent objects.
  {
    Hasher h;
    h.u64(mesh->uid());
    h.u64(texture->uid());
    mesh_hash = h.value();
  }

  PaperRenderFuncs::MeshData* mesh_data;
  auto it = object_data_.find(mesh_hash);
  if (it != object_data_.end()) {
    mesh_data = reinterpret_cast<PaperRenderFuncs::MeshData*>(it->second);
  } else {
    mesh_data = PaperRenderFuncs::NewMeshData(
        frame_, mesh, texture, num_indices, num_shadow_volume_indices);
    object_data_.insert(it, std::make_pair(mesh_hash, mesh_data));
  }

  // Allocate and initialize per-instance data.
  PaperRenderFuncs::MeshDrawData* draw_data = PaperRenderFuncs::NewMeshDrawData(
      frame_, transform.matrix, material.color(), drawable_flags);

  // TODO(ES-103): avoid reaching in to impl::CommandBuffer for keep-alive.
  frame_->command_buffer()->KeepAlive(texture.get());

  // Compute a depth metric for sorting objects.
#if 1
  // As long as the camera is above the top of the viewing volume and the scene
  // is composed of parallel-planar surfaces, we can simply subtract the
  // object's elevation from the camera's elevation.  Given these constraints,
  // this metric is superior to the alternate one below, which can provide
  // incorrect results at glancing angles (i.e. where the center of one object
  // is closer to the camera than the other, but is nevertheless partly behind
  // the other object from the camera's perspective.
  float depth = camera_pos_.z - transform.matrix[3][2];
#else
  // Compute the vector from the camera to the object, and project it against
  // the camera's direction to obtain the depth.
  float depth = glm::dot(vec3(transform[3]) - camera_pos_, camera_dir_);
#endif

  auto sort_key =
      material.opaque()
          ? SortKey::NewOpaque(pipeline_hash, mesh_hash, depth).key()
          : SortKey::NewTranslucent(pipeline_hash, mesh_hash, depth).key();

  auto queue_flags = material.opaque() ? PaperRenderQueueFlagBits::kOpaque
                                       : PaperRenderQueueFlagBits::kTranslucent;

  render_queue_->PushDrawCall(
      {.render_queue_item =
           {.sort_key = sort_key,
            .object_data = mesh_data,
            .instance_data = draw_data,
            .render_queue_funcs = {PaperRenderFuncs::RenderMesh}},
       .render_queue_flags = queue_flags});
}

void PaperDrawCallFactory::SetConfig(const PaperRendererConfig& config) {
  // NOTE: nothing currently to do here.  This will change, e.g. when we
  // add other shadow techniques.
}

std::vector<UniformBinding> PaperDrawCallFactory::BeginFrame(
    const FramePtr& frame, PaperScene* scene,
    PaperTransformStack* transform_stack, PaperRenderQueue* render_queue,
    PaperShapeCache* shape_cache, const Camera& camera) {
  FXL_DCHECK(!frame_ && frame && transform_stack && render_queue &&
             shape_cache);
  frame_ = frame;
  transform_stack_ = transform_stack;
  render_queue_ = render_queue;
  shape_cache_ = shape_cache;

  // A camera's transform doesn't move the camera; it is applied to the rest of
  // the scene to "move it away from the camera".  Therefore, the camera's
  // position in the scene can be obtained by inverting it and applying it to
  // the origin, or equivalently by inverting the transform and taking the
  // rightmost (translation) column.
  camera_pos_ = vec3(glm::column(glm::inverse(camera.transform()), 3));

  // The camera points down the negative-Z axis, so its world-space direction
  // can be obtained by applying the camera transform to the direction vector
  // [0, 0, -1, 0] (remembering that directions vectors have a w-coord of 0, vs.
  // 1 for position vectors).  This is equivalent to taking the negated third
  // column of the transform.
  camera_dir_ = -vec3(glm::column(camera.transform(), 2));

  // Populated below, then returned.
  std::vector<UniformBinding> scene_uniforms;

  // Generate a UniformBinding for the camera and ambient light data.
  {
    auto writable_binding =
        NewPaperShaderUniformBinding<PaperShaderCameraAmbient>(frame);
    writable_binding.first->vp_matrix =
        camera.projection() * camera.transform();
    writable_binding.first->ambient_light_color = scene->ambient_light.color;
    scene_uniforms.push_back(writable_binding.second);
  }

  // Generate a uniform binding containing data for all point lights, if any.
  num_lights_ = scene->num_point_lights();
  if (num_lights_ > 0) {
    auto writable_binding =
        NewPaperShaderUniformBinding<PaperShaderPointLight>(frame, num_lights_);
    auto* point_lights = writable_binding.first;
    for (size_t i = 0; i < num_lights_; ++i) {
      const PaperPointLight& light = scene->point_lights[i];
      point_lights[i].position = vec4(light.position, 1);
      point_lights[i].color = vec4(light.color, 1);
      point_lights[i].falloff = light.falloff;
    }
    scene_uniforms.push_back(writable_binding.second);
  }

  return scene_uniforms;
}

void PaperDrawCallFactory::EndFrame() {
  FXL_DCHECK(frame_);
  frame_ = nullptr;
  transform_stack_ = nullptr;
  render_queue_ = nullptr;
  shape_cache_ = nullptr;
  object_data_.clear();

  camera_pos_ = vec3(0, 0, 0);
  camera_dir_ = vec3(0, 0, 0);
  num_lights_ = 0;
}

PaperDrawCallFactory::SortKey PaperDrawCallFactory::SortKey::NewOpaque(
    Hash pipeline_hash, Hash draw_hash, float depth) {
  // Depth must be non-negative, otherwise comparing the bit representations
  // won't work.
  FXL_DCHECK(depth >= 0) << " is: " << depth;

  // Prioritize minimizing pipeline changes over depth-sorting; both are more
  // important than minimizing mesh/texture state changes (in practice, almost
  // every draw call uses a separate mesh/texture anyway).
  // TODO(ES-105): We currently don't have multiple pipelines used in the opaque
  // pass, so we sort primarily by depth.  However, when we eventually do have
  // multiple pipelines, we may want to rewrite the pipeline hashes with a value
  // that reflects whether objects drawn using that pipeline tend to be drawn
  // in front or back.  For example, if we wanted to draw the background with a
  // shiny metallic BRDF, and everything else with a matte diffuse shader then
  // we should definitely draw the background last to avoid drawing expensive
  // pixels that will later be overdrawn; this isn't guaranteed if we sort by
  // the pipeline hash.
  uint64_t depth_key(glm::floatBitsToUint(depth));
  return SortKey((pipeline_hash.val << 48) | depth_key << 16 |
                 (draw_hash.val & 0xffff));
}

PaperDrawCallFactory::SortKey PaperDrawCallFactory::SortKey::NewTranslucent(
    Hash pipeline_hash, Hash draw_hash, float depth) {
  // Depth must be non-negative, otherwise comparing the bit representations
  // won't work.
  FXL_DCHECK(depth >= 0) << " is: " << depth;

  // Prioritize back-to-front order over state changes.
  uint64_t depth_key(glm::floatBitsToUint(depth) ^ 0xffffffffu);
  return SortKey((depth_key << 32) | (pipeline_hash.val & 0xffff0000u) |
                 (draw_hash.val & 0xffffu));
}

}  // namespace escher
