// 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/lib/ui/gfx/resources/renderers/renderer.h"

#include <trace/event.h>

#include "lib/escher/impl/ssdo_sampler.h"
#include "lib/escher/renderer/renderer.h"
#include "lib/escher/scene/model.h"
#include "lib/escher/scene/stage.h"

#include "garnet/lib/ui/gfx/engine/session.h"
#include "garnet/lib/ui/gfx/resources/camera.h"
#include "garnet/lib/ui/gfx/resources/dump_visitor.h"
#include "garnet/lib/ui/gfx/resources/import.h"
#include "garnet/lib/ui/gfx/resources/material.h"
#include "garnet/lib/ui/gfx/resources/nodes/entity_node.h"
#include "garnet/lib/ui/gfx/resources/nodes/node.h"
#include "garnet/lib/ui/gfx/resources/nodes/opacity_node.h"
#include "garnet/lib/ui/gfx/resources/nodes/scene.h"
#include "garnet/lib/ui/gfx/resources/nodes/shape_node.h"
#include "garnet/lib/ui/gfx/resources/nodes/traversal.h"
#include "garnet/lib/ui/gfx/resources/shapes/circle_shape.h"
#include "garnet/lib/ui/gfx/resources/shapes/shape.h"
#include "garnet/lib/ui/gfx/resources/view.h"
#include "garnet/lib/ui/gfx/resources/view_holder.h"

namespace scenic_impl {
namespace gfx {

const ResourceTypeInfo Renderer::kTypeInfo = {ResourceType::kRenderer,
                                              "Renderer"};

const uint32_t Renderer::kRequiredSwapchainPixelMultiple =
    escher::impl::SsdoSampler::kSsdoAccelDownsampleFactor;

Renderer::Renderer(Session* session, ResourceId id)
    : Resource(session, id, Renderer::kTypeInfo) {
  escher::MaterialPtr default_material_ =
      fxl::MakeRefCounted<escher::Material>();
  default_material_->set_color(escher::vec3(0.f, 0.f, 0.f));
}

Renderer::~Renderer() = default;

std::vector<escher::Object> Renderer::CreateDisplayList(
    const ScenePtr& scene, escher::vec2 screen_dimensions,
    escher::BatchGpuUploader* uploader) {
  TRACE_DURATION("gfx", "Renderer::CreateDisplayList");

  VisitorContext visitor_context(default_material_, /* opacity= */ 1.0f,
                                 disable_clipping_, uploader);

  // Construct a display list from the tree.
  Visitor v(std::move(visitor_context));
  scene->Accept(&v);

  return v.TakeDisplayList();
}

void Renderer::SetCamera(CameraPtr camera) { camera_ = std::move(camera); }

bool Renderer::SetShadowTechnique(
    ::fuchsia::ui::gfx::ShadowTechnique technique) {
  shadow_technique_ = technique;
  return true;
}

void Renderer::DisableClipping(bool disable_clipping) {
  disable_clipping_ = disable_clipping;
}

Renderer::Visitor::Visitor(Renderer::VisitorContext context)
    : context_(context) {}

std::vector<escher::Object> Renderer::Visitor::TakeDisplayList() {
  return std::move(display_list_);
}

void Renderer::Visitor::Visit(Memory* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(Image* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(ImagePipe* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(Buffer* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(View* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(ViewHolder* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(EntityNode* r) { VisitNode(r); }

void Renderer::Visitor::Visit(OpacityNode* r) {
  if (r->opacity() == 0) {
    return;
  }

  float old_opacity = context_.opacity;
  context_.opacity *= r->opacity();

  VisitNode(r);

  context_.opacity = old_opacity;
}

void Renderer::Visitor::VisitNode(Node* r) {
  size_t previous_display_size = display_list_.size();

  VisitAndMaybeClipNode(r);

  bool view_is_rendering_element = display_list_.size() > previous_display_size;
  if (r->view() && view_is_rendering_element) {
    // TODO(SCN-1099) Add a test to ensure this signal isn't triggered when this
    // view is not rendering.
    r->view()->SignalRender();
  }
}

std::vector<escher::Object> Renderer::Visitor::GenerateClippeeDisplayList(
    Node* r) {
  // Gather the escher::Objects corresponding to the children and imports.
  VisitorContext clippee_context(context_);
  Renderer::Visitor clippee_visitor(clippee_context);
  ForEachChildAndImportFrontToBack(
      *r, [&clippee_visitor](Node* node) { node->Accept(&clippee_visitor); });

  return clippee_visitor.TakeDisplayList();
}

std::vector<escher::Object> Renderer::Visitor::GenerateClipperDisplayList(
    Node* r) {
  // Create a VisitorContext with no material for the clippers.
  const escher::MaterialPtr kNoMaterial;
  VisitorContext clipper_context(kNoMaterial, context_.opacity,
                                 context_.disable_clipping,
                                 context_.batch_gpu_uploader);

  // The node's children and imports must be clipped by the
  // Shapes/ShapeNodes amongst the node's parts.  First gather the
  // escher::Objects corresponding to these ShapeNodes.
  Renderer::Visitor clipper_visitor(clipper_context);
  ForEachPartFrontToBack(*r, [&clipper_visitor](Node* node) {
    if (node->IsKindOf<ShapeNode>()) {
      node->Accept(&clipper_visitor);
    } else {
      // TODO(MZ-167): accept non-ShapeNode parts.  This might already work
      // (i.e. it might be as simple as saying
      // "part->Accept(&part_visitor)"), but this hasn't been tested.
      FXL_LOG(WARNING) << "Renderer::Visitor::VisitNode(): Clipping only "
                          "supports ShapeNode parts.";
    }
  });

  return clipper_visitor.TakeDisplayList();
}

void Renderer::Visitor::VisitAndMaybeClipNode(Node* r) {
  // If not clipping, recursively visit all descendants in the normal fashion.
  if (!r->clip_to_self() || context_.disable_clipping) {
    ForEachDirectDescendantFrontToBack(
        *r, [this](Node* node) { node->Accept(this); });
    return;
  }

  // Check whether there's anything to clip.
  auto clippees = GenerateClippeeDisplayList(r);
  if (clippees.empty()) {
    // Nothing to clip!  Just draw the parts as usual.
    ForEachPartFrontToBack(*r, [this](Node* node) { node->Accept(this); });
    return;
  }

  // Gather the objects used to form the clip regions.
  auto clippers = GenerateClipperDisplayList(r);
  if (clippers.empty()) {
    // The clip is empty so there's nothing to draw.
    return;
  }

  // Some chicanery is required to draw in the order specified by
  // ForEachDirectDescendantFrontToBack().  Namely, all clippers that are
  // also visible (i.e. have a non-null material) need to be drawn twice:
  // once as a clipper (with the material removed), and later as a clippee
  // (with the material intact).
  // TODO(MZ-176): are there some constraints that we can put on allowable
  // elevations that would allow us to relax the draw-order constraint,
  // and thereby not render the objects twice?
  for (auto& obj : clippers) {
    if (obj.material()) {
      clippees.push_back(obj);
      obj.set_material(escher::MaterialPtr());
    }
  }

  // Create a new "clip object" from the display-lists generated by the
  // two visitors above.
  display_list_.push_back(
      escher::Object(std::move(clippers), std::move(clippees)));
}

void Renderer::Visitor::Visit(Scene* r) { VisitNode(r); }

void Renderer::Visitor::Visit(Compositor* r) { FXL_DCHECK(false); }

void Renderer::Visitor::Visit(DisplayCompositor* r) { FXL_DCHECK(false); }

void Renderer::Visitor::Visit(LayerStack* r) { FXL_DCHECK(false); }

void Renderer::Visitor::Visit(Layer* r) { FXL_DCHECK(false); }

void Renderer::Visitor::Visit(ShapeNode* r) {
  auto& shape = r->shape();
  auto& material = r->material();
  if (material) {
    material->Accept(this);
  }
  if (shape) {
    escher::MaterialPtr escher_material =
        material ? material->escher_material() : context_.default_material;
    if (escher_material && context_.opacity < 1) {
      // When we want to support other material types (e.g. metallic shaders),
      // we'll need to change this. If we want to support semitransparent
      // textures and materials, we'll need more pervasive changes.
      glm::vec4 color = escher_material->color();
      color.a *= context_.opacity;
      escher_material =
          escher::Material::New(color, escher_material->texture());
      escher_material->set_opaque(false);
    }

    display_list_.push_back(
        shape->GenerateRenderObject(r->GetGlobalTransform(), escher_material));
  }
  // We don't need to call |VisitNode| because shape nodes don't have
  // children or parts.
}

void Renderer::Visitor::Visit(CircleShape* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(RectangleShape* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(RoundedRectangleShape* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(MeshShape* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(Material* r) {
  r->UpdateEscherMaterial(context_.batch_gpu_uploader);
}

void Renderer::Visitor::Visit(Import* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(Camera* r) {
  // TODO: use camera's projection matrix.
  Visit(r->scene().get());
}

void Renderer::Visitor::Visit(Renderer* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(Light* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(AmbientLight* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(DirectionalLight* r) { FXL_CHECK(false); }

void Renderer::Visitor::Visit(PointLight* r) { FXL_CHECK(false); }

}  // namespace gfx
}  // namespace scenic_impl
