#include "stdafx.h"
#include "Buffer.h"

#ifdef GUI_GTK

namespace gui {

	static GLenum glUsage(BufferUsage usage) {
		switch (usage) {
		case bufferStatic:
			return GL_STATIC_DRAW;
		case bufferDynamic:
			return GL_DYNAMIC_DRAW;
		case bufferReplace:
			return GL_STREAM_DRAW;
		default:
			return GL_DYNAMIC_DRAW;
		}
	}

	GLBuffer::GLBuffer(GLSurface &surface, VertexBufferBase *buffer) : surface(surface) {
		surface.makeCurrent();
		elementSize = buffer->elemSize();
		currentCount = buffer->count();
		usage = buffer->usage;

		glCreateBuffers(1, &this->buffer);
		glNamedBufferData(this->buffer, elementSize * buffer->count(), buffer->buffer(), glUsage(usage));
	}

	GLBuffer::GLBuffer(GLSurface &surface, IndexBufferBase *buffer) : surface(surface) {
		surface.makeCurrent();
		elementSize = sizeof(Nat);
		currentCount = buffer->count();
		usage = buffer->usage;

		glCreateBuffers(1, &this->buffer);
		glNamedBufferData(this->buffer, elementSize * buffer->count(), buffer->buffer(), glUsage(usage));
	}

	GLBuffer::~GLBuffer() {
		surface.makeCurrent();

		glDeleteBuffers(1, &buffer);
	}

	void GLBuffer::update(VertexBufferBase *buffer, const DirtyRange &dirty) {
		if (buffer->count() == currentCount && usage == buffer->usage) {
			size_t offset = dirty.begin * elementSize;
			glNamedBufferSubData(this->buffer, offset, dirty.count() * elementSize,
								(const char *)buffer->buffer() + offset);
		} else {
			currentCount = buffer->count();
			usage = buffer->usage;
			glNamedBufferData(this->buffer, elementSize * buffer->count(), buffer->buffer(), glUsage(usage));
		}
	}

	void GLBuffer::update(IndexBufferBase *buffer, const DirtyRange &dirty) {
		if (buffer->count() == currentCount && usage == buffer->usage) {
			size_t offset = dirty.begin * elementSize;
			glNamedBufferSubData(this->buffer, offset, dirty.count() * elementSize,
								(const char *)buffer->buffer() + offset);
		} else {
			currentCount = buffer->count();
			usage = buffer->usage;
			glNamedBufferData(this->buffer, elementSize * buffer->count(), buffer->buffer(), glUsage(usage));
		}
	}

}

#endif
