// 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.

#include "cobalt/renderer/rasterizer/egl/draw_rrect_color.h"

#include <GLES2/gl2.h>

#include "cobalt/renderer/backend/egl/utils.h"
#include "egl/generated_shader_impl.h"
#include "starboard/memory.h"

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

namespace {
const int kVertexCount = 4 * 6;
}  // namespace

DrawRRectColor::DrawRRectColor(GraphicsState* graphics_state,
    const BaseState& base_state, const math::RectF& rect,
    const render_tree::RoundedCorners& corners,
    const render_tree::ColorRGBA& color)
    : DrawObject(base_state),
      rect_(rect),
      corners_(corners),
      vertex_buffer_(NULL) {
  color_ = GetDrawColor(color) * base_state_.opacity;
  graphics_state->ReserveVertexData(kVertexCount * sizeof(VertexAttributes));

  // Extract scale from the transform and move it into the vertex attributes
  // so that the anti-aliased edges remain 1 pixel wide.
  math::Vector2dF scale = RemoveScaleFromTransform();
  rect_.Scale(scale.x(), scale.y());
  corners_ = corners_.Scale(scale.x(), scale.y());
}

void DrawRRectColor::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  // Draw the rect with an extra pixel outset for anti-aliasing. The fragment
  // shader will handle the rounded corners.
  VertexAttributes attributes[kVertexCount];
  math::RectF outer_rect(rect_);
  outer_rect.Outset(1.0f, 1.0f);

  RRectAttributes rrect[4];
  GetRRectAttributes(outer_rect, rect_, corners_, rrect);
  for (int r = 0, v = 0; r < arraysize(rrect); ++r) {
    attributes[v  ].position[0] = rrect[r].bounds.x();
    attributes[v  ].position[1] = rrect[r].bounds.y();
    attributes[v  ].rcorner =
        RCorner(attributes[v  ].position, rrect[r].rcorner);
    attributes[v+1].position[0] = rrect[r].bounds.right();
    attributes[v+1].position[1] = rrect[r].bounds.y();
    attributes[v+1].rcorner =
        RCorner(attributes[v+1].position, rrect[r].rcorner);
    attributes[v+2].position[0] = rrect[r].bounds.x();
    attributes[v+2].position[1] = rrect[r].bounds.bottom();
    attributes[v+2].rcorner =
        RCorner(attributes[v+2].position, rrect[r].rcorner);
    attributes[v+3].position[0] = rrect[r].bounds.right();
    attributes[v+3].position[1] = rrect[r].bounds.bottom();
    attributes[v+3].rcorner =
        RCorner(attributes[v+3].position, rrect[r].rcorner);
    attributes[v+4] = attributes[v+1];
    attributes[v+5] = attributes[v+2];
    v += 6;
  }

  vertex_buffer_ = graphics_state->AllocateVertexData(sizeof(attributes));
  SbMemoryCopy(vertex_buffer_, attributes, sizeof(attributes));
}

void DrawRRectColor::ExecuteRasterize(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  ShaderProgram<ShaderVertexRcorner,
                ShaderFragmentRcornerColor>* program;
  program_manager->GetProgram(&program);
  graphics_state->UseProgram(program->GetHandle());
  graphics_state->UpdateClipAdjustment(
      program->GetVertexShader().u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(
      program->GetVertexShader().u_view_matrix(),
      base_state_.transform);
  graphics_state->Scissor(base_state_.scissor.x(), base_state_.scissor.y(),
      base_state_.scissor.width(), base_state_.scissor.height());
  graphics_state->VertexAttribPointer(
      program->GetVertexShader().a_position(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributes), vertex_buffer_ +
      offsetof(VertexAttributes, position));
  graphics_state->VertexAttribPointer(
      program->GetVertexShader().a_rcorner(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributes), vertex_buffer_ +
      offsetof(VertexAttributes, rcorner));
  graphics_state->VertexAttribFinish();

  GL_CALL(glUniform4f(program->GetFragmentShader().u_color(),
                      color_.r(), color_.g(), color_.b(), color_.a()));
  GL_CALL(glDrawArrays(GL_TRIANGLES, 0, kVertexCount));
}

base::TypeId DrawRRectColor::GetTypeId() const {
  return ShaderProgram<ShaderVertexRcorner,
                       ShaderFragmentRcornerColor>::GetTypeId();
}

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