package ocelot.desktop.graphics.buffer import ocelot.desktop.util.{Logging, Resource} import org.lwjgl.BufferUtils import org.lwjgl.opengl.GL15 import java.nio.ByteBuffer class Buffer[T <: BufferPut] extends Logging with Resource { val target: Int = GL15.GL_ARRAY_BUFFER val buffer: Int = GL15.glGenBuffers() var capacity: Int = _ var stride: Int = _ override def freeResource(): Unit = { super.freeResource() GL15.glDeleteBuffers(buffer) logger.debug(s"Destroyed buffer (ID: $buffer) of ${capacity * stride} bytes") } def this(elements: Seq[T]) = { this() createStatic(elements) } def write(offset: Int, buf: ByteBuffer): Unit = { bind() GL15.glBufferSubData(target, offset * stride, buf) } def resize(newCap: Int): Unit = { createDynamic(this.stride, newCap) } protected def createDynamic(stride: Int, cap: Int): Unit = { bind() GL15.glBufferData(target, stride * cap, GL15.GL_DYNAMIC_DRAW) this.stride = stride capacity = cap } protected def createStatic(elements: Seq[T]): Unit = { assert(elements.nonEmpty, "Zero size immutable buffer") extractMeta(elements.head) bind() val buf = storeElements(elements) GL15.glBufferData(target, buf, GL15.GL_STATIC_DRAW) capacity = elements.length } private def storeElements(elements: Seq[T]): ByteBuffer = { val data = BufferUtils.createByteBuffer(elements.length * elements.head.stride) for (element <- elements) { element.put(data) } data.flip data } protected def extractMeta(head: T): Unit = { stride = head.stride } def bind(): Unit = { GL15.glBindBuffer(target, buffer) } }