/*
 * Copyright 2017 The Cobalt Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef COBALT_RENDERER_RASTERIZER_SKIA_HARDWARE_MESH_H_
#define COBALT_RENDERER_RASTERIZER_SKIA_HARDWARE_MESH_H_

#include <memory>
#include <vector>

#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/renderer/backend/egl/graphics_context.h"
#include "cobalt/renderer/rasterizer/skia/vertex_buffer_object.h"
#include "third_party/glm/glm/vec2.hpp"
#include "third_party/glm/glm/vec3.hpp"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {

class HardwareMesh : public render_tree::Mesh {
 public:
  HardwareMesh(
      std::unique_ptr<std::vector<render_tree::Mesh::Vertex> > vertices,
      DrawMode draw_mode, backend::GraphicsContextEGL* cobalt_context)
      : vertices_(std::move(vertices)),
        draw_mode_(CheckDrawMode(draw_mode)),
        cobalt_context_(cobalt_context) {
    DCHECK(vertices_);
  }

  uint32 GetEstimatedSizeInBytes() const override;

  // Float array of vertices, contiguously interleaved X, Y, Z, U, V coords.
  const float* GetVertices() const {
    DCHECK(vertices_ && vertices_->size());
    return reinterpret_cast<const float*>(vertices_->data());
  }

  const size_t GetVertexCount() const {
    DCHECK(vertices_);
    return vertices_->size();
  }

  const render_tree::Mesh::DrawMode GetDrawMode() const {
    return draw_mode_ == GL_TRIANGLE_FAN
               ? render_tree::Mesh::DrawMode::kDrawModeTriangleFan
               : draw_mode_ == GL_TRIANGLE_STRIP
                     ? render_tree::Mesh::DrawMode::kDrawModeTriangleStrip
                     : render_tree::Mesh::DrawMode::kDrawModeTriangles;
  }

  // Obtains a vertex buffer object from this mesh. Called right before first
  // rendering it so that the graphics context has already been made current.
  const VertexBufferObject* GetVBO() const;

  ~HardwareMesh() override;

 private:
  static GLenum CheckDrawMode(DrawMode mode) {
    switch (mode) {
      case kDrawModeTriangles:
        return GL_TRIANGLES;
      case kDrawModeTriangleStrip:
        return GL_TRIANGLE_STRIP;
      case kDrawModeTriangleFan:
        return GL_TRIANGLE_FAN;
      default:
        NOTREACHED() << "Unsupported Mesh DrawMode detected, "
                        "defaulting to GL_TRIANGLE_STRIP";
        return GL_TRIANGLE_STRIP;
    }
  }

  // Logically the mesh is the same, but internally upon fetching the VBO,
  // the vertex list has been copied from CPU to GPU memory.
  mutable std::unique_ptr<std::vector<render_tree::Mesh::Vertex> > vertices_;
  mutable std::unique_ptr<VertexBufferObject> vbo_;
  const GLenum draw_mode_;
  backend::GraphicsContextEGL* cobalt_context_;

  // Used to keep track of the thread from which we create the vertex buffer
  // object, so that we can ensure that regardless of which thread destroys
  // this HardwareMesh instance, we will always ensure that the owned VBO is
  // destroyed on the thread it was created from.
  mutable base::MessageLoop* rasterizer_message_loop_ = nullptr;
};

}  // namespace skia
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // COBALT_RENDERER_RASTERIZER_SKIA_HARDWARE_MESH_H_
