// Copyright 2017 Google Inc. 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_EGL_DRAW_OBJECT_H_
#define COBALT_RENDERER_RASTERIZER_EGL_DRAW_OBJECT_H_

#include <GLES2/gl2.h>

#include "base/callback.h"
#include "base/optional.h"
#include "cobalt/base/type_id.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect.h"
#include "cobalt/render_tree/color_rgba.h"
#include "cobalt/render_tree/rounded_corners.h"
#include "cobalt/renderer/backend/egl/texture.h"
#include "cobalt/renderer/rasterizer/egl/graphics_state.h"
#include "cobalt/renderer/rasterizer/egl/shader_program_manager.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace egl {

// Base type to rasterize various objects via GL commands.
class DrawObject {
 public:
  typedef base::optional<render_tree::RoundedCorners> OptionalRoundedCorners;

  // Callback to get a scratch "1D" texture of the given |size|. If such a
  // request was previously fulfilled for the relevant render tree node, then
  // the cached |texture| and |region| will be returned, and |is_new| will be
  // false; this is a hint as to whether the texture region needs to be
  // initialized. If the request succeeded, then |texture| will point to a 2D
  // texture whose |region| is a row meeting the size requirement; otherwise,
  // |texture| will be nullptr.
  struct TextureInfo {
    const backend::TextureEGL* texture;
    math::RectF region;
    bool is_new;
  };
  typedef base::Callback<void(float size, TextureInfo* out_texture_info)>
      GetScratchTextureFunction;

  // Structure containing the common attributes for all DrawObjects.
  struct BaseState {
    BaseState();
    BaseState(const BaseState& other);

    math::Matrix3F transform;
    math::Rect scissor;

    // |rounded_scissor_rect| is only relevant when |rounded_scissor_corners|
    // exists.
    math::RectF rounded_scissor_rect;
    OptionalRoundedCorners rounded_scissor_corners;

    float opacity;
  };

  virtual ~DrawObject() {}

  // This stage is used to update the vertex buffer for the rasterize
  // stage. Vertex data is handled by the GraphicsState to minimize the number
  // of vertex buffers needed. Once this stage is executed, the rasterizer will
  // then notify the GraphicsState to send all vertex data from all draw
  // objects to the GPU.
  virtual void ExecuteUpdateVertexBuffer(GraphicsState* graphics_state,
      ShaderProgramManager* program_manager) = 0;

  // This stage is responsible for issuing the GPU commands to do the actual
  // rendering.
  virtual void ExecuteRasterize(GraphicsState* graphics_state,
      ShaderProgramManager* program_manager) = 0;

  // Return a TypeId that can be used to sort draw objects in order to minimize
  // state changes. This may be the class' TypeId, or the TypeId of the shader
  // program which the class uses.
  virtual base::TypeId GetTypeId() const = 0;

 protected:
  // Structures describing vertex data for rendering rounded rectangles.
  struct RCorner {
    // Constructor to transform a RCorner value into a format which the
    // shader function IsOutsideRCorner() expects. This expresses the current
    // vertex position as a scaled offset relevant for the corner, and provides
    // scalars to assist in calculating the antialiased edge. For more details,
    // see function_is_outside_rcorner.inc.
    RCorner(const float (&position)[2], const RCorner& init);
    RCorner() {}
    float x, y;
    float rx, ry;
  };
  struct RRectAttributes {
    math::RectF bounds;   // The region in which to use the rcorner data.
    RCorner rcorner;
  };

  DrawObject() {}
  explicit DrawObject(const BaseState& base_state);

  // Extract the scale vector from this object's transform.
  math::Vector2dF GetScale() const;

  // Remove scale from the transform, and return the scale vector.
  math::Vector2dF RemoveScaleFromTransform();

  // Utility function to get the render color for the blend modes that will
  // be used. These modes expect alpha to be pre-multiplied.
  static render_tree::ColorRGBA GetDrawColor(
      const render_tree::ColorRGBA& color) {
    return render_tree::ColorRGBA(color.r() * color.a(), color.g() * color.a(),
                                  color.b() * color.a(), color.a());
  }

  // Return a uint32_t suitable to be transferred as 4 unsigned bytes
  // representing color to a GL shader.
  static uint32_t GetGLRGBA(float r, float g, float b, float a);
  static uint32_t GetGLRGBA(const render_tree::ColorRGBA& color) {
    return GetGLRGBA(color.r(), color.g(), color.b(), color.a());
  }

  // Get the vertex attributes to use to draw the given rounded rect. Each
  // corner uses a different attribute. These RCorner values must be transformed
  // before being passed to the shader. (See RCorner constructor.)
  static void GetRRectAttributes(const math::RectF& bounds,
      math::RectF rect, render_tree::RoundedCorners corners,
      RRectAttributes (&out_attributes)[4]);

  // Get the vertex attributes to draw the given rounded rect excluding the
  // inscribed rect. These RCorner values must be transformed before being
  // passed to the shader. (See RCorner constructor.)
  static void GetRRectAttributes(const math::RectF& bounds,
      math::RectF rect, render_tree::RoundedCorners corners,
      RRectAttributes (&out_attributes)[8]);

  BaseState base_state_;

 private:
  // Return the RCorner values for the given rounded rect, and the normalized
  // rect and corner values used.
  static void GetRCornerValues(math::RectF* rect,
      render_tree::RoundedCorners* corners,
      RRectAttributes out_rcorners[4]);
};

}  // namespace egl
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // COBALT_RENDERER_RASTERIZER_EGL_DRAW_OBJECT_H_
