ref: 1abd3333d5da9542e54dd6a89aa515e9e71a6c87
parent: 67c7e4a194003c15539488e48c726d86747ff4a7
author: David <gek@katherine>
date: Fri Feb 19 07:50:05 EST 2021
Added error checking and removed error checking if error checking is disabled
--- a/include/GL/gl.h
+++ b/include/GL/gl.h
@@ -575,6 +575,7 @@
GL_LICENSE = 0x1F04,
/* Errors */
+ GL_NO_ERROR = 0x0,
GL_INVALID_VALUE = 0x0501,
GL_INVALID_ENUM = 0x0500,
GL_INVALID_OPERATION = 0x0502,
@@ -651,7 +652,8 @@
GL_TEXT_SIZE40x40 = 5,
GL_TEXT_SIZE48x48 = 6,
GL_TEXT_SIZE56x56 = 7,
- GL_TEXT_SIZE64x64 = 8
+ GL_TEXT_SIZE64x64 = 8,
+ GL_MAX_TEXT_SIZE = 8
} GLTEXTSIZE;
enum {
GL_CURRENT_BIT = 0x00000001,
@@ -843,6 +845,7 @@
void glGetIntegerv(GLint pname,GLint *params);
void glGetFloatv(GLint pname, GLfloat *v);
const GLubyte* glGetString(GLenum name);
+GLenum glGetError();
void glFrontFace(GLint mode);
/* opengl 1.2 arrays */
--- a/include/zfeatures.h
+++ b/include/zfeatures.h
@@ -4,14 +4,24 @@
/* It is possible to enable/disable (compile time) features in this
header file. */
+//Enables setting the error flags when there's an error, so you can check it with glGetError, should only be used in development builds.
+#define TGL_FEATURE_ERROR_CHECK 0
+//Strict out-of-memory checking. All OpenGL function calls are invalidated (ALL OF THEM) if a GL_OUT_OF_MEMORY error occurs.
+//This slows down the renderer so we don't usually do it.
+#define TGL_FEATURE_STRICT_OOM_CHECKS 0
+//Clientside Arrays
#define TGL_FEATURE_ARRAYS 1
+//This library has a super cool opcode system based on function pointers, it's pretty fast too.
#define TGL_FEATURE_DISPLAYLISTS 1
+//Lighting is expensive on texture-mapped polygons.
#define TGL_FEATURE_LIT_TEXTURES 1
//NOTE: Polygon Offset does nothing at the moment.
#define TGL_FEATURE_POLYGON_OFFSET 0
+//Enable the patternized "discard"-ing of pixels.
#define TGL_FEATURE_POLYGON_STIPPLE 0
-
+//Enable GL_BLEND functionality
#define TGL_FEATURE_BLEND 1
+
//A stipple pattern is 128 bytes in size.
#define TGL_POLYGON_STIPPLE_BYTES 128
//A stipple pattern is 2^5 (32) bits wide.
@@ -21,9 +31,13 @@
#define TGL_POLYGON_STIPPLE_MASK_X 31
#define TGL_POLYGON_STIPPLE_MASK_Y 31
-//These are features useful for integrating TinyGL with other renderers.
+
+
+//Prevent ZB_copyFrameBuffer from copying certain colors.
#define TGL_FEATURE_NO_COPY_COLOR 0
+//Don't draw (texture mapped) pixels whose color is the NO_DRAW_COLOR
#define TGL_FEATURE_NO_DRAW_COLOR 0
+//Regardless of the current clear color, always clear using the NO_COPY_COLOR
#define TGL_FEATURE_FORCE_CLEAR_NO_COPY_COLOR 0
#define TGL_NO_COPY_COLOR 0xff00ff
#define TGL_NO_DRAW_COLOR 0xff00ff
@@ -32,8 +46,10 @@
//^ mask to check for while drawing/copying.
+//DO NOT TURN THESE ON, I don't maintain them and I actively #error them out.
#define TGL_FEATURE_8_BITS 0
#define TGL_FEATURE_24_BITS 0
+
//These are the only maintained modes.
#define TGL_FEATURE_16_BITS 0
#define TGL_FEATURE_32_BITS 1
@@ -48,8 +64,9 @@
#define TGL_FEATURE_RENDER_BITS 16
#else
-#error Unsupported TGL_FEATURE_RENDER_BITS
+#error "Unsupported TGL_FEATURE_XX_BITS"
#endif
-#endif /* _tgl_features_h_ */
+#endif
+/* _tgl_features_h_ */
--- a/src/api.c
+++ b/src/api.c
@@ -4,7 +4,7 @@
void glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
GLParam p[5];
-
+#include "error_check_no_context.h"
p[0].op = OP_Vertex;
p[1].f = x;
p[2].f = y;
@@ -24,7 +24,7 @@
void glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
GLParam p[4];
-
+#include "error_check_no_context.h"
p[0].op = OP_Normal;
p[1].f = x;
p[2].f = y;
@@ -39,7 +39,7 @@
void glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
GLParam p[8];
-
+#include "error_check_no_context.h"
p[0].op = OP_Color;
p[1].f = r;
p[2].f = g;
@@ -62,7 +62,7 @@
void glColor4fv(GLfloat* v) {
GLParam p[8];
-
+#include "error_check_no_context.h"
p[0].op = OP_Color;
p[1].f = v[0];
p[2].f = v[1];
@@ -92,7 +92,7 @@
void glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
GLParam p[5];
-
+#include "error_check_no_context.h"
p[0].op = OP_TexCoord;
p[1].f = s;
p[2].f = t;
@@ -108,7 +108,12 @@
void glEdgeFlag(GLint flag) {
GLParam p[2];
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+if(flag != GL_TRUE && flag != GL_FALSE)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#endif
p[0].op = OP_EdgeFlag;
p[1].i = flag;
@@ -119,9 +124,14 @@
void glShadeModel(GLint mode) {
GLParam p[2];
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(mode != GL_FLAT && mode != GL_SMOOTH)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(mode == GL_FLAT || mode == GL_SMOOTH);
-
+#endif
p[0].op = OP_ShadeModel;
p[1].i = mode;
@@ -130,9 +140,14 @@
void glCullFace(GLint mode) {
GLParam p[2];
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!(mode == GL_BACK || mode == GL_FRONT || mode == GL_FRONT_AND_BACK))
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(mode == GL_BACK || mode == GL_FRONT || mode == GL_FRONT_AND_BACK);
-
+#endif
p[0].op = OP_CullFace;
p[1].i = mode;
@@ -141,9 +156,14 @@
void glFrontFace(GLint mode) {
GLParam p[2];
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!(mode == GL_CCW || mode == GL_CW))
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(mode == GL_CCW || mode == GL_CW);
-
+#endif
mode = (mode != GL_CCW);
p[0].op = OP_FrontFace;
@@ -154,7 +174,14 @@
void glPolygonMode(GLint face, GLint mode) {
GLParam p[3];
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+if(!( (face == GL_BACK || face == GL_FRONT || face == GL_FRONT_AND_BACK)&&
+ (mode == GL_POINT || mode == GL_LINE || mode == GL_FILL) )
+ )
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#endif
assert(face == GL_BACK || face == GL_FRONT || face == GL_FRONT_AND_BACK);
assert(mode == GL_POINT || mode == GL_LINE || mode == GL_FILL);
@@ -166,13 +193,14 @@
}
void glDepthMask(GLint i){
+#include "error_check_no_context.h"
gl_get_context()->zb->depth_write = (i==GL_TRUE);
}
/* glEnable / glDisable */
-
+//TODO go to glopEnableDisable and add error checking there on values there.
void glEnable(GLint cap) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_EnableDisable;
p[1].i = cap;
p[2].i = 1;
@@ -182,7 +210,7 @@
void glDisable(GLint cap) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_EnableDisable;
p[1].i = cap;
p[2].i = 0;
@@ -194,7 +222,7 @@
void glBegin(GLint mode) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_Begin;
p[1].i = mode;
@@ -203,7 +231,7 @@
void glEnd(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_End;
gl_add_op(p);
@@ -213,7 +241,7 @@
void glMatrixMode(GLint mode) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_MatrixMode;
p[1].i = mode;
@@ -223,7 +251,7 @@
void glLoadMatrixf(const GLfloat* m) {
GLParam p[17];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_LoadMatrix;
for (i = 0; i < 16; i++)
p[i + 1].f = m[i];
@@ -233,7 +261,7 @@
void glLoadIdentity(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_LoadIdentity;
gl_add_op(p);
@@ -242,7 +270,7 @@
void glMultMatrixf(const GLfloat* m) {
GLParam p[17];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_MultMatrix;
for (i = 0; i < 16; i++)
p[i + 1].f = m[i];
@@ -252,7 +280,7 @@
void glPushMatrix(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_PushMatrix;
gl_add_op(p);
@@ -260,7 +288,7 @@
void glPopMatrix(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_PopMatrix;
gl_add_op(p);
@@ -268,7 +296,7 @@
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
GLParam p[5];
-
+#include "error_check_no_context.h"
p[0].op = OP_Rotate;
p[1].f = angle;
p[2].f = x;
@@ -280,7 +308,7 @@
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
GLParam p[4];
-
+#include "error_check_no_context.h"
p[0].op = OP_Translate;
p[1].f = x;
p[2].f = y;
@@ -291,7 +319,7 @@
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
GLParam p[4];
-
+#include "error_check_no_context.h"
p[0].op = OP_Scale;
p[1].f = x;
p[2].f = y;
@@ -302,7 +330,7 @@
void glViewport(GLint x, GLint y, GLint width, GLint height) {
GLParam p[5];
-
+#include "error_check_no_context.h"
p[0].op = OP_Viewport;
p[1].i = x;
p[2].i = y;
@@ -314,7 +342,7 @@
void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble farv) {
GLParam p[7];
-
+#include "error_check_no_context.h"
p[0].op = OP_Frustum;
p[1].f = left;
p[2].f = right;
@@ -331,9 +359,14 @@
void glMaterialfv(GLint mode, GLint type, GLfloat* v) {
GLParam p[7];
GLint i, n;
-
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!(mode == GL_FRONT || mode == GL_BACK || mode == GL_FRONT_AND_BACK))
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(mode == GL_FRONT || mode == GL_BACK || mode == GL_FRONT_AND_BACK);
-
+#endif
p[0].op = OP_Material;
p[1].i = mode;
p[2].i = type;
@@ -351,7 +384,7 @@
void glMaterialf(GLint mode, GLint type, GLfloat v) {
GLParam p[7];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_Material;
p[1].i = mode;
p[2].i = type;
@@ -364,7 +397,7 @@
void glColorMaterial(GLint mode, GLint type) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_ColorMaterial;
p[1].i = mode;
p[2].i = type;
@@ -375,11 +408,11 @@
void glLightfv(GLint light, GLint type, GLfloat* v) {
GLParam p[7];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_Light;
p[1].i = light;
p[2].i = type;
- /* TODO: 3 composants ? */
+ /* TODO: 3 components ? */
for (i = 0; i < 4; i++)
p[3 + i].f = v[i];
@@ -389,7 +422,7 @@
void glLightf(GLint light, GLint type, GLfloat v) {
GLParam p[7];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_Light;
p[1].i = light;
p[2].i = type;
@@ -402,7 +435,7 @@
void glLightModeli(GLint pname, GLint param) {
GLParam p[6];
-
+#include "error_check_no_context.h"
p[0].op = OP_LightModel;
p[1].i = pname;
p[2].f = (GLfloat)param;
@@ -417,7 +450,7 @@
void glLightModelfv(GLint pname, GLfloat* param) {
GLParam p[6];
GLint i;
-
+#include "error_check_no_context.h"
p[0].op = OP_LightModel;
p[1].i = pname;
for (i = 0; i < 4; i++)
@@ -430,7 +463,7 @@
void glClear(GLint mask) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_Clear;
p[1].i = mask;
@@ -439,7 +472,7 @@
void glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
GLParam p[5];
-
+#include "error_check_no_context.h"
p[0].op = OP_ClearColor;
p[1].f = r;
p[2].f = g;
@@ -451,7 +484,7 @@
void glClearDepth(GLdouble depth) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_ClearDepth;
p[1].f = depth;
@@ -459,10 +492,10 @@
}
/* textures */
-
+//TODO Check inputs into glopTexImage2D
void glTexImage2D(GLint target, GLint level, GLint components, GLint width, GLint height, GLint border, GLint format, GLint type, void* pixels) {
GLParam p[10];
-
+#include "error_check_no_context.h"
p[0].op = OP_TexImage2D;
p[1].i = target;
p[2].i = level;
@@ -479,7 +512,7 @@
void glBindTexture(GLint target, GLint texture) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_BindTexture;
p[1].i = target;
p[2].i = texture;
@@ -489,7 +522,7 @@
void glTexEnvi(GLint target, GLint pname, GLint param) {
GLParam p[8];
-
+#include "error_check_no_context.h"
p[0].op = OP_TexEnv;
p[1].i = target;
p[2].i = pname;
@@ -504,7 +537,7 @@
void glTexParameteri(GLint target, GLint pname, GLint param) {
GLParam p[8];
-
+#include "error_check_no_context.h"
p[0].op = OP_TexParameter;
p[1].i = target;
p[2].i = pname;
@@ -519,7 +552,7 @@
void glPixelStorei(GLint pname, GLint param) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_PixelStore;
p[1].i = pname;
p[2].i = param;
@@ -531,7 +564,7 @@
void glInitNames(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_InitNames;
gl_add_op(p);
@@ -539,7 +572,7 @@
void glPushName(GLuint name) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_PushName;
p[1].i = name;
@@ -548,7 +581,7 @@
void glPopName(void) {
GLParam p[1];
-
+#include "error_check_no_context.h"
p[0].op = OP_PopName;
gl_add_op(p);
@@ -556,7 +589,7 @@
void glLoadName(GLuint name) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_LoadName;
p[1].i = name;
@@ -565,6 +598,7 @@
void glPolygonOffset(GLfloat factor, GLfloat units) {
GLParam p[3];
+#include "error_check_no_context.h"
p[0].op = OP_PolygonOffset;
p[1].f = factor;
p[2].f = units;
@@ -575,7 +609,7 @@
void glCallList(GLuint list) {
GLParam p[2];
-
+#include "error_check_no_context.h"
p[0].op = OP_CallList;
p[1].i = list;
@@ -582,12 +616,13 @@
gl_add_op(p);
}
+//TODO: Implement a barrier for worker threads if we ever add multithreading support.
void glFlush(void) { /* nothing to do */
}
void glHint(GLint target, GLint mode) {
GLParam p[3];
-
+#include "error_check_no_context.h"
p[0].op = OP_Hint;
p[1].i = target;
p[2].i = mode;
@@ -599,5 +634,6 @@
void glDebug(GLint mode) {
GLContext* c = gl_get_context();
+#include "error_check.h"
c->print_flag = mode;
}
--- a/src/arrays.c
+++ b/src/arrays.c
@@ -51,6 +51,7 @@
void glArrayElement(GLint i) {
GLParam p[2];
+#include "error_check_no_context.h"
p[0].op = OP_ArrayElement;
p[1].i = i;
gl_add_op(p);
@@ -60,6 +61,7 @@
void glEnableClientState(GLenum array) {
GLParam p[2];
+#include "error_check_no_context.h"
p[0].op = OP_EnableClientState;
switch (array) {
@@ -86,6 +88,7 @@
void glDisableClientState(GLenum array) {
GLParam p[2];
+#include "error_check_no_context.h"
p[0].op = OP_DisableClientState;
switch (array) {
@@ -116,7 +119,14 @@
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
GLParam p[4];
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(type != GL_FLOAT)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(type == GL_FLOAT);
+#endif
p[0].op = OP_VertexPointer;
p[1].i = size;
p[2].i = stride;
@@ -132,7 +142,14 @@
void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
GLParam p[4];
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(type != GL_FLOAT)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(type == GL_FLOAT);
+#endif
p[0].op = OP_ColorPointer;
p[1].i = size;
p[2].i = stride;
@@ -147,7 +164,14 @@
void glNormalPointer(GLenum type, GLsizei stride, const GLvoid* pointer) {
GLParam p[3];
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(type != GL_FLOAT)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(type == GL_FLOAT);
+#endif
p[0].op = OP_NormalPointer;
p[1].i = stride;
p[2].p = (void*)pointer;
@@ -162,7 +186,14 @@
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
GLParam p[4];
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(type != GL_FLOAT)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
assert(type == GL_FLOAT);
+#endif
p[0].op = OP_TexCoordPointer;
p[1].i = size;
p[2].i = stride;
--- a/src/clip.c
+++ b/src/clip.c
@@ -407,18 +407,21 @@
#endif
if (c->texture_2d_enabled) {
+ //if(c->current_texture)
+ {
#ifdef PROFILE
- count_triangles_textured++;
+ count_triangles_textured++;
#endif
- ZB_setTexture(c->zb, c->current_texture->images[0].pixmap);
+ ZB_setTexture(c->zb, c->current_texture->images[0].pixmap);
#if TGL_FEATURE_BLEND == 1
- if(c->zb->enable_blend)
- ZB_fillTriangleMappingPerspective(c->zb, &p0->zp, &p1->zp, &p2->zp);
- else
- ZB_fillTriangleMappingPerspectiveNOBLEND(c->zb, &p0->zp, &p1->zp, &p2->zp);
+ if(c->zb->enable_blend)
+ ZB_fillTriangleMappingPerspective(c->zb, &p0->zp, &p1->zp, &p2->zp);
+ else
+ ZB_fillTriangleMappingPerspectiveNOBLEND(c->zb, &p0->zp, &p1->zp, &p2->zp);
#else
- ZB_fillTriangleMappingPerspectiveNOBLEND(c->zb, &p0->zp, &p1->zp, &p2->zp);
+ ZB_fillTriangleMappingPerspectiveNOBLEND(c->zb, &p0->zp, &p1->zp, &p2->zp);
#endif
+ }
} else if (c->current_shade_model == GL_SMOOTH) {
//ZB_fillTriangleSmooth(c->zb, &p0->zp, &p1->zp, &p2->zp);
#if TGL_FEATURE_BLEND == 1
--- /dev/null
+++ b/src/error_check.h
@@ -1,0 +1,39 @@
+//Error check #included into every command which references the current context as "c"
+#ifndef RETVAL
+#define RETVAL /* a comment*/
+#endif
+
+
+#if TGL_FEATURE_ERROR_CHECK == 1
+//LEVEL 1 ERROR_CHECK
+#error should never execute.
+#ifndef ERROR_FLAG
+//LEVEL 2 ERROR_FLAG
+
+//BEGIN LEVEL 3
+#if TGL_FEATURE_STRICT_OOM_CHECKS == 1
+ if(c->error_flag == GL_OUT_OF_MEMORY)
+ return RETVAL;
+#else
+ /* a comment */
+#endif
+//EOF LEVEL 3
+
+#elif ERROR_FLAG != GL_OUT_OF_MEMORY
+//LEVEL 2 ERROR_FLAG
+//Deal with the smalltime error case.
+ {c->error_flag = ERROR_FLAG; return RETVAL;}
+//OUT OF MEMORY ELSE
+#else
+//LEVEL 2 ERROR_FLAG
+//Deal with the out-of-memory case
+ {c->error_flag = GL_OUT_OF_MEMORY; return RETVAL;}
+//^ end of TGL_FEATURE_ERROR_CHECK check,
+#endif
+//LEVEL 1 ERROR_CHECK
+#endif
+//^End of TGL_FEATURE_ERROR_CHECK, level 0
+
+//Cleanup
+#undef RETVAL
+#undef ERROR_FLAG
--- /dev/null
+++ b/src/error_check_no_context.h
@@ -1,0 +1,15 @@
+#ifndef RETVAL
+#define RETVAL /* a comment*/
+#endif
+
+#if TGL_FEATURE_ERROR_CHECK == 1
+ GLContext* c = gl_get_context();
+#error should never execute
+#if TGL_FEATURE_STRICT_OOM_CHECKS == 1
+ if(c->error_flag == GL_OUT_OF_MEMORY)
+ return RETVAL;
+#endif
+
+#endif
+
+#undef RETVAL
--- a/src/get.c
+++ b/src/get.c
@@ -3,7 +3,7 @@
#define TINYGL_VERSION 0.8
void glGetIntegerv(GLint pname, GLint* params) {
GLContext* c = gl_get_context();
-
+#include "error_check.h"
switch (pname) {
case GL_BLEND:
*params = c->zb->enable_blend;
@@ -115,6 +115,12 @@
const GLubyte* extensions_string = (const GLubyte*)"TGL_TEXTURE "
"TGL_SMOOTHSHADING "
"TGL_LIGHTING "
+#if TGL_FEATURE_ERROR_CHECK == 1
+"TGL_FEATURE_ERROR_CHECK "
+#endif
+#if TGL_FEATURE_STRICT_OOM_CHECKS == 1
+"TGL_FEATURE_STRICT_OOM_CHECKS "
+#endif
#if TGL_FEATURE_ARRAYS == 1
"TGL_FEATURE_ARRAYS "
#endif
@@ -179,6 +185,7 @@
GLint i;
GLint mnr = 0; /* just a trick to return the correct matrix */
GLContext* c = gl_get_context();
+#include "error_check.h"
switch (pname) {
case GL_TEXTURE_MATRIX:
mnr++;
--- a/src/init.c
+++ b/src/init.c
@@ -5,9 +5,13 @@
void initSharedState(GLContext* c) {
GLSharedState* s = &c->shared_state;
s->lists = gl_zalloc(sizeof(GLList*) * MAX_DISPLAY_LISTS);
+ if(!s->lists)
+ gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
s->texture_hash_table = gl_zalloc(sizeof(GLTexture*) * TEXTURE_HASH_TABLE_SIZE);
-
- alloc_texture(c, 0); // MEMORY LEAK
+ if(!s->texture_hash_table)
+ gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
+ alloc_texture(c, 0);
+#include "error_check.h"
}
void endSharedState(GLContext* c) {
@@ -66,14 +70,17 @@
GLint i;
c = gl_zalloc(sizeof(GLContext));
+ if(!c) gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
gl_ctx = c;
c->zb = zbuffer;
-
+#if TGL_FEATURE_ERROR_CHECK == 1
+ c->error_flag = GL_NO_ERROR;
+#endif
/* allocate GLVertex array */
c->vertex_max = POLYGON_MAX_VERTEX;
c->vertex = gl_malloc(POLYGON_MAX_VERTEX * sizeof(GLVertex));
-
+ if(!c->vertex) gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
/* viewport */
v = &c->viewport;
v->xmin = 0;
@@ -84,7 +91,8 @@
/* shared state */
initSharedState(c);
-
+ /* ztext */
+ c->textsize = 1;
/* lists */
c->exec_flag = 1;
@@ -194,6 +202,7 @@
for (i = 0; i < 3; i++) {
c->matrix_stack[i] = gl_zalloc(c->matrix_stack_depth_max[i] * sizeof(M4));
+ if (!(c->matrix_stack[i])) gl_fatal_error("TINYGL_CANNOT_INIT_OOM");
c->matrix_stack_ptr[i] = c->matrix_stack[i];
}
--- a/src/light.c
+++ b/src/light.c
@@ -202,7 +202,10 @@
// FEATURES
int zEnableSpecular = 1; // Enable specular lighting
-void glSetEnableSpecular(GLint s) { zEnableSpecular = s; }
+void glSetEnableSpecular(GLint s) {
+#include "error_check_no_context.h"
+ zEnableSpecular = s;
+}
/* non optimized lightening model */
void gl_shade_vertex(GLContext* c, GLVertex* v) {
GLfloat R, G, B, A;
@@ -315,6 +318,15 @@
/* testing specular buffer code */
/* dot_spec= pow(dot_spec,m->shininess);*/
specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess);
+#if TGL_FEATURE_ERROR_CHECK == 1
+//The GL_OUT_OF_MEMORY flag will already be set.
+#include "error_check.h"
+#else
+ //As it turns out, this is actually handled inside of specbuf_get_buffer!
+ //if(!specbuf)
+ // gl_fatal_error("BAD SPECBUF_GET_BUFFER");
+#endif
+
idx = (GLint)(dot_spec * SPECULAR_BUFFER_SIZE);
if (idx > SPECULAR_BUFFER_SIZE)
idx = SPECULAR_BUFFER_SIZE; //NOTE by GEK: this is poorly written, it's actually 1 larger.
--- a/src/list.c
+++ b/src/list.c
@@ -47,18 +47,33 @@
c->shared_state.lists[list] = NULL;
}
void glDeleteLists(GLuint list, GLuint range) {
+#include "error_check_no_context.h"
for (GLuint i = 0; i < list + range; i++)
glDeleteList(list + i);
}
-void glDeleteList(GLuint list) { delete_list(gl_get_context(), list); }
+void glDeleteList(GLuint list) {
+#include "error_check_no_context.h"
+delete_list(gl_get_context(), list);
+}
static GLList* alloc_list(GLContext* c, GLint list) {
GLList* l;
GLParamBuffer* ob;
-
+#define RETVAL NULL
+#include "error_check.h"
l = gl_zalloc(sizeof(GLList));
ob = gl_zalloc(sizeof(GLParamBuffer));
+#if TGL_FEATURE_ERROR_CHECK
+if(!l || !ob)
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#define RETVAL NULL
+#include "error_check.h"
+
+#else
+if(!l || !ob)
+ gl_fatal_error("GL_OUT_OF_MEMORY");
+#endif
ob->next = NULL;
l->first_op_buffer = ob;
@@ -99,7 +114,7 @@
GLint op, op_size;
GLParamBuffer *ob, *ob1;
GLint index, i;
-
+#include "error_check.h"
op = p[0].op;
op_size = op_table_size[op];
index = c->current_op_buffer_index;
@@ -109,6 +124,13 @@
if ((index + op_size) > (OP_BUFFER_MAX_SIZE - 2)) {
ob1 = gl_zalloc(sizeof(GLParamBuffer));
+if(!ob1)
+#if TGL_FEATURE_ERROR_CHECK
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#include "error_check.h"
+#else
+ gl_fatal_error("GL_OUT_OF_MEMORY");
+#endif
ob1->next = NULL;
ob->next = ob1;
@@ -129,14 +151,16 @@
void gl_add_op(GLParam* p) {
GLContext* c = gl_get_context();
+#include "error_check.h"
GLint op;
-
op = p[0].op;
if (c->exec_flag) {
op_table_func[op](c, p);
+#include "error_check.h"
}
if (c->compile_flag) {
gl_compile_op(c, p);
+#include "error_check.h"
}
if (c->print_flag) {
// gl_print_op(stderr, p);
@@ -152,14 +176,16 @@
void glopCallList(GLContext* c, GLParam* p) {
GLList* l;
GLint list, op;
-
+#include "error_check.h"
list = p[1].ui;
l = find_list(c, list);
+
if (l == NULL)
- gl_fatal_error("list %d not defined", list);
+ {tgl_warning("\nBAD CALL LIST OP");}
p = l->first_op_buffer->ops;
while (1) {
+ #include "error_check.h"
op = p[0].op;
if (op == OP_EndList)
break;
@@ -175,15 +201,33 @@
void glNewList(GLuint list, GLint mode) {
GLList* l;
GLContext* c = gl_get_context();
+#include "error_check.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+
+ if(!(mode == GL_COMPILE || mode == GL_COMPILE_AND_EXECUTE))
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+ if(!(c->compile_flag == 0))
+#define ERROR_FLAG GL_INVALID_OPERATION
+#include "error_check.h"
+
+#else
assert(mode == GL_COMPILE || mode == GL_COMPILE_AND_EXECUTE);
assert(c->compile_flag == 0);
-
+#endif
l = find_list(c, list);
if (l != NULL)
delete_list(c, list);
l = alloc_list(c, list);
-
+#include "error_check.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(l==NULL)
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#include "error_check.h"
+#else
+ if(l==NULL) gl_fatal_error("Could not find or allocate list.");
+#endif
c->current_op_buffer = l->first_op_buffer;
c->current_op_buffer_index = 0;
@@ -194,9 +238,14 @@
void glEndList(void) {
GLContext* c = gl_get_context();
GLParam p[1];
-
+#include "error_check.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(c->compile_flag != 1)
+#define ERROR_FLAG GL_INVALID_OPERATION
+#include "error_check.h"
+#else
assert(c->compile_flag == 1);
-
+#endif
/* end of list */
p[0].op = OP_EndList;
gl_compile_op(c, p);
@@ -216,7 +265,8 @@
GLContext* c = gl_get_context();
GLint count, i, list;
GLList** lists;
-
+#define RETVAL 0
+#include "error_check.h"
lists = c->shared_state.lists;
count = 0;
for (i = 0; i < MAX_DISPLAY_LISTS; i++) {
--- a/src/memory.c
+++ b/src/memory.c
@@ -10,7 +10,3 @@
void* gl_malloc(GLint size) { return malloc(size); }
void* gl_zalloc(GLint size) { return calloc(1, size); }
-
-void gl_memcpy(void* dest, void* src, GLuint size){
- memcpy(dest,src,size);
-}
--- a/src/misc.c
+++ b/src/misc.c
@@ -4,9 +4,10 @@
void glPolygonStipple(void* a) {
#if TGL_FEATURE_POLYGON_STIPPLE == 1
GLContext* c = gl_get_context();
+#include "error_check.h"
ZBuffer* zb = c->zb;
- gl_memcpy(zb->stipplepattern, a, TGL_POLYGON_STIPPLE_BYTES);
+ memcpy(zb->stipplepattern, a, TGL_POLYGON_STIPPLE_BYTES);
for (GLint i = 0; i < TGL_POLYGON_STIPPLE_BYTES; i++) {
zb->stipplepattern[i] = ((GLubyte*)a)[i];
}
@@ -49,6 +50,7 @@
}
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
GLParam p[3];
+#include "error_check_no_context.h"
p[0].op = OP_BlendFunc;
p[1].i = sfactor;
p[2].i = dfactor;
@@ -63,6 +65,7 @@
void glBlendEquation(GLenum mode) {
GLParam p[2];
+#include "error_check_no_context.h"
p[0].op = OP_BlendEquation;
p[1].i = mode;
gl_add_op(p);
@@ -74,6 +77,7 @@
}
void glPointSize(GLfloat f){
GLParam p[2]; p[0].op = OP_PointSize;
+#include "error_check_no_context.h"
p[1].f = f;
gl_add_op(p);
}
@@ -184,4 +188,16 @@
void glopPolygonOffset(GLContext* c, GLParam* p) {
c->offset_factor = p[1].f;
c->offset_units = p[2].f;
+}
+
+GLenum glGetError(){
+#if TGL_FEATURE_ERROR_CHECK == 1
+ GLContext* c = gl_get_context();
+ GLenum eflag = c->error_flag;
+ if(eflag != GL_OUT_OF_MEMORY) //Unrecoverable!
+ c->error_flag = GL_NO_ERROR;
+ return eflag;
+#else
+ return GL_NO_ERROR;
+#endif
}
--- a/src/specbuf.c
+++ b/src/specbuf.c
@@ -30,8 +30,15 @@
if (oldest == NULL || c->specbuf_num_buffers < MAX_SPECULAR_BUFFERS) {
/* create new buffer */
GLSpecBuf* buf = gl_malloc(sizeof(GLSpecBuf));
- if (!buf)
- gl_fatal_error("could not allocate specular buffer");
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!buf)
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#define RETVAL NULL
+#include "error_check.h"
+#else
+// if (!buf)
+// gl_fatal_error("GL_OUT_OF_MEMORY: CANNOT ALLOCATE SPECBUF");
+#endif
c->specbuf_num_buffers++;
buf->next = c->specbuf_first;
c->specbuf_first = buf;
--- a/src/texture.c
+++ b/src/texture.c
@@ -19,10 +19,23 @@
void* glGetTexturePixmap(GLint text, GLint level, GLint* xsize, GLint* ysize) {
GLTexture* tex;
GLContext* c = gl_get_context();
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!(text >= 0 && level < MAX_TEXTURE_LEVELS))
+#define ERROR_FLAG GL_INVALID_ENUM
+#define RETVAL NULL
+#include "error_check.h"
+#else
assert(text >= 0 && level < MAX_TEXTURE_LEVELS);
+#endif
tex = find_texture(c, text);
if (!tex)
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_ENUM
+#define RETVAL NULL
+#include "error_check.h"
+#else
return NULL;
+#endif
*xsize = tex->images[level].xsize;
*ysize = tex->images[level].ysize;
return tex->images[level].pixmap;
@@ -54,8 +67,17 @@
GLTexture* alloc_texture(GLContext* c, GLint h) {
GLTexture *t, **ht;
-
+#define RETVAL NULL
+#include "error_check.h"
t = gl_zalloc(sizeof(GLTexture));
+ if(!t)
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#define RETVAL NULL
+#include "error_check.h"
+#else
+ {}//gl_fatal_error("GL_OUT_OF_MEMORY");
+#endif
ht = &c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE];
@@ -81,7 +103,7 @@
GLContext* c = gl_get_context();
GLint max, i;
GLTexture* t;
-
+#include "error_check.h"
max = 0;
for (i = 0; i < TEXTURE_HASH_TABLE_SIZE; i++) {
t = c->shared_state.texture_hash_table[i];
@@ -92,7 +114,7 @@
}
}
for (i = 0; i < n; i++) {
- textures[i] = max + i + 1;
+ textures[i] = max + i + 1; //MARK: How texture handles are created.
}
}
@@ -100,12 +122,13 @@
GLContext* c = gl_get_context();
GLint i;
GLTexture* t;
-
+#include "error_check.h"
for (i = 0; i < n; i++) {
t = find_texture(c, textures[i]);
if (t != NULL && t != 0) {
if (t == c->current_texture) {
glBindTexture(GL_TEXTURE_2D, 0);
+#include "error_check.h"
}
free_texture(c, textures[i]);
}
@@ -116,13 +139,27 @@
GLint target = p[1].i;
GLint texture = p[2].i;
GLTexture* t;
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(!(target == GL_TEXTURE_2D && target > 0))
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
- assert(target == GL_TEXTURE_2D && texture >= 0);
-
+#else
+ //assert(target == GL_TEXTURE_2D && target > 0);
+#endif
t = find_texture(c, texture);
if (t == NULL) {
t = alloc_texture(c, texture);
+#include "error_check.h"
}
+ if(t == NULL) { //Failed malloc.
+#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
+ }
c->current_texture = t;
}
@@ -141,7 +178,12 @@
GLint do_free;
if (!(target == GL_TEXTURE_2D && level == 0 && components == 3 && border == 0 && format == GL_RGB && type == GL_UNSIGNED_BYTE)) {
+#if TGL_FEATURE_ERROR_CHECK
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
gl_fatal_error("glTexImage2D: combination of parameters not handled!!");
+#endif
}
do_free = 0;
@@ -163,18 +205,39 @@
gl_free(im->pixmap);
#if TGL_FEATURE_RENDER_BITS == 24
im->pixmap = gl_malloc(width * height * 3);
- if (im->pixmap) {
+ if (im->pixmap || !(TGL_FEATURE_ERROR_CHECK == 1)) {
memcpy(im->pixmap, pixels1, width * height * 3);
+ } else {
+#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
}
#elif TGL_FEATURE_RENDER_BITS == 32
im->pixmap = gl_malloc(width * height * 4);
- if (im->pixmap) {
+ if (im->pixmap || !(TGL_FEATURE_ERROR_CHECK == 1)) {
gl_convertRGB_to_8A8R8G8B(im->pixmap, pixels1, width, height);
+ }else {
+#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
}
#elif TGL_FEATURE_RENDER_BITS == 16
im->pixmap = gl_malloc(width * height * 2);
- if (im->pixmap) {
+ if (im->pixmap || !(TGL_FEATURE_ERROR_CHECK == 1)) {
gl_convertRGB_to_5R6G5B(im->pixmap, pixels1, width, height);
+ }else {
+#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
}
#else
#error TODO
@@ -190,8 +253,17 @@
GLint param = p[3].i;
if (target != GL_TEXTURE_ENV) {
+
error:
+#if TGL_FEATURE_ERROR_CHECK == 1
+
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#else
gl_fatal_error("glTexParameter: unsupported option");
+ exit(1);
+#endif
+
}
if (pname != GL_TEXTURE_ENV_MODE)
@@ -221,6 +293,7 @@
}
}
+//TODO: implement this.
void glopPixelStore(GLContext* c, GLParam* p) {
GLint pname = p[1].i;
GLint param = p[2].i;
--- a/src/vertex.c
+++ b/src/vertex.c
@@ -193,11 +193,16 @@
/* quick fix to avoid crashes on large polygons */
if (n >= c->vertex_max) {
GLVertex* newarray;
- c->vertex_max <<= 1; /* just GLdouble size */
+ c->vertex_max <<= 1; /* just double size */
newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max);
- if (!newarray) {
- gl_fatal_error("unable to allocate GLVertex array.\n");
- }
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if (!newarray)
+#define ERROR_FLAG GL_OUT_OF_MEMORY
+#include "error_check.h"
+
+#else
+ //Assume it went alright.
+#endif
memcpy(newarray, c->vertex, n * sizeof(GLVertex));
gl_free(c->vertex);
c->vertex = newarray;
@@ -217,6 +222,8 @@
if (c->lighting_enabled) {
gl_shade_vertex(c, v);
+#include "error_check.h"
+//^ Don't proceed on an OUT OF MEMORY error.
} else {
v->color = c->current_color;
}
@@ -324,8 +331,14 @@
}
void glopEnd(GLContext* c, GLParam* param) {
- assert(c->in_begin == 1);
-
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(c->in_begin != 1)
+#define ERROR_FLAG GL_INVALID_OPERATION
+#include "error_check.h"
+#else
+ //assert(c->in_begin == 1);
+ //Assume it went alright.
+#endif
if (c->begin_type == GL_LINE_LOOP) {
if (c->vertex_cnt >= 3) {
gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
--- a/src/zbuffer.c
+++ b/src/zbuffer.c
@@ -106,6 +106,7 @@
if (frame_buffer == NULL) {
zb->pbuf = gl_malloc(zb->ysize * zb->linesize);
+ if(!zb->pbuf) exit(1);
zb->frame_buffer_allocated = 1;
} else {
zb->pbuf = frame_buffer;
--- a/src/zgl.h
+++ b/src/zgl.h
@@ -156,7 +156,9 @@
typedef struct GLContext {
/* Z buffer */
ZBuffer* zb;
-
+#if TGL_FEATURE_ERROR_CHECK == 1
+ GLenum error_flag;
+#endif
/* lights */
GLLight lights[MAX_LIGHTS];
GLLight* first_light;
@@ -279,6 +281,9 @@
V3 rasterpos;
GLubyte rasterposvalid;
GLfloat pzoomx, pzoomy;
+
+ /* text */
+ GLTEXTSIZE textsize;
} GLContext;
extern GLContext* gl_ctx;
--- a/src/ztext.c
+++ b/src/ztext.c
@@ -6,20 +6,26 @@
//#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
-GLTEXTSIZE textsize = 1;
+
void glTextSize(GLTEXTSIZE mode) {
+#include "error_check_no_context.h"
+#if TGL_FEATURE_ERROR_CHECK == 1
+ if(mode < 1 || GL_MAX_TEXT_SIZE < mode)
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+#endif
GLParam p[2];
p[0].op = OP_TextSize;
p[1].ui = mode;
gl_add_op(p);
}
-void glopTextSize(GLContext* c, GLParam* p) { textsize = p[1].ui; } // Set text size
+void glopTextSize(GLContext* c, GLParam* p) { c->textsize = p[1].ui; } // Set text size
void renderchar(GLbyte* bitmap, GLint _x, GLint _y, GLuint p) {
GLint x, y;
GLint set;
- // int mask;
- GLint mult = textsize;
+ GLContext* c = gl_get_context();
+ GLint mult = c->textsize;
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
set = bitmap[x] & 1 << y;
@@ -33,10 +39,7 @@
void glopPlotPixel(GLContext* c, GLParam* p) {
GLint x = p[1].i;
- PIXEL pix = p[2].ui;
- // PIXEL* pbuf = c->zb->pbuf;
-
- //c->zb->pbuf[x] = pix;
+ PIXEL pix = p[2].ui;;
#if TGL_FEATURE_BLEND == 1
ZBuffer* zb = c->zb;
PIXEL* targ = zb->pbuf + x;
@@ -53,10 +56,11 @@
void glPlotPixel(GLint x, GLint y, GLuint pix) {
GLParam p[3];
-
+ GLContext* c = gl_get_context();
+#include "error_check.h"
// PIXEL* pbuf = gl_get_context()->zb->pbuf;
- GLint w = gl_get_context()->zb->xsize;
- GLint h = gl_get_context()->zb->ysize;
+ GLint w = c->zb->xsize;
+ GLint h = c->zb->ysize;
p[0].op = OP_PlotPixel;
if (x > 0 && x < w && y > 0 && y < h) {
@@ -69,14 +73,22 @@
}
}
void glDrawText(const GLubyte* text, GLint x, GLint y, GLuint p) {
+GLContext* c = gl_get_context();
+
+#include "error_check.h"
if (!text)
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define ERROR_FLAG GL_INVALID_VALUE
+#include "error_check.h"
+#else
return;
+#endif
// PIXEL* pbuf = gl_get_context()->zb->pbuf;
- GLint w = gl_get_context()->zb->xsize;
- GLint h = gl_get_context()->zb->ysize;
+ GLint w = c->zb->xsize;
+ GLint h = c->zb->ysize;
GLint xoff = 0;
GLint yoff = 0;
- GLint mult = textsize;
+ GLint mult = c->textsize;
for (GLint i = 0; text[i] != '\0' && y + 7 < h; i++) {
if (text[i] != '\n' && text[i] < 127 && xoff + x < w) {
renderchar(font8x8_basic[text[i]], x + xoff, y + yoff, p);