shithub: tinygl

Download patch

ref: 36d0422a66ec59a4f61f91a7bb56855fb97017a6
parent: 03f5d05b72f0c07308b2eab32c0c904f63af5799
author: David <gek@katherine>
date: Sun Feb 21 10:21:53 EST 2021

Feedback implemented

--- a/include/GL/gl.h
+++ b/include/GL/gl.h
@@ -834,6 +834,10 @@
 void glClearColor(GLfloat r,GLfloat g,GLfloat b,GLfloat a);
 void glClearDepth(GLdouble depth);
 
+/* Feedback */
+void glFeedbackBuffer(GLint size, GLenum type, GLfloat* buf);
+void glPassThrough(GLfloat token);
+
 /* selection */
 GLint glRenderMode(GLint mode);
 void glSelectBuffer(GLint size,GLuint *buf);
--- a/src/clip.c
+++ b/src/clip.c
@@ -53,6 +53,8 @@
 	if (p0->clip_code == 0) {
 		if (c->render_mode == GL_SELECT) {
 			gl_add_select(c, p0->zp.z, p0->zp.z);
+		}else if (c->render_mode == GL_FEEDBACK){
+			gl_add_feedback(c,GL_POINT_TOKEN,p0,NULL,NULL,0);
 		} else {
 			ZB_plot(c->zb, &p0->zp);
 		}
@@ -109,6 +111,14 @@
 	if ((cc1 | cc2) == 0) {
 		if (c->render_mode == GL_SELECT) {
 			gl_add_select1(c, p1->zp.z, p2->zp.z, p2->zp.z);
+		}else if (c->render_mode == GL_FEEDBACK){
+			gl_add_feedback(
+				c,	GL_LINE_TOKEN,
+				p1,
+				p2,
+				NULL,
+				0
+			);
 		} else {
 			if (c->zb->depth_test)
 				ZB_line_z(c->zb, &p1->zp, &p2->zp);
@@ -364,6 +374,15 @@
 //see vertex.c to see how the draw functions are assigned.
 void gl_draw_triangle_select(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2) { 
 	gl_add_select1(c, p0->zp.z, p1->zp.z, p2->zp.z); 
+}
+void gl_draw_triangle_feedback(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2){
+	gl_add_feedback(
+					c,	GL_POLYGON_TOKEN,
+					p0,
+					p1,
+					p2,
+					0
+				);
 }
 
 #ifdef PROFILE
--- a/src/get.c
+++ b/src/get.c
@@ -171,6 +171,8 @@
 "TGL_FEATURE_TINYGL_RUNTIME_COMPAT_TEST "
 #endif
 "TGL_BUFFER_EXT "
+"TGL_FEEDBACK "
+"TGL_SELECT "
 "TGL_SOFTWARE_ACCELERATED";
 const GLubyte* glGetString(GLenum name){
 	switch(name){
--- a/src/select.c
+++ b/src/select.c
@@ -1,5 +1,4 @@
 #include "zgl.h"
-//Gek does not maintain or test this feature.
 
 GLint glRenderMode(GLint mode) {
 	GLContext* c = gl_get_context();
@@ -6,8 +5,7 @@
 	GLint result = 0;
 
 	switch (c->render_mode) {
-	case GL_RENDER:
-		break;
+	case GL_RENDER:break;
 	case GL_SELECT:
 		if (c->select_overflow) {
 			result = -c->select_hits;
@@ -28,7 +26,7 @@
 		c->feedback_ptr = c->feedback_buffer;
 	break;
 	default:
-		assert(0);
+		gl_fatal_error("GLContext's Rendermode was somehow erroneously set.");
 	}
 	switch (mode) {
 	case GL_RENDER:
@@ -35,8 +33,16 @@
 		c->render_mode = GL_RENDER;
 		break;
 	case GL_SELECT:
+		
+#if TGL_FEATURE_ERROR_CHECK == 1
+		if(c->select_buffer == NULL)
+#define ERROR_FLAG GL_INVALID_OPERATION
+#define RETVAL 0
+#include "error_check.h"
+#else
+		if(c->select_buffer == NULL)return;
+#endif
 		c->render_mode = GL_SELECT;
-		assert(c->select_buffer != NULL);
 		c->select_ptr = c->select_buffer;
 		c->select_hits = 0;
 		c->select_overflow = 0;
@@ -43,12 +49,28 @@
 		c->select_hit = NULL;
 		break;
 	case GL_FEEDBACK:
+#if TGL_FEATURE_ERROR_CHECK == 1
+		if(c->feedback_buffer == NULL)
+#define ERROR_FLAG GL_INVALID_OPERATION
+#define RETVAL 0
+#include "error_check.h"
+#else
+		if(c->feedback_buffer == NULL) return 0;
+#endif
 		c->render_mode = GL_FEEDBACK;
 		c->feedback_hits = 0;
 		c->feedback_ptr = c->feedback_buffer;
+		c->feedback_overflow = 0;
 	break;
 	default:
-		assert(0);
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define RETVAL 0
+#define ERROR_FLAG GL_INVALID_ENUM
+#include "error_check.h"
+
+#else
+		return 0;
+#endif
 	}
 	return result;
 }
@@ -60,12 +82,165 @@
 #define ERROR_FLAG GL_INVALID_OPERATION
 #include "error_check.h"
 #else
-	assert(c->render_mode != GL_SELECT);
+	if(c->render_mode == GL_SELECT) return;
 #endif
 	c->select_buffer = buf;
 	c->select_size = size;
 }
 
+void glFeedbackBuffer(GLint size, GLenum type, GLfloat* buf){
+	GLContext* c = gl_get_context();
+#if TGL_FEATURE_ERROR_CHECK == 1
+	if(c->render_mode == GL_FEEDBACK ||
+		!(
+			type == GL_2D ||
+			type == GL_3D ||
+			type == GL_3D_COLOR ||
+			type == GL_3D_COLOR_TEXTURE ||
+			type == GL_4D_COLOR_TEXTURE
+		)
+	)
+#define ERROR_FLAG GL_INVALID_OPERATION
+#include "error_check.h"
+#else
+	if(c->render_mode == GL_FEEDBACK ||
+	!(
+		type == GL_2D ||
+		type == GL_3D ||
+		type == GL_3D_COLOR ||
+		type == GL_3D_COLOR_TEXTURE ||
+		type == GL_4D_COLOR_TEXTURE
+	)
+	)return;
+#endif	
+	c->feedback_buffer = buf;
+	c->feedback_size = size;
+	c->feedback_type = type;
+}
+
+void gl_add_feedback(GLContext* c, GLfloat token,
+										GLVertex* v1,
+										GLVertex* v2,
+										GLVertex* v3,
+										GLfloat passthrough_token_value
+){
+	if(c->feedback_overflow) return;
+	GLuint feedback_hits_needed = 2;
+	GLuint vertex_feedback_hits_needed = 0;
+	GLuint vertex_pos_hits_needed = 2;
+	GLuint vertex_color_hits_needed = 4;
+	GLuint vertex_texture_hits_needed = 4;
+	GLuint done = 0;
+	switch(c->feedback_type){
+		case GL_2D: vertex_feedback_hits_needed = 2;
+			vertex_pos_hits_needed = 2;
+			vertex_color_hits_needed = 0;
+			vertex_texture_hits_needed = 0; break;
+		case GL_3D: vertex_feedback_hits_needed = 3; 
+			vertex_pos_hits_needed = 3;
+			vertex_color_hits_needed = 0;
+			vertex_texture_hits_needed = 0; break;
+		case GL_3D_COLOR: vertex_feedback_hits_needed = 3 + 4; 
+			vertex_pos_hits_needed = 3;
+			vertex_color_hits_needed = 4;
+			vertex_texture_hits_needed = 0; break;
+		case GL_3D_COLOR_TEXTURE: vertex_feedback_hits_needed = 3 + 4 + 4; 
+			vertex_pos_hits_needed = 3;
+			vertex_color_hits_needed = 4;
+			vertex_texture_hits_needed = 4; break;
+		case GL_4D_COLOR_TEXTURE: vertex_feedback_hits_needed = 4 + 4 + 4; 
+			vertex_pos_hits_needed = 4;
+			vertex_color_hits_needed = 4;
+			vertex_texture_hits_needed = 4; break;
+		default: 
+				vertex_feedback_hits_needed = 0; 
+				vertex_pos_hits_needed = 0; 
+				vertex_color_hits_needed = 0; 
+				vertex_texture_hits_needed = 0;
+		break;
+	}
+	if(token == GL_PASS_THROUGH_TOKEN) feedback_hits_needed = 1 + 1; //GL_PASSTHROUGH_TOKEN, value
+	else if(token == GL_POINT_TOKEN) feedback_hits_needed = 1 + 1*vertex_feedback_hits_needed; //GL_POINT_TOKEN vertex
+	else if(token == GL_LINE_TOKEN || token == GL_LINE_RESET_TOKEN) feedback_hits_needed = 1 + 2*vertex_feedback_hits_needed; //2 verts
+	else if(token == GL_POLYGON_TOKEN) feedback_hits_needed = 1 + 1 + 3*vertex_feedback_hits_needed; //GL_POLYGON_TOKEN, "3", v,v,v
+	else if(token == GL_BITMAP_TOKEN) feedback_hits_needed = 1 + 1*vertex_feedback_hits_needed; //GL_BITMAP_TOKEN vertex
+	else if(token == GL_DRAW_PIXEL_TOKEN || token == GL_COPY_PIXEL_TOKEN)
+		feedback_hits_needed = 1 + 1*vertex_feedback_hits_needed; //token vertex
+	else return;
+	c->feedback_hits += feedback_hits_needed;
+	if(c->feedback_hits > (GLint)c->feedback_size){
+		c->feedback_overflow = 1;
+		c->feedback_hits -= feedback_hits_needed;
+		return;
+	}
+	//c->feedback_hits -= feedback_hits_needed;
+#if TGL_FEATURE_ERROR_CHECK == 1
+#define DONE_ERROR_CHECK {if(++done > feedback_hits_needed) {gl_fatal_error("\nBAD FEEDBACK BUFFER WRITE DETECTED\n");}}
+#else
+#define DONE_ERROR_CHECK /* a comment*/
+#endif
+	#define WRITE_FLOAT(f) {DONE_ERROR_CHECK;*(c->feedback_ptr++) = f;}
+	#define WRITE_UINT(u) {DONE_ERROR_CHECK;*( ((GLuint*)c->feedback_ptr++)) = u;}
+	#define WRITE_VERTEX(v){\
+		if(vertex_pos_hits_needed == 2){\
+			WRITE_FLOAT(v->zp.x)\
+			WRITE_FLOAT(v->zp.y)\
+		}\
+		if(vertex_pos_hits_needed == 3){\
+			WRITE_FLOAT(v->zp.x)\
+			WRITE_FLOAT(v->zp.y)\
+			WRITE_FLOAT(v->zp.z)\
+		}\
+		if(vertex_pos_hits_needed == 4){\
+			WRITE_FLOAT(v->zp.x)\
+			WRITE_FLOAT(v->zp.y)\
+			WRITE_FLOAT(v->zp.z)\
+			WRITE_FLOAT(v->pc.W)\
+		}\
+		if(vertex_color_hits_needed == 4){\
+			WRITE_FLOAT(v->color.X)\
+			WRITE_FLOAT(v->color.Y)\
+			WRITE_FLOAT(v->color.Z)\
+			WRITE_FLOAT(v->color.W)\
+		}\
+		if(vertex_texture_hits_needed == 4){\
+			WRITE_FLOAT(v->tex_coord.X)\
+			WRITE_FLOAT(v->tex_coord.Y)\
+			WRITE_FLOAT(v->tex_coord.Z)\
+			WRITE_FLOAT(v->tex_coord.W)\
+		}\
+	}
+	if(token == GL_PASS_THROUGH_TOKEN) {
+		WRITE_UINT(GL_PASS_THROUGH_TOKEN);
+		WRITE_FLOAT(passthrough_token_value);
+	}else if(token == GL_LINE_TOKEN || token == GL_LINE_RESET_TOKEN){
+		WRITE_UINT(token);
+		WRITE_VERTEX(v1);
+		WRITE_VERTEX(v2);
+	} else if(token == GL_POLYGON_TOKEN) {
+		WRITE_UINT(GL_POLYGON_TOKEN);
+		WRITE_UINT(3);
+		WRITE_VERTEX(v1);
+		WRITE_VERTEX(v2);
+		WRITE_VERTEX(v3);
+	} else if(token == GL_BITMAP_TOKEN) {
+		WRITE_UINT(GL_BITMAP_TOKEN);
+		WRITE_VERTEX(v1);
+	} else if(token == GL_DRAW_PIXEL_TOKEN || token == GL_COPY_PIXEL_TOKEN) {
+		WRITE_UINT(token);
+		WRITE_VERTEX(v1);
+	}
+#if TGL_FEATURE_ERROR_CHECK == 1
+	if(done != feedback_hits_needed)
+		gl_fatal_error("Failed to write enough information to the buffer.");
+#endif
+	return;
+}
+void glPassThrough(GLfloat token){
+GLContext* c = gl_get_context();
+#include "error_check.h"
+	gl_add_feedback(c,GL_PASS_THROUGH_TOKEN,NULL,NULL,NULL,token);
+}
 void glopInitNames(GLContext* c, GLParam* p) {
 	if (c->render_mode == GL_SELECT) {
 		c->name_stack_size = 0;
@@ -80,6 +255,11 @@
 		c->select_hit = NULL;
 	}
 }
+
+
+
+
+
 
 void glopPopName(GLContext* c, GLParam* p) {
 	if (c->render_mode == GL_SELECT) {
--- a/src/vertex.c
+++ b/src/vertex.c
@@ -106,6 +106,9 @@
 	if (c->render_mode == GL_SELECT) {
 		c->draw_triangle_front = gl_draw_triangle_select;
 		c->draw_triangle_back = gl_draw_triangle_select;
+	}else if (c->render_mode == GL_FEEDBACK){
+		c->draw_triangle_front = gl_draw_triangle_feedback;
+		c->draw_triangle_back = gl_draw_triangle_feedback;
 	} else {
 		switch (c->polygon_mode_front) {
 		case GL_POINT:
--- a/src/zgl.h
+++ b/src/zgl.h
@@ -238,7 +238,7 @@
 	GLuint feedback_size;
 	GLint feedback_hits;
 	GLubyte feedback_overflow;
-	
+	GLenum feedback_type;
 	/* names */
 	GLuint name_stack[MAX_NAME_STACK_DEPTH];
 	GLint name_stack_size;
@@ -301,7 +301,7 @@
 	GLint rasterpos_zz;
 	GLubyte rasterposvalid;
 	GLfloat pzoomx, pzoomy;
-
+	GLVertex rastervertex;
 	/* text */
 	GLTEXTSIZE textsize;
 
@@ -327,6 +327,7 @@
 void gl_draw_triangle_line(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
 void gl_draw_triangle_fill(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
 void gl_draw_triangle_select(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
+void gl_draw_triangle_feedback(GLContext* c, GLVertex* p0, GLVertex* p1, GLVertex* p2);
 
 /* matrix.c */
 void gl_print_matrix(const GLfloat* m);
@@ -334,8 +335,16 @@
 void glopLoadIdentity(GLContext *c,GLParam *p);
 void glopTranslate(GLContext *c,GLParam *p);*/
 
-/* light.c */
+/* select.c */
 void gl_add_select(GLContext* c, GLuint zmin, GLuint zmax);
+void gl_add_feedback(GLContext* c, GLfloat token,
+										GLVertex* v1,
+										GLVertex* v2,
+										GLVertex* v3,
+										GLfloat passthrough_token_value
+);
+
+/* light.c */
 void gl_enable_disable_light(GLContext* c, GLint light, GLint v);
 void gl_shade_vertex(GLContext* c, GLVertex* v);
 
--- a/src/zraster.c
+++ b/src/zraster.c
@@ -51,6 +51,7 @@
 			}
 			c->rasterpos.v[0] = v.zp.x;
 			c->rasterpos.v[1] = v.zp.y;
+			c->rastervertex = v;
 			//c->rasterpos.v[2] = v.zp.z;
 			c->rasterpos_zz = v.zp.z >> ZB_POINT_Z_FRAC_BITS; //I believe this is it?
 			c->rasterposvalid = 1;
@@ -123,10 +124,16 @@
 	TGL_BLEND_VARS
 	//Looping over the source pixels.
 	if(c->render_mode == GL_SELECT){
-		gl_add_select(c, 0, 0);
+		gl_add_select(c, zz, zz);
 		return;
 	} else if(c->render_mode == GL_FEEDBACK){
-		//TODO
+		gl_add_feedback(
+			c,	GL_DRAW_PIXEL_TOKEN,
+			&(c->rastervertex),
+			NULL,
+			NULL,
+			0
+		);
 		return;
 	}
 	for(GLint sx = 0; sx < w; sx++)