// 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 "starboard/configuration.h"
#if SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)

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

#include <algorithm>

#include "base/logging.h"
#include "cobalt/renderer/backend/egl/utils.h"
#include "cobalt/renderer/egl_and_gles.h"
#include "starboard/memory.h"

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

DrawRectShadowSpread::VertexAttributesSquare::VertexAttributesSquare(
    float x, float y, uint32_t in_color) {
  position[0] = x;
  position[1] = y;
  color = in_color;
}

DrawRectShadowSpread::VertexAttributesRound::VertexAttributesRound(
    float x, float y, const RCorner& inner, const RCorner& outer) {
  position[0] = x;
  position[1] = y;
  rcorner_inner = RCorner(position, inner);
  rcorner_outer = RCorner(position, outer);
}

DrawRectShadowSpread::DrawRectShadowSpread(
    GraphicsState* graphics_state, const BaseState& base_state,
    const math::RectF& inner_rect, const OptionalRoundedCorners& inner_corners,
    const math::RectF& outer_rect, const OptionalRoundedCorners& outer_corners,
    const render_tree::ColorRGBA& color)
    : DrawObject(base_state), vertex_buffer_(nullptr), index_buffer_(nullptr) {
  color_ = GetDrawColor(color) * base_state_.opacity;

  // 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();
  math::RectF inside_rect(inner_rect);
  math::RectF outside_rect(outer_rect);
  inside_rect.Scale(scale.x(), scale.y());
  outside_rect.Scale(scale.x(), scale.y());

  if (inner_corners || outer_corners) {
    // If using rounded corners, then both inner and outer rects must have
    // rounded corner definitions.
    DCHECK(inner_corners);
    DCHECK(outer_corners);
    render_tree::RoundedCorners inside_corners =
        inner_corners->Scale(scale.x(), scale.y());
    render_tree::RoundedCorners outside_corners =
        outer_corners->Scale(scale.x(), scale.y());
    SetGeometry(graphics_state, inside_rect, inside_corners, outside_rect,
                outside_corners);
  } else {
    SetGeometry(graphics_state, inside_rect, outside_rect);
  }
}

void DrawRectShadowSpread::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state, ShaderProgramManager* program_manager) {
  if (attributes_square_.size() > 0) {
    vertex_buffer_ = graphics_state->AllocateVertexData(
        attributes_square_.size() * sizeof(attributes_square_[0]));
    SbMemoryCopy(vertex_buffer_, &attributes_square_[0],
                 attributes_square_.size() * sizeof(attributes_square_[0]));
  } else if (attributes_round_.size() > 0) {
    vertex_buffer_ = graphics_state->AllocateVertexData(
        attributes_round_.size() * sizeof(attributes_round_[0]));
    SbMemoryCopy(vertex_buffer_, &attributes_round_[0],
                 attributes_round_.size() * sizeof(attributes_round_[0]));
    index_buffer_ = graphics_state->AllocateVertexIndices(indices_.size());
    SbMemoryCopy(index_buffer_, &indices_[0],
                 indices_.size() * sizeof(indices_[0]));
  }
}

void DrawRectShadowSpread::ExecuteRasterize(
    GraphicsState* graphics_state, ShaderProgramManager* program_manager) {
  if (vertex_buffer_ == nullptr) {
    return;
  }

  // Draw the box shadow.
  if (attributes_square_.size() > 0) {
    ShaderProgram<ShaderVertexColor, ShaderFragmentColor>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, attributes_square_.size()));
  } else {
    ShaderProgram<ShaderVertexRcorner2, ShaderFragmentRcorner2Color>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    GL_CALL(glUniform4f(program->GetFragmentShader().u_color(), color_.r(),
                        color_.g(), color_.b(), color_.a()));
    GL_CALL(
        glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT,
                       graphics_state->GetVertexIndexPointer(index_buffer_)));
  }
}

base::TypeId DrawRectShadowSpread::GetTypeId() const {
  if (attributes_square_.size() > 0) {
    return ShaderProgram<ShaderVertexColor, ShaderFragmentColor>::GetTypeId();
  } else {
    return ShaderProgram<ShaderVertexRcorner2,
                         ShaderFragmentRcorner2Color>::GetTypeId();
  }
}

void DrawRectShadowSpread::SetupVertexShader(GraphicsState* graphics_state,
                                             const ShaderVertexColor& shader) {
  graphics_state->UpdateClipAdjustment(shader.u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(shader.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(
      shader.a_position(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesSquare),
      vertex_buffer_ + offsetof(VertexAttributesSquare, position));
  graphics_state->VertexAttribPointer(
      shader.a_color(), 4, GL_UNSIGNED_BYTE, GL_TRUE,
      sizeof(VertexAttributesSquare),
      vertex_buffer_ + offsetof(VertexAttributesSquare, color));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowSpread::SetupVertexShader(
    GraphicsState* graphics_state, const ShaderVertexRcorner2& shader) {
  graphics_state->UpdateClipAdjustment(shader.u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(shader.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(
      shader.a_position(), 2, GL_FLOAT, GL_FALSE, sizeof(VertexAttributesRound),
      vertex_buffer_ + offsetof(VertexAttributesRound, position));
  graphics_state->VertexAttribPointer(
      shader.a_rcorner_inner(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound),
      vertex_buffer_ + offsetof(VertexAttributesRound, rcorner_inner));
  graphics_state->VertexAttribPointer(
      shader.a_rcorner_outer(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound),
      vertex_buffer_ + offsetof(VertexAttributesRound, rcorner_outer));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowSpread::SetGeometry(GraphicsState* graphics_state,
                                       const math::RectF& inner_rect,
                                       const math::RectF& outer_rect) {
  // Draw the box shadow's spread. This is a triangle strip covering the area
  // between outer rect and inner rect.
  uint32_t color = GetGLRGBA(color_);

  if (inner_rect.IsEmpty()) {
    attributes_square_.reserve(4);
    attributes_square_.emplace_back(outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(outer_rect.right(), outer_rect.y(), color);
    attributes_square_.emplace_back(outer_rect.x(), outer_rect.bottom(), color);
    attributes_square_.emplace_back(outer_rect.right(), outer_rect.bottom(),
                                    color);
  } else {
    math::RectF inside_rect(inner_rect);
    inside_rect.Intersect(outer_rect);
    attributes_square_.reserve(10);
    attributes_square_.emplace_back(outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(inside_rect.x(), inside_rect.y(), color);
    attributes_square_.emplace_back(outer_rect.right(), outer_rect.y(), color);
    attributes_square_.emplace_back(inside_rect.right(), inside_rect.y(),
                                    color);
    attributes_square_.emplace_back(outer_rect.right(), outer_rect.bottom(),
                                    color);
    attributes_square_.emplace_back(inside_rect.right(), inside_rect.bottom(),
                                    color);
    attributes_square_.emplace_back(outer_rect.x(), outer_rect.bottom(), color);
    attributes_square_.emplace_back(inside_rect.x(), inside_rect.bottom(),
                                    color);
    attributes_square_.emplace_back(outer_rect.x(), outer_rect.y(), color);
    attributes_square_.emplace_back(inside_rect.x(), inside_rect.y(), color);
  }

  graphics_state->ReserveVertexData(attributes_square_.size() *
                                    sizeof(attributes_square_[0]));
}

void DrawRectShadowSpread::SetGeometry(
    GraphicsState* graphics_state, const math::RectF& inner_rect,
    const render_tree::RoundedCorners& inner_corners,
    const math::RectF& outer_rect,
    const render_tree::RoundedCorners& outer_corners) {
  // Draw the area between the inner rounded rect and outer rounded rect. Add
  // a 1-pixel border to include antialiasing.
  math::RectF bounds(outer_rect);
  bounds.Outset(1.0f, 1.0f);

  // Get the render quads for the inner rounded rect excluding its inscribed
  // rectangle.
  RRectAttributes rrect_inner[8];
  GetRRectAttributes(bounds, inner_rect, inner_corners, rrect_inner);

  // Get the render quads for the outer rounded rect.
  RRectAttributes rrect_outer[4];
  GetRRectAttributes(bounds, outer_rect, outer_corners, rrect_outer);

  // Add geometry to draw the area between the inner rrect and outer rrect.
  for (int i = 0; i < arraysize(rrect_inner); ++i) {
    for (int o = 0; o < arraysize(rrect_outer); ++o) {
      math::RectF intersection =
          math::IntersectRects(rrect_inner[i].bounds, rrect_outer[o].bounds);
      if (!intersection.IsEmpty()) {
        // Use two triangles to draw the intersection.
        const RCorner& inner = rrect_inner[i].rcorner;
        const RCorner& outer = rrect_outer[o].rcorner;
        uint16_t vert = static_cast<uint16_t>(attributes_round_.size());
        attributes_round_.emplace_back(intersection.x(), intersection.y(),
                                       inner, outer);
        attributes_round_.emplace_back(intersection.right(), intersection.y(),
                                       inner, outer);
        attributes_round_.emplace_back(intersection.x(), intersection.bottom(),
                                       inner, outer);
        attributes_round_.emplace_back(intersection.right(),
                                       intersection.bottom(), inner, outer);
        indices_.emplace_back(vert);
        indices_.emplace_back(vert + 1);
        indices_.emplace_back(vert + 2);
        indices_.emplace_back(vert + 1);
        indices_.emplace_back(vert + 2);
        indices_.emplace_back(vert + 3);
      }
    }
  }

  graphics_state->ReserveVertexData(attributes_round_.size() *
                                    sizeof(attributes_round_[0]));
  graphics_state->ReserveVertexIndices(indices_.size());
}

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

#endif  // SB_API_VERSION >= SB_ALL_RENDERERS_REQUIRED_VERSION || SB_HAS(GLES2)
