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

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

#include "base/logging.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;
}  // namespace

DrawRectRadialGradient::DrawRectRadialGradient(GraphicsState* graphics_state,
    const BaseState& base_state, const math::RectF& rect,
    const render_tree::RadialGradientBrush& brush,
    const GetScratchTextureFunction& get_scratch_texture)
    : DrawObject(base_state),
      lookup_texture_(nullptr),
      vertex_buffer_(nullptr) {
  // Calculate the number of pixels needed for the color lookup texture. There
  // should be enough so that each color stop has a pixel with the color
  // blended at 100%. However, since the lookup texture will be used with
  // linear filtering, reducing the texture size will only impact accuracy at
  // the color stops (but not between them).
  const float kLookupSizes[] = {
    // These represent breakpoints that are likely to be used.
    1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 8.0f, 10.0f, 20.0f, 50.0f, 100.0f,
  };
  const render_tree::ColorStopList& color_stops = brush.color_stops();

  int lookup_size_index = 0;
  for (int i = 0; i < color_stops.size();) {
    float scaled = color_stops[i].position * kLookupSizes[lookup_size_index];
    float fraction = scaled - std::floor(scaled);
    if (fraction > 0.001f && lookup_size_index < arraysize(kLookupSizes) - 1) {
      ++lookup_size_index;
      i = 0;
    } else {
      ++i;
    }
  }

  // Create and initialize the lookup texture if needed. Reserve an additional
  // pixel to represent color stop position 1.0 blended to 100%.
  float lookup_size = kLookupSizes[lookup_size_index] + 1.0f;
  TextureInfo texture_info;
  get_scratch_texture.Run(lookup_size, &texture_info);
  lookup_texture_ = texture_info.texture;
  lookup_region_ = texture_info.region;

  // Add the geometry if a lookup texture was available.
  if (lookup_texture_) {
    if (texture_info.is_new) {
      InitializeLookupTexture(brush);
    }

    attributes_.reserve(kVertexCount);
    math::PointF offset_center(brush.center());
    math::PointF offset_scale(1.0f / std::max(brush.radius_x(), 0.001f),
                              1.0f / std::max(brush.radius_y(), 0.001f));
    AddVertex(rect.x(), rect.y(), offset_center, offset_scale);
    AddVertex(rect.right(), rect.y(), offset_center, offset_scale);
    AddVertex(rect.right(), rect.bottom(), offset_center, offset_scale);
    AddVertex(rect.x(), rect.bottom(), offset_center, offset_scale);
    graphics_state->ReserveVertexData(
        attributes_.size() * sizeof(VertexAttributes));
  }
}

void DrawRectRadialGradient::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  if (attributes_.size() > 0) {
    vertex_buffer_ = graphics_state->AllocateVertexData(
        attributes_.size() * sizeof(VertexAttributes));
    SbMemoryCopy(vertex_buffer_, &attributes_[0],
                 attributes_.size() * sizeof(VertexAttributes));
  }
}

void DrawRectRadialGradient::ExecuteRasterize(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  if (attributes_.size() > 0) {
    ShaderProgram<ShaderVertexOffset,
                  ShaderFragmentOpacityTexcoord1d>* 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_offset(), 2, GL_FLOAT, GL_FALSE,
        sizeof(VertexAttributes), vertex_buffer_ +
        offsetof(VertexAttributes, offset));
    graphics_state->VertexAttribFinish();

    // Map radial length [0, 1] to texture coordinates for the lookup texture.
    // |u_texcoord_transform| represents (u-scale, u-add, u-max, v-center).
    const float kTextureWidthScale = 1.0f / lookup_texture_->GetSize().width();
    GL_CALL(glUniform4f(program->GetFragmentShader().u_texcoord_transform(),
        (lookup_region_.width() - 1.0f) * kTextureWidthScale,
        (lookup_region_.x() + 0.5f) * kTextureWidthScale,
        (lookup_region_.right() - 0.5f) * kTextureWidthScale,
        (lookup_region_.y() + 0.5f) / lookup_texture_->GetSize().height()));
    GL_CALL(glUniform1f(program->GetFragmentShader().u_opacity(),
        base_state_.opacity));
    graphics_state->ActiveBindTexture(
        program->GetFragmentShader().u_texture_texunit(),
        lookup_texture_->GetTarget(), lookup_texture_->gl_handle());
    GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, attributes_.size()));
  }
}

base::TypeId DrawRectRadialGradient::GetTypeId() const {
  return ShaderProgram<ShaderVertexColorOffset,
                       ShaderFragmentOpacityTexcoord1d>::GetTypeId();
}

void DrawRectRadialGradient::InitializeLookupTexture(
    const render_tree::RadialGradientBrush& brush) {
  const render_tree::ColorStopList& color_stops = brush.color_stops();

  // The lookup texture is a row of RGBA pixels. Ensure the last pixel contains
  // the last color stop blended to 100%.
  // NOTE: The base_state_.opacity should not be baked into the lookup texture
  //       as opacity can be animated.
  const float kTexelToStop = 1.0f / (lookup_region_.width() - 1.0f);
  const float kStopToTexel = lookup_region_.width() - 1.0f;
  uint8_t* lookup_buffer =
      new uint8_t[static_cast<int>(lookup_region_.width()) * 4];

  size_t color_index = 0;
  float position_prev = 0.0f;
  float position_next = color_stops[color_index].position * kStopToTexel;
  float position_scale = 1.0f / std::max(position_next - position_prev, 1.0f);
  render_tree::ColorRGBA color_prev =
      GetDrawColor(color_stops[color_index].color);
  render_tree::ColorRGBA color_next = color_prev;
  uint8_t* pixel = lookup_buffer;

  // Fill in the blended colors according to the color stops.
  for (float texel = 0.0f; texel < lookup_region_.width(); texel += 1.0f) {
    while (texel > position_next) {
      position_prev = position_next;
      color_prev = color_next;
      if (color_index < color_stops.size()) {
        // Advance to the next color stop.
        ++color_index;
        position_next = color_stops[color_index].position * kStopToTexel;
        color_next = GetDrawColor(color_stops[color_index].color);
      } else {
        // Persist the current color stop to the end.
        position_next = lookup_region_.width();
      }
      position_scale = 1.0f / std::max(position_next - position_prev, 1.0f);
    }

    // Write the blended color to the lookup texture buffer.
    float blend_ratio = (texel - position_prev) * position_scale;
    render_tree::ColorRGBA color = color_prev * (1.0f - blend_ratio) +
                                   color_next * blend_ratio;
    pixel[0] = color.rgb8_r();
    pixel[1] = color.rgb8_g();
    pixel[2] = color.rgb8_b();
    pixel[3] = color.rgb8_a();
    pixel += 4;
  }

  // Update the lookup texture.
  DCHECK_EQ(lookup_texture_->GetFormat(), GL_RGBA);
  GL_CALL(glBindTexture(lookup_texture_->GetTarget(),
                        lookup_texture_->gl_handle()));
  GL_CALL(glTexSubImage2D(lookup_texture_->GetTarget(), 0,
                          static_cast<GLint>(lookup_region_.x()),
                          static_cast<GLint>(lookup_region_.y()),
                          static_cast<GLsizei>(lookup_region_.width()), 1,
                          lookup_texture_->GetFormat(), GL_UNSIGNED_BYTE,
                          lookup_buffer));
  GL_CALL(glBindTexture(lookup_texture_->GetTarget(), 0));

  delete[] lookup_buffer;
}

void DrawRectRadialGradient::AddVertex(float x, float y,
    const math::PointF& offset_center, const math::PointF& offset_scale) {
  VertexAttributes attributes = {
    { x, y },
    { (x - offset_center.x()) * offset_scale.x(),
      (y - offset_center.y()) * offset_scale.y() },
  };
  attributes_.push_back(attributes);
}

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