#include "buffer.hpp"


Buffer::Buffer(GLenum t): target(t) {
    glGenBuffers(1, &buffer);
}


bool Buffer::bind() {
    glBindBuffer(target, buffer);
    return true;
}


bool Buffer::bind(const GLvoid* data, GLsizeiptr size, GLenum usage) {
    glBindBuffer(target, buffer);
    glBufferData(target, size, data, usage);
    return true;
}


Buffer::~Buffer() {
    glDeleteBuffers(1, &buffer);
}


ArrayBuffer::ArrayBuffer(size_t ilen): itemlen(ilen), vbo(GL_ARRAY_BUFFER) {
    assert(itemlen);
    glGenVertexArrays(1, &vertexArray);
}


ArrayBuffer::~ArrayBuffer() {
    glDeleteVertexArrays(1, &vertexArray);
}


bool ArrayBuffer::bind() {
    vbo.bind(); // XXX: needed?
    glBindVertexArray(vertexArray);
    return true;
}


bool ArrayBuffer::bind(const GLfloat* buf, size_t num, GLenum usage) {
    assert(num && num % itemlen == 0);
    vbo.bind(buf, num * sizeof(GLfloat), usage);
    glBindVertexArray(vertexArray);
    return true;
}


bool ArrayBuffer::setAttrib(Program* program, const char* name, size_t pos, size_t len) {
    bind();
    assert(pos + len <= itemlen);
    GLint attrib = glGetAttribLocation(*program, name);
    if (attrib < 0 || glerr()) {
        LOG("cannot find attrib '%s'", name);
        return false;
    }
    glEnableVertexAttribArray(attrib);
    glVertexAttribPointer(attrib, len, GL_FLOAT, GL_FALSE, itemlen * sizeof(GLfloat), (void*)(pos * sizeof(GLfloat)));
    return true;
}