ref: 2d8758d2ff5ec69fbb4c5d341fa35f0ffe6cd361
parent: 3ca166d5abe3e594626de355a000fdc911d18cee
author: David <gek@katherine>
date: Sat Feb 20 20:28:50 EST 2021
Added buffers
--- a/README.md
+++ b/README.md
@@ -89,7 +89,9 @@
* Added glDrawArrays
+* Added Buffers
+
Note that this Softrast **is not GL 1.1 compliant** and does not constitute a complete GL implementation.
You *will* have to tweak your code to work with this library. That said, once you have, it will run anywhere that you can get
@@ -217,6 +219,13 @@
This function can be added to display lists.
Plot pixel directly to the buffer.
+
+### glGenBuffers, glDeleteBuffers, glBindBuffer (valid target: ARRAY_BUFFER), glBindBufferAsArray
+
+Serverside buffers! Makes it a bit easier to do clientside array stuff at the moment.
+may be the site of future hardware acceleration.
+
+Please look at the model.c demo to see how to use these functions. They function very similarly to their GL 2.0+ counterparts.
## TOGGLEABLE FEATURES
--- a/SDL_Examples/model.c
+++ b/SDL_Examples/model.c
@@ -287,6 +287,7 @@
char needsRGBAFix = 0;
unsigned int count = 40;
GLuint modelDisplayList = 0;
+ GLuint buffers[4]; //pos,color,normal,texcoord
int dlExists = 0;
int doTextures = 1;
char* modelName = "extrude.obj";
@@ -438,6 +439,7 @@
dlExists = 1;
} else {
LoadModelArrays(m.d, m.npoints, m.c, m.n, m.t);
+ /*
if(ModelArray.colors)glEnableClientState(GL_COLOR_ARRAY);
if(ModelArray.points)glEnableClientState(GL_VERTEX_ARRAY);
if(ModelArray.normals)glEnableClientState(GL_NORMAL_ARRAY);
@@ -447,6 +449,47 @@
if(ModelArray.normals)glNormalPointer(GL_FLOAT,0,ModelArray.normals); //Must be 3!
if(ModelArray.colors)glColorPointer(3,GL_FLOAT,0,ModelArray.colors);
if(ModelArray.texcoords)glTexCoordPointer(2,GL_FLOAT,0,ModelArray.texcoords);
+ */
+ glGenBuffers(4, buffers);
+ for(int i = 0; i < 4; i++){
+ printf("\nBuffer %d is %d", i , buffers[i]);
+ if(buffers[i] == 0){
+ printf("\nBuffer allocation failed for buffer %d!\n", i);
+ return 1;
+ }
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+ glBufferData(GL_ARRAY_BUFFER,
+ sizeof(GLfloat) * 3 * ModelArray.npoints,
+ ModelArray.points,
+ GL_STATIC_DRAW);
+ if(glMapBuffer(GL_ARRAY_BUFFER,0) == NULL)
+ printf("\nglBufferData failed for buffer %d!\n", 0);
+ glBindBufferAsArray(GL_VERTEX_BUFFER, buffers[0],GL_FLOAT,3,0);
+ if(ModelArray.colors){
+ glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
+ glBufferData(GL_ARRAY_BUFFER,
+ sizeof(GLfloat) * 3 * ModelArray.npoints,
+ ModelArray.colors,
+ GL_STATIC_DRAW);
+ glBindBufferAsArray(GL_COLOR_BUFFER, buffers[1],GL_FLOAT,3,0);
+ }
+ if(ModelArray.normals){
+ glBindBuffer(GL_ARRAY_BUFFER, buffers[2]);
+ glBufferData(GL_ARRAY_BUFFER,
+ sizeof(GLfloat) * 3 * ModelArray.npoints,
+ ModelArray.normals,
+ GL_STATIC_DRAW);
+ glBindBufferAsArray(GL_NORMAL_BUFFER, buffers[2],GL_FLOAT,3,0);
+ }
+ if(ModelArray.texcoords){
+ glBindBuffer(GL_ARRAY_BUFFER, buffers[3]);
+ glBufferData(GL_ARRAY_BUFFER,
+ sizeof(GLfloat) * 2 * ModelArray.npoints,
+ ModelArray.texcoords,
+ GL_STATIC_DRAW);
+ glBindBufferAsArray(GL_TEXTURE_COORD_BUFFER,buffers[3],GL_FLOAT,2,0);
+ }
}
freemodel(&m);
}
--- a/config.mk
+++ b/config.mk
@@ -3,6 +3,7 @@
CC= gcc
CFLAGS= -Wall -O3 -g -std=c99 -Wno-undef -march=native -DNDEBUG
+#CFLAGS= -Wall -O1 -g -std=c99 -Wno-undef -DNDEBUG
LFLAGS=
--- a/include/GL/gl.h
+++ b/include/GL/gl.h
@@ -46,12 +46,18 @@
GL_POLYGON = 0x0009,
GL_EDGE_FLAG = 0x0B43,
+ /* Necessary for glBufferData */
+ GL_STATIC_DRAW = 0x88E4,
/* Vertex Arrays */
GL_VERTEX_ARRAY = 0x8074,
+ GL_VERTEX_BUFFER = 0x8074,
GL_NORMAL_ARRAY = 0x8075,
+ GL_NORMAL_BUFFER = 0x8075,
GL_COLOR_ARRAY = 0x8076,
+ GL_COLOR_BUFFER = 0x8076,
GL_INDEX_ARRAY = 0x8077,
GL_TEXTURE_COORD_ARRAY = 0x8078,
+ GL_TEXTURE_COORD_BUFFER = 0x8078,
GL_EDGE_FLAG_ARRAY = 0x8079,
GL_VERTEX_ARRAY_SIZE = 0x807A,
GL_VERTEX_ARRAY_TYPE = 0x807B,
@@ -607,7 +613,8 @@
GL_POLYGON_OFFSET_EXT = 0x8037,
GL_POLYGON_OFFSET_FACTOR_EXT = 0x8038,
GL_POLYGON_OFFSET_BIAS_EXT = 0x8039,
-
+ /* GL */
+ GL_ARRAY_BUFFER = 0x8892,
/* GL_EXT_vertex_array */
GL_VERTEX_ARRAY_EXT = 0x8074,
GL_NORMAL_ARRAY_EXT = 0x8075,
@@ -880,6 +887,22 @@
const GLvoid *pointer);
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer);
+/* opengl 2.0 buffers */
+void glGenBuffers( GLsizei n,
+ GLuint * buffers);
+void glDeleteBuffers( GLsizei n,
+ const GLuint * buffers);
+void glBindBuffer( GLenum target,
+ GLuint buffer);
+GLboolean glIsBuffer( GLuint buffer);
+void *glMapBuffer( GLenum target,
+ GLenum access);
+void glBufferData( GLenum target,
+ GLsizei size,
+ const void * data,
+ GLenum usage);
+//Bonus ducks!
+void glBindBufferAsArray(GLenum target, GLuint buffer, GLenum type, GLint size, GLint stride);
/* opengl 1.2 polygon offset */
void glPolygonOffset(GLfloat factor, GLfloat units);
--- a/src/arrays.c
+++ b/src/arrays.c
@@ -7,6 +7,292 @@
#define NORMAL_ARRAY 0x0004
#define TEXCOORD_ARRAY 0x0008
+//Code for buffers is here too!
+
+
+GLint free_buffer(GLint handle){
+ GLContext* c = gl_get_context();
+ GLSharedState* s = &(c->shared_state);
+ if(handle == 0 || handle > MAX_BUFFERS) return 1; //error flag
+//HANDLE IS HENCEFORTH AN INDEX, AND NOT A HANDLE!!!
+ handle--;
+ if(s->buffers[handle]){ //if this handle exists...
+ if(c->boundarraybuffer == (handle+1)) c->boundarraybuffer = 0;
+ if(s->buffers[handle]->data) //if this handle has data...
+ {
+ void* d = s->buffers[handle]->data;
+ gl_free(s->buffers[handle]->data); //free the data...
+ //deal with the possible bindings...
+ if(c->vertex_array == d) {c->vertex_array = NULL;c->client_states &= ~VERTEX_ARRAY;}
+ if(c->color_array == d) {c->color_array = NULL;c->client_states &= ~COLOR_ARRAY;}
+ if(c->normal_array == d) {c->normal_array = NULL;c->client_states &= ~NORMAL_ARRAY;}
+ if(c->texcoord_array == d) {c->texcoord_array = NULL;c->client_states &= ~TEXCOORD_ARRAY;}
+ }
+ gl_free(s->buffers[handle]); //free the buffer...
+ s->buffers[handle] = NULL; //Set it to null...
+ return 0;
+ } else {
+ return 0;
+ }
+}
+GLint check_buffer(GLint handle){ //1 means used, 0 means free, 2 means invalid
+ GLContext* c = gl_get_context();
+ GLSharedState* s = &(c->shared_state);
+ if(handle == 0 || handle > MAX_BUFFERS) return 2; //error flag
+ handle--;
+ if(s->buffers[handle]) return 1;
+ return 0;
+}
+GLboolean glIsBuffer( GLuint buffer){
+ if(check_buffer(buffer) == 1) return GL_TRUE;
+ return GL_FALSE;
+}
+
+
+static inline GLBuffer* get_buffer(GLint handle){
+ GLContext* c = gl_get_context();
+ GLSharedState* s = &(c->shared_state);
+ if(handle == 0 || handle > MAX_BUFFERS) return NULL;
+ handle--;
+ return s->buffers[handle];
+}
+GLint create_buffer(GLint handle){
+ GLContext* c = gl_get_context();
+ GLSharedState* s = &(c->shared_state);
+ if(handle == 0 || handle > MAX_BUFFERS) return 1; //error flag
+ handle--;//convert from handle to index
+ if(s->buffers[handle]) free_buffer(handle+1); //this is no longer the handle so we have to add 1.
+ //This buffer is now free for usage!
+ s->buffers[handle] = gl_zalloc(sizeof(GLBuffer));
+
+ if(!(s->buffers[handle])){
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#define RETVAL 1
+#include "error_check.h"
+#else
+ gl_fatal_error("GL_OUT_OF_MEMORY");
+#endif
+ }
+ s->buffers[handle]->data = NULL;
+ s->buffers[handle]->size = 0;
+ return 0;
+}
+
+void glGenBuffers( GLsizei n,
+ GLuint * buffers)
+{
+ #include "error_check.h"
+ if(n > MAX_BUFFERS) goto error;
+
+ {
+ GLint n_left = n;
+ GLuint names[n];
+ for(int i = 1; i <= MAX_BUFFERS && n_left > 0; i++)
+ if(!check_buffer(i)) names[(n_left--)-1] = i;
+
+ if(n_left) goto error; //We were unable to find enough free names.
+ for(int i = 0; i < n; i++){
+ create_buffer(names[i]);
+
+//we have this error check here to quit out early in case of GL_OUT_OF_MEMORY
+#include "error_check.h"
+ buffers[i] = names[i];
+ }
+ }
+ return;
+ error:
+ for(int i = 0; i < n; i++)
+ buffers[i] = 0;
+ return;
+}
+void glDeleteBuffers( GLsizei n,
+ const GLuint * buffers)
+{
+ #include "error_check.h"
+ for(GLint i = 0; i < n; i++) free_buffer(buffers[i]);
+}
+
+
+//TODO GL_ARRAY_BUFFER, at a minimum.
+void glBindBuffer( GLenum target,
+ GLuint buffer)
+{
+ GLContext* c = gl_get_context();
+ #include "error_check.h"
+ if(buffer == 0 ||
+ check_buffer(buffer) == 1){
+ if(target == GL_ARRAY_BUFFER) c->boundarraybuffer = buffer;
+ }
+ return;
+}
+
+void glBindBufferAsArray(GLenum target,
+ GLuint buffer,
+ GLenum type, //GL_FLOAT
+ GLint size, //number of floats
+ GLint stride){ //floats between items
+ GLContext* c = gl_get_context();
+ #include "error_check.h"
+ if(target != GL_VERTEX_BUFFER &&
+ target != GL_NORMAL_BUFFER &&
+ target != GL_COLOR_BUFFER &&
+ target != GL_TEXTURE_COORD_BUFFER){
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
+ return;
+#endif
+
+ }
+ if(buffer == 0)
+ switch(target){
+ case GL_VERTEX_BUFFER:
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(size, type, stride, NULL);
+ c->boundvertexbuffer = buffer;
+ return;
+ break;
+ case GL_NORMAL_BUFFER:
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(type, stride, NULL);
+ c->boundnormalbuffer = buffer;
+ return;
+ break;
+ case GL_COLOR_BUFFER:
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColorPointer(size, type, stride, NULL);
+ c->boundcolorbuffer = buffer;
+ return;
+ break;
+ case GL_TEXTURE_COORD_BUFFER:
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(size, type, stride, NULL);
+ c->boundtexcoordbuffer = buffer;
+ return;
+ break;
+ default:return;
+ }
+ if(check_buffer(buffer) != 1 ||
+ type != GL_FLOAT){
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
+ tgl_warning("\ncheck_buffer failed on buffer, or incorrect type\n");
+ return;
+#endif
+ }
+ GLBuffer* buf = c->shared_state.buffers[buffer-1];
+ if(!buf || (buf->data == NULL) || (buf->size == 0)){
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_OPERATION
+#include "error_check.h"
+#else
+ tgl_warning("\nbuffer was null, buffer data was null, or buffer size was 0\n");
+ return;
+#endif
+ }
+ switch(target){
+ case GL_VERTEX_BUFFER:
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(size, type, stride, buf->data);
+ c->boundvertexbuffer = buffer;
+ break;
+ case GL_NORMAL_BUFFER:
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(type, stride, buf->data);
+ c->boundnormalbuffer = buffer;
+ break;
+ case GL_COLOR_BUFFER:
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(size, type, stride, buf->data);
+ c->boundcolorbuffer = buffer;
+ break;
+ case GL_TEXTURE_COORD_BUFFER:
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(size, type, stride, buf->data);
+ c->boundtexcoordbuffer = buffer;
+ break;
+
+ default:return;
+ }
+ return;
+}
+
+void *glMapBuffer( GLenum target,
+ GLenum access)
+{
+ GLContext* c = gl_get_context();
+#define RETVAL NULL
+#include "error_check.h"
+ GLint handle = 0;
+ if(target == GL_ARRAY_BUFFER) handle = c->boundarraybuffer;
+ if(target == GL_VERTEX_BUFFER) handle = c->boundvertexbuffer;
+ if(target == GL_TEXTURE_COORD_BUFFER) handle = c->boundtexcoordbuffer;
+ if(target == GL_NORMAL_BUFFER) handle = c->boundnormalbuffer;
+ if(target == GL_COLOR_BUFFER) handle = c->boundcolorbuffer;
+ {
+ if(check_buffer(handle) == 1)
+ return c->shared_state.buffers[handle-1]->data;
+ }
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define RETVAL NULL
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
+ return NULL;
+#endif
+}
+void glBufferData( GLenum target,
+ GLsizei size,
+ const void * data,
+ GLenum usage) //Usage parameter is ignored.
+{
+ GLContext* c = gl_get_context();
+#include "error_check.h"
+ GLint handle = 0;
+ GLBuffer* buf = NULL;
+ if(target == GL_ARRAY_BUFFER) handle = c->boundarraybuffer;
+ if(target == GL_VERTEX_BUFFER) handle = c->boundvertexbuffer;
+ if(target == GL_TEXTURE_COORD_BUFFER) handle = c->boundtexcoordbuffer;
+ if(target == GL_NORMAL_BUFFER) handle = c->boundnormalbuffer;
+ if(target == GL_COLOR_BUFFER) handle = c->boundcolorbuffer;
+ if(check_buffer(handle) == 1)
+ buf = c->shared_state.buffers[handle-1];
+ else {
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
+ return;
+#endif
+ }
+ if(buf->data) gl_free(buf->data);
+ buf->data = NULL; buf->size = 0;
+ buf->data = gl_malloc(size);
+ buf->size = size;
+ if(!(buf->data)){
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#include "error_check.h"
+#else
+ gl_fatal_error("GL_OUT_OF_MEMORY")
+#endif
+ }
+ memcpy(buf->data, data, size);
+}
+
+
+
+
+
+
+
+
+
+
void glopArrayElement(GLContext* c, GLParam* param) {
GLint i;
GLint states = c->client_states;
--- a/src/get.c
+++ b/src/get.c
@@ -170,6 +170,7 @@
#if TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST == 1
"TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST "
#endif
+"TGL_BUFFER_EXT "
"TGL_SOFTWARE_ACCELERATED";
const GLubyte* glGetString(GLenum name){
switch(name){
--- a/src/init.c
+++ b/src/init.c
@@ -1,5 +1,5 @@
#include "zgl.h"
-
+#include "msghandling.h"
GLContext* gl_ctx;
void initSharedState(GLContext* c) {
@@ -10,6 +10,9 @@
s->texture_hash_table = gl_zalloc(sizeof(GLTexture*) * TEXTURE_HASH_TABLE_SIZE);
if(!s->texture_hash_table)
gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
+ s->buffers = gl_zalloc(sizeof(GLBuffer*) * MAX_BUFFERS);
+ if(!s->buffers)
+ gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
alloc_texture(c, 0);
#include "error_check.h"
}
@@ -61,6 +64,17 @@
}
}
gl_free(s->texture_hash_table);
+ for(i = 0; i < MAX_BUFFERS; i++){
+ if(s->buffers[i])
+ {
+ //tgl_warning("\nFound a buffer that needs deleting! its handle is %d\n",i+1);
+ if(s->buffers[i]->data){
+ gl_free(s->buffers[i]->data);
+ //tgl_warning("\nIt has data too! its handle is %d\n",i+1);
+ }
+ gl_free(s->buffers[i]);
+ }
+ }
}
#if TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST == 1
@@ -121,6 +135,12 @@
initSharedState(c);
/* ztext */
c->textsize = 1;
+ /* buffer */
+ c->boundarraybuffer = 0; //no bound buffer
+ c->boundvertexbuffer = 0; //no bound buffer
+ c->boundcolorbuffer = 0; //no bound buffer
+ c->boundnormalbuffer = 0; //no bound buffer
+ c->boundtexcoordbuffer = 0; //no bound buffer
/* lists */
c->exec_flag = 1;
--- a/src/texture.c
+++ b/src/texture.c
@@ -6,7 +6,6 @@
static GLTexture* find_texture(GLContext* c, GLint h) {
GLTexture* t;
-
t = c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
while (t != NULL) {
if (t->handle == h)
--- a/src/zgl.h
+++ b/src/zgl.h
@@ -7,6 +7,8 @@
#include <assert.h>
#include <math.h>
#include <stdlib.h>
+//Needed for memcpy
+#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979323
#endif
@@ -50,6 +52,8 @@
#define TGL_OFFSET_LINE 0x2
#define TGL_OFFSET_POINT 0x4
+
+
typedef struct GLSpecBuf {
GLint shininess_i;
GLint last_used;
@@ -134,7 +138,6 @@
/* textures */
#define TEXTURE_HASH_TABLE_SIZE 256
-
typedef struct GLTexture {
GLImage images[MAX_TEXTURE_LEVELS];
GLint handle;
@@ -141,11 +144,18 @@
struct GLTexture *next, *prev;
} GLTexture;
-/* shared state */
+/* buffers */
+#define MAX_BUFFERS 2048
+typedef struct GLBuffer{
+ void* data;
+ GLuint size;
+} GLBuffer;
+/* shared state */
typedef struct GLSharedState {
GLList** lists;
GLTexture** texture_hash_table;
+ GLBuffer** buffers;
} GLSharedState;
struct GLContext;
@@ -285,6 +295,13 @@
/* text */
GLTEXTSIZE textsize;
+
+ /* buffers */
+ GLint boundarraybuffer; //0 if no buffer is bound.
+ GLint boundvertexbuffer;
+ GLint boundnormalbuffer;
+ GLint boundcolorbuffer;
+ GLint boundtexcoordbuffer;
} GLContext;
extern GLContext* gl_ctx;