// 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_rect_shadow_blur.h"

#include <GLES2/gl2.h>
#include <algorithm>

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

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

namespace {
const float kSqrt2 = 1.414213562f;
const float kSqrtPi = 1.772453851f;

// The blur kernel extends for a limited number of sigmas.
const float kBlurExtentInSigmas = 3.0f;

// The error function is used to calculate the gaussian blur. Inputs for
// the error function should be scaled by 1 / (sqrt(2) * sigma). Alternatively,
// it can be viewed as kBlurDistance is the input value at which the blur
// intensity is effectively 0.
const float kBlurDistance = kBlurExtentInSigmas / kSqrt2;

void SetBlurRRectUniforms(const ShaderFragmentColorBlurRrects& shader,
    math::RectF rect, render_tree::RoundedCorners corners, float sigma) {
  const float kBlurExtentInPixels = kBlurExtentInSigmas * sigma;
  const float kOffsetScale = kBlurDistance / kBlurExtentInPixels;

  // Ensure a minimum radius for each corner to avoid division by zero.
  // NOTE: The rounded rect is already specified in terms of sigma.
  const float kMinSize = 0.01f * kOffsetScale;
  rect.Outset(kMinSize, kMinSize);
  corners = corners.Inset(-kMinSize, -kMinSize, -kMinSize, -kMinSize);
  corners = corners.Normalize(rect);

  // A normalized rounded rect should have at least one Y value which the
  // corners do not cross.
  const float kCenterY =
      0.5f * (rect.y() + std::max(corners.top_left.vertical,
                                  corners.top_right.vertical)) +
      0.5f * (rect.bottom() - std::max(corners.bottom_left.vertical,
                                       corners.bottom_right.vertical));

  // The blur extent is (blur_size.y, rect_min.y, rect_max.y, rect_center.y).
  GL_CALL(glUniform4f(shader.u_blur_extent(),
                      kBlurExtentInPixels * kOffsetScale,
                      rect.y(), rect.bottom(), kCenterY));

  // The blur rounded rect is split into top and bottom halves.
  // The "start" values represent (left_start.xy, right_start.xy).
  // The "scale" values represent (left_radius.x, 1 / left_radius.y,
  //   right_radius.x, 1 / right_radius.y). The sign of the scale value helps
  //   to translate between position and corner offset values, where the corner
  //   offset is positive if the position is inside the rounded corner.
  GL_CALL(glUniform4f(shader.u_blur_start_top(),
                      rect.x() + corners.top_left.horizontal,
                      rect.y() + corners.top_left.vertical,
                      rect.right() - corners.top_right.horizontal,
                      rect.y() + corners.top_right.vertical));
  GL_CALL(glUniform4f(shader.u_blur_start_bottom(),
                      rect.x() + corners.bottom_left.horizontal,
                      rect.bottom() - corners.bottom_left.vertical,
                      rect.right() - corners.bottom_right.horizontal,
                      rect.bottom() - corners.bottom_right.vertical));
  GL_CALL(glUniform4f(shader.u_blur_scale_top(),
                      -corners.top_left.horizontal,
                      -1.0f / corners.top_left.vertical,
                      corners.top_right.horizontal,
                      -1.0f / corners.top_right.vertical));
  GL_CALL(glUniform4f(shader.u_blur_scale_bottom(),
                      -corners.bottom_left.horizontal,
                      1.0f / corners.bottom_left.vertical,
                      corners.bottom_right.horizontal,
                      1.0f / corners.bottom_right.vertical));
}
}  // namespace

DrawRectShadowBlur::VertexAttributesSquare::VertexAttributesSquare(
    float x, float y, float offset_scale) {
  position[0] = x;
  position[1] = y;
  offset[0] = x * offset_scale;
  offset[1] = y * offset_scale;
}

DrawRectShadowBlur::VertexAttributesRound::VertexAttributesRound(
    float x, float y, float offset_scale, const RCorner& rcorner) {
  position[0] = x;
  position[1] = y;
  offset[0] = x * offset_scale;
  offset[1] = y * offset_scale;
  rcorner_scissor = RCorner(position, rcorner);
}

DrawRectShadowBlur::DrawRectShadowBlur(GraphicsState* graphics_state,
    const BaseState& base_state, const math::RectF& base_rect,
    const OptionalRoundedCorners& base_corners, const math::RectF& spread_rect,
    const OptionalRoundedCorners& spread_corners,
    const render_tree::ColorRGBA& color, float blur_sigma, bool inset)
    : DrawObject(base_state),
      spread_rect_(spread_rect),
      spread_corners_(spread_corners),
      blur_sigma_(blur_sigma),
      is_inset_(inset),
      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 scaled_base_rect(base_rect);
  scaled_base_rect.Scale(scale.x(), scale.y());
  OptionalRoundedCorners scaled_base_corners(base_corners);
  if (scaled_base_corners) {
    scaled_base_corners = scaled_base_corners->Scale(scale.x(), scale.y());
  }
  spread_rect_.Scale(scale.x(), scale.y());
  if (spread_corners_) {
    spread_corners_ = spread_corners_->Scale(scale.x(), scale.y());
  }

  // The blur algorithms used by the shaders do not produce good results with
  // separate x and y blur sigmas. Select a single blur sigma to approximate
  // the desired blur.
  blur_sigma_ *= std::sqrt(scale.x() * scale.y());

  SetGeometry(graphics_state, scaled_base_rect, scaled_base_corners);
}

void DrawRectShadowBlur::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 DrawRectShadowBlur::ExecuteRasterize(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  if (vertex_buffer_ == nullptr) {
    return;
  }

  // Draw the blurred shadow.
  if (spread_corners_) {
    ShaderProgram<ShaderVertexOffsetRcorner,
                  ShaderFragmentColorBlurRrects>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    SetFragmentUniforms(program->GetFragmentShader().u_color(),
                        program->GetFragmentShader().u_scale_add());
    SetBlurRRectUniforms(program->GetFragmentShader(),
                         spread_rect_, *spread_corners_, blur_sigma_);
    GL_CALL(glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT,
        graphics_state->GetVertexIndexPointer(index_buffer_)));
  } else {
    ShaderProgram<ShaderVertexOffset,
                  ShaderFragmentColorBlur>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    SetFragmentUniforms(program->GetFragmentShader().u_color(),
                        program->GetFragmentShader().u_scale_add());
    GL_CALL(glUniform4f(program->GetFragmentShader().u_blur_rect(),
                        spread_rect_.x(), spread_rect_.y(),
                        spread_rect_.right(), spread_rect_.bottom()));
    GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, attributes_square_.size()));
  }
}

base::TypeId DrawRectShadowBlur::GetTypeId() const {
  if (spread_corners_) {
    return ShaderProgram<ShaderVertexOffsetRcorner,
                         ShaderFragmentColorBlurRrects>::GetTypeId();
  } else {
    return ShaderProgram<ShaderVertexOffset,
                         ShaderFragmentColorBlur>::GetTypeId();
  }
}

void DrawRectShadowBlur::SetupVertexShader(GraphicsState* graphics_state,
    const ShaderVertexOffset& 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_offset(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesSquare), vertex_buffer_ +
      offsetof(VertexAttributesSquare, offset));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowBlur::SetupVertexShader(GraphicsState* graphics_state,
    const ShaderVertexOffsetRcorner& 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_offset(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound), vertex_buffer_ +
      offsetof(VertexAttributesRound, offset));
  graphics_state->VertexAttribPointer(
      shader.a_rcorner(), 4, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributesRound), vertex_buffer_ +
      offsetof(VertexAttributesRound, rcorner_scissor));
  graphics_state->VertexAttribFinish();
}

void DrawRectShadowBlur::SetFragmentUniforms(
    GLint color_uniform, GLint scale_add_uniform) {
  GL_CALL(glUniform4f(color_uniform,
                      color_.r(), color_.g(), color_.b(), color_.a()));
  if (is_inset_) {
    // Invert the shadow.
    GL_CALL(glUniform2f(scale_add_uniform, -1.0f, 1.0f));
  } else {
    // Keep the normal (outset) shadow.
    GL_CALL(glUniform2f(scale_add_uniform, 1.0f, 0.0f));
  }
}

void DrawRectShadowBlur::SetGeometry(GraphicsState* graphics_state,
    const math::RectF& base_rect, const OptionalRoundedCorners& base_corners) {
  const float kBlurExtentInPixels = kBlurExtentInSigmas * blur_sigma_;

  if (base_corners || spread_corners_) {
    // If rounded rects are specified, then both the base and spread rects
    // must have rounded corners.
    DCHECK(base_corners);
    DCHECK(spread_corners_);

    if (is_inset_) {
      // Extend the outer rect to include the antialiased edge.
      math::RectF outer_rect(base_rect);
      outer_rect.Outset(1.0f, 1.0f);
      RRectAttributes rrect_outer[4];
      GetRRectAttributes(outer_rect, base_rect, *base_corners, rrect_outer);
      // Inset the spread rect by the blur extent. Use that as the inner bounds.
      RRectAttributes rrect_inner[8];
      math::RectF inner_rect(spread_rect_);
      inner_rect.Inset(kBlurExtentInPixels, kBlurExtentInPixels);
      if (!inner_rect.IsEmpty()) {
        // Get the inner bounds excluding the inscribed rect.
        render_tree::RoundedCorners inner_corners = spread_corners_->Inset(
            kBlurExtentInPixels, kBlurExtentInPixels, kBlurExtentInPixels,
            kBlurExtentInPixels);
        inner_corners = inner_corners.Normalize(inner_rect);
        GetRRectAttributes(outer_rect, inner_rect, inner_corners, rrect_inner);
      } else {
        // The blur covers everything inside the outer rect.
        rrect_inner[0].bounds = outer_rect;
      }
      SetGeometry(graphics_state, rrect_outer, rrect_inner);
    } else {
      // Extend the outer rect to include the blur.
      math::RectF outer_rect(spread_rect_);
      outer_rect.Outset(kBlurExtentInPixels, kBlurExtentInPixels);
      // Exclude the inscribed rect of the base rounded rect.
      RRectAttributes rrect[8];
      GetRRectAttributes(outer_rect, base_rect, *base_corners, rrect);
      SetGeometry(graphics_state, rrect);
    }
  } else {
    // Handle box shadow with square corners.
    if (is_inset_) {
      math::RectF inner_rect(spread_rect_);
      inner_rect.Inset(kBlurExtentInPixels, kBlurExtentInPixels);
      SetGeometry(graphics_state, inner_rect, base_rect);
    } else {
      math::RectF outer_rect(spread_rect_);
      outer_rect.Outset(kBlurExtentInPixels, kBlurExtentInPixels);
      SetGeometry(graphics_state, base_rect, outer_rect);
    }
  }
}

void DrawRectShadowBlur::SetGeometry(GraphicsState* graphics_state,
    const math::RectF& inner_rect, const math::RectF& outer_rect) {
  // The spread rect and offsets should be expressed in terms of sigma for the
  // shader.
  float offset_scale = kBlurDistance / (kBlurExtentInSigmas * blur_sigma_);
  spread_rect_.Scale(offset_scale, offset_scale);

  // The box shadow is a triangle strip covering the area between outer rect
  // and inner rect.
  if (inner_rect.IsEmpty()) {
    attributes_square_.reserve(4);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.bottom(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.bottom(), offset_scale);
  } 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(), offset_scale);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        inside_rect.right(), inside_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.right(), outer_rect.bottom(), offset_scale);
    attributes_square_.emplace_back(
        inside_rect.right(), inside_rect.bottom(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.bottom(), offset_scale);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.bottom(), offset_scale);
    attributes_square_.emplace_back(
        outer_rect.x(), outer_rect.y(), offset_scale);
    attributes_square_.emplace_back(
        inside_rect.x(), inside_rect.y(), offset_scale);
  }

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

void DrawRectShadowBlur::SetGeometry(GraphicsState* graphics_state,
    const RRectAttributes (&rrect)[8]) {
  // The spread rect and offsets should be expressed in terms of sigma for the
  // shader.
  float offset_scale = kBlurDistance / (kBlurExtentInSigmas * blur_sigma_);
  spread_rect_.Scale(offset_scale, offset_scale);
  *spread_corners_ = spread_corners_->Scale(offset_scale, offset_scale);

  // The shadowed area is already split into quads.
  for (int i = 0; i < arraysize(rrect); ++i) {
    AddQuad(rrect[i].bounds, offset_scale, rrect[i].rcorner);
  }

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

void DrawRectShadowBlur::SetGeometry(GraphicsState* graphics_state,
    const RRectAttributes (&rrect_outer)[4],
    const RRectAttributes (&rrect_inner)[8]) {
  // The spread rect and offsets should be expressed in terms of sigma for the
  // shader.
  float offset_scale = kBlurDistance / (kBlurExtentInSigmas * blur_sigma_);
  spread_rect_.Scale(offset_scale, offset_scale);
  *spread_corners_ = spread_corners_->Scale(offset_scale, offset_scale);

  // Draw the area between the inner rect and outer rect using the outer rect's
  // rounded corners. The inner quads already exclude the inscribed rectangle.
  for (int i = 0; i < arraysize(rrect_inner); ++i) {
    for (int o = 0; o < arraysize(rrect_outer); ++o) {
      math::RectF rect = math::IntersectRects(
          rrect_inner[i].bounds, rrect_outer[o].bounds);
      if (!rect.IsEmpty()) {
        AddQuad(rect, offset_scale, rrect_outer[o].rcorner);
      }
    }
  }

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

void DrawRectShadowBlur::AddQuad(const math::RectF& rect, float scale,
    const RCorner& rcorner) {
  uint16_t vert = static_cast<uint16_t>(attributes_round_.size());
  attributes_round_.emplace_back(rect.x(), rect.y(), scale, rcorner);
  attributes_round_.emplace_back(rect.right(), rect.y(), scale, rcorner);
  attributes_round_.emplace_back(rect.x(), rect.bottom(), scale, rcorner);
  attributes_round_.emplace_back(rect.right(), rect.bottom(), scale, rcorner);
  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);
}

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