// 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 "src/ui/lib/escher/paper/paper_shape_cache.h"

#include <unordered_set>

#include "src/ui/lib/escher/escher.h"
#include "src/ui/lib/escher/geometry/bounding_box.h"
#include "src/ui/lib/escher/mesh/indexed_triangle_mesh_clip.h"
#include "src/ui/lib/escher/mesh/indexed_triangle_mesh_upload.h"
#include "src/ui/lib/escher/mesh/tessellation.h"
#include "src/ui/lib/escher/renderer/batch_gpu_uploader.h"
#include "src/ui/lib/escher/shape/rounded_rect.h"
#include "src/ui/lib/escher/util/alloca.h"
#include "src/ui/lib/escher/util/hasher.h"
#include "src/ui/lib/escher/util/pair_hasher.h"
#include "src/ui/lib/escher/util/trace_macros.h"

namespace escher {

namespace {

// Returned when there is no shape to draw, for example when a circle with zero
// radius is requested, or when all vertices of a tessellated shape are clipped
// by clip planes.
const PaperShapeCacheEntry kNullCacheEntry;

// Helper used by GetRoundedRectMesh() and others.  Defined as a standalone
// function instead of a private method on PaperShapeCache to avoid needing to
// include any IndexedTriangleMesh headers in our header.
PaperShapeCacheEntry ProcessTriangleMesh2d(IndexedTriangleMesh2d<vec2> mesh,
                                           const MeshSpec& mesh_spec, const plane3* clip_planes3,
                                           size_t num_clip_planes, const BoundingBox& bounding_box,
                                           PaperRendererShadowType shadow_type, Escher* escher,
                                           BatchGpuUploader* uploader) {
  TRACE_DURATION("gfx", "PaperShapeCache::ProcessTriangleMesh2d");
  FX_DCHECK(mesh_spec == PaperShapeCache::kStandardMeshSpec());

  // Convert 3d clip planes to 2d before clipping.
  std::vector<plane2> clip_planes_vec;
  for (size_t i = 0; i < num_clip_planes; ++i) {
    // Check to make sure the incoming 3D clip plane is not parallel
    // to the z=0 plane. If the two planes intersect, add in the
    // constructed plane2 to the vector of plane2s.
    if (1.f - fabs(clip_planes3[i].dir().z) > 0.001) {
      clip_planes_vec.push_back(plane2(clip_planes3[i]));
    };
  }

  // Grab the raw pointer data from the vector
  // and update the total number of clip planes.
  plane2* clip_planes = clip_planes_vec.data();
  num_clip_planes = clip_planes_vec.size();

  IndexedTriangleMesh2d<vec2> tri_mesh;
  std::tie(tri_mesh, std::ignore) =
      IndexedTriangleMeshClip(std::move(mesh), clip_planes, num_clip_planes);

  switch (shadow_type) {
    case PaperRendererShadowType::kShadowVolume: {
      TRACE_DURATION("gfx", "PaperShapeCache::ProcessTriangleMesh2d[shadow_volume]");

      using Edge = IndexedTriangleMesh2d<vec2>::EdgeType;
      std::unordered_set<Edge, PairHasher> silhouette_edges;

      const uint32_t original_index_count = tri_mesh.index_count();
      const uint32_t original_vertex_count = tri_mesh.vertex_count();
      auto& indices = tri_mesh.indices;

      // Find silhouette edges, and generate opposite face of the shadow volume.
      {
        TRACE_DURATION("gfx", "PaperShapeCache::ProcessTriangleMesh2d[shadow_volume_1]");

        // We're going to double the number of indices in order to mirror the
        // opposite face of the shadow volume, and then add 6 indices (two
        // triangles) per silhouette edge to connect the two faces together with
        // quads.  Empirically, we estimate that there is about one silhouette
        // edge per triangle of the original mesh.
        indices.reserve(tri_mesh.index_count() * 2 + tri_mesh.triangle_count() * 6);

        for (size_t i = 0; i < original_index_count; i += 3) {
          MeshSpec::IndexType* tri = indices.data() + i;
          for (size_t j = 0; j < 3; ++j) {
            // Mirror the triangle on the opposite face of the shadow volume.
            // The index order is reversed.
            indices.push_back(tri[(3 - j) % 3] + original_vertex_count);

            // Look for silhouette edges.
            Edge edge{tri[j], tri[(j + 1) % 3]};
            Edge opposite{edge.second, edge.first};

            auto it = silhouette_edges.find(opposite);
            if (it != silhouette_edges.end()) {
              // The opposite edge was already seen in the mesh, so neither this
              // edge nor the opposite can be a silhouette edge.
              silhouette_edges.erase(it);
            } else {
              // No opposite edge was found, so this edge is a candidate to be a
              // silhouette edge (of course, it may be removed later if its
              // opposite appears).
              silhouette_edges.insert(edge);
            }
          }
        }
      }

      // Finish creating the mesh.  Extrude side faces, copy vertex attributes,
      // and add an additional kBlendWeight1 attribute for computing the shape
      // of the volume in the vertex shader.
      IndexedTriangleMesh2d<vec2, float> out_mesh;
      {
        TRACE_DURATION("gfx", "PaperShapeCache::ProcessTriangleMesh2d[shadow_volume_2]");

        // Extrude side faces between matching silhouette edges.  Flip the edge
        // direction in order to maintain the desired winding order.
        for (auto& edge : silhouette_edges) {
          indices.push_back(edge.second);
          indices.push_back(edge.first);
          indices.push_back(edge.first + original_vertex_count);
          indices.push_back(edge.first + original_vertex_count);
          indices.push_back(edge.second + original_vertex_count);
          indices.push_back(edge.second);
        }

        // Create the output mesh.  Gank the modified indices from the previous
        // mesh, then duplicate the mirrored vertices (there will be exactly
        // twice as many vertices in the new mesh).  We also need an additional
        // attribute that is used as a switch, so that the mirrored vertices are
        // "extruded" away from the light source, whereas the original vertices
        // are left in their original world-space positions; this attribute is 0
        // for original vertices and 1 for mirrored vertices.
        out_mesh.indices = std::move(tri_mesh.indices);
        out_mesh.positions.reserve(original_vertex_count * 2);
        out_mesh.attributes1.reserve(original_vertex_count * 2);
        out_mesh.attributes2.reserve(original_vertex_count * 2);
        for (size_t i = 0; i < original_vertex_count; ++i) {
          out_mesh.positions.push_back(tri_mesh.positions[i]);
          out_mesh.attributes1.push_back(tri_mesh.attributes1[i]);
          out_mesh.attributes2.push_back(0);
        }
        for (size_t i = 0; i < original_vertex_count; ++i) {
          out_mesh.positions.push_back(tri_mesh.positions[i]);
          out_mesh.attributes1.push_back(tri_mesh.attributes1[i]);
          out_mesh.attributes2.push_back(1);
        }
      }

      FX_DCHECK(out_mesh.IsValid());
      FX_DCHECK(mesh_spec == PaperShapeCache::kStandardMeshSpec());

      const uint32_t shadow_volume_index_count = out_mesh.index_count();
      return PaperShapeCacheEntry{
          .mesh =
              IndexedTriangleMeshUpload(escher, uploader, PaperShapeCache::kShadowVolumeMeshSpec(),
                                        bounding_box, std::move(out_mesh)),
          .num_indices = original_index_count,
          .num_shadow_volume_indices = shadow_volume_index_count,
      };
    } break;
    default:
      auto num_indices = tri_mesh.index_count();
      return PaperShapeCacheEntry{
          .mesh = IndexedTriangleMeshUpload(escher, uploader, mesh_spec, bounding_box,
                                            std::move(tri_mesh)),
          .num_indices = num_indices,
          .num_shadow_volume_indices = 0,
      };
  }
}

PaperShapeCacheEntry ProcessTriangleMesh3d(IndexedTriangleMesh3d<vec2> mesh,
                                           const MeshSpec& mesh_spec, const plane3* clip_planes,
                                           size_t num_clip_planes, const BoundingBox& bounding_box,
                                           PaperRendererShadowType shadow_type, Escher* escher,
                                           BatchGpuUploader* uploader) {
  TRACE_DURATION("gfx", "PaperShapeCache::ProcessTriangleMesh3d");
  FX_DCHECK((mesh_spec == MeshSpec{{MeshAttribute::kPosition3D, MeshAttribute::kUV}}));

  IndexedTriangleMesh3d<vec2> tri_mesh;
  std::tie(tri_mesh, std::ignore) =
      IndexedTriangleMeshClip(std::move(mesh), clip_planes, num_clip_planes);

  auto index_count = tri_mesh.index_count();
  return PaperShapeCacheEntry{
      .mesh =
          IndexedTriangleMeshUpload(escher, uploader, mesh_spec, bounding_box, std::move(tri_mesh)),
      .num_indices = index_count,
      .num_shadow_volume_indices = 0,
  };
}
}  // namespace

PaperShapeCache::PaperShapeCache(EscherWeakPtr escher, const PaperRendererConfig& config)
    : escher_(std::move(escher)), shadow_type_(config.shadow_type) {}

PaperShapeCache::~PaperShapeCache() { FX_DCHECK(!uploader_); }

void PaperShapeCache::BeginFrame(BatchGpuUploader* uploader, uint64_t frame_number) {
  FX_DCHECK(uploader && !uploader_);
  uploader_ = uploader;

  // Workaround because Scenic Screenshotter always uses frame #0.
  if (frame_number > 0) {
    FX_DCHECK(frame_number >= frame_number_)
        << "old/new frame#: " << frame_number_ << "/" << frame_number;
    frame_number_ = frame_number;
  }
}

void PaperShapeCache::EndFrame() {
  FX_DCHECK(uploader_);
  uploader_ = nullptr;

  TRACE_DURATION("gfx", "PaperShapeCache::EndFrame", "cache_hits",
                 cache_hit_count_ + cache_hit_after_plane_culling_count_,
                 "cache_hits_after_plane_culling", cache_hit_after_plane_culling_count_,
                 "cache_misses", cache_miss_count_);
  cache_hit_count_ = 0;
  cache_hit_after_plane_culling_count_ = 0;
  cache_miss_count_ = 0;

  TrimCache();
}

void PaperShapeCache::SetConfig(const PaperRendererConfig& config) {
  FX_DCHECK(!uploader_) << "Cannot change config in the middle of a frame.";
  if (shadow_type_ == config.shadow_type)
    return;

  shadow_type_ = config.shadow_type;

  // NOTE: could optimize this to retain cached meshes in some cases.  For
  // example, switching shadow types kShadowMap <--> kNone.  For now we just
  // blow away the cache any time there is a change.
  cache_.clear();
}

const PaperShapeCacheEntry& PaperShapeCache::GetRoundedRectMesh(const RoundedRectSpec& spec,
                                                                const plane3* clip_planes,
                                                                size_t num_clip_planes) {
  TRACE_DURATION("gfx", "PaperShapeCache::GetRoundedRectMesh");
  if (spec.width <= 0.f || spec.height <= 0.f)
    return kNullCacheEntry;

  Hash rect_hash;
  {
    Hasher h;
    h.u32(EnumCast(ShapeType::kRoundedRect));
    h.struc(spec);
    rect_hash = h.value();
  }

  const BoundingBox bounding_box(-0.5f * vec3(spec.width, spec.height, 0),
                                 0.5f * vec3(spec.width, spec.height, 0));

  return GetShapeMesh(
      rect_hash, bounding_box, clip_planes, num_clip_planes,
      [this, &spec, &bounding_box](const plane3* unculled_clip_planes,
                                   size_t num_unculled_clip_planes) {
        // No mesh was found, so we need to generate one.

        uint32_t vertex_count;
        uint32_t index_count;
        std::tie(vertex_count, index_count) = GetRoundedRectMeshVertexAndIndexCounts(spec);

        MeshSpec mesh_spec{{MeshAttribute::kPosition2D, MeshAttribute::kUV}};
        IndexedTriangleMesh2d<vec2> mesh;
        mesh.resize_indices(index_count);
        mesh.resize_vertices(vertex_count);

        GenerateRoundedRectIndices(spec, mesh_spec, mesh.indices.data(), mesh.total_index_bytes());
        GenerateRoundedRectVertices(spec, mesh_spec, mesh.positions.data(),
                                    mesh.total_position_bytes(), mesh.attributes1.data(),
                                    mesh.total_attribute1_bytes());

        return ProcessTriangleMesh2d(std::move(mesh), mesh_spec, unculled_clip_planes,
                                     num_unculled_clip_planes, bounding_box, shadow_type_,
                                     escher_.get(), uploader_);
      });
}

const PaperShapeCacheEntry& PaperShapeCache::GetCircleMesh(float radius, const plane3* clip_planes,
                                                           size_t num_clip_planes) {
  TRACE_DURATION("gfx", "PaperShapeCache::GetCircleMesh");
  if (radius <= 0.f)
    return kNullCacheEntry;

  Hash circle_hash;
  {
    Hasher h;
    h.u32(EnumCast(ShapeType::kCircle));
    h.f32(radius);
    circle_hash = h.value();
  }

  const BoundingBox bounding_box(-vec3(radius, radius, 0), vec3(radius, radius, 0));

  return GetShapeMesh(
      circle_hash, bounding_box, clip_planes, num_clip_planes,
      [this, radius, &bounding_box](const plane3* unculled_clip_planes,
                                    size_t num_unculled_clip_planes) {
        // No mesh was found, so we need to generate one.

        MeshSpec mesh_spec{{MeshAttribute::kPosition2D, MeshAttribute::kUV}};
        constexpr uint32_t kCircleSubdivisions = 3;
        IndexedTriangleMesh2d<vec2> mesh =
            NewCircleIndexedTriangleMesh(mesh_spec, kCircleSubdivisions, vec2(0, 0), radius);

        return ProcessTriangleMesh2d(std::move(mesh), mesh_spec, unculled_clip_planes,
                                     num_unculled_clip_planes, bounding_box, shadow_type_,
                                     escher_.get(), uploader_);
      });
}

const PaperShapeCacheEntry& PaperShapeCache::GetRectMesh(vec2 min, vec2 max,
                                                         const plane3* clip_planes,
                                                         size_t num_clip_planes) {
  TRACE_DURATION("gfx", "PaperShapeCache::GetRectMesh");

  const BoundingBox bounding_box = BoundingBox::NewChecked(vec3(min, 0), vec3(max, 0), 1);
  if (bounding_box.is_empty()) {
    return kNullCacheEntry;
  }

  Hash rect_hash;
  {
    Hasher h;
    h.u32(EnumCast(ShapeType::kRect));
    h.f32(min.x);
    h.f32(min.y);
    h.f32(max.x);
    h.f32(max.y);
    rect_hash = h.value();
  }

  return GetShapeMesh(
      rect_hash, bounding_box, clip_planes, num_clip_planes,
      [this, min, max, &bounding_box](const plane3* unculled_clip_planes,
                                      size_t num_unculled_clip_planes) {
        // No mesh was found, so we need to generate one.

        MeshSpec mesh_spec{{MeshAttribute::kPosition2D, MeshAttribute::kUV}};
        IndexedTriangleMesh2d<vec2> mesh;
        mesh.indices = std::vector<MeshSpec::IndexType>{0, 1, 2, 0, 2, 3};
        mesh.positions = std::vector<vec2>{vec2(min.x, min.y), vec2(max.x, min.y),
                                           vec2(max.x, max.y), vec2(min.x, max.y)};
        mesh.attributes1 = std::vector<vec2>{vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1)};

        return ProcessTriangleMesh2d(std::move(mesh), mesh_spec, unculled_clip_planes,
                                     num_unculled_clip_planes, bounding_box, shadow_type_,
                                     escher_.get(), uploader_);
      });
}

const PaperShapeCacheEntry& PaperShapeCache::GetBoxMesh(const plane3* clip_planes,
                                                        size_t num_clip_planes) {
  Hash box_hash;
  {
    Hasher h;
    h.u32(EnumCast(ShapeType::kBox));
    box_hash = h.value();
  }

  const BoundingBox bounding_box(vec3(0, 0, 0), vec3(1, 1, 1));
  return GetShapeMesh(
      box_hash, bounding_box, nullptr, 0,
      [this, &bounding_box](const plane3* unculled_clip_planes, size_t num_unculled_clip_planes) {
        // No mesh was found, so we need to generate one.
        MeshSpec mesh_spec{{MeshAttribute::kPosition3D, MeshAttribute::kUV}};
        IndexedTriangleMesh3d<vec2> mesh = NewCubeIndexedTriangleMesh(mesh_spec);
        return ProcessTriangleMesh3d(std::move(mesh), mesh_spec, unculled_clip_planes,
                                     num_unculled_clip_planes, bounding_box, shadow_type_,
                                     escher_.get(), uploader_);
      });
}

const PaperShapeCacheEntry& PaperShapeCache::GetShapeMesh(const Hash& shape_hash,
                                                          const BoundingBox& bounding_box,
                                                          const plane3* clip_planes,
                                                          size_t num_clip_planes,
                                                          CacheMissMeshGenerator mesh_generator) {
  TRACE_DURATION("gfx", "PaperShapeCache::GetShapeMesh");
  FX_DCHECK(clip_planes || num_clip_planes == 0);

  // We will first look up the mesh via |lookup_hash|, but may later use
  // |shape_hash| as an optimization.
  Hash lookup_hash;
  {
    Hasher h(shape_hash);
    for (size_t i = 0; i < num_clip_planes; ++i) {
      h.struc(clip_planes[i]);
    }
    lookup_hash = h.value();
  }

  // Attempt to find a pre-clipped shape in the cache.
  // TODO(ES-142): do we need to quantize the clip_planes to avoid
  // numerical precision errors when the planes are transformed into the
  // object's coordinate system?  Seems like this should perhaps be the
  // responsibility of the caller.
  // TODO(ES-142): similarly, the caller should be responsible for
  // sorting the planes if desired.  For example, if the same planes are
  // provided in a different order, the cache would fail to find the pre-clipped
  // mesh.
  if (auto* entry = FindEntry(lookup_hash)) {
    ++cache_hit_count_;
    return *entry;
  }

  // There are two separate optimizations to perform against the bounding box:
  //   1) If a plane clips all 8 corners then don't bother considering the other
  //      planes.  Return nullptr because there is nothing to render.
  //   2) If a plane does not clip any of the 8 corners, then proceed to the
  //      next plane.  Don't bother clipping individual triangles with such
  //      planes, because we know they will all pass.
  size_t num_unculled_clip_planes = num_clip_planes;
  plane3* unculled_clip_planes = ESCHER_ALLOCA(plane3, num_clip_planes);
  if (auto bbox_was_completely_clipped = CullPlanesAgainstBoundingBox(
          bounding_box, clip_planes, unculled_clip_planes, &num_unculled_clip_planes)) {
    // Cache a null MeshPtr, so that a subsequent lookup won't have to do
    // the CPU work of testing planes against the bounding box.
    ++cache_hit_count_;

    AddEntry(lookup_hash, kNullCacheEntry);
    return kNullCacheEntry;
  }

  // If some of the planes were culled, recompute the lookup hash and try again.
  Hash lookup_hash2;
  if (num_clip_planes == num_unculled_clip_planes) {
    // No planes were culled; we will need to tessellate/clip/upload a new Mesh.
    // When we cache the new mesh, we will only create one entry for it.
    lookup_hash2 = lookup_hash;
  } else {
    FX_DCHECK(num_unculled_clip_planes < num_clip_planes) << "insane.";

    // The following is an optimization for the common case where at least one
    // clip plane is culled.  This avoids each frame failing the |lookup_hash|
    // lookup, then culling the clip planes in order to perform a successful
    // lookup with |lookup_hash2|.  Instead, by caching the result with both
    // |lookup_hash| and |lookup_hash2| we allow subsequent frames to succeed
    // immediately with |lookup_hash|.
    //
    // The reason that we don't only store the result under |lookup_hash| is the
    // also-common case where the initial set of planes differs each frame, but
    // the set of unculled planes remaining after culling is the same from frame
    // to frame.  In other words, the case where |lookup_hash| differs, but
    // |lookup_hash2| is the same.  For example, this would occur when the mesh
    // is moving within the interior of a large clip volume.  In this case, all
    // planes are being translated with respect to the mesh, so |lookup_hash|
    // differs, but all planes are being culled, so |lookup_hash2| is the same.

    // Compute |lookup_hash2| like |lookup_hash|, except use culled clip planes.
    Hasher h(shape_hash);
    for (size_t i = 0; i < num_unculled_clip_planes; ++i) {
      h.struc(unculled_clip_planes[i]);
    }
    lookup_hash2 = h.value();

    if (auto* entry = FindEntry(lookup_hash2)) {
      // NOTE: FX_DCHECK(entry->mesh) might seem reasonable here, but there
      // still is a possibility that the generated mesh will be completely
      // clipped.

      // Woo-hoo!  We found the mesh under the second lookup key.  Before
      // returning it, re-cache it under the original lookup key so that it can
      // be looked up more efficiently next time.
      ++cache_hit_after_plane_culling_count_;
      AddEntry(lookup_hash, *entry);

      // TODO(ES-142): by caching under |lookup_hash| here, there is the
      // possibility of pathological behavior under "stop and go" motion.  For
      // example, if an unclipped mesh stops for a few frames then it will be
      // looked up successfully via |lookup_hash|, but when it starts to move
      // again it may find that the |lookup_hash2| entry has already been
      // evicted.  A solution might a variant AddEntry(key, key2, mesh) such
      // that whenever a mesh is looked up via |key|, the timestamp for |key2|
      // is also updated.

      return *entry;
    }
  }
  ++cache_miss_count_;

  PaperShapeCacheEntry new_entry;
  {
    TRACE_DURATION("gfx", "PaperShapeCache::GetShapeMesh[mesh_generator]");
    new_entry = mesh_generator(unculled_clip_planes, num_unculled_clip_planes);
  }

  AddEntry(lookup_hash, new_entry);
  if (lookup_hash2 != lookup_hash) {
    AddEntry(lookup_hash2, new_entry);
  }
  // Slightly inefficient to look up the newly-inserted entry, but nothing
  // compared to what we just did to create/upload the new mesh.
  return *FindEntry(lookup_hash);
}

bool PaperShapeCache::CullPlanesAgainstBoundingBox(const BoundingBox& bounding_box,
                                                   const plane3* planes,
                                                   plane3* unculled_planes_out,
                                                   size_t* num_planes_inout) {
  TRACE_DURATION("gfx", "PaperShapeCache::CullPlanesAgainstBoundingBox");
  const size_t num_planes = *num_planes_inout;
  size_t& num_unculled_planes_out = *num_planes_inout = 0;

  for (size_t i = 0; i < num_planes; ++i) {
    auto& plane = planes[i];
    const uint32_t num_clipped_corners = bounding_box.NumClippedCorners(plane);
    if (num_clipped_corners > 0) {
      unculled_planes_out[num_unculled_planes_out++] = plane;
      if (num_clipped_corners == 8)
        return true;
    }
  }
  return false;
}

PaperShapeCacheEntry* PaperShapeCache::FindEntry(const Hash& hash) {
  auto it = cache_.find(hash);
  if (it != cache_.end()) {
    it->second.last_touched_frame = frame_number_;
    return &it->second;
  }
  return nullptr;
}

void PaperShapeCache::AddEntry(const Hash& hash, PaperShapeCacheEntry entry) {
  auto it = cache_.find(hash);
  if (it != cache_.end()) {
    FX_DCHECK(false) << "CacheEntry already exists.";
    return;
  }
  FX_DCHECK(entry.last_touched_frame <= frame_number_);
  entry.last_touched_frame = frame_number_;
  cache_.insert({hash, std::move(entry)});
}

// TODO(SCN-957): rather than rolling our own ad-hoc cache eviction strategy,
// (which is already a performance bottleneck) we should plug in a reusable
// cache that performs better and is well-tested.
void PaperShapeCache::TrimCache() {
  TRACE_DURATION("gfx", "PaperShapeCache::TrimCache", "num_entries", cache_.size());
  for (auto it = cache_.begin(); it != cache_.end();) {
    if (frame_number_ - it->second.last_touched_frame >= kNumFramesBeforeEviction) {
      TRACE_DURATION("gfx", "PaperShapeCache::TrimCache[erase]");
      it = cache_.erase(it);
    } else {
      ++it;
    }
  }
}

}  // namespace escher
