/*
 * Copyright 2023 Rive
 */

#include "rive/renderer/gl/gl_state.hpp"

#include "shaders/constants.glsl"

namespace rive::gpu
{
void GLState::invalidate()
{
  // Invalidate all cached state.
  memset(&m_validState, 0, sizeof(m_validState));

  // PLS only ever culls the CCW face when culling is enabled.
  glFrontFace(GL_CW);
  glDepthRangef(0, 1);
  glDepthFunc(GL_GREATER);
  glClearDepthf(0);
  glClearStencil(0);

  // ANGLE_shader_pixel_local_storage doesn't allow dither.
  glDisable(GL_DITHER);

  // Low-effort attempt to reset core state we don't use to default values.
  glDisable(GL_POLYGON_OFFSET_FILL);
#ifndef RIVE_WEBGL
  // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.18
  // WebGL 2.0 behaves as though PRIMITIVE_RESTART_FIXED_INDEX were always
  // enabled.
  glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
#endif
  glDisable(GL_RASTERIZER_DISCARD);
  glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  glDisable(GL_SAMPLE_COVERAGE);
  // glDisable(GL_COLOR_LOGIC_OP);
  // glDisable(GL_INDEX_LOGIC_OP);
  // glDisable(GL_ALPHA_TEST);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  glPixelStorei(GL_PACK_ALIGNMENT, 4);
  glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

#ifndef RIVE_ANDROID
  // D3D and Metal both have a provoking vertex convention of "first" for flat
  // varyings, and it's very costly for ANGLE to implement the OpenGL
  // convention of "last" on these backends. To workaround this, ANGLE
  // provides the ANGLE_provoking_vertex extension. When this extension is
  // present, we can just set the provoking vertex to "first" and trust that
  // it will be fast.
  if (m_capabilities.ANGLE_provoking_vertex)
  {
    glProvokingVertexANGLE(GL_FIRST_VERTEX_CONVENTION_ANGLE);
  }
#endif

  // WebGL doesn't support glMaxShaderCompilerThreadsKHR.
#ifndef RIVE_WEBGL
  if (m_capabilities.KHR_parallel_shader_compile)
  {
    // Allow GL's shader compilation to use 2 background threads.
    //
    // Parallel compilation is documented to be enabled by default, but on
    // some drivers the parallel compilation does not actually activate
    // without explicitly setting this.
    //
    // NOTE: the spec states that apps may use "0xffffffff" to mean "use the
    // maximum number of threads", but that seems like an easy invitation
    // for a driver bug, so we are explicit about the number of threads.
    //
    // FIXME: When AsyncPipelineManager starts using >1 thread, we should
    // incorporate its same logic here.
    glMaxShaderCompilerThreadsKHR(2);
  }
#endif
}

void GLState::setScissor(
    IAABB scissor,
    uint32_t renderTargetHeight,
    bool bottomUp)
{
  assert(scissor.left >= 0);
  assert(scissor.right >= scissor.left);
  assert(scissor.top >= 0);
  assert(scissor.bottom >= scissor.top);
  setScissorRaw(
      scissor.left,
      bottomUp ? renderTargetHeight - scissor.bottom : scissor.top,
      scissor.width(),
      scissor.height());
}

void GLState::setScissor(
    AABBu16 scissor,
    uint32_t renderTargetHeight,
    bool bottomUp)
{
  assert(scissor.right >= scissor.left);
  assert(scissor.bottom >= scissor.top);
  setScissorRaw(
      scissor.left,
      bottomUp ? renderTargetHeight - scissor.bottom : scissor.top,
      scissor.width(),
      scissor.height());
}

void GLState::setScissorRaw(
    uint32_t left,
    uint32_t top,
    uint32_t width,
    uint32_t height)
{
  if (!m_validState.scissorBox ||
      m_scissorBox != std::array<uint32_t, 4>{left, top, width, height})
  {
    glScissor(left, top, width, height);
    m_scissorBox = {left, top, width, height};
    m_validState.scissorBox = true;
  }

  if (!m_validState.scissorEnabled || !m_scissorEnabled)
  {
    glEnable(GL_SCISSOR_TEST);
    m_scissorEnabled = true;
    m_validState.scissorEnabled = true;
  }
}

void GLState::disableScissor()
{
  if (!m_validState.scissorEnabled || m_scissorEnabled)
  {
    glDisable(GL_SCISSOR_TEST);
    m_scissorEnabled = false;
    m_validState.scissorEnabled = true;
  }
}

static void gl_enable_disable(GLenum state, bool enabled)
{
  if (enabled)
    glEnable(state);
  else
    glDisable(state);
}

void GLState::setDepthStencilEnabled(bool depthEnabled, bool stencilEnabled)
{
  if (!m_validState.depthStencilEnabled || m_depthTestEnabled != depthEnabled)
  {
    gl_enable_disable(GL_DEPTH_TEST, depthEnabled);
    m_depthTestEnabled = depthEnabled;
  }

  if (!m_validState.depthStencilEnabled ||
      m_stencilTestEnabled != stencilEnabled)
  {
    gl_enable_disable(GL_STENCIL_TEST, stencilEnabled);
    m_stencilTestEnabled = stencilEnabled;
  }

  m_validState.depthStencilEnabled = true;
}

void GLState::setCullFace(GLenum cullFace)
{
  if (!m_validState.cullFace || cullFace != m_cullFace)
  {
    if (cullFace == GL_NONE)
    {
      glDisable(GL_CULL_FACE);
    }
    else
    {
      if (!m_validState.cullFace || m_cullFace == GL_NONE)
      {
        glEnable(GL_CULL_FACE);
      }
      glCullFace(cullFace);
    }
    m_cullFace = cullFace;
    m_validState.cullFace = true;
  }
}

static GLenum gl_stencil_op(StencilOp op)
{
  switch (op)
  {
    case StencilOp::keep:
      return GL_KEEP;
    case StencilOp::replace:
      return GL_REPLACE;
    case StencilOp::zero:
      return GL_ZERO;
    case StencilOp::decrClamp:
      return GL_DECR;
    case StencilOp::incrWrap:
      return GL_INCR_WRAP;
    case StencilOp::decrWrap:
      return GL_DECR_WRAP;
  }
  RIVE_UNREACHABLE();
}

static GLenum gl_stencil_func(gpu::StencilCompareOp compareOp)
{
  switch (compareOp)
  {
    case gpu::StencilCompareOp::less:
      return GL_LESS;
    case gpu::StencilCompareOp::equal:
      return GL_EQUAL;
    case gpu::StencilCompareOp::lessOrEqual:
      return GL_LEQUAL;
    case gpu::StencilCompareOp::notEqual:
      return GL_NOTEQUAL;
    case gpu::StencilCompareOp::always:
      return GL_ALWAYS;
  }
  RIVE_UNREACHABLE();
}

static GLenum gl_cull_face(CullFace riveCullFace)
{
  switch (riveCullFace)
  {
    case CullFace::none:
      return GL_NONE;
    case CullFace::clockwise:
      return GL_FRONT;
    case CullFace::counterclockwise:
      return GL_BACK;
  }
  RIVE_UNREACHABLE();
}

void GLState::setBlendEquation(gpu::BlendEquation blendEquation)
{
  if (m_validState.blendEquation && blendEquation == m_blendEquation)
  {
    return;
  }
  if (!m_validState.blendEquation ||
      m_blendEquation == gpu::BlendEquation::none)
  {
    glEnable(GL_BLEND);
  }
  switch (blendEquation)
  {
    case gpu::BlendEquation::none:
      glDisable(GL_BLEND);
      break;
    case gpu::BlendEquation::srcOver:
      glBlendEquation(GL_FUNC_ADD);
      glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
      break;
    case gpu::BlendEquation::plus:
      glBlendEquation(GL_FUNC_ADD);
      glBlendFunc(GL_ONE, GL_ONE);
      break;
    case gpu::BlendEquation::min:
      glBlendEquation(GL_MIN);
      glBlendFunc(GL_ONE, GL_ONE);
      break;
    case gpu::BlendEquation::max:
      glBlendEquation(GL_MAX);
      glBlendFunc(GL_ONE, GL_ONE);
      break;
    case gpu::BlendEquation::layerMask:
      // dst * srcAlpha on every channel, alpha included, so a texel the
      // content left transparent stays transparent.
      glBlendEquation(GL_FUNC_ADD);
      glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
      break;
    case gpu::BlendEquation::screen:
      glBlendEquation(GL_SCREEN_KHR);
      break;
    case gpu::BlendEquation::overlay:
      glBlendEquation(GL_OVERLAY_KHR);
      break;
    case gpu::BlendEquation::darken:
      glBlendEquation(GL_DARKEN_KHR);
      break;
    case gpu::BlendEquation::lighten:
      glBlendEquation(GL_LIGHTEN_KHR);
      break;
    case gpu::BlendEquation::colorDodge:
      glBlendEquation(GL_COLORDODGE_KHR);
      break;
    case gpu::BlendEquation::colorBurn:
      glBlendEquation(GL_COLORBURN_KHR);
      break;
    case gpu::BlendEquation::hardLight:
      glBlendEquation(GL_HARDLIGHT_KHR);
      break;
    case gpu::BlendEquation::softLight:
      glBlendEquation(GL_SOFTLIGHT_KHR);
      break;
    case gpu::BlendEquation::difference:
      glBlendEquation(GL_DIFFERENCE_KHR);
      break;
    case gpu::BlendEquation::exclusion:
      glBlendEquation(GL_EXCLUSION_KHR);
      break;
    case gpu::BlendEquation::multiply:
      glBlendEquation(GL_MULTIPLY_KHR);
      break;
    case gpu::BlendEquation::hue:
      glBlendEquation(GL_HSL_HUE_KHR);
      break;
    case gpu::BlendEquation::saturation:
      glBlendEquation(GL_HSL_SATURATION_KHR);
      break;
    case gpu::BlendEquation::color:
      glBlendEquation(GL_HSL_COLOR_KHR);
      break;
    case gpu::BlendEquation::luminosity:
      glBlendEquation(GL_HSL_LUMINOSITY_KHR);
      break;
  }
  m_blendEquation = blendEquation;
  m_validState.blendEquation = true;
}

void GLState::setWriteMasks(
    bool colorWriteMask,
    bool depthWriteMask,
    uint8_t stencilWriteMask)
{
  if (!m_validState.writeMasks)
  {
    glColorMask(colorWriteMask, colorWriteMask, colorWriteMask, colorWriteMask);
    glDepthMask(depthWriteMask);
    glStencilMask(stencilWriteMask);
    m_colorWriteMask = colorWriteMask;
    m_depthWriteMask = depthWriteMask;
    m_stencilWriteMask = stencilWriteMask;
    m_validState.writeMasks = true;
  }
  else
  {
    if (colorWriteMask != m_colorWriteMask)
    {
      glColorMask(
          colorWriteMask,
          colorWriteMask,
          colorWriteMask,
          colorWriteMask);
      m_colorWriteMask = colorWriteMask;
    }
    if (depthWriteMask != m_depthWriteMask)
    {
      glDepthMask(depthWriteMask);
      m_depthWriteMask = depthWriteMask;
    }
    if (stencilWriteMask != m_stencilWriteMask)
    {
      glStencilMask(stencilWriteMask);
      m_stencilWriteMask = stencilWriteMask;
    }
  }
}

void GLState::setPipelineState(
    const gpu::PipelineState& pipelineState,
    ScissorAction scissorAction)
{
  switch (scissorAction)
  {
    case ScissorAction::disable:
      disableScissor();
      break;

    case ScissorAction::ignore:
      break;
  }

  setDepthStencilEnabled(
      pipelineState.depthTestEnabled,
      pipelineState.stencilTestEnabled);
  if (pipelineState.stencilTestEnabled)
  {
    if (!pipelineState.stencilDoubleSided)
    {
      glStencilFunc(
          gl_stencil_func(pipelineState.stencilFrontOps.compareOp),
          pipelineState.stencilReference,
          pipelineState.stencilCompareMask);
      glStencilOp(
          gl_stencil_op(pipelineState.stencilFrontOps.stencilFailOp),
          gl_stencil_op(pipelineState.stencilFrontOps.depthFailOp),
          gl_stencil_op(pipelineState.stencilFrontOps.depthStencilPassOp));
    }
    else
    {
      glStencilFuncSeparate(
          GL_FRONT,
          gl_stencil_func(pipelineState.stencilFrontOps.compareOp),
          pipelineState.stencilReference,
          pipelineState.stencilCompareMask);
      glStencilOpSeparate(
          GL_FRONT,
          gl_stencil_op(pipelineState.stencilFrontOps.stencilFailOp),
          gl_stencil_op(pipelineState.stencilFrontOps.depthFailOp),
          gl_stencil_op(pipelineState.stencilFrontOps.depthStencilPassOp));
      glStencilFuncSeparate(
          GL_BACK,
          gl_stencil_func(pipelineState.stencilBackOps.compareOp),
          pipelineState.stencilReference,
          pipelineState.stencilCompareMask);
      glStencilOpSeparate(
          GL_BACK,
          gl_stencil_op(pipelineState.stencilBackOps.stencilFailOp),
          gl_stencil_op(pipelineState.stencilBackOps.depthFailOp),
          gl_stencil_op(pipelineState.stencilBackOps.depthStencilPassOp));
    }
  }
  setCullFace(gl_cull_face(pipelineState.cullFace));
  setBlendEquation(pipelineState.blendEquation);
  setWriteMasks(
      pipelineState.colorWriteEnabled,
      pipelineState.depthWriteEnabled,
      pipelineState.stencilWriteMask);
}

void GLState::bindProgram(GLuint programID)
{
  if (!m_validState.boundProgramID || programID != m_boundProgramID)
  {
    glUseProgram(programID);
    m_boundProgramID = programID;
    m_validState.boundProgramID = true;
  }
}

void GLState::bindVAO(GLuint vao)
{
  if (!m_validState.boundVAO || vao != m_boundVAO)
  {
    glBindVertexArray(vao);
    m_boundVAO = vao;
    m_validState.boundVAO = true;
  }
}

void GLState::bindBuffer(GLenum target, GLuint bufferID)
{
  switch (target)
  {
    default:
      // Don't track GL_ELEMENT_ARRAY_BUFFER, since it is tied to the VAO
      // state.
      glBindBuffer(target, bufferID);
      return;
    case GL_ARRAY_BUFFER:
      if (!m_validState.boundArrayBufferID || bufferID != m_boundArrayBufferID)
      {
        glBindBuffer(GL_ARRAY_BUFFER, bufferID);
        m_boundArrayBufferID = bufferID;
        m_validState.boundArrayBufferID = true;
      }
      break;
    case GL_UNIFORM_BUFFER:
      if (!m_validState.boundUniformBufferID ||
          bufferID != m_boundUniformBufferID)
      {
        glBindBuffer(GL_UNIFORM_BUFFER, bufferID);
        m_boundUniformBufferID = bufferID;
        m_validState.boundUniformBufferID = true;
      }
      break;
  }
}

void GLState::deleteProgram(GLuint programID)
{
  glDeleteProgram(programID);
  if (m_validState.boundProgramID && m_boundProgramID == programID)
    m_boundProgramID = 0;
}

void GLState::deleteVAO(GLuint vao)
{
  glDeleteVertexArrays(1, &vao);
  if (m_validState.boundVAO && m_boundVAO == vao)
    m_boundVAO = 0;
}

void GLState::deleteBuffer(GLuint bufferID)
{
  glDeleteBuffers(1, &bufferID);
  if (m_validState.boundArrayBufferID && m_boundArrayBufferID == bufferID)
    m_boundArrayBufferID = 0;
  if (m_validState.boundUniformBufferID && m_boundUniformBufferID == bufferID)
    m_boundUniformBufferID = 0;
}
} // namespace rive::gpu
