// 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:
  DrawObject() {}
  explicit DrawObject(const BaseState& base_state);

  // 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());
  }

  // Set shader uniforms for a rounded rect. Specify a non-zero inset if
  // the rect will be used with anti-aliasing (e.g. 0.5 inset for a 1-pixel
  // anti-aliasing border).
  static void SetRRectUniforms(GLint rect_uniform, GLint corners_uniform,
      const math::RectF& rect, const render_tree::RoundedCorners& corners,
      float inset);

  BaseState base_state_;
};

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

#endif  // COBALT_RENDERER_RASTERIZER_EGL_DRAW_OBJECT_H_
