shithub: tinygl

Download patch

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);