glshim updated. added changes from https://github.com/ptitSeb/glshim

This commit is contained in:
lubomyr
2015-09-14 15:58:23 +03:00
parent fc1daf4fbf
commit 1b17a094d4
7 changed files with 147 additions and 102 deletions

View File

@@ -202,16 +202,18 @@ GLfloat *copy_eval_double(GLenum target, GLint ustride, GLint uorder,
return points;
}
void normalize_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count) {
*max = 0;
*min = -1;
for (int i = 0; i < count; i++) {
void getminmax_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count) {
if (!count) return;
*max = indices[0];
*min = indices[0];
for (int i = 1; i < count; i++) {
GLsizei n = indices[i];
if (*min == -1)
*min = n;
*min = (n < *min) ? n : *min;
*max = (n > *max) ? n : *max;
if( n < *min) *min = n;
if (n > *max) *max = n;
}
}
void normalize_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count) {
getminmax_indices(indices, max, min, count);
for (int i = 0; i < count; i++) {
indices[i] -= *min;
}

View File

@@ -19,4 +19,5 @@ GLvoid *copy_gl_pointer_raw(pointer_state_t *ptr, GLsizei width, GLsizei skip, G
GLfloat *gl_pointer_index(pointer_state_t *ptr, GLint index);
GLfloat *copy_eval_double(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder, const GLdouble *points);
void normalize_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count);
void getminmax_indices(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count);
#endif

View File

@@ -1366,12 +1366,13 @@ void glEndList() {
state.lists[list - 1] = GetFirst(state.list.active);
state.list.compiling = false;
end_renderlist(state.list.active);
if (gl_batch) {
init_batch();
} else state.list.active = NULL;
state.list.active = NULL;
if (state.list.mode == GL_COMPILE_AND_EXECUTE) {
glCallList(list);
}
if (gl_batch) {
init_batch();
}
}
}

View File

@@ -125,7 +125,7 @@ int rendermode_dimensions(GLenum mode) {
extern GLuint gl_mergelist;
bool islistscompatible_renderlist(renderlist_t *a, renderlist_t *b) {
if (!gl_mergelist)
if (!gl_mergelist || !a)
return false;
// check if 2 "pure rendering" list are compatible for merge
@@ -204,7 +204,7 @@ void renderlist_linestrip_lines(renderlist_t *a, GLushort *indices, int count) {
}
}
void renderlist_triangletrip_triangles(renderlist_t *a, GLushort *indices, int count) {
void renderlist_trianglestrip_triangles(renderlist_t *a, GLushort *indices, int count) {
GLushort *ind = a->indices;
int len = (ind)? a->ilen:a->len;
int ilen = (len-2)*3;
@@ -395,7 +395,7 @@ void append_renderlist(renderlist_t *a, renderlist_t *b) {
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
alloc_a_indices;
renderlist_triangletrip_triangles(a, newind, 0);
renderlist_trianglestrip_triangles(a, newind, 0);
a->mode = GL_TRIANGLES;
copy_a_indices;
break;
@@ -442,7 +442,7 @@ void append_renderlist(renderlist_t *a, renderlist_t *b) {
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
renderlist_triangletrip_triangles(b, a->indices + ilen_a, a->len);
renderlist_trianglestrip_triangles(b, a->indices + ilen_a, a->len);
break;
case GL_TRIANGLE_FAN:
case GL_POLYGON:
@@ -470,6 +470,7 @@ void append_renderlist(renderlist_t *a, renderlist_t *b) {
a->len += b->len;
a->ilen += ilen_b;
//all done
a->stage = STAGE_DRAW; // just in case
return;
}
void adjust_renderlist(renderlist_t *list);
@@ -846,7 +847,8 @@ void draw_renderlist(renderlist_t *list) {
vtx.type = GL_FLOAT;
vtx.size = 3;
vtx.stride = 0;
select_glDrawElements(&vtx, list->mode, list->len, GL_UNSIGNED_SHORT, indices);
vtx.buffer = NULL;
select_glDrawElements(&vtx, list->mode, list->ilen, GL_UNSIGNED_SHORT, indices);
} else {
if (state.polygon_mode == GL_LINE && list->mode_init>=GL_TRIANGLES) {
int n, s;
@@ -935,6 +937,7 @@ void draw_renderlist(renderlist_t *list) {
vtx.type = GL_FLOAT;
vtx.size = 3;
vtx.stride = 0;
vtx.buffer = NULL;
select_glDrawArrays(&vtx, list->mode, 0, list->len);
} else {
int len = list->len;
@@ -1083,8 +1086,6 @@ void rlNormal3f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z) {
GLfloat *normal = (list->normal + (i * 3));
memcpy(normal, list->lastNormal, sizeof(GLfloat) * 3);
}
} else {
resize_renderlist(list);
}
GLfloat *normal = list->lastNormal;
@@ -1099,12 +1100,10 @@ void rlColor4f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
if (list->len) for (i = 0; i < list->len-1; i++) {
GLfloat *color = (list->color + (i * 4));
memcpy(color, state.color, sizeof(GLfloat) * 4);
} else {
}/* else {
GLfloat *color = list->color;
color[0] = r; color[1] = g; color[2] = b; color[3] = a;
}
} else {
resize_renderlist(list);
}*/
}
GLfloat *color = state.color;
@@ -1120,8 +1119,6 @@ void rlSecondary3f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b) {
GLfloat *secondary = (list->secondary + (i * 4));
memcpy(secondary, state.secondary, sizeof(GLfloat) * 4);
}
} else {
resize_renderlist(list);
}
GLfloat *color = state.secondary;
@@ -1230,26 +1227,24 @@ void rlTexCoord2f(renderlist_t *list, GLfloat s, GLfloat t) {
memcpy(tex, state.texcoord[0], sizeof(GLfloat) * 2);
tex += 2;
}
} else {
resize_renderlist(list);
}
GLfloat *tex = state.texcoord[0];
tex[0] = s; tex[1] = t;
}
void rlMultiTexCoord2f(renderlist_t *list, GLenum target, GLfloat s, GLfloat t) {
if (list->tex[target-GL_TEXTURE0] == NULL) {
list->tex[target-GL_TEXTURE0] = alloc_sublist(2, list->cap);
const int tmu = target - GL_TEXTURE0;
if (list->tex[tmu] == NULL) {
list->tex[tmu] = alloc_sublist(2, list->cap);
// catch up
GLfloat *tex = list->tex[target-GL_TEXTURE0];
GLfloat *tex = list->tex[tmu];
if (list->len) for (int i = 0; i < list->len-1; i++) {
memcpy(tex, state.texcoord[target-GL_TEXTURE0], sizeof(GLfloat) * 2);
memcpy(tex, state.texcoord[tmu], sizeof(GLfloat) * 2);
tex += 2;
}
} else {
resize_renderlist(list);
}
GLfloat *tex = state.texcoord[target-GL_TEXTURE0];
GLfloat *tex = state.texcoord[tmu];
tex[0] = s; tex[1] = t;
}
@@ -1286,7 +1281,7 @@ void rlPushCall(renderlist_t *list, packed_call_t *data) {
cl->calls[cl->len++] = data;
}
renderlist_t* GetFirst(const renderlist_t* list) {
renderlist_t* GetFirst(renderlist_t* list) {
while(list->prev)
list = list->prev;
return list;

View File

@@ -139,7 +139,7 @@ typedef struct _renderlist_t {
#define NewStage(l, s) if (l->stage+StageExclusive[l->stage] > s) {l = extend_renderlist(l);} l->stage = s
renderlist_t* GetFirst(const renderlist_t* list);
renderlist_t* GetFirst(renderlist_t* list);
extern renderlist_t *alloc_renderlist();
extern renderlist_t *extend_renderlist(renderlist_t *list);

View File

@@ -1,5 +1,35 @@
#include "render.h"
void push_hit() {
// push current hit to hit list, and re-init current hit
if (state.selectbuf.hit) {
if (!state.selectbuf.overflow) {
if (state.selectbuf.zmin<0.0f) state.selectbuf.zmin=0.0f; // not really normalized...
if (state.selectbuf.zmax>1.0f) state.selectbuf.zmax=1.0f; // TODO, normalize for good?
int tocopy = state.namestack.top + 3;
if (tocopy+state.selectbuf.pos > state.selectbuf.size) {
state.selectbuf.overflow = 1;
tocopy = state.selectbuf.size - state.selectbuf.pos;
}
if(tocopy>0)
state.selectbuf.buffer[state.selectbuf.pos+0] = state.namestack.top;
if(tocopy>1)
state.selectbuf.buffer[state.selectbuf.pos+1] = (unsigned int)(state.selectbuf.zmin * INT_MAX );
if(tocopy>2)
state.selectbuf.buffer[state.selectbuf.pos+2] = (unsigned int)(state.selectbuf.zmax * INT_MAX );
if(tocopy>3)
memcpy(state.selectbuf.buffer + state.selectbuf.pos + 3, state.namestack.names, (tocopy-3) * sizeof(GLuint));
state.selectbuf.count++;
state.selectbuf.pos += tocopy;
}
state.selectbuf.hit = 0;
}
state.selectbuf.zmin = 1.0f;
state.selectbuf.zmax = 0.0f;
}
GLint glRenderMode(GLenum mode) {
int ret = 0;
if ((mode==GL_SELECT) || (mode==GL_RENDER)) { // missing GL_FEEDBACK
@@ -8,15 +38,32 @@ GLint glRenderMode(GLenum mode) {
errorShim(GL_INVALID_ENUM);
return 0;
}
if (state.render_mode == GL_SELECT)
ret = state.selectbuf.count/4;
if (state.render_mode == GL_SELECT) {
push_hit();
ret = state.selectbuf.count;
}
if (mode == GL_SELECT) {
if (state.selectbuf.buffer == NULL) {// error, cannot use Select Mode without select buffer
errorShim(GL_INVALID_OPERATION);
return 0;
}
state.selectbuf.count = 0;
state.selectbuf.pos = 0;
state.selectbuf.overflow = 0;
state.selectbuf.zmin = 1.0f;
state.selectbuf.zmax = 0.0f;
state.selectbuf.hit = 0;
}
if((mode==GL_SELECT) && (state.gl_batch)) {
state.gl_batch = 0;
flush();
}
if((mode==GL_RENDER) && (state.gl_batch==0) && (gl_batch==1)) {
state.gl_batch = 1;
flush();
}
state.render_mode = mode;
return ret;
}
@@ -33,6 +80,7 @@ void glPopName() {
noerrorShim();
if (state.render_mode != GL_SELECT)
return;
push_hit();
if (state.namestack.top>0)
state.namestack.top--;
else
@@ -45,6 +93,7 @@ void glPushName(GLuint name) {
return;
if (state.namestack.names==0)
return;
push_hit();
if (state.namestack.top < 1024) {
state.namestack.names[state.namestack.top++] = name;
}
@@ -56,7 +105,10 @@ void glLoadName(GLuint name) {
return;
if (state.namestack.names == 0)
return;
state.namestack.names[state.namestack.top] = name;
push_hit();
if (state.namestack.top == 0)
return;
state.namestack.names[state.namestack.top-1] = name;
}
void glSelectBuffer(GLsizei size, GLuint *buffer) {
@@ -86,15 +138,15 @@ void select_transform(GLfloat *a) {
matrix_vector(projection, tmp, a);
//matrix_vector(model_proj, a, a);
}
GLboolean select_point_in_viewscreen(const GLfloat *a) {
/*
Return True is point is inside the Viewport
*/
if (a[0]<-1.0f) return false;
if (a[1]<-1.0f) return false;
if (a[0]>+1.0f) return false;
if (a[1]>+1.0f) return false;
if (a[0]>-1.0 && a[0]<1.0 && a[1]>-1.0 && a[1]<1.0) {
return true;
}
return false;
}
@@ -113,26 +165,28 @@ GLboolean select_segment_in_viewscreen(const GLfloat *a, const GLfloat *b) {
vx=b[0]-a[0];
vy=b[1]-a[1];
GLfloat p[4] = {-vx, vx, -vy, vy};
GLfloat q[4] = {a[0] + 1.0f, -1.0f - a[0], a[1] + 1.0f, -1.0f - a[1]};
GLfloat u1 = -1e10;
GLfloat u2 = +1e10;
GLfloat q[4] = {a[0] + 1.0f, +1.0f - a[0], a[1] + 1.0f, +1.0f - a[1]};
GLfloat u1 = 0.0f;
GLfloat u2 = 1.0f;
for (int i=0; i<4; i++) {
if (p[i] == 0.0f) {
if (q[i]<0)
if (q[i]<0.0f)
return false;
} else {
GLfloat t =q[i] / p[i];
if ((p[i]<0.0f) && (u1<t))
u1 = t;
else if ((p[i]>0.0f) && (u2>t))
u2 = t;
if (p[i]<0.0) {
if(t>u2) return false;
else if(u1<t)
u1 = t;
}
else if (p[i]>0.0) {
if(t<u1) return false;
else if (u2>t)
u2 = t;
}
}
}
if ((u1 > u2) || (u1>1) || (u1<0))
return false;
return true;
}
@@ -140,10 +194,10 @@ GLboolean select_triangle_in_viewscreen(const GLfloat *a, const GLfloat *b, cons
/*
Return True is the triangle is in the viewscreen, or completly include, or include the viewscreen
*/
// fast, check either point inside the viewscreen
if (select_point_in_viewscreen(a)) return true;
if (select_point_in_viewscreen(b)) return true;
if (select_point_in_viewscreen(c)) return true;
// Check if any segment intersect the viewscreen (include test if any point is inside the viewscreen)
if (select_segment_in_viewscreen(a, b)) return true;
if (select_segment_in_viewscreen(b, c)) return true;
if (select_segment_in_viewscreen(c, a)) return true;
// Now check if the viewscreen is completly inside the triangle
#define sign(p1, p2, p3) (p1[0]-p3[0])*(p2[1]-p3[1])-(p2[0]-p3[0])*(p1[1]-p3[1])
@@ -161,10 +215,6 @@ GLboolean select_triangle_in_viewscreen(const GLfloat *a, const GLfloat *b, cons
}
#undef sign
// Check if any segment intersect the viewscreen
if (select_segment_in_viewscreen(a, b)) return true;
if (select_segment_in_viewscreen(b, c)) return true;
if (select_segment_in_viewscreen(c, a)) return true;
return false;
}
@@ -174,67 +224,60 @@ void select_glDrawArrays(const pointer_state_t* vtx, GLenum mode, GLuint first,
if (state.selectbuf.buffer == NULL) return;
GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type,
vtx->size, vtx->stride,
GL_FLOAT, 3, 0, count);
GL_FLOAT, 3, 0, count+first);
GLfloat tmp[3];
GLfloat zmin=1.0f, zmax=0.0f;
init_select();
#define FOUND() { \
free(vert); \
for (int j=i+1; j<count; j++) { \
select_transform(vert+j*3); \
if (vert[j*3+2]<zmin) zmin=vert[j*3+2]; \
if (vert[j*3+2]>zmax) zmax=vert[j*3+2]; \
} \
if (zmin<0.0f) zmin = 0.0f; \
if (zmax>1.0f) zmax = 1.0f; \
if (state.selectbuf.count+4<state.selectbuf.size) { \
state.selectbuf.buffer[state.selectbuf.count++] = state.selectbuf.count/4; \
state.selectbuf.buffer[state.selectbuf.count++] = zmin*(1<<31); \
state.selectbuf.buffer[state.selectbuf.count++] = zmax*(1<<31); \
state.selectbuf.buffer[state.selectbuf.count++] = state.namestack.names[state.namestack.top];\
} \
return; }
for (int i=first; i<count; i++) {
if (zmin<state.selectbuf.zmin) state.selectbuf.zmin=zmin; \
if (zmax>state.selectbuf.zmax) state.selectbuf.zmax=zmax; \
state.selectbuf.hit = 1; \
free(vert); \
return; \
}
// transform the points
for (int i=first; i<count+first; i++) {
select_transform(vert+i*3);
if (vert[i*3+2]<zmin) zmin=vert[i*3+2];
if (vert[i*3+2]>zmax) zmax=vert[i*3+2];
//matrix_vector(projection, vert+i*3, tmp);
//matrix_vector(modelview, tmp, vert+i*3);
}
// intersect with screen now
GLfloat *vert2 = vert + first*3;
for (int i=0; i<count; i++) {
switch (mode) {
case GL_POINTS:
if (select_point_in_viewscreen(vert+i*3))
if (select_point_in_viewscreen(vert2+i*3))
FOUND();
break;
case GL_LINES:
if (i%2==1) {
if (select_segment_in_viewscreen(vert+(i-1)*3, vert+i*3))
if (select_segment_in_viewscreen(vert2+(i-1)*3, vert2+i*3))
FOUND();
}
break;
case GL_LINE_STRIP:
case GL_LINE_LOOP: //FIXME: the last "loop" segment is missing here
if (i>0) {
if (select_segment_in_viewscreen(vert+(i-1)*3, vert+i*3))
if (select_segment_in_viewscreen(vert2+(i-1)*3, vert2+i*3))
FOUND();
}
break;
case GL_TRIANGLES:
if (i%3==2) {
if (select_triangle_in_viewscreen(vert+(i-2)*3, vert+(i-1)*3, vert+i*3))
if (select_triangle_in_viewscreen(vert2+(i-2)*3, vert2+(i-1)*3, vert2+i*3))
FOUND();
}
break;
case GL_TRIANGLE_STRIP:
if (i>1) {
if (select_triangle_in_viewscreen(vert+(i-2)*3, vert+(i-1)*3, vert+i*3))
if (select_triangle_in_viewscreen(vert2+(i-2)*3, vert2+(i-1)*3, vert2+i*3))
FOUND();
}
break;
case GL_TRIANGLE_FAN:
if (i>1) {
if (select_triangle_in_viewscreen(vert, vert+(i-1)*3, vert+i*3))
if (select_triangle_in_viewscreen(vert2, vert2+(i-1)*3, vert2+i*3))
FOUND();
}
break;
@@ -253,8 +296,8 @@ void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count
GLushort *ind = (GLushort*)indices;
GLsizei min, max;
normalize_indices(indices, &max, &min, count);
getminmax_indices(indices, &max, &min, count);
max++;
GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type,
vtx->size, vtx->stride,
GL_FLOAT, 3, 0, max);
@@ -266,18 +309,16 @@ void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count
if (vert[i*3+2]<zmin) zmin=vert[i*3+2];
if (vert[i*3+2]>zmax) zmax=vert[i*3+2];
}
if (zmin<0.0f) zmin = 0.0f;
if (zmax>1.0f) zmax = 1.0f;
#define FOUND() { \
free(vert); \
if (zmin<0.0f) zmin = 0.0f; \
if (zmax>1.0f) zmax = 1.0f; \
if (state.selectbuf.count+4<state.selectbuf.size) { \
state.selectbuf.buffer[state.selectbuf.count++] = state.selectbuf.count/4; \
state.selectbuf.buffer[state.selectbuf.count++] = zmin*(1<<31); \
state.selectbuf.buffer[state.selectbuf.count++] = zmax*(1<<31); \
state.selectbuf.buffer[state.selectbuf.count++] = state.namestack.names[state.namestack.top];\
} \
return; }
if (zmin<state.selectbuf.zmin) state.selectbuf.zmin=zmin; \
if (zmax>state.selectbuf.zmax) state.selectbuf.zmax=zmax; \
state.selectbuf.hit = 1; \
free(vert); \
return; \
}
for (int i=0; i<count; i++) {
switch (mode) {

View File

@@ -97,9 +97,14 @@ typedef struct {
} namestack_t;
typedef struct {
int count;
GLuint count;
GLuint *buffer;
GLuint size;
GLuint size;
GLfloat zmin;
GLfloat zmax;
GLuint overflow;
GLuint pos;
GLboolean hit;
} selectbuf_t;
typedef struct {