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

#include <algorithm>

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

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

namespace {

math::Rect ToGLRect(int x, int y, int width, int height,
                    const math::Size& target_size) {
  // Incoming origin is top-left, but GL origin is bottom-left, so flip
  // vertically.
  return math::Rect(x, target_size.height() - (y + height), width, height);
}

}  // namespace

GraphicsState::GraphicsState()
    : render_target_handle_(0),
      render_target_serial_(0),
      frame_index_(0),
      vertex_data_capacity_(0),
      vertex_data_reserved_(kVertexDataAlignment - 1),
      vertex_data_allocated_(0),
      vertex_index_capacity_(0),
      vertex_index_reserved_(0),
      vertex_index_allocated_(0),
      vertex_buffers_updated_(false) {
  // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGet.xml
  // GL_MAX_VERTEX_ATTRIBS should return at least 8. So default to that in
  // case the glGetIntergerv call fails.
  max_vertex_attribs_ = 8;
  GL_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs_));

  GL_CALL(glGenBuffers(kNumFramesBuffered, vertex_data_buffer_handle_));
  GL_CALL(glGenBuffers(kNumFramesBuffered, vertex_index_buffer_handle_));
  for (int frame = 0; frame < kNumFramesBuffered; ++frame) {
    DCHECK_NE(vertex_data_buffer_handle_[frame], 0);
    DCHECK_NE(vertex_index_buffer_handle_[frame], 0);
  }
  SbMemorySet(clip_adjustment_, 0, sizeof(clip_adjustment_));
  SetDirty();
  blend_enabled_ = false;
  Reset();
}

GraphicsState::~GraphicsState() {
  GL_CALL(glDeleteBuffers(kNumFramesBuffered, vertex_data_buffer_handle_));
  GL_CALL(glDeleteBuffers(kNumFramesBuffered, vertex_index_buffer_handle_));
}

void GraphicsState::SetDirty() {
  state_dirty_ = true;
  clip_adjustment_dirty_ = true;
}

void GraphicsState::BeginFrame() {
  DCHECK_EQ(vertex_data_allocated_, 0);
  if (vertex_data_reserved_ > vertex_data_capacity_) {
    vertex_data_capacity_ = vertex_data_reserved_;
    vertex_data_buffer_.reset(new uint8_t[vertex_data_capacity_]);
  }
  DCHECK_EQ(vertex_index_allocated_, 0);
  if (vertex_index_reserved_ > vertex_index_capacity_) {
    vertex_index_capacity_ = vertex_index_reserved_;
    vertex_index_buffer_.reset(new uint16_t[vertex_index_capacity_]);
  }

  // Reset to default GL state. Assume the current state is dirty, so just
  // set the cached state. The actual GL state will be updated to match the
  // cached state when needed.
  SetDirty();
  blend_enabled_ = false;
}

void GraphicsState::EndFrame() {
  // Reset the vertex data and index buffers.
  vertex_data_reserved_ = kVertexDataAlignment - 1;
  vertex_data_allocated_ = 0;
  vertex_index_reserved_ = 0;
  vertex_index_allocated_ = 0;
  vertex_buffers_updated_ = false;
  frame_index_ = (frame_index_ + 1) % kNumFramesBuffered;

  // Force default GL state. The current state may be marked dirty, so don't
  // rely on any functions which check the cached state before issuing GL calls.
  GL_CALL(glDisable(GL_BLEND));
  GL_CALL(glUseProgram(0));

  // Since the GL state was changed without going through the cache, mark it
  // as dirty.
  SetDirty();
}

void GraphicsState::Clear() { Clear(0.0f, 0.0f, 0.0f, 0.0f); }

void GraphicsState::Clear(float r, float g, float b, float a) {
  if (state_dirty_) {
    Reset();
  }

  GL_CALL(glClearColor(r, g, b, a));
  GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
}

void GraphicsState::UseProgram(GLuint program) {
  if (state_dirty_) {
    Reset();
  }

  if (program_ != program) {
    program_ = program;
    clip_adjustment_dirty_ = true;
    GL_CALL(glUseProgram(program));
  }

  if (vertex_data_allocated_ > 0 &&
      array_buffer_handle_ != vertex_data_buffer_handle_[frame_index_]) {
    array_buffer_handle_ = vertex_data_buffer_handle_[frame_index_];
    GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, array_buffer_handle_));
  }
  if (vertex_index_allocated_ > 0 &&
      index_buffer_handle_ != vertex_index_buffer_handle_[frame_index_]) {
    index_buffer_handle_ = vertex_index_buffer_handle_[frame_index_];
    GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_handle_));
  }

  // Disable any vertex attribute arrays that will not be used.
  disable_vertex_attrib_array_mask_ = enabled_vertex_attrib_array_mask_;
}

void GraphicsState::BindFramebuffer(
    const backend::RenderTarget* render_target) {
  if (render_target == nullptr) {
    // Unbind the framebuffer immediately.
    if (render_target_handle_ != 0) {
      GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));
    }
    render_target_handle_ = 0;
    render_target_serial_ = 0;
    render_target_size_.SetSize(0, 0);
    SetClipAdjustment();
  } else if (render_target->GetPlatformHandle() != render_target_handle_ ||
             render_target->GetSerialNumber() != render_target_serial_ ||
             render_target->GetSize() != render_target_size_) {
    render_target_handle_ = render_target->GetPlatformHandle();
    render_target_serial_ = render_target->GetSerialNumber();
    render_target_size_ = render_target->GetSize();
    SetClipAdjustment();

    if (!state_dirty_) {
      GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, render_target_handle_));
    }
  }
}

void GraphicsState::Viewport(int x, int y, int width, int height) {
  math::Rect new_viewport = ToGLRect(x, y, width, height, render_target_size_);
  if (viewport_ != new_viewport) {
    viewport_ = new_viewport;
    if (!state_dirty_) {
      GL_CALL(glViewport(viewport_.x(), viewport_.y(),
                         viewport_.width(), viewport_.height()));
    }
  }
}

void GraphicsState::Scissor(int x, int y, int width, int height) {
  math::Rect new_scissor = ToGLRect(x, y, width, height, render_target_size_);
  if (scissor_ != new_scissor) {
    scissor_ = new_scissor;
    if (!state_dirty_) {
      GL_CALL(glScissor(scissor_.x(), scissor_.y(),
                        scissor_.width(), scissor_.height()));
    }
  }
}

void GraphicsState::EnableBlend() {
  if (!blend_enabled_) {
    blend_enabled_ = true;
    GL_CALL(glEnable(GL_BLEND));
  }
}

void GraphicsState::DisableBlend() {
  if (blend_enabled_) {
    blend_enabled_ = false;
    GL_CALL(glDisable(GL_BLEND));
  }
}

void GraphicsState::ActiveBindTexture(GLenum texture_unit, GLenum target,
                                      GLuint texture) {
  int texunit_index = texture_unit - GL_TEXTURE0;

  // Update only if it doesn't match the current state.
  if (texunit_index >= kNumTextureUnitsCached ||
      texunit_target_[texunit_index] != target ||
      texunit_texture_[texunit_index] != texture) {
    if (texture_unit_ != texture_unit) {
      texture_unit_ = texture_unit;
      GL_CALL(glActiveTexture(texture_unit));
    }
    GL_CALL(glBindTexture(target, texture));

    if (texunit_index < kNumTextureUnitsCached) {
      texunit_target_[texunit_index] = target;
      texunit_texture_[texunit_index] = texture;
    }
  }
}

void GraphicsState::ActiveBindTexture(GLenum texture_unit, GLenum target,
                                      GLuint texture, GLint texture_wrap_mode) {
  int texunit_index = texture_unit - GL_TEXTURE0;

  if (texture_unit_ != texture_unit) {
    texture_unit_ = texture_unit;
    GL_CALL(glActiveTexture(texture_unit));
    GL_CALL(glBindTexture(target, texture));
  } else if (texunit_index >= kNumTextureUnitsCached ||
             texunit_target_[texunit_index] != target ||
             texunit_texture_[texunit_index] != texture) {
    GL_CALL(glBindTexture(target, texture));
  }

  if (texunit_index < kNumTextureUnitsCached) {
    texunit_target_[texunit_index] = target;
    texunit_texture_[texunit_index] = texture;
  }

  GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, texture_wrap_mode));
  GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, texture_wrap_mode));
}

void GraphicsState::SetClipAdjustment() {
  clip_adjustment_dirty_ = true;

  // Clip adjustment is a vec4 used to transform a given 2D position from view
  // space to clip space. Given a 2D position, pos, the output is:
  // output = pos * clip_adjustment_.xy + clip_adjustment_.zw

  if (render_target_size_.width() > 0) {
    clip_adjustment_[0] = 2.0f / render_target_size_.width();
    clip_adjustment_[2] = -1.0f;
  } else {
    clip_adjustment_[0] = 0.0f;
    clip_adjustment_[2] = 0.0f;
  }

  if (render_target_size_.height() > 0) {
    // Incoming origin is top-left, but GL origin is bottom-left, so flip the
    // image vertically.
    clip_adjustment_[1] = -2.0f / render_target_size_.height();
    clip_adjustment_[3] = 1.0f;
  } else {
    clip_adjustment_[1] = 0.0f;
    clip_adjustment_[3] = 0.0f;
  }
}

void GraphicsState::UpdateClipAdjustment(GLint handle) {
  if (clip_adjustment_dirty_) {
    clip_adjustment_dirty_ = false;
    GL_CALL(glUniform4fv(handle, 1, clip_adjustment_));
  }
}

void GraphicsState::UpdateTransformMatrix(GLint handle,
                                          const math::Matrix3F& transform) {
  // Manually transpose our row-major matrix to column-major. Don't rely on
  // glUniformMatrix3fv to do it, since the driver may not support that.
  float transpose[] = {transform(0, 0), transform(1, 0), transform(2, 0),
                       transform(0, 1), transform(1, 1), transform(2, 1),
                       transform(0, 2), transform(1, 2), transform(2, 2)};
  GL_CALL(glUniformMatrix3fv(handle, 1, GL_FALSE, transpose));
}

void GraphicsState::ReserveVertexData(size_t bytes) {
  DCHECK_EQ(vertex_data_allocated_, 0);
  DCHECK(!vertex_buffers_updated_);
  vertex_data_reserved_ +=
      bytes + (kVertexDataAlignment - 1) & ~(kVertexDataAlignment - 1);
}

uint8_t* GraphicsState::AllocateVertexData(size_t bytes) {
  DCHECK(!vertex_buffers_updated_);

  // Ensure the start address is aligned.
  uintptr_t start_address =
      reinterpret_cast<uintptr_t>(&vertex_data_buffer_[0]) +
          vertex_data_allocated_ + (kVertexDataAlignment - 1) &
      ~(kVertexDataAlignment - 1);

  vertex_data_allocated_ =
      start_address - reinterpret_cast<uintptr_t>(&vertex_data_buffer_[0]) +
      bytes;

  DCHECK_LE(vertex_data_allocated_, vertex_data_reserved_);
  return reinterpret_cast<uint8_t*>(start_address);
}

void GraphicsState::ReserveVertexIndices(size_t count) {
  DCHECK_EQ(vertex_index_allocated_, 0);
  DCHECK(!vertex_buffers_updated_);
  vertex_index_reserved_ += count;
}

uint16_t* GraphicsState::AllocateVertexIndices(size_t count) {
  uint16_t* client_pointer = &vertex_index_buffer_[vertex_index_allocated_];
  vertex_index_allocated_ += count;
  DCHECK_LE(vertex_index_allocated_, vertex_index_reserved_);
  return client_pointer;
}

const void* GraphicsState::GetVertexIndexPointer(
    const uint16_t* client_pointer) {
  DCHECK_GE(client_pointer, &vertex_index_buffer_[0]);
  DCHECK_LE(client_pointer, &vertex_index_buffer_[vertex_index_allocated_]);
  const GLvoid* gl_pointer = reinterpret_cast<const GLvoid*>(
      reinterpret_cast<const uint8_t*>(client_pointer) -
      reinterpret_cast<const uint8_t*>(&vertex_index_buffer_[0]));
  return gl_pointer;
}

void GraphicsState::UpdateVertexBuffers() {
  DCHECK(!vertex_buffers_updated_);
  vertex_buffers_updated_ = true;

  if (state_dirty_) {
    Reset();
  }

  if (vertex_data_allocated_ > 0) {
    if (array_buffer_handle_ != vertex_data_buffer_handle_[frame_index_]) {
      array_buffer_handle_ = vertex_data_buffer_handle_[frame_index_];
      GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, array_buffer_handle_));
    }
    GL_CALL(glBufferData(GL_ARRAY_BUFFER, vertex_data_allocated_,
                         &vertex_data_buffer_[0], GL_DYNAMIC_DRAW));
  }

  if (vertex_index_allocated_ > 0) {
    if (index_buffer_handle_ != vertex_index_buffer_handle_[frame_index_]) {
      index_buffer_handle_ = vertex_index_buffer_handle_[frame_index_];
      GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_handle_));
    }
    GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                         vertex_index_allocated_ * sizeof(uint16_t),
                         &vertex_index_buffer_[0], GL_DYNAMIC_DRAW));
  }
}

void GraphicsState::VertexAttribPointer(GLint index, GLint size, GLenum type,
                                        GLboolean normalized, GLsizei stride,
                                        const void* client_pointer) {
  const GLvoid* gl_pointer = reinterpret_cast<const GLvoid*>(
      reinterpret_cast<const uint8_t*>(client_pointer) -
      &vertex_data_buffer_[0]);
  GL_CALL(
      glVertexAttribPointer(index, size, type, normalized, stride, gl_pointer));

  // Ensure the vertex attrib array is enabled.
  const uint32_t mask = 1 << index;
  if ((enabled_vertex_attrib_array_mask_ & mask) == 0) {
    enabled_vertex_attrib_array_mask_ |= mask;
    GL_CALL(glEnableVertexAttribArray(index));
  }
  disable_vertex_attrib_array_mask_ &= ~mask;
}

void GraphicsState::VertexAttribFinish() {
  enabled_vertex_attrib_array_mask_ &= ~disable_vertex_attrib_array_mask_;
  for (int index = 0; disable_vertex_attrib_array_mask_ != 0; ++index) {
    if ((disable_vertex_attrib_array_mask_ & 1) != 0) {
      GL_CALL(glDisableVertexAttribArray(index));
    }
    disable_vertex_attrib_array_mask_ >>= 1;
  }
}

void GraphicsState::Reset() {
  program_ = 0;

  GL_CALL(glDisable(GL_DITHER));
  GL_CALL(glDisable(GL_STENCIL_TEST));
  GL_CALL(glDisable(GL_CULL_FACE));

  GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, render_target_handle_));
  GL_CALL(glViewport(viewport_.x(), viewport_.y(),
                     viewport_.width(), viewport_.height()));
  GL_CALL(glScissor(scissor_.x(), scissor_.y(),
                    scissor_.width(), scissor_.height()));
  GL_CALL(glEnable(GL_SCISSOR_TEST));

  array_buffer_handle_ = 0;
  index_buffer_handle_ = 0;
  texture_unit_ = 0;
  SbMemorySet(&texunit_target_, 0, sizeof(texunit_target_));
  SbMemorySet(&texunit_texture_, 0, sizeof(texunit_texture_));
  clip_adjustment_dirty_ = true;

  enabled_vertex_attrib_array_mask_ = 0;
  disable_vertex_attrib_array_mask_ = 0;
  for (int index = 0; index < max_vertex_attribs_; ++index) {
    GL_CALL(glDisableVertexAttribArray(index));
  }

  if (vertex_buffers_updated_) {
    if (vertex_data_allocated_ > 0) {
      array_buffer_handle_ = vertex_data_buffer_handle_[frame_index_];
      GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, array_buffer_handle_));
    }
    if (vertex_index_allocated_ > 0) {
      index_buffer_handle_ = vertex_index_buffer_handle_[frame_index_];
      GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_handle_));
    }
  }

  if (blend_enabled_) {
    GL_CALL(glEnable(GL_BLEND));
  } else {
    GL_CALL(glDisable(GL_BLEND));
  }
  GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));

  GL_CALL(glDisable(GL_DEPTH_TEST));

  state_dirty_ = false;
}

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

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