// 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 "garnet/lib/ui/gfx/engine/engine_renderer.h"

#include <trace/event.h>

#include "garnet/lib/ui/gfx/engine/frame_timings.h"
#include "garnet/lib/ui/gfx/resources/camera.h"
#include "garnet/lib/ui/gfx/resources/compositor/layer.h"
#include "garnet/lib/ui/gfx/resources/dump_visitor.h"
#include "garnet/lib/ui/gfx/resources/lights/ambient_light.h"
#include "garnet/lib/ui/gfx/resources/lights/directional_light.h"
#include "garnet/lib/ui/gfx/resources/renderers/renderer.h"
#include "garnet/lib/ui/gfx/resources/stereo_camera.h"
#include "lib/escher/hmd/pose_buffer_latching_shader.h"
#include "lib/escher/impl/image_cache.h"
#include "lib/escher/renderer/paper_renderer.h"
#include "lib/escher/renderer/shadow_map.h"
#include "lib/escher/renderer/shadow_map_renderer.h"
#include "lib/escher/scene/model.h"
#include "lib/escher/scene/stage.h"
#include "lib/escher/vk/image.h"

// TODO(SCN-1113): Move this someplace.  PoseBufferLatchingShader assumes this,
// but we can't put it there because it lives in a Zircon-ignorant part of
// Escher.
#include <type_traits>
static_assert(
    std::is_same<zx_time_t, int64_t>::value,
    "PoseBufferLatchingShader incorrectly assumes that zx_time_t is int64_t");

namespace scenic_impl {
namespace gfx {

EngineRenderer::EngineRenderer(escher::EscherWeakPtr weak_escher)
    : escher_(std::move(weak_escher)),
      paper_renderer_(escher::PaperRenderer::New(escher_)),
      shadow_renderer_(
          escher::ShadowMapRenderer::New(escher_, paper_renderer_->model_data(),
                                         paper_renderer_->model_renderer())),
      pose_buffer_latching_shader_(
          std::make_unique<escher::hmd::PoseBufferLatchingShader>(escher_)) {
  paper_renderer_->set_sort_by_pipeline(false);
}

EngineRenderer::~EngineRenderer() = default;

void EngineRenderer::RenderLayers(const escher::FramePtr& frame,
                                  zx_time_t target_presentation_time,
                                  const escher::ImagePtr& output_image,
                                  const std::vector<Layer*>& layers) {
  // TODO(SCN-1119): change this to say "EngineRenderer::RenderLayers".
  TRACE_DURATION("gfx", "Compositor::DrawFrame");
  FXL_CHECK(!layers.empty());

  auto overlay_model =
      DrawOverlaysToModel(layers, frame, target_presentation_time);
  const auto& bottom_layer = layers[0];
  DrawLayer(frame, target_presentation_time, bottom_layer, output_image,
            overlay_model.get());
}

std::unique_ptr<escher::Model> EngineRenderer::DrawOverlaysToModel(
    const std::vector<Layer*>& layers, const escher::FramePtr& frame,
    zx_time_t target_presentation_time) {
  TRACE_DURATION("gfx", "EngineRenderer::DrawOverlaysToModel");

  if (layers.size() <= 1) {
    return nullptr;
  }

  std::vector<escher::Object> layer_objects;
  layer_objects.reserve(layers.size() - 1);

  // Render each layer, except the bottom one. Create an escher::Object for
  // each layer, which will be composited as part of rendering the final
  // layer.
  auto recycler = escher_->resource_recycler();
  for (size_t i = 1; i < layers.size(); ++i) {
    auto layer = layers[i];
    auto texture = escher::Texture::New(
        recycler, GetLayerFramebufferImage(layer->width(), layer->height()),
        vk::Filter::eLinear);

    DrawLayer(frame, target_presentation_time, layers[i], texture->image(),
              nullptr);

    // TODO(SCN-1093): it would be preferable to insert barriers instead of
    // using semaphores.
    auto semaphore = escher::Semaphore::New(escher_->vk_device());
    frame->SubmitPartialFrame(semaphore);
    texture->image()->SetWaitSemaphore(std::move(semaphore));

    auto material = escher::Material::New(layer->color(), std::move(texture));
    material->set_opaque(layer->opaque());

    layer_objects.push_back(escher::Object::NewRect(
        escher::Transform(layer->translation()), std::move(material)));
  }

  return std::make_unique<escher::Model>(std::move(layer_objects));
}

// Helper function for DrawLayer().
static void InitEscherStage(
    escher::Stage* stage, const escher::ViewingVolume& viewing_volume,
    const std::vector<AmbientLightPtr>& ambient_lights,
    const std::vector<DirectionalLightPtr>& directional_lights) {
  stage->set_viewing_volume(viewing_volume);

  if (ambient_lights.empty()) {
    constexpr float kIntensity = 0.3f;
    FXL_LOG(WARNING) << "scenic::gfx::Compositor::InitEscherStage(): no "
                        "ambient light was provided.  Using one with "
                        "intensity: "
                     << kIntensity << ".";
    stage->set_fill_light(escher::AmbientLight(kIntensity));
  } else {
    if (ambient_lights.size() > 1) {
      FXL_LOG(WARNING)
          << "scenic::gfx::Compositor::InitEscherStage(): only a single "
             "ambient light is supported, but "
          << ambient_lights.size() << " were provided.  Using the first one.";
    }
    stage->set_fill_light(escher::AmbientLight(ambient_lights[0]->color()));
  }

  if (directional_lights.empty()) {
    constexpr float kHeading = 1.5f * M_PI;
    constexpr float kElevation = 1.5f * M_PI;
    constexpr float kIntensity = 0.3f;
    constexpr float kDispersion = 0.15f * M_PI;
    FXL_LOG(WARNING) << "scenic::gfx::Compositor::InitEscherStage(): no "
                        "directional light was provided (heading: "
                     << kHeading << ", elevation: " << kElevation
                     << ", intensity: " << kIntensity << ").";
    stage->set_key_light(
        escher::DirectionalLight(escher::vec2(kHeading, kElevation),
                                 kDispersion, escher::vec3(kIntensity)));
  } else {
    if (directional_lights.size() > 1) {
      FXL_LOG(WARNING)
          << "scenic::gfx::Compositor::InitEscherStage(): only a single "
             "directional light is supported, but "
          << directional_lights.size()
          << " were provided.  Using the first one.";
    }
    auto& light = directional_lights[0];
    stage->set_key_light(escher::DirectionalLight(
        light->direction(), 0.15f * M_PI, light->color()));
  }
}

void EngineRenderer::DrawLayer(const escher::FramePtr& frame,
                               zx_time_t target_presentation_time, Layer* layer,
                               const escher::ImagePtr& output_image,
                               const escher::Model* overlay_model) {
  TRACE_DURATION("gfx", "EngineRenderer::DrawLayer");
  FXL_DCHECK(layer->IsDrawable());

  float stage_width = static_cast<float>(output_image->width());
  float stage_height = static_cast<float>(output_image->height());

  if (layer->size().x != stage_width || layer->size().y != stage_height) {
    // TODO(SCN-248): Should be able to render into a viewport of the
    // output image, but we're not that fancy yet.
    layer->error_reporter()->ERROR()
        << "TODO(MZ-248): scenic::gfx::EngineRenderer::DrawLayer()"
           ": layer size of "
        << layer->size().x << "x" << layer->size().y
        << " does not match output image size of " << stage_width << "x"
        << stage_height;
    return;
  }

  auto& renderer = layer->renderer();
  auto& scene = renderer->camera()->scene();

  escher::Stage stage;
  InitEscherStage(&stage, layer->GetViewingVolume(), scene->ambient_lights(),
                  scene->directional_lights());
  escher::Model model(renderer->CreateDisplayList(renderer->camera()->scene(),
                                                  escher::vec2(layer->size())));

  // Set the renderer's shadow mode, and generate a shadow map if necessary.
  escher::ShadowMapPtr shadow_map;
  switch (renderer->shadow_technique()) {
    case ::fuchsia::ui::gfx::ShadowTechnique::UNSHADOWED:
      paper_renderer_->set_shadow_type(escher::PaperRendererShadowType::kNone);
      break;
    case ::fuchsia::ui::gfx::ShadowTechnique::SCREEN_SPACE:
      paper_renderer_->set_shadow_type(escher::PaperRendererShadowType::kSsdo);
      break;
    case ::fuchsia::ui::gfx::ShadowTechnique::MOMENT_SHADOW_MAP:
      FXL_DLOG(WARNING) << "Moment shadow maps not implemented";
    // Fallthrough to regular shadow maps.
    case ::fuchsia::ui::gfx::ShadowTechnique::SHADOW_MAP:
      paper_renderer_->set_shadow_type(
          escher::PaperRendererShadowType::kShadowMap);

      shadow_map = shadow_renderer_->GenerateDirectionalShadowMap(
          frame, stage, model, stage.key_light().direction(),
          stage.key_light().color());
      break;
  }

  auto draw_frame_lambda = [this, paper_renderer{paper_renderer_.get()}, frame,
                            target_presentation_time, &stage, &model,
                            &output_image, &shadow_map,
                            &overlay_model](escher::Camera camera) {
    if (camera.pose_buffer()) {
      camera.SetLatchedPoseBuffer(pose_buffer_latching_shader_->LatchPose(
          frame, camera, camera.pose_buffer(), target_presentation_time));
    }
    paper_renderer->DrawFrame(frame, stage, model, camera, output_image,
                              shadow_map, overlay_model);
  };

  if (renderer->camera()->IsKindOf<StereoCamera>()) {
    auto stereo_camera = renderer->camera()->As<StereoCamera>();
    for (const auto eye : {StereoCamera::Eye::LEFT, StereoCamera::Eye::RIGHT}) {
      escher::Camera camera = stereo_camera->GetEscherCamera(eye);
      draw_frame_lambda(camera);
    }
  } else {
    escher::Camera camera =
        renderer->camera()->GetEscherCamera(stage.viewing_volume());
    draw_frame_lambda(camera);
  }
}

escher::ImagePtr EngineRenderer::GetLayerFramebufferImage(uint32_t width,
                                                          uint32_t height) {
  escher::ImageInfo info;
  info.format = vk::Format::eB8G8R8A8Srgb;
  info.width = width;
  info.height = height;
  info.usage = vk::ImageUsageFlagBits::eColorAttachment |
               vk::ImageUsageFlagBits::eSampled;
  return escher_->image_cache()->NewImage(info);
}

}  // namespace gfx
}  // namespace scenic_impl
