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

#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
