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

#include <GLES2/gl2.h>

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

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

namespace {
struct VertexAttributes {
  float position[2];
  float texcoord[2];
};
}  // namespace

DrawRectTexture::DrawRectTexture(GraphicsState* graphics_state,
                                 const BaseState& base_state,
                                 const math::RectF& rect,
                                 const backend::TextureEGL* texture,
                                 const math::Matrix3F& texcoord_transform)
    : DrawObject(base_state),
      texcoord_transform_(texcoord_transform),
      rect_(rect),
      textures_{texture, NULL, NULL},
      vertex_buffer_(NULL),
      tile_texture_(false) {
  DCHECK(textures_[0]);
  graphics_state->ReserveVertexData(4 * sizeof(VertexAttributes));
}

DrawRectTexture::DrawRectTexture(
    GraphicsState* graphics_state, const BaseState& base_state,
    const math::RectF& rect, const backend::TextureEGL* y_texture,
    const backend::TextureEGL* u_texture, const backend::TextureEGL* v_texture,
    const float (&color_transform_in_column_major)[16],
    const math::Matrix3F& texcoord_transform)
    : DrawObject(base_state),
      texcoord_transform_(texcoord_transform),
      rect_(rect),
      textures_{y_texture, u_texture, v_texture},
      vertex_buffer_(NULL),
      tile_texture_(false) {
  DCHECK(textures_[0]);
  DCHECK(textures_[1]);
  DCHECK(textures_[2]);
  static_assert(
      sizeof(color_transform_) == sizeof(color_transform_in_column_major),
      "color_transform_ and color_transform_in_column_major size mismatch");

  SbMemoryCopy(color_transform_, color_transform_in_column_major,
               sizeof(color_transform_));
  graphics_state->ReserveVertexData(4 * sizeof(VertexAttributes));
}

void DrawRectTexture::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  VertexAttributes attributes[4] = {
    { { rect_.x(), rect_.bottom() },      // uv = (0,1)
      { texcoord_transform_(0, 1) + texcoord_transform_(0, 2),
        texcoord_transform_(1, 1) + texcoord_transform_(1, 2) } },
    { { rect_.right(), rect_.bottom() },  // uv = (1,1)
      { texcoord_transform_(0, 0) + texcoord_transform_(0, 1) +
          texcoord_transform_(0, 2),
        texcoord_transform_(1, 0) + texcoord_transform_(1, 1) +
          texcoord_transform_(1, 2) } },
    { { rect_.right(), rect_.y() },       // uv = (1,0)
      { texcoord_transform_(0, 0) + texcoord_transform_(0, 2),
        texcoord_transform_(1, 0) + texcoord_transform_(1, 2) } },
    { { rect_.x(), rect_.y() },           // uv = (0,0)
      { texcoord_transform_(0, 2), texcoord_transform_(1, 2) } },
  };
  COMPILE_ASSERT(sizeof(attributes) == 4 * sizeof(VertexAttributes),
                 bad_padding);
  vertex_buffer_ = graphics_state->AllocateVertexData(
      sizeof(attributes));
  SbMemoryCopy(vertex_buffer_, attributes, sizeof(attributes));

  for (int i = 0; i < arraysize(attributes); ++i) {
    tile_texture_ = tile_texture_ ||
        attributes[i].texcoord[0] < 0.0f || attributes[i].texcoord[0] > 1.0f ||
        attributes[i].texcoord[1] < 0.0f || attributes[i].texcoord[1] > 1.0f;
  }
}

void DrawRectTexture::SetupVertexShader(
    GraphicsState* graphics_state, const ShaderVertexTexcoord& vertex_shader) {
  graphics_state->UpdateClipAdjustment(vertex_shader.u_clip_adjustment());
  graphics_state->UpdateTransformMatrix(vertex_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(
      vertex_shader.a_position(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributes),
      vertex_buffer_ + offsetof(VertexAttributes, position));
  graphics_state->VertexAttribPointer(
      vertex_shader.a_texcoord(), 2, GL_FLOAT, GL_FALSE,
      sizeof(VertexAttributes),
      vertex_buffer_ + offsetof(VertexAttributes, texcoord));
  graphics_state->VertexAttribFinish();
}

template <typename FragmentShader>
void DrawRectTexture::SetupFragmentShaderAndDraw(
    GraphicsState* graphics_state, const FragmentShader& fragment_shader) {
  for (int i = 0; i < SB_ARRAY_SIZE_INT(textures_); ++i) {
    if (textures_[i] == NULL) {
      break;
    }

    if (tile_texture_) {
      graphics_state->ActiveBindTexture(fragment_shader.u_texture_texunit(i),
                                        textures_[i]->GetTarget(),
                                        textures_[i]->gl_handle(), GL_REPEAT);
    } else {
      graphics_state->ActiveBindTexture(fragment_shader.u_texture_texunit(i),
                                        textures_[i]->GetTarget(),
                                        textures_[i]->gl_handle());
    }
  }

  GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));

  if (!tile_texture_) {
    return;
  }

  for (int i = 0; i < SB_ARRAY_SIZE_INT(textures_); ++i) {
    if (textures_[i] == NULL) {
      break;
    }

    graphics_state->ActiveBindTexture(
        fragment_shader.u_texture_texunit(i), textures_[i]->GetTarget(),
        textures_[i]->gl_handle(), GL_CLAMP_TO_EDGE);
  }
}

void DrawRectTexture::ExecuteRasterize(GraphicsState* graphics_state,
                                       ShaderProgramManager* program_manager) {
  if (textures_[1] == NULL) {
    ShaderProgram<ShaderVertexTexcoord, ShaderFragmentTexcoord>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    SetupFragmentShaderAndDraw(graphics_state, program->GetFragmentShader());
  } else {
    ShaderProgram<ShaderVertexTexcoord, ShaderFragmentTexcoordYuv3>* program;
    program_manager->GetProgram(&program);
    graphics_state->UseProgram(program->GetHandle());
    SetupVertexShader(graphics_state, program->GetVertexShader());
    GL_CALL(glUniformMatrix4fv(
        program->GetFragmentShader().u_color_transform_matrix(), 1, GL_FALSE,
        color_transform_));
    SetupFragmentShaderAndDraw(graphics_state, program->GetFragmentShader());
  }
}

base::TypeId DrawRectTexture::GetTypeId() const {
  return textures_[1] == NULL
             ? ShaderProgram<ShaderVertexTexcoord,
                             ShaderFragmentTexcoord>::GetTypeId()
             : ShaderProgram<ShaderVertexTexcoord,
                             ShaderFragmentTexcoordYuv3>::GetTypeId();
}

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