/*
 * Copyright 2022 Rive
 */

#include "buffer_ring_gl.hpp"

#include <algorithm>

namespace rive::pls
{
BufferGL::BufferGL(GLenum target, size_t capacity, size_t itemSizeInBytes) :
    BufferRingShadowImpl(capacity, itemSizeInBytes), m_target(target)
{
    glGenBuffers(kBufferRingSize, m_ids);
    for (int i = 0; i < kBufferRingSize; ++i)
    {
        glBindBuffer(m_target, m_ids[i]);
        glBufferData(m_target, capacity * itemSizeInBytes, nullptr, GL_DYNAMIC_DRAW);
    }
}

BufferGL::~BufferGL() { glDeleteBuffers(kBufferRingSize, m_ids); }

void BufferGL::onUnmapAndSubmitBuffer(int bufferIdx, size_t bytesWritten)
{
    glBindBuffer(m_target, m_ids[bufferIdx]);
    glBufferSubData(m_target, 0, bytesWritten, shadowBuffer());
}

static GLenum internalformat_gl(TexelBufferRing::Format format)
{
    switch (format)
    {
        case TexelBufferRing::Format::rgba8:
            return GL_RGBA8;
        case TexelBufferRing::Format::rgba32f:
            return GL_RGBA32F;
        case TexelBufferRing::Format::rgba32ui:
            return GL_RGBA32UI;
    }
    RIVE_UNREACHABLE();
}

static GLenum format_gl(TexelBufferRing::Format format)
{
    switch (format)
    {
        case TexelBufferRing::Format::rgba8:
        case TexelBufferRing::Format::rgba32f:
            return GL_RGBA;
        case TexelBufferRing::Format::rgba32ui:
            return GL_RGBA_INTEGER;
    }
    RIVE_UNREACHABLE();
}

static GLenum type_gl(TexelBufferRing::Format format)
{
    switch (format)
    {
        case TexelBufferRing::Format::rgba8:
            return GL_UNSIGNED_BYTE;
        case TexelBufferRing::Format::rgba32f:
            return GL_FLOAT;
        case TexelBufferRing::Format::rgba32ui:
            return GL_UNSIGNED_INT;
    }
    RIVE_UNREACHABLE();
}

static GLenum filter_gl(TexelBufferRing::Filter filter)
{
    switch (filter)
    {
        case TexelBufferRing::Filter::nearest:
            return GL_NEAREST;
        case TexelBufferRing::Filter::linear:
            return GL_LINEAR;
    }
    RIVE_UNREACHABLE();
}

TexelBufferGL::TexelBufferGL(Format format,
                             size_t widthInItems,
                             size_t height,
                             size_t texelsPerItem,
                             GLenum activeTextureIdx,
                             Filter filter) :
    TexelBufferRing(format, widthInItems, height, texelsPerItem),
    m_activeTextureIdx(activeTextureIdx)
{
    GLenum filterGL = filter_gl(filter);
    glGenTextures(kBufferRingSize, m_ids);
    glActiveTexture(activeTextureIdx);
    for (int i = 0; i < kBufferRingSize; ++i)
    {
        glBindTexture(GL_TEXTURE_2D, m_ids[i]);
        glTexStorage2D(GL_TEXTURE_2D, 1, internalformat_gl(m_format), widthInTexels(), m_height);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterGL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterGL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
}

TexelBufferGL::~TexelBufferGL() { glDeleteTextures(kBufferRingSize, m_ids); }

void TexelBufferGL::submitTexels(int textureIdx, size_t updateWidthInTexels, size_t updateHeight)
{
    glActiveTexture(m_activeTextureIdx);
    glBindTexture(GL_TEXTURE_2D, m_ids[textureIdx]);
    if (updateWidthInTexels > 0 && updateHeight > 0)
    {
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
        glTexSubImage2D(GL_TEXTURE_2D,
                        0,
                        0,
                        0,
                        updateWidthInTexels,
                        updateHeight,
                        format_gl(m_format),
                        type_gl(m_format),
                        shadowBuffer());
    }
}
} // namespace rive::pls
