diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gl.c | 15 | ||||
-rw-r--r-- | src/graphics/vertex_buffer.c | 111 | ||||
-rw-r--r-- | src/window/window.c | 3 |
3 files changed, 128 insertions, 1 deletions
@@ -1,6 +1,6 @@ #include "../include/mgl/gl.h" #include <dlfcn.h> -#include <GL/gl.h> +/*#include <GL/gl.h>*/ #include <stdio.h> typedef struct { @@ -53,7 +53,20 @@ int mgl_gl_load(mgl_gl *self) { { &self->glTexCoord2f, "glTexCoord2f" }, { &self->glOrtho, "glOrtho" }, { &self->glMatrixMode, "glMatrixMode" }, + { &self->glPushMatrix, "glPushMatrix" }, + { &self->glPopMatrix, "glPopMatrix" }, { &self->glLoadIdentity, "glLoadIdentity" }, + { &self->glTranslatef, "glTranslatef" }, + { &self->glGenBuffers, "glGenBuffers" }, + { &self->glBindBuffer, "glBindBuffer" }, + { &self->glDeleteBuffers, "glDeleteBuffers" }, + { &self->glBufferData, "glBufferData" }, + { &self->glBufferSubData, "glBufferSubData" }, + { &self->glDrawArrays, "glDrawArrays" }, + { &self->glEnableClientState, "glEnableClientState" }, + { &self->glVertexPointer, "glVertexPointer" }, + { &self->glColorPointer, "glColorPointer" }, + { &self->glTexCoordPointer, "glTexCoordPointer" }, { NULL, NULL } }; diff --git a/src/graphics/vertex_buffer.c b/src/graphics/vertex_buffer.c new file mode 100644 index 0000000..415f574 --- /dev/null +++ b/src/graphics/vertex_buffer.c @@ -0,0 +1,111 @@ +#include "../../include/mgl/graphics/vertex_buffer.h" +#include "../../include/mgl/graphics/texture.h" +#include "../../include/mgl/mgl.h" + +/* TODO: Cache vertex buffer */ +/* + TODO: Add option to only use vertices and color or vertices and texture coordinates. + In such cases we should call glEnableClientState/glDisableClientState(GL_COLOR_ARRAY/GL_TEXTURE_COORD_ARRAY) and others. +*/ + +static unsigned int mgl_vertex_buffer_usage_to_gl_usage(mgl_vertex_buffer_usage usage) { + switch(usage) { + case MGL_USAGE_STREAM: return GL_STREAM_DRAW; + case MGL_USAGE_DYNAMIC: return GL_DYNAMIC_DRAW; + case MGL_USAGE_STATIC: return GL_STATIC_DRAW; + } + return GL_STREAM_DRAW; +} + +static unsigned int mgl_primitive_type_to_gl_mode(mgl_primitive_type primitive_type) { + switch(primitive_type) { + case MGL_PRIMITIVE_POINTS: return GL_POINTS; + case MGL_PRIMITIVE_LINES: return GL_LINES; + case MGL_PRIMITIVE_LINE_STRIP: return GL_LINE_STRIP; + case MGL_PRIMITIVE_TRIANGLES: return GL_TRIANGLES; + case MGL_PRIMITIVE_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; + case MGL_PRIMITIVE_TRIANGLE_FAN: return GL_TRIANGLE_FAN; + case MGL_PRIMITIVE_QUADS: return GL_QUADS; + case MGL_PRIMITIVE_QUAD_STRIP: return GL_QUAD_STRIP; + case MGL_PRIMITIVE_POLYGON: return GL_POLYGON; + } + return MGL_PRIMITIVE_QUADS; +} + +int mgl_vertex_buffer_init(mgl_vertex_buffer *self, mgl_primitive_type primitive_type, mgl_vertex_buffer_usage usage) { + self->id = 0; + self->vertex_count = 0; + self->primitive_type = primitive_type; + self->usage = usage; + self->position = (mgl_vec2f){ 0.0f, 0.0f }; + + mgl_context *context = mgl_get_context(); + context->gl.glGenBuffers(1, &self->id); + if(self->id == 0) + return -1; + + return 0; +} + +void mgl_vertex_buffer_deinit(mgl_vertex_buffer *self) { + mgl_context *context = mgl_get_context(); + if(self->id) { + context->gl.glDeleteBuffers(1, &self->id); + self->id = 0; + } + self->vertex_count = 0; + self->primitive_type = 0; + self->usage = 0; +} + +static void mgl_vertex_buffer_set_gl_buffer_pointers(mgl_context *context) { + context->gl.glVertexPointer(2, GL_FLOAT, sizeof(mgl_vertex), (void*)offsetof(mgl_vertex, position)); + context->gl.glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(mgl_vertex), (void*)offsetof(mgl_vertex, color)); + context->gl.glTexCoordPointer(2, GL_FLOAT, sizeof(mgl_vertex), (void*)offsetof(mgl_vertex, texcoords)); +} + +/* TODO: Check for glBufferData error */ +static int mgl_vertex_buffer_resize(mgl_vertex_buffer *self, mgl_vertex *vertices, size_t vertex_count) { + mgl_context *context = mgl_get_context(); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, self->id); + context->gl.glBufferData(GL_ARRAY_BUFFER, sizeof(mgl_vertex) * vertex_count, vertices, mgl_vertex_buffer_usage_to_gl_usage(self->usage)); + mgl_vertex_buffer_set_gl_buffer_pointers(context); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, 0); + self->vertex_count = vertex_count; + return 0; +} + +void mgl_vertex_buffer_set_position(mgl_vertex_buffer *self, mgl_vec2f position) { + self->position = position; +} + +/* TODO: Check for glBufferSubData error */ +int mgl_vertex_buffer_update(mgl_vertex_buffer *self, mgl_vertex *vertices, size_t vertex_count) { + if(vertex_count != self->vertex_count) + return mgl_vertex_buffer_resize(self, vertices, vertex_count); + + mgl_context *context = mgl_get_context(); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, self->id); + context->gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(mgl_vertex) * vertex_count, vertices); + mgl_vertex_buffer_set_gl_buffer_pointers(context); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, 0); + return 0; +} + +/* TODO: Optimize bind texture */ +void mgl_vertex_buffer_draw(mgl_context *context, mgl_vertex_buffer *self, mgl_texture *texture) { + if(self->vertex_count == 0 || self->id == 0) + return; + + /* TODO: Optimize this */ + context->gl.glPushMatrix(); + context->gl.glTranslatef(self->position.x, self->position.y, 0.0f); + + context->gl.glBindTexture(GL_TEXTURE_2D, texture ? texture->id : 0); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, self->id); + context->gl.glDrawArrays(mgl_primitive_type_to_gl_mode(self->primitive_type), 0, self->vertex_count); + context->gl.glBindBuffer(GL_ARRAY_BUFFER, 0); + context->gl.glBindTexture(GL_TEXTURE_2D, 0); + + context->gl.glPopMatrix(); +} diff --git a/src/window/window.c b/src/window/window.c index 80c3ccf..691a647 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -84,6 +84,9 @@ int mgl_window_create_with_params(mgl_window *self, const char *title, int width context->gl.glEnable(GL_TEXTURE_2D); context->gl.glEnable(GL_BLEND); context->gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + context->gl.glEnableClientState(GL_VERTEX_ARRAY); + context->gl.glEnableClientState(GL_COLOR_ARRAY); + context->gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); XWindowAttributes gwa; gwa.width = 0; |