diff --git a/project/jni/glshim/Android.mk b/project/jni/glshim/Android.mk index ba896bb31..86c098937 100644 --- a/project/jni/glshim/Android.mk +++ b/project/jni/glshim/Android.mk @@ -40,7 +40,7 @@ LOCAL_SRC_FILES := \ src/gl/math/eval.c \ src/glx/streaming.c -LOCAL_CFLAGS += -g -std=c99 -funwind-tables -O3 -DGL_EXPORTS -D_THREAD_SAFE=1 -DBCMHOST +LOCAL_CFLAGS += -g -std=c99 -funwind-tables -O3 -DBCMHOST LOCAL_LDLIBS := -ldl -llog -lEGL diff --git a/project/jni/glshim/CMakeLists.txt b/project/jni/glshim/CMakeLists.txt old mode 100644 new mode 100755 index c44fcf5ae..45aead7b1 --- a/project/jni/glshim/CMakeLists.txt +++ b/project/jni/glshim/CMakeLists.txt @@ -12,12 +12,11 @@ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) if(BCMHOST) include_directories(/opt/vc/include /opt/vc/include/interface/vcos/pthreads /opt/vc/include/interface/vmcs_host/linux) link_directories(/opt/vc/lib) - add_definitions(-DBCMHOST -D_GNU_SOURCE) + add_definitions(-DBCMHOST) endif() link_directories(${CMAKE_BINARY_DIR}/lib) -add_definitions(-O2) -include(flags.cmake) +add_definitions(-g -std=gnu99 -funwind-tables -O3) include_directories(include) add_subdirectory(src) diff --git a/project/jni/glshim/src/config.h b/project/jni/glshim/src/config.h index a02ae550b..199a0e58f 100755 --- a/project/jni/glshim/src/config.h +++ b/project/jni/glshim/src/config.h @@ -105,6 +105,13 @@ #define skip_glGetFramebufferAttachmentParameteriv #define skip_glGetRenderbufferParameteriv +#define skip_glFlush +#define skip_glFinish + +// matrix don't go to stack well, because values are pointer, not immediate... +#define skip_glLoadMatrixf +#define skip_glMultMatrixf + // don't compile these into display lists #define direct_glColorPointer #define direct_glDeleteLists @@ -113,8 +120,6 @@ #define direct_glEnableClientState #define direct_glClientActiveTexture #define direct_glFeedbackBuffer -#define direct_glFinish -#define direct_glFlush #define direct_glGenLists #define direct_glIndexPointer #define direct_glInterleavedArrays diff --git a/project/jni/glshim/src/gl/framebuffers.c b/project/jni/glshim/src/gl/framebuffers.c index bc0018489..6b0a08beb 100755 --- a/project/jni/glshim/src/gl/framebuffers.c +++ b/project/jni/glshim/src/gl/framebuffers.c @@ -1,4 +1,5 @@ #include "framebuffers.h" + #ifndef ANDROID #include #endif @@ -55,6 +56,7 @@ void glGenFramebuffers(GLsizei n, GLuint *ids) { void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) { //printf("glDeleteFramebuffers(%i, %p), framebuffers[0]=%u\n", n, framebuffers, framebuffers[0]); + if (state.gl_batch) flush(); LOAD_GLES_OES(glDeleteFramebuffers); errorGL(); @@ -63,6 +65,7 @@ void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) { GLboolean glIsFramebuffer(GLuint framebuffer) { //printf("glIsFramebuffer(%u)\n", framebuffer); + if (state.gl_batch) flush(); LOAD_GLES_OES(glIsFramebuffer); errorGL(); @@ -72,22 +75,28 @@ GLboolean glIsFramebuffer(GLuint framebuffer) { GLenum fb_status; GLenum glCheckFramebufferStatus(GLenum target) { - //LOAD_GLES_OES(glCheckFramebufferStatus); - - //errorGL(); - //GLenum result = gles_glCheckFramebufferStatus(target); + if (state.gl_batch) flush(); +//#define BEFORE 1 +#ifdef BEFORE GLenum result = fb_status; noerrorShim(); +#else + LOAD_GLES_OES(glCheckFramebufferStatus); + + errorGL(); + GLenum result = gles_glCheckFramebufferStatus(target); +#endif +#undef BEFORE //printf("glCheckFramebufferStatus(0x%04X)=0x%04X\n", target, result); return result; } void glBindFramebuffer(GLenum target, GLuint framebuffer) { //printf("glBindFramebuffer(0x%04X, %u), list=%s\n", target, framebuffer, state.list.active?"active":"none"); - PUSH_IF_COMPILING(glBindFramebuffer); + //PUSH_IF_COMPILING(glBindFramebuffer); + if (state.gl_batch) flush(); LOAD_GLES_OES(glBindFramebuffer); LOAD_GLES_OES(glCheckFramebufferStatus); -// fixme lubomyr LOAD_GLES(glGetError); if (target == GL_FRAMEBUFFER) { @@ -124,6 +133,7 @@ void glBindFramebuffer(GLenum target, GLuint framebuffer) { } void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { + if (state.gl_batch) flush(); LOAD_GLES_OES(glFramebufferTexture2D); LOAD_GLES(glTexImage2D); LOAD_GLES(glBindTexture); @@ -202,6 +212,7 @@ void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbu } void glDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers) { + if (state.gl_batch) flush(); LOAD_GLES_OES(glDeleteRenderbuffers); // check if we delete a depthstencil @@ -275,7 +286,7 @@ void glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum int } void glBindRenderbuffer(GLenum target, GLuint renderbuffer) { - PUSH_IF_COMPILING(glBindRenderbuffer); + if (state.gl_batch) flush(); LOAD_GLES_OES(glBindRenderbuffer); //printf("glBindRenderbuffer(0x%04X, %u)\n", target, renderbuffer); @@ -287,6 +298,7 @@ void glBindRenderbuffer(GLenum target, GLuint renderbuffer) { GLboolean glIsRenderbuffer(GLuint renderbuffer) { //printf("glIsRenderbuffer(%u)\n", renderbuffer); + if (state.gl_batch) flush(); LOAD_GLES_OES(glIsRenderbuffer); errorGL(); diff --git a/project/jni/glshim/src/gl/gl.c b/project/jni/glshim/src/gl/gl.c index a6cfe6509..b31daccf1 100755 --- a/project/jni/glshim/src/gl/gl.c +++ b/project/jni/glshim/src/gl/gl.c @@ -1,5 +1,5 @@ #include "gl.h" - +/* glstate_t state = {.color = {1.0f, 1.0f, 1.0f, 1.0f}, .secondary = {0.0f, 0.0f, 0.0f, 0.0f}, .render_mode = 0, @@ -15,9 +15,11 @@ glstate_t state = {.color = {1.0f, 1.0f, 1.0f, 1.0f}, .texture.active = 0, .buffers = {NULL, NULL, NULL, NULL}, .shim_error = 0, - .last_error = GL_NO_ERROR + .last_error = GL_NO_ERROR, + .gl_batch = 0 }; - +*/ +glstate_t state; void* gles = NULL; GLuint readhack = 0; @@ -25,6 +27,7 @@ GLint readhack_x = 0; GLint readhack_y = 0; GLfloat readhack_depth = 0.0f; GLuint readhack_seq = 0; +GLuint gl_batch = 0; __attribute__((constructor)) void initialize_glshim() { @@ -34,6 +37,7 @@ void initialize_glshim() { memset(&state, 0, sizeof(state)); memcpy(state.color, white, sizeof(GLfloat)*4); state.last_error = GL_NO_ERROR; + state.normal[3] = 1.0f; // default normal is 0/0/1 // init read hack char *env_readhack = getenv("LIBGL_READHACK"); @@ -45,7 +49,18 @@ void initialize_glshim() { readhack = 2; printf("LIBGL: glReadPixel Depth Hack (for games that read GLDepth always at the same place, same 1x1 size)\n"); } - + char *env_batch = getenv("LIBGL_BATCH"); + if (env_batch && strcmp(env_batch, "1") == 0) { + gl_batch = 1; + printf("LIBGL: Batch mode enabled\n"); + } + if (env_batch && strcmp(env_batch, "0") == 0) { + gl_batch = 0; + printf("LIBGL: Batch mode disabled\n"); + } + + if (gl_batch) init_batch(); + state.gl_batch = gl_batch; } // config functions @@ -437,6 +452,8 @@ void glDisableClientState(GLenum cap) { #endif GLboolean glIsEnabled(GLenum cap) { + // should flush for now... to be optimized later! + if (state.gl_batch) flush(); LOAD_GLES(glIsEnabled); noerrorShim(); switch (cap) { @@ -477,10 +494,6 @@ static renderlist_t *arrays_to_renderlist(renderlist_t *list, GLenum mode, list->color = copy_gl_pointer(&state.pointers.color, 4, skip, count, state.pointers.color.buffer); } if (state.enable.secondary_array/* && state.enable.color_array*/) { -/* GLfloat *second_color = copy_gl_pointer(&state.pointers.secondary, 4, skip, count, state.pointers.secondary.buffer); - for (int i=0; ilen*4; i++) - list->color[i] += second_color[i]; - free(second_color);*/ list->secondary = copy_gl_pointer(&state.pointers.secondary, 4, skip, count, state.pointers.secondary.buffer); // alpha chanel is always 0 for secondary... } if (state.enable.normal_array) { @@ -504,7 +517,7 @@ static inline bool should_intercept_render(GLenum mode) { (/*state.enable.texture_2d[2] && */(state.enable.texgen_s[2] || state.enable.texgen_t[2] || state.enable.texgen_r[2])) || (/*state.enable.texture_2d[3] && */(state.enable.texgen_s[3] || state.enable.texgen_t[3] || state.enable.texgen_r[3])) || (mode == GL_LINES && state.enable.line_stipple) || - (mode == GL_QUADS) || (state.list.active && state.list.compiling) + (mode == GL_QUADS) || (state.list.active && (state.list.compiling || state.gl_batch)) ); } @@ -514,11 +527,11 @@ void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indic errorShim(GL_INVALID_VALUE); return; } -// PUSH_IF_COMPILING(glDrawElements); + noerrorShim(); GLushort *sindices = copy_gl_array((state.buffers.elements)?state.buffers.elements->data + (uintptr_t)indices:indices, type, 1, 0, GL_UNSIGNED_SHORT, 1, 0, count); - bool compiling = (state.list.active && state.list.compiling); + bool compiling = (state.list.active && (state.list.compiling || state.gl_batch)); if (compiling) { renderlist_t *list = NULL; @@ -532,7 +545,8 @@ void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indic list->indices = sindices; list->ilen = count; end_renderlist(list); - //state.list.active = extend_renderlist(state.list.active); + + state.list.active = extend_renderlist(list); return; } @@ -577,7 +591,7 @@ void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indic if (mode == GL_POLYGON) mode = GL_TRIANGLE_FAN; if (state.render_mode == GL_SELECT) { - select_glDrawElements(mode, count, GL_UNSIGNED_SHORT, sindices); + select_glDrawElements(&state.pointers.vertex, mode, count, GL_UNSIGNED_SHORT, sindices); } else { // secondary color... GLfloat *final_colors = NULL; @@ -667,8 +681,6 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { errorShim(GL_INVALID_VALUE); return; } -// PUSH_IF_COMPILING(glDrawArrays); - noerrorShim(); LOAD_GLES(glNormalPointer); LOAD_GLES(glVertexPointer); @@ -676,22 +688,13 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { LOAD_GLES(glTexCoordPointer); renderlist_t *list, *active = state.list.active; - if (active && state.list.compiling) { + if (active && (state.list.compiling || state.gl_batch)) { NewStage(state.list.active, STAGE_DRAW); list = state.list.active; arrays_to_renderlist(list, mode, first, count+first); + state.list.active = extend_renderlist(list); return; } -#define shift_pointer(a, b) \ - if (state.enable.b && state.pointers.a.buffer) state.pointers.a.pointer = state.pointers.a.buffer->data + (uintptr_t)state.pointers.a.pointer; - - shift_pointer(color, color_array); - shift_pointer(secondary, secondary_array); - shift_pointer(vertex, vertex_array); - for (int aa=0; aa=GL_TRIANGLES) mode = GL_LINE_LOOP; @@ -708,6 +711,18 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { // like texgen, stipple, npot LOAD_GLES(glDrawArrays); +#define shift_pointer(a, b) \ + if (state.enable.b && state.pointers.a.buffer) state.pointers.a.pointer = state.pointers.a.buffer->data + (uintptr_t)state.pointers.a.pointer; + + shift_pointer(color, color_array); + shift_pointer(secondary, secondary_array); + shift_pointer(vertex, vertex_array); + for (int aa=0; aadata; @@ -798,7 +810,8 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { shift_pointer(tex_coord[aa], tex_coord_array[aa]); shift_pointer(normal, normal_array); #undef shift_pointer -// } + } + } } #ifndef USE_ES2 @@ -806,28 +819,20 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) { t.size = s; t.type = type; t.stride = stride; t.pointer = pointer; t.buffer = state.buffers.vertex void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -// errorGL(); -// LOAD_GLES(glVertexPointer); noerrorShim(); clone_gl_pointer(state.pointers.vertex, size); } void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -// errorGL(); -// LOAD_GLES(glColorPointer); noerrorShim(); clone_gl_pointer(state.pointers.color, size); } void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) { -// errorGL(); -// LOAD_GLES(glNormalPointer); noerrorShim(); clone_gl_pointer(state.pointers.normal, 3); } void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -// errorGL(); -// LOAD_GLES(glTexCoordPointer); noerrorShim(); clone_gl_pointer(state.pointers.tex_coord[state.texture.client], size); } @@ -910,10 +915,10 @@ void glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) { vert = 4; break; default: - errorShim(GL_INVALID_ENUM); - return; + errorShim(GL_INVALID_ENUM); + return; } - if (! stride) + if (!stride) stride = tex * gl_sizeof(tf) + color * gl_sizeof(cf) + normal * gl_sizeof(nf) + @@ -941,7 +946,7 @@ void glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) { // immediate mode functions void glBegin(GLenum mode) { - if (! state.list.active) + if (!state.list.active) state.list.active = alloc_renderlist(); NewStage(state.list.active, STAGE_DRAW); state.list.active->mode = mode; @@ -950,14 +955,14 @@ void glBegin(GLenum mode) { } void glEnd() { - if (! state.list.active) return; - // check if TEXTUREx is activate and no TexCoord, in that cas, create a dummy one base on state... + if (!state.list.active) return; + // check if TEXTUREx is activate and no TexCoord (or texgen), in that cas, create a dummy one base on state... for (int a=0; atex[a]==0)) + if (state.enable.texture_2d[a] && ((state.list.active->tex[a]==0) && (!state.enable.texgen_s[a]))) rlMultiTexCoord2f(state.list.active, GL_TEXTURE0+a, state.texcoord[a][0], state.texcoord[a][1]); // render if we're not in a display list - if (! state.list.compiling) { - renderlist_t *mylist = state.list.active; + if (!(state.list.compiling || state.gl_batch)) { + renderlist_t *mylist = state.list.active; state.list.active = NULL; end_renderlist(mylist); draw_renderlist(mylist); @@ -969,9 +974,12 @@ void glEnd() { } void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) { + state.normal[0] = nx; state.normal[1] = ny; state.normal[2] = nz; if (state.list.active) { if (state.list.active->stage != STAGE_DRAW) { - PUSH_IF_COMPILING(glNormal3f); + if (state.list.active->stage != STAGE_DRAW) { + PUSH_IF_COMPILING(glNormal3f); + } } else { rlNormal3f(state.list.active, nx, ny, nz); noerrorShim(); @@ -994,31 +1002,33 @@ void glVertex3f(GLfloat x, GLfloat y, GLfloat z) { } void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { + // change the state first thing + state.color[0] = red; state.color[1] = green; + state.color[2] = blue; state.color[3] = alpha; if (state.list.active) { - if (state.list.active->stage != STAGE_DRAW) { - PUSH_IF_COMPILING(glColor4f); - } else - rlColor4f(state.list.active, red, green, blue, alpha); - noerrorShim(); + if (state.list.active->stage != STAGE_DRAW) { + PUSH_IF_COMPILING(glColor4f); + } + rlColor4f(state.list.active, red, green, blue, alpha); + noerrorShim(); } #ifndef USE_ES2 else { LOAD_GLES(glColor4f); gles_glColor4f(red, green, blue, alpha); - state.color[0] = red; state.color[1] = green; - state.color[2] = blue; state.color[3] = alpha; errorGL(); } #endif } void glSecondaryColor3f(GLfloat r, GLfloat g, GLfloat b) { + // change the state first thing + state.secondary[0] = r; state.secondary[1] = g; + state.secondary[2] = b; if (state.list.active) { rlSecondary3f(state.list.active, r, g, b); noerrorShim(); } else { - state.secondary[0] = r; state.secondary[1] = g; - state.secondary[2] = b; noerrorShim(); } } @@ -1026,7 +1036,7 @@ void glSecondaryColor3f(GLfloat r, GLfloat g, GLfloat b) { #ifndef USE_ES2 void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { LOAD_GLES(glMaterialfv); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { //TODO: Materialfv can be done per vertex, how to handle that ?! //NewStage(state.list.active, STAGE_MATERIAL); rlMaterialfv(state.list.active, face, pname, params); @@ -1041,7 +1051,7 @@ void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { } void glMaterialf(GLenum face, GLenum pname, const GLfloat param) { LOAD_GLES(glMaterialf); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { GLfloat params[4]; memset(params, 0, 4*sizeof(GLfloat)); params[0] = param; @@ -1059,23 +1069,23 @@ void glMaterialf(GLenum face, GLenum pname, const GLfloat param) { #endif void glTexCoord2f(GLfloat s, GLfloat t) { + state.texcoord[0][0] = s; state.texcoord[0][1] = t; if (state.list.active) { rlTexCoord2f(state.list.active, s, t); noerrorShim(); } else { - state.texcoord[0][0] = s; state.texcoord[0][1] = t; - noerrorShim(); + noerrorShim(); } } void glMultiTexCoord2f(GLenum target, GLfloat s, GLfloat t) { - // TODO, error if taget is unsuported texture.... + state.texcoord[target-GL_TEXTURE0][0] = s; state.texcoord[target-GL_TEXTURE0][1] = t; + // TODO, error if target is unsuported texture.... if (state.list.active) { rlMultiTexCoord2f(state.list.active, target, s, t); noerrorShim(); } else { - state.texcoord[target-GL_TEXTURE0][0] = s; state.texcoord[target-GL_TEXTURE0][1] = t; - noerrorShim(); + noerrorShim(); } } void glArrayElement(GLint i) { @@ -1189,6 +1199,10 @@ void glNewList(GLuint list, GLenum mode) { if (! glIsList(list)) return; noerrorShim(); + if (state.gl_batch) { + state.gl_batch = 0; + flush(); + } state.list.name = list; state.list.mode = mode; // TODO: if state.list.active is already defined, we probably need to clean up here @@ -1201,11 +1215,13 @@ void glEndList() { GLuint list = state.list.name; if (state.list.compiling) { // Free the previous list if it exist... - free_renderlist(state.lists[list - 1]); + free_renderlist(state.lists[list - 1]); state.lists[list - 1] = state.list.first; state.list.compiling = false; - end_renderlist(state.list.active); - state.list.active = NULL; + end_renderlist(state.list.active); + if (gl_batch) { + init_batch(); + } else state.list.active = NULL; if (state.list.mode == GL_COMPILE_AND_EXECUTE) { glCallList(list); } @@ -1214,9 +1230,8 @@ void glEndList() { void glCallList(GLuint list) { noerrorShim(); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { NewStage(state.list.active, STAGE_CALLLIST); - /*state.list.active = extend_renderlist(state.list.active);*/ state.list.active->glcall_list = list; return; } @@ -1227,7 +1242,7 @@ void glCallList(GLuint list) { } void glPushCall(void *call) { - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { NewStage(state.list.active, STAGE_GLCALL); rlPushCall(state.list.active, call); } @@ -1305,7 +1320,7 @@ void glPolygonMode(GLenum face, GLenum mode) { errorShim(GL_INVALID_ENUM); if (face == GL_BACK) return; //TODO, handle face enum for polygon mode != GL_FILL - if (state.list.compiling && (state.list.active)) { + if ((state.list.compiling || state.gl_batch) && (state.list.active)) { NewStage(state.list.active, STAGE_POLYGON); /* if (state.list.active->polygon_mode) state.list.active = extend_renderlist(state.list.active);*/ @@ -1434,9 +1449,81 @@ GLenum glGetError( void) { } void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { + PUSH_IF_COMPILING(glBlendColor); LOAD_GLES_OES(glBlendColor); if (gles_glBlendColor) gles_glBlendColor(red, green, blue, alpha); else printf("stub glBlendColor(%f, %f, %f, %f)\n", red, green, blue, alpha); } + +void flush() { + // flush internal list +//printf("flush state.list.active=%p, gl_batch=%i(%i)\n", state.list.active, state.gl_batch, gl_batch); + renderlist_t *mylist = state.list.active; + if (mylist) { + GLuint old = state.gl_batch; + state.list.active = NULL; + state.gl_batch = 0; + end_renderlist(mylist); + draw_renderlist(mylist); + free_renderlist(mylist); + state.gl_batch = old; + } + state.list.active = (state.gl_batch)?alloc_renderlist():NULL; +} + +void init_batch() { + state.list.active = alloc_renderlist(); + state.gl_batch = 1; +} + +void glFlush() { + LOAD_GLES(glFlush); + + if (state.list.active && !state.gl_batch) { + errorShim(GL_INVALID_OPERATION); + return; + } + + if (state.gl_batch) flush(); + + gles_glFlush(); + errorGL(); +} +void glFinish() { + LOAD_GLES(glFinish); + + if (state.list.active && !state.gl_batch) { + errorShim(GL_INVALID_OPERATION); + return; + } + if (state.gl_batch) flush(); + + gles_glFinish(); + errorGL(); +} + +void glLoadMatrixf(const GLfloat * m) { + LOAD_GLES(glLoadMatrixf); + + if ((state.list.active || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_MATRIX); + state.list.active->matrix_op = 1; + memcpy(state.list.active->matrix_val, m, 16*sizeof(GLfloat)); + return; + } + gles_glLoadMatrixf(m); +} + +void glMultMatrixf(const GLfloat * m) { + LOAD_GLES(glMultMatrixf); + + if ((state.list.active || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_MATRIX); + state.list.active->matrix_op = 2; + memcpy(state.list.active->matrix_val, m, 16*sizeof(GLfloat)); + return; + } + gles_glMultMatrixf(m); +} diff --git a/project/jni/glshim/src/gl/gl.h b/project/jni/glshim/src/gl/gl.h index 95d2f29b0..60d4b50c1 100755 --- a/project/jni/glshim/src/gl/gl.h +++ b/project/jni/glshim/src/gl/gl.h @@ -128,7 +128,6 @@ static void load_gles_lib() { } } gles = dlopen(GLES_LIB, RTLD_LOCAL | RTLD_LAZY); -// fixme lubomyr printf("libGL backend: %s\n", GLES_LIB); } @@ -145,7 +144,6 @@ static void load_egl_lib() { } } egl = dlopen(EGL_LIB, RTLD_LOCAL | RTLD_LAZY); -// fixme lubomyr printf("libGL egl backend: %s\n", EGL_LIB); } @@ -227,7 +225,7 @@ static void load_egl_lib() { } #define PUSH_IF_COMPILING_EXT(nam, ...) \ - if (state.list.compiling && state.list.active) { \ + if ((state.list.compiling || state.gl_batch) && state.list.active) { \ NewStage(state.list.active, STAGE_GLCALL); \ push_##nam(__VA_ARGS__); \ noerrorShim(); \ @@ -393,10 +391,17 @@ static inline const GLboolean valid_vertex_type(GLenum type) { #include "framebuffers.h" extern void glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glFlush(); +extern void glFinish(); + +void flush(); +void init_batch(); #include "state.h" extern glstate_t state; +extern GLuint gl_batch; // 0 = off, 1 = on + static inline void errorGL() { // next glGetError will be from GL state.shim_error = 0; } diff --git a/project/jni/glshim/src/gl/list.c b/project/jni/glshim/src/gl/list.c index 96a405728..8b16f9a24 100755 --- a/project/jni/glshim/src/gl/list.c +++ b/project/jni/glshim/src/gl/list.c @@ -8,10 +8,9 @@ if (ref) \ ref = (GLfloat *)realloc(ref, n * sizeof(GLfloat) * cap) -static GLushort *cached_q2t = NULL; -static unsigned long cached_q2t_len = 0; - renderlist_t *alloc_renderlist() { + int a; + renderlist_t *list = (renderlist_t *)malloc(sizeof(renderlist_t)); list->len = 0; list->ilen = 0; @@ -36,7 +35,14 @@ renderlist_t *alloc_renderlist() { list->pushattribute = 0; list->popattribute = false; - int a; + list->raster_op = 0; + for (a=0; a<3; a++) + list->raster_xyz[a]=0.0f; + + list->matrix_op = 0; + for (a=0; a<16; a++) + list->matrix_val[a]=((a%4)==0)?1.0f:0.0f; // load identity matrix + for (a=0; atex[a] = NULL; list->material = NULL; @@ -45,7 +51,6 @@ renderlist_t *alloc_renderlist() { list->lightmodel = NULL; list->lightmodelparam = GL_LIGHT_MODEL_AMBIENT; list->indices = NULL; - list->q2t = false; list->set_texture = false; list->texture = 0; list->polygon_mode = 0; @@ -56,13 +61,299 @@ renderlist_t *alloc_renderlist() { return list; } +bool ispurerender_renderlist(renderlist_t *list) { + // return true if renderlist contains only rendering command, no state changes + if (list->calls.len) + return false; + if (list->glcall_list) + return false; + if (list->matrix_op) + return false; + if (list->raster_op) + return false; + if (list->raster) + return false; + if (list->pushattribute) + return false; + if (list->popattribute) + return false; + if (list->material || list->light) + return false; + if (list->texgen) + return false; + if (list->mode_init == 0) + return false; + + return true; +} + +int rendermode_dimensions(GLenum mode) { + // return 1 for points, 2 for any lines, 3 for any triangles, 4 for any Quad and 5 for polygon + switch (mode) { + case GL_POINTS: + return 1; + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + return 2; + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: + return 3; + case GL_QUADS: + case GL_QUAD_STRIP: + return 4; + case GL_POLYGON: + return 5; + } + return 0; +} + +bool islistscompatible_renderlist(renderlist_t *a, renderlist_t *b) { + // check if 2 "pure rendering" list are compatible for merge + if (a->mode_init != b->mode_init) { + int a_mode = rendermode_dimensions(a->mode_init); + int b_mode = rendermode_dimensions(b->mode_init); + if ((a_mode == 5) || (b_mode == 5)) + return false; // Let's not merge polygons + if ((a_mode == 0) || (b_mode == 0)) + return false; // undetermined is not good + if (a_mode == 4) a_mode = 3; // quads are handled as triangles + if (b_mode == 4) b_mode = 3; + if (a_mode != b_mode) + return false; + } +/* if ((a->indices==NULL) != (b->indices==NULL)) + return false;*/ + if (a->polygon_mode != b->polygon_mode) + return false; + if ((a->vert==NULL) != (b->vert==NULL)) + return false; + if ((a->normal==NULL) != (b->normal==NULL)) + return false; + if ((a->color==NULL) != (b->color==NULL)) + return false; + if ((a->secondary==NULL) != (b->secondary==NULL)) + return false; + for (int i=0; itex[i]==NULL) != (b->tex[i]==NULL)) + return false; + if ((a->set_texture==b->set_texture) && (a->texture != b->texture)) + return false; + if (!a->set_texture && b->set_texture) + return false; + + return true; +} + +void renderlist_createindices(renderlist_t *a) { + int ilen = a->len; + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 0; iindices[i] = i; + } + a->ilen = ilen; +} + +#define vind(i) (ind)?ind[i]:i + +void renderlist_lineloop_lines(renderlist_t *a) { + GLushort *ind = a->indices; + int ilen = a->ilen; + if (ilen==0) ilen = a->len; + ilen = ilen*2; // new size is 2* + return + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 0; iindices[i] = vind((i+1)/2); + } + // go back to initial point + a->indices[ilen-1] = a->indices[0]; + a->ilen = ilen; + if (ind) free(ind); + a->mode = GL_LINES; +} + +void renderlist_linestrip_lines(renderlist_t *a) { + GLushort *ind = a->indices; + int ilen = a->ilen; + if (ilen==0) ilen = a->len; + ilen = ilen*2-2; // new size is 2* + if (ilen<0) ilen=0; + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 0; iindices[i] = vind((i+1)/2); + } + a->ilen = ilen; + if (ind) free(ind); + a->mode = GL_LINES; +} + +void renderlist_triangletrip_triangles(renderlist_t *a) { + GLushort *ind = a->indices; + int len = a->ilen; + if (len==0) len = a->len; + int ilen = (len-2)*3; + if (ilen<0) ilen=0; + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 2; iindices[(i-2)*3+(i%2)] = vind(i-2); + a->indices[(i-2)*3+1-(i%2)] = vind(i-1); + a->indices[(i-2)*3+2] = vind(i); + } + a->ilen = ilen; + if (ind) free(ind); + a->mode = GL_TRIANGLES; +} + +void renderlist_trianglefan_triangles(renderlist_t *a) { + GLushort *ind = a->indices; + int len = a->ilen; + if (len==0) len = a->len; + int ilen = (len-2)*3; + if (ilen<0) ilen=0; + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 2; iindices[(i-2)*3+0] = vind(0); + a->indices[(i-2)*3+1] = vind(i-1); + a->indices[(i-2)*3+2] = vind(i); + } + a->ilen = ilen; + if (ind) free(ind); + a->mode = GL_TRIANGLES; +} + +void renderlist_quads_triangles(renderlist_t *a) { + GLushort *ind = a->indices; + int len = a->ilen; + if (len==0) len = a->len; + int ilen = len*3/2; + if (ilen<0) ilen=0; + a->indices = (GLushort*)malloc(ilen*sizeof(GLushort)); + for (int i = 0; iindices[i*3/2+0] = vind(i+0); + a->indices[i*3/2+1] = vind(i+1); + a->indices[i*3/2+2] = vind(i+2); + + a->indices[i*3/2+3] = vind(i+0); + a->indices[i*3/2+4] = vind(i+2); + a->indices[i*3/2+5] = vind(i+3); + } + a->ilen = ilen; + if (ind) free(ind); + a->mode = GL_TRIANGLES; +} +#undef vind + +void append_renderlist(renderlist_t *a, renderlist_t *b) { + // append all draw elements of b in a + // check if "a" needs to be converted + switch (a->mode) { + case GL_LINE_LOOP: + renderlist_lineloop_lines(a); + break; + case GL_LINE_STRIP: + renderlist_linestrip_lines(a); + break; + case GL_QUAD_STRIP: + case GL_TRIANGLE_STRIP: + renderlist_triangletrip_triangles(a); + break; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + renderlist_trianglefan_triangles(a); + break; + case GL_QUADS: + renderlist_quads_triangles(a); + break; + default: + break; + } + // check if "b" needs to be converted + switch (b->mode) { + case GL_LINE_LOOP: + renderlist_lineloop_lines(b); + break; + case GL_LINE_STRIP: + renderlist_linestrip_lines(b); + break; + case GL_QUAD_STRIP: + case GL_TRIANGLE_STRIP: + renderlist_triangletrip_triangles(b); + break; + case GL_TRIANGLE_FAN: + case GL_POLYGON: + renderlist_trianglefan_triangles(b); + break; + case GL_QUADS: + renderlist_quads_triangles(b); + break; + default: + break; + } + // check for differences in "indices" in both list + if ((a->indices==NULL) != (b->indices==NULL)) { + if (a->indices==NULL) renderlist_createindices(a); + if (b->indices==NULL) renderlist_createindices(b); + } + // lets append all the arrays + int cap = a->cap; + while (a->len + b->len >= cap) cap += DEFAULT_RENDER_LIST_CAPACITY; + if (a->cap != cap) { + a->cap = cap; + realloc_sublist(a->vert, 3, cap); + realloc_sublist(a->normal, 3, cap); + realloc_sublist(a->color, 4, cap); + realloc_sublist(a->secondary, 4, cap); + for (int i=0; itex[i], 2, cap); + } + // arrays + if (a->vert) memcpy(a->vert+a->len*3, b->vert, b->len*3*sizeof(GLfloat)); + if (a->normal) memcpy(a->normal+a->len*3, b->normal, b->len*3*sizeof(GLfloat)); + if (a->color) memcpy(a->color+a->len*4, b->color, b->len*4*sizeof(GLfloat)); + if (a->secondary) memcpy(a->secondary+a->len*4, b->secondary, b->len*4*sizeof(GLfloat)); + for (int i=0; itex[i]) memcpy(a->tex[i]+a->len*2, b->tex[i], b->len*2*sizeof(GLfloat)); + + // indices + if (a->indices) { + a->indices = realloc(a->indices, (a->ilen+b->ilen)*sizeof(GLushort)); + for (int i=0; iilen; i++) a->indices[a->ilen+i]=b->indices[i]+a->len; + } + // lenghts + a->len += b->len; + a->ilen += b->ilen; + + //all done + return; +} + renderlist_t *extend_renderlist(renderlist_t *list) { - renderlist_t *new = alloc_renderlist(); - list->next = new; - new->prev = list; - if (list->open) - end_renderlist(list); - return new; + if ((list->prev!=NULL) && ispurerender_renderlist(list) && islistscompatible_renderlist(list->prev, list)) { + // close first! + if (list->open) + end_renderlist(list); + // append list! +//printf("merge list 0x%04X(0x%04X) %i(%i) - %i + 0x%04X(0x%04X) %i(%i) - %i", +// list->prev->mode_init, list->prev->mode, list->prev->len, list->prev->cap, list->prev->ilen, list->mode_init, list->mode, list->len, list->cap, list->ilen); + append_renderlist(list->prev, list); +//printf(" -> %i(%i) - %i\n", list->prev->len, list->prev->cap, list->prev->ilen); + renderlist_t *new = alloc_renderlist(); + new->prev = list->prev; + list->prev->next = new; + // detach + list->prev = NULL; + // free list now + free_renderlist(list); + return new; + } else { + renderlist_t *new = alloc_renderlist(); + list->next = new; + new->prev = list; + if (list->open) + end_renderlist(list); + return new; + } } void free_renderlist(renderlist_t *list) { @@ -112,7 +403,7 @@ void free_renderlist(renderlist_t *list) { if (list->lightmodel) free(list->lightmodel); - if ((list->indices) && (!list->q2t)) + if (list->indices) free(list->indices); if (list->raster) { @@ -139,55 +430,6 @@ void resize_renderlist(renderlist_t *list) { } } -void q2t_renderlist(renderlist_t *list) { - if (!list->len || !list->vert || list->q2t) return; - // TODO: split to multiple lists if list->len > 65535 - int a = 0, b = 1, c = 2, d = 3; - int winding[6] = { - a, b, d, - b, c, d, - }; - unsigned long len = list->len * 6 / 4; - - // q2t on glDrawElements? - GLushort *old_indices = NULL; - GLushort *indices; - if (list->indices) - old_indices = list->indices; - // free(list->indices); - if ((len > cached_q2t_len) || (old_indices)) { - if (old_indices) { - indices = malloc(len * sizeof(GLushort)); - } else { - if (cached_q2t) - free(cached_q2t); - cached_q2t = malloc(len * sizeof(GLushort)); - cached_q2t_len = len; - } - int k = 0; - for (int i = 0; i < list->len; i += 4) { - for (int j = 0; j < 6; j++) { - if (old_indices) - indices[k+j] = old_indices[i + winding[j]]; - else - cached_q2t[k+j] = i + winding[j]; - } - k += 6; - } - } - - if (!old_indices) { -// list->indices = cached_q2t; - list->q2t = true; - } else { - free(old_indices); - list->indices = indices; - } - - list->ilen = len; - return; -} - void end_renderlist(renderlist_t *list) { if (! list->open) return; @@ -209,8 +451,7 @@ void end_renderlist(renderlist_t *list) { if (list->len==4) { list->mode = GL_TRIANGLE_FAN; } else { - list->mode = GL_TRIANGLES; - q2t_renderlist(list); + renderlist_quads_triangles(list); } break; case GL_POLYGON: @@ -224,6 +465,10 @@ void end_renderlist(renderlist_t *list) { void draw_renderlist(renderlist_t *list) { if (!list) return; + // go to 1st... + while (list->prev) list = list->prev; + // ok, go on now, draw everything +//printf("draw_renderlist %p, gl_batch=%i, size=%i, next=%p\n", list, state.gl_batch, list->len, list->next); LOAD_GLES(glDrawArrays); LOAD_GLES(glDrawElements); #ifdef USE_ES2 @@ -239,7 +484,6 @@ void draw_renderlist(renderlist_t *list) { GLfloat *final_colors; int old_tex; GLushort *indices; - do { // push/pop attributes if (list->pushattribute) @@ -249,23 +493,43 @@ void draw_renderlist(renderlist_t *list) { // do call_list if (list->glcall_list) glCallList(list->glcall_list); - // optimize zero-length segments out earlier? call_list_t *cl = &list->calls; if (cl->len > 0) { for (int i = 0; i < cl->len; i++) { glPackedCall(cl->calls[i]); } } + if (list->matrix_op) { + switch (list->matrix_op) { + case 1: // load + glLoadMatrixf(list->matrix_val); + break; + case 2: // mult + glMultMatrixf(list->matrix_val); + break; + } + } old_tex = state.texture.active; if (list->set_texture) { glBindTexture(list->target_texture, list->texture); } // raster + if (list->raster_op) { + if (list->raster_op==1) { + glRasterPos3f(list->raster_xyz[0], list->raster_xyz[1], list->raster_xyz[2]); + } else if (list->raster_op==2) { + glWindowPos3f(list->raster_xyz[0], list->raster_xyz[1], list->raster_xyz[2]); + } else if (list->raster_op==3) { + glPixelZoom(list->raster_xyz[0], list->raster_xyz[1]); + } else if ((list->raster_op&0x10000) == 0x10000) { + glPixelTransferf(list->raster_op&0xFFFF, list->raster_xyz[0]); + } + } if (list->raster) { - rasterlist_t * r = list->raster; - //glBitmap(r->width, r->height, r->xorig, r->yorig, r->xmove, r->ymove, r->raster); - render_raster_list(list->raster); - } + rasterlist_t * r = list->raster; + //glBitmap(r->width, r->height, r->xorig, r->yorig, r->xmove, r->ymove, r->raster); + render_raster_list(list->raster); + } if (list->material) { @@ -309,12 +573,11 @@ void draw_renderlist(renderlist_t *list) { ) } - if (list->polygon_mode) - glPolygonMode(GL_FRONT_AND_BACK, list->polygon_mode); + if (list->polygon_mode) { + glPolygonMode(GL_FRONT_AND_BACK, list->polygon_mode);} if (! list->len) continue; - #ifdef USE_ES2 if (list->vert) { glEnableVertexAttribArray(0); @@ -337,8 +600,6 @@ void draw_renderlist(renderlist_t *list) { } indices = list->indices; - if (list->q2t && !(state.polygon_mode == GL_LINE)) - indices = cached_q2t; final_colors = NULL; if (list->color) { @@ -406,95 +667,177 @@ void draw_renderlist(renderlist_t *list) { GLenum mode; mode = list->mode; if ((state.polygon_mode == GL_LINE) && (mode>=GL_TRIANGLES)) - mode = GL_LINE_LOOP; + mode = GL_LINES; if ((state.polygon_mode == GL_POINT) && (mode>=GL_TRIANGLES)) mode = GL_POINTS; if (indices) { - if (state.render_mode == GL_SELECT) { - select_glDrawElements(list->mode, list->len, GL_UNSIGNED_SHORT, indices); + if (state.render_mode == GL_SELECT) { + pointer_state_t vtx; + vtx.pointer = list->vert; + vtx.type = GL_FLOAT; + vtx.size = 3; + vtx.stride = 0; + select_glDrawElements(&vtx, list->mode, list->len, GL_UNSIGNED_SHORT, indices); } else { if (state.polygon_mode == GL_LINE && list->mode_init>=GL_TRIANGLES) { int n, s; - GLushort ind_line[list->ilen*3+1]; + int ilen = list->ilen; + GLushort ind_line[ilen*3+1]; + int k=0; switch (list->mode_init) { case GL_TRIANGLES: - n = 3; - s = 3; + // 1 triangle -> 3 lines + for (int i = 0; i2) { + ind_line[k++] = indices[0]; ind_line[k++] = indices[1]; + } + for (int i = 2; iilen; - s = list->ilen; + case GL_TRIANGLE_FAN: + // first 3 points a triangle, then a 2 lines per new point too + if (ilen>2) { + ind_line[k++] = indices[0]; ind_line[k++] = indices[1]; + } + for (int i = 2; imode == GL_TRIANGLE_FAN) { + // just 1 Quad + for (int i=0; i<4; i++) { + ind_line[k++] = indices[i+0]; ind_line[k++] = indices[(i+1)%4]; + } + } else { + // list of triangles, 2 per quads... + for (int i=0; i2) { + ind_line[k++] = indices[0]; ind_line[k++] = indices[1]; + } + for (int i = 2; iilen; - s = list->ilen; + case GL_POLYGON: + // if polygons have been merged, then info is lost... + if (ilen) { + ind_line[k++] = indices[0]; ind_line[k++] = indices[1]; + } + for (int i = 1; iilen; i+=s) { - memcpy(ind_line+k, indices+i-n, sizeof(GLushort)*n); - k+=n; - } - //gles_glDrawElements(mode, n, GL_UNSIGNED_SHORT, indices+i-n); - gles_glDrawElements(mode, k, GL_UNSIGNED_SHORT, ind_line); + gles_glDrawElements(mode, k, GL_UNSIGNED_SHORT, ind_line); } else { gles_glDrawElements(mode, list->ilen, GL_UNSIGNED_SHORT, indices); } } } else { if (state.render_mode == GL_SELECT) { - select_glDrawArrays(list->mode, 0, list->len); + pointer_state_t vtx; + vtx.pointer = list->vert; + vtx.type = GL_FLOAT; + vtx.size = 3; + vtx.stride = 0; + select_glDrawArrays(&vtx, list->mode, 0, list->len); } else { int len = list->len; if ((state.polygon_mode == GL_LINE) && (list->mode_init>=GL_TRIANGLES)) { int n, s; - if (list->q2t) - len = len*4/6; GLushort ind_line[len*3+1]; - switch (list->mode_init) { - case GL_TRIANGLES: - n = 3; - s = 3; - break; - case GL_TRIANGLE_STRIP: - n = 3; - s = 1; - break; - case GL_TRIANGLE_FAN: // wrong here... - n = len; - s = len; - break; - case GL_QUADS: - n = 4; - s = 4; - break; - case GL_QUAD_STRIP: - n = 4; - s = 1; - break; - default: // Polygon and other? - n = len; - s = len; - break; - } int k=0; - for (int i=n; i<=len; i+=s) - for (int j=0; jmode_init) { + case GL_TRIANGLES: + // 1 triangle -> 3 lines + for (int i = 0; i2) { + ind_line[k++] = 0; ind_line[k++] = 1; + } + for (int i = 2; i2) { + ind_line[k++] = 0; ind_line[k++] = 1; + } + for (int i = 2; imode == GL_TRIANGLE_FAN) { + // just 1 Quad + for (int i=0; i<4; i++) { + ind_line[k++] = i+0; ind_line[k++] = (i+1)%4; + } + } else { + // cannot go there! + } + break; + case GL_QUAD_STRIP: + // first 4 points is a quad, then 2 points per new quad + if (len>2) { + ind_line[k++] = 0; ind_line[k++] = 1; + } + for (int i = 2; iset_texture = true; } +void rlRasterOp(renderlist_t *list, int op, GLfloat x, GLfloat y, GLfloat z) { + list->raster_op = op; + list->raster_xyz[0] = x; + list->raster_xyz[1] = y; + list->raster_xyz[2] = z; +} + void rlPushCall(renderlist_t *list, packed_call_t *data) { call_list_t *cl = &list->calls; if (!cl->calls) { diff --git a/project/jni/glshim/src/gl/list.h b/project/jni/glshim/src/gl/list.h index ddb3ea5de..921f1ff83 100755 --- a/project/jni/glshim/src/gl/list.h +++ b/project/jni/glshim/src/gl/list.h @@ -9,6 +9,7 @@ typedef enum { STAGE_POP, STAGE_CALLLIST, STAGE_GLCALL, + STAGE_MATRIX, STAGE_BINDTEX, STAGE_RASTER, STAGE_MATERIAL, @@ -95,7 +96,6 @@ typedef struct _renderlist_t { GLfloat *secondary; GLfloat *tex[MAX_TEX]; GLushort *indices; - GLboolean q2t; GLuint glcall_list; rasterlist_t *raster; @@ -105,6 +105,12 @@ typedef struct _renderlist_t { GLbitfield pushattribute; GLboolean popattribute; + int raster_op; + GLfloat raster_xyz[3]; + + int matrix_op; + GLfloat matrix_val[16]; + khash_t(material) *material; khash_t(light) *light; khash_t(texgen) *texgen; @@ -128,7 +134,6 @@ extern renderlist_t *alloc_renderlist(); extern renderlist_t *extend_renderlist(renderlist_t *list); extern void free_renderlist(renderlist_t *list); extern void draw_renderlist(renderlist_t *list); -extern void q2t_renderlist(renderlist_t *list); extern void end_renderlist(renderlist_t *list); extern void rlBindTexture(renderlist_t *list, GLenum target, GLuint texture); @@ -142,4 +147,5 @@ extern void rlTexCoord2f(renderlist_t *list, GLfloat s, GLfloat t); extern void rlMultiTexCoord2f(renderlist_t *list, GLenum texture, GLfloat s, GLfloat t); extern void rlVertex3f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z); extern void rlSecondary3f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b); +extern void rlRasterOp(renderlist_t *list, int op, GLfloat x, GLfloat y, GLfloat z); #endif diff --git a/project/jni/glshim/src/gl/raster.c b/project/jni/glshim/src/gl/raster.c index 5a74f07a8..2ba9be55f 100755 --- a/project/jni/glshim/src/gl/raster.c +++ b/project/jni/glshim/src/gl/raster.c @@ -19,6 +19,12 @@ extern void matrix_column_row(const GLfloat *a, GLfloat *b); extern void matrix_vector(const GLfloat *a, const GLfloat *b, GLfloat *c); void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_RASTER); + rlRasterOp(state.list.active, 1, x, y, z); + noerrorShim(); + return; + } #if 1 // Transform xyz coordinates with currzent modelview and projection matrix... GLfloat glmatrix[16], projection[16], modelview[16]; @@ -44,6 +50,12 @@ void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) { } void glWindowPos3f(GLfloat x, GLfloat y, GLfloat z) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_RASTER); + rlRasterOp(state.list.active, 2, x, y, z); + noerrorShim(); + return; + } rPos.x = x; rPos.y = y; rPos.z = z; @@ -60,12 +72,24 @@ void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { } void glPixelZoom(GLfloat xfactor, GLfloat yfactor) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_RASTER); + rlRasterOp(state.list.active, 3, xfactor, yfactor, 0.0f); + noerrorShim(); + return; + } zoomx = xfactor; zoomy = yfactor; //printf("LIBGL: glPixelZoom(%f, %f)\n", xfactor, yfactor); } void glPixelTransferf(GLenum pname, GLfloat param) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { + NewStage(state.list.active, STAGE_RASTER); + rlRasterOp(state.list.active, pname|0x10000, param, 0.0f, 0.0f); + noerrorShim(); + return; + } //printf("LIBGL: glPixelTransferf(%04x, %f)\n", pname, param); switch(pname) { case GL_RED_SCALE: @@ -141,7 +165,9 @@ GLuint raster_to_texture() renderlist_t *old_list = state.list.active; if (old_list) state.list.active = NULL; // deactivate list... GLboolean compiling = state.list.compiling; + GLuint state_batch = state.gl_batch; state.list.compiling = false; + state.gl_batch = 0; glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT ); GLuint old_tex_unit, old_tex; glGetIntegerv(GL_ACTIVE_TEXTURE, &old_tex_unit); @@ -173,6 +199,7 @@ GLuint raster_to_texture() glPopAttrib(); if (old_list) state.list.active = old_list; state.list.compiling = compiling; + state.gl_batch = state_batch; return raster_texture; } @@ -184,7 +211,7 @@ void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, // TODO: negative width/height mirrors bitmap? noerrorShim(); if ((!width && !height) || (bitmap==0)) { - if (state.list.compiling) { + if (state.list.compiling || state.gl_batch) { if (state.list.active->raster) state.list.active = extend_renderlist(state.list.active); // already a raster in the list, create a new one rasterlist_t *r = state.list.active->raster = (rasterlist_t*)malloc(sizeof(rasterlist_t)); @@ -235,7 +262,7 @@ void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, rasterlist_t rast; rasterlist_t *r; - if (state.list.compiling) { + if (state.list.compiling || state.gl_batch) { NewStage(state.list.active, STAGE_RASTER); /* if (state.list.active->raster) state.list.active = extend_renderlist(state.list.active);*/ // already a raster in the list, create a new one @@ -254,7 +281,7 @@ void glBitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, r->zoomx = zoomx; r->zoomy = zoomy; LOAD_GLES(glDeleteTextures); - if (!state.list.compiling) { + if (!(state.list.compiling || state.gl_batch)) { render_raster_list(r); gles_glDeleteTextures(1, &r->texture); r->texture = 0; @@ -309,7 +336,7 @@ void glDrawPixels(GLsizei width, GLsizei height, GLenum format, rasterlist_t rast; rasterlist_t *r; - if (state.list.compiling) { + if (state.list.compiling || gl_batch) { NewStage(state.list.active, STAGE_RASTER); /* if (state.list.active->raster) state.list.active = extend_renderlist(state.list.active);*/ // already a raster in the list, create a new one @@ -328,7 +355,7 @@ void glDrawPixels(GLsizei width, GLsizei height, GLenum format, r->zoomx = zoomx; r->zoomy = zoomy; LOAD_GLES(glDeleteTextures); - if (!state.list.compiling) { + if (!(state.list.compiling || state.gl_batch)) { render_raster_list(r); gles_glDeleteTextures(1, &r->texture); r->texture = 0; diff --git a/project/jni/glshim/src/gl/render.c b/project/jni/glshim/src/gl/render.c index eac0823d7..9c36c275f 100755 --- a/project/jni/glshim/src/gl/render.c +++ b/project/jni/glshim/src/gl/render.c @@ -1,4 +1,4 @@ -#include "raster.h" +#include "render.h" GLint glRenderMode(GLenum mode) { int ret = 0; @@ -11,9 +11,10 @@ GLint glRenderMode(GLenum mode) { if (state.render_mode == GL_SELECT) ret = state.selectbuf.count/4; if (mode == GL_SELECT) { - if (state.selectbuf.buffer == NULL) // error, cannot use Select Mode without select buffer + if (state.selectbuf.buffer == NULL) {// error, cannot use Select Mode without select buffer errorShim(GL_INVALID_OPERATION); return 0; + } state.selectbuf.count = 0; } state.render_mode = mode; @@ -78,11 +79,12 @@ void init_select() { void select_transform(GLfloat *a) { /* - Transfor a[3] using projection and modelview matrix (init with init_select) + Transform a[3] using projection and modelview matrix (init with init_select) */ GLfloat tmp[3]; matrix_vector(modelview, a, tmp); matrix_vector(projection, tmp, a); + //matrix_vector(model_proj, a, a); } GLboolean select_point_in_viewscreen(const GLfloat *a) { /* @@ -166,12 +168,12 @@ GLboolean select_triangle_in_viewscreen(const GLfloat *a, const GLfloat *b, cons return false; } -void select_glDrawArrays(GLenum mode, GLuint first, GLuint count) { +void select_glDrawArrays(const pointer_state_t* vtx, GLenum mode, GLuint first, GLuint count) { if (count == 0) return; - if (state.pointers.vertex.pointer == NULL) return; + if (vtx->pointer == NULL) return; if (state.selectbuf.buffer == NULL) return; - GLfloat *vert = copy_gl_array(state.pointers.vertex.pointer, state.pointers.vertex.type, - state.pointers.vertex.size, state.pointers.vertex.stride, + GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type, + vtx->size, vtx->stride, GL_FLOAT, 3, 0, count); GLfloat tmp[3]; GLfloat zmin=1.0f, zmax=0.0f; @@ -244,17 +246,17 @@ void select_glDrawArrays(GLenum mode, GLuint first, GLuint count) { #undef FOUND } -void select_glDrawElements(GLenum mode, GLuint count, GLenum type, GLvoid * indices) { +void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count, GLenum type, GLvoid * indices) { if (count == 0) return; - if (state.pointers.vertex.pointer == NULL) return; + if (vtx->pointer == NULL) return; GLushort *ind = (GLushort*)indices; GLsizei min, max; normalize_indices(indices, &max, &min, count); - GLfloat *vert = copy_gl_array(state.pointers.vertex.pointer, state.pointers.vertex.type, - state.pointers.vertex.size, state.pointers.vertex.stride, + GLfloat *vert = copy_gl_array(vtx->pointer, vtx->type, + vtx->size, vtx->stride, GL_FLOAT, 3, 0, max); GLfloat tmp[3]; init_select(); diff --git a/project/jni/glshim/src/gl/render.h b/project/jni/glshim/src/gl/render.h index 3caff2ef7..471f56d69 100755 --- a/project/jni/glshim/src/gl/render.h +++ b/project/jni/glshim/src/gl/render.h @@ -9,6 +9,6 @@ void glPushName(GLuint name); void glLoadName(GLuint name); void glSelectBuffer(GLsizei size, GLuint *buffer); -void select_glDrawElements(GLenum mode, GLuint count, GLenum type, GLvoid * indices); -void select_glDrawArrays(GLenum mode, GLuint first, GLuint count); +void select_glDrawElements(const pointer_state_t* vtx, GLenum mode, GLuint count, GLenum type, GLvoid * indices); +void select_glDrawArrays(const pointer_state_t* vtx, GLenum mode, GLuint first, GLuint count); #endif diff --git a/project/jni/glshim/src/gl/stack.c b/project/jni/glshim/src/gl/stack.c index a9aad3ad8..1f3afe624 100755 --- a/project/jni/glshim/src/gl/stack.c +++ b/project/jni/glshim/src/gl/stack.c @@ -6,7 +6,7 @@ glclientstack_t *clientStack = NULL; void glPushAttrib(GLbitfield mask) { //printf("glPushAttrib(0x%04X)\n", mask); noerrorShim(); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { NewStage(state.list.active, STAGE_PUSH); state.list.active->pushattribute = mask; return; @@ -257,6 +257,7 @@ void glPushClientAttrib(GLbitfield mask) { for (a=0; atex_enable[a] = state.enable.tex_coord_array[a]; } + /* memcpy(&cur->verts, &state.pointers.vertex, sizeof(pointer_state_t)); cur->ref_verts = (void*)state.pointers.vertex.pointer; memcpy(&cur->color, &state.pointers.color, sizeof(pointer_state_t)); @@ -269,7 +270,9 @@ void glPushClientAttrib(GLbitfield mask) { memcpy(&cur->tex[a], &state.pointers.tex_coord[a], sizeof(pointer_state_t)); cur->ref_tex[a] = (void*)state.pointers.tex_coord[a].pointer; } - cur->client = state.texture.client; + */ + memcpy(&(cur->pointers), &state.pointers, sizeof(pointer_states_t)); + cur->client = state.texture.client; } clientStack->len++; @@ -289,7 +292,7 @@ void glPushClientAttrib(GLbitfield mask) { void glPopAttrib() { //printf("glPopAttrib()\n"); noerrorShim(); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { NewStage(state.list.active, STAGE_POP); state.list.active->popattribute = true; return; @@ -518,8 +521,9 @@ void glPopClientAttrib() { } } + /* if (state.pointers.vertex.pointer != cur->ref_verts) { - memcpy(&state.pointers.vertex, &cur->verts, sizeof(pointer_state_t)); + memcpy(&state.pointers.vertex, &cur->pointers.verts, sizeof(pointer_state_t)); //if (state.pointers.vertex.pointer) gles_glVertexPointer(state.pointers.vertex.size, state.pointers.vertex.type, state.pointers.vertex.stride, state.pointers.vertex.pointer); } if (state.pointers.color.pointer != cur->ref_colors) { @@ -542,6 +546,8 @@ void glPopClientAttrib() { //} } } + */ + memcpy(&state.pointers, &(cur->pointers), sizeof(pointer_states_t)); if (state.texture.client != cur->client) glClientActiveTexture(GL_TEXTURE0+cur->client); } diff --git a/project/jni/glshim/src/gl/stack.h b/project/jni/glshim/src/gl/stack.h index 87d53d77f..d93815edc 100755 --- a/project/jni/glshim/src/gl/stack.h +++ b/project/jni/glshim/src/gl/stack.h @@ -145,18 +145,19 @@ typedef struct { GLboolean tex_enable[MAX_TEX]; GLboolean normal_enable; GLboolean secondary_enable; - pointer_state_t verts; + pointer_states_t pointers; + /*pointer_state_t verts; pointer_state_t color; pointer_state_t normal; pointer_state_t tex[MAX_TEX]; - pointer_state_t secondary; + pointer_state_t secondary;*/ // lets track old pointer address to avoid useless copy back - GLvoid *ref_verts, + /*GLvoid *ref_verts, *ref_colors, *ref_secondary, *ref_normal, *ref_tex[MAX_TEX]; - + */ unsigned int len; unsigned int cap; } glclientstack_t; diff --git a/project/jni/glshim/src/gl/state.h b/project/jni/glshim/src/gl/state.h index 9c1ea5497..9360891c3 100755 --- a/project/jni/glshim/src/gl/state.h +++ b/project/jni/glshim/src/gl/state.h @@ -127,6 +127,7 @@ typedef struct { GLfloat color[4]; GLfloat secondary[4]; GLfloat texcoord[MAX_TEX][2]; + GLfloat normal[3]; int render_mode; int polygon_mode; namestack_t namestack; @@ -137,6 +138,7 @@ typedef struct { buffers_t buffers; int shim_error; GLenum last_error; + GLuint gl_batch; } glstate_t; #endif diff --git a/project/jni/glshim/src/gl/texgen.c b/project/jni/glshim/src/gl/texgen.c index 0291956ce..7fb394739 100755 --- a/project/jni/glshim/src/gl/texgen.c +++ b/project/jni/glshim/src/gl/texgen.c @@ -22,7 +22,7 @@ void glTexGeni(GLenum coord, GLenum pname, GLint param) { void glTexGenfv(GLenum coord, GLenum pname, const GLfloat *param) { //printf("glTexGenfv(0x%04X, 0x%04X, [%.02f, ...]), texture=%i\n", coord, pname, param[0], state.texture.active); - if (state.list.compiling && state.list.active) { + if ((state.list.compiling || state.gl_batch) && state.list.active) { NewStage(state.list.active, STAGE_TEXGEN); rlTexGenfv(state.list.active, coord, pname, param); noerrorShim(); @@ -65,6 +65,7 @@ void glTexGenfv(GLenum coord, GLenum pname, const GLfloat *param) { */ } void glGetTexGenfv(GLenum coord,GLenum pname,GLfloat *params) { + if (gl_batch) flush(); noerrorShim(); switch(pname) { case GL_TEXTURE_GEN_MODE: @@ -115,10 +116,37 @@ void vector_matrix(const GLfloat *a, const GLfloat *b, GLfloat *c) { } void vector_normalize(GLfloat *a) { +#ifdef __ARM_NEON__ + asm volatile ( + "vld1.32 {d4}, [%0] \n\t" //d4={x0,y0} + "flds s10, [%0, #8] \n\t" //d5[0]={z0} + + "vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4 + "vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1] + "vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5 + + "vmov.f32 d1, d0 \n\t" //d1 = d0 + "vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0) + "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3 +/* "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1 + "vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2 + "vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 */ // 1 iteration should be enough + + "vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4 + "vst1.32 d4, [%0] \n\t" // + "fsts s10, [%0, #8] \n\t" // + + :"+&r"(a): + : "d0", "d1", "d2", "d3", "d4", "d5", "memory" + ); +#else float det=1.0f/sqrtf(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]); a[0]*=det; a[1]*=det; a[2]*=det; +#endif } void matrix_column_row(const GLfloat *a, GLfloat *b) { @@ -161,6 +189,18 @@ void matrix_inverse(const GLfloat *m, GLfloat *r) { for (int i = 0; i < 16; i++) r[i] *= det; } +void matrix_mul(const GLfloat *a, const GLfloat *b, GLfloat *c) { + memset(c, 0, sizeof(GLfloat)*16); +// c = a * b + for (int j=0 ; j<4; ++j) { + for (int i=0 ; i<4; ++i) { + for (int k=0; k<4; ++k) { + c[i*4+j] += a[k*4+j] * b[i*4+k]; + } + } + } +} + void dot_loop(const GLfloat *verts, const GLfloat *params, GLfloat *out, GLint count, GLushort *indices) { for (int i = 0; i < count; i++) { GLushort k = indices?indices[i]:i; @@ -170,10 +210,10 @@ void dot_loop(const GLfloat *verts, const GLfloat *params, GLfloat *out, GLint c void sphere_loop(const GLfloat *verts, const GLfloat *norm, GLfloat *out, GLint count, GLushort *indices) { // based on https://www.opengl.org/wiki/Mathematics_of_glTexGen - if (!norm) { +/* if (!norm) { printf("LIBGL: GL_SPHERE_MAP without Normals\n"); return; - } + }*/ // First get the ModelviewMatrix GLfloat ModelviewMatrix[16], InvModelview[16]; glGetFloatv(GL_MODELVIEW_MATRIX, InvModelview); @@ -189,7 +229,7 @@ void sphere_loop(const GLfloat *verts, const GLfloat *norm, GLfloat *out, GLint GLushort k = indices?indices[i]:i; matrix_vector(ModelviewMatrix, verts+k*3, eye); vector_normalize(eye); - vector_matrix(norm+k*3, InvModelview, eye_norm); + vector_matrix((norm)?(norm+k*3):state.normal, InvModelview, eye_norm); vector_normalize(eye_norm); a=dot(eye, eye_norm)*2.0f; for (int j=0; j<3; j++) diff --git a/project/jni/glshim/src/gl/texgen.h b/project/jni/glshim/src/gl/texgen.h index a4327e1c2..b9d2e3fe9 100755 --- a/project/jni/glshim/src/gl/texgen.h +++ b/project/jni/glshim/src/gl/texgen.h @@ -14,6 +14,7 @@ extern void vector_normalize(GLfloat *a); extern void matrix_column_row(const GLfloat *a, GLfloat *b); extern void matrix_row_column(const GLfloat *a, GLfloat *b); extern void matrix_inverse(const GLfloat *m, GLfloat *r); +extern void matrix_mul(const GLfloat *a, const GLfloat *b, GLfloat *c); extern void glLoadTransposeMatrixf(const GLfloat *m); extern void glLoadTransposeMatrixd(const GLdouble *m); diff --git a/project/jni/glshim/src/gl/texture.c b/project/jni/glshim/src/gl/texture.c index 316a078be..ee6ab8687 100755 --- a/project/jni/glshim/src/gl/texture.c +++ b/project/jni/glshim/src/gl/texture.c @@ -177,6 +177,15 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, //printf("glTexImage2D on target=0x%04X with unpack_row_length(%i), size(%i,%i) and skip(%i,%i), format(internal)=%04x(%04x), type=%04x, data=%08x, level=%i (mipmap_need=%i, mipmap_auto=%i) => texture=%u (streamed=%i)\n", target, state.texture.unpack_row_length, width, height, state.texture.unpack_skip_pixels, state.texture.unpack_skip_rows, format, internalformat, type, data, level, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->mipmap_need:0, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->mipmap_auto:0, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->texture:0, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->streamed:0); + // proxy case + if (target == GL_PROXY_TEXTURE_2D) { + proxy_width = ((width<2048)?0:width; + proxy_height = ((height<2048)?0:height; + return; + } + //PUSH_IF_COMPILING(glTexImage2D); + if (state.gl_batch) flush(); + GLvoid *datab = (GLvoid*)data; if (state.buffers.unpack) @@ -185,13 +194,6 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLvoid *pixels = (GLvoid *)datab; border = 0; //TODO: something? noerrorShim(); - // proxy case - if (target == GL_PROXY_TEXTURE_2D) { - proxy_width = ((width<2048)?0:width; - proxy_height = ((height<2048)?0:height; - return; - } - PUSH_IF_COMPILING(glTexImage2D); if (!tested_env) { char *env_mipmap = getenv("LIBGL_MIPMAP"); @@ -229,6 +231,14 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, texshrink = 4; printf("LIBGL: Texture shink, mode 4 selected (only > 256 /2, >=1024 /4 )\n"); } + if (env_shrink && strcmp(env_shrink, "5") == 0) { + texshrink = 5; + printf("LIBGL: Texture shink, mode 5 selected (every > 256 is downscaled to 256 )\n"); + } + if (env_shrink && strcmp(env_shrink, "6") == 0) { + texshrink = 6; + printf("LIBGL: Texture shink, mode 6 selected (only > 128 /2, >=512 is downscaled to 256 )\n"); + } char *env_dump = getenv("LIBGL_TEXDUMP"); if (env_dump && strcmp(env_dump, "1") == 0) { texdump = 1; @@ -314,7 +324,7 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, } if (bound && (texshrink==4)) { if (((width > 256) && (height > 8)) || ((height > 256) && (width > 8))) { - if ((texshrink==4) && ((width>=1024) || (height>=1024))) { + if ((width>=1024) || (height>=1024)) { GLvoid *out = pixels; pixel_quarterscale(pixels, &out, width, height, format, type); if (out != pixels && pixels!=datab) @@ -335,6 +345,43 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, } } } + if (bound && (texshrink==5)) { + while (((width > 256) && (height > 8)) || ((height > 256) && (width > 8))) { + GLvoid *out = pixels; + pixel_halfscale(pixels, &out, width, height, format, type); + if (out != pixels && pixels!=datab) + free(pixels); + pixels = out; + width /= 2; + height /= 2; + bound->shrink++; + } + } + if (bound && (texshrink==6)) { + if (((width > 128) && (height > 8)) || ((height > 128) && (width > 8))) { + if ((width>=512) || (height>=512)) { + while (((width > 256) && (height > 8)) || ((height > 256) && (width > 8))) { + GLvoid *out = pixels; + pixel_halfscale(pixels, &out, width, height, format, type); + if (out != pixels && pixels!=datab) + free(pixels); + pixels = out; + width /= 2; + height /= 2; + bound->shrink++; + } + } else { + GLvoid *out = pixels; + pixel_halfscale(pixels, &out, width, height, format, type); + if (out != pixels && pixels!=datab) + free(pixels); + pixels = out; + width /= 2; + height /= 2; + bound->shrink = 1; + } + } + } if (texdump) { if (bound) { @@ -455,11 +502,14 @@ void glTexImage2D(GLenum target, GLint level, GLint internalformat, void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) { + + //PUSH_IF_COMPILING(glTexSubImage2D); + if (state.gl_batch) flush(); + GLvoid *datab = (GLvoid*)data; if (state.buffers.unpack) datab += (uintptr_t)state.buffers.pack->data; GLvoid *pixels = (GLvoid*)datab; - PUSH_IF_COMPILING(glTexSubImage2D); LOAD_GLES(glTexSubImage2D); LOAD_GLES(glTexParameteri); @@ -683,7 +733,7 @@ GLboolean glIsTexture( GLuint texture) { void glBindTexture(GLenum target, GLuint texture) { noerrorShim(); - if ((target!=GL_PROXY_TEXTURE_2D) && (state.list.compiling && state.list.active)) { + if ((target!=GL_PROXY_TEXTURE_2D) && ((state.list.compiling || state.gl_batch) && state.list.active)) { // check if already a texture binded, if yes, create a new list NewStage(state.list.active, STAGE_BINDTEX); rlBindTexture(state.list.active, target, texture); @@ -835,6 +885,7 @@ void glTexParameterf(GLenum target, GLenum pname, GLfloat param) { } void glDeleteTextures(GLsizei n, const GLuint *textures) { + if (state.gl_batch) flush(); noerrorShim(); LOAD_GLES(glDeleteTextures); khash_t(tex) *list = state.texture.list; @@ -874,6 +925,7 @@ void glDeleteTextures(GLsizei n, const GLuint *textures) { void glGenTextures(GLsizei n, GLuint * textures) { if (n<=0) return; + if (state.gl_batch) flush(); LOAD_GLES(glGenTextures); gles_glGenTextures(n, textures); errorGL(); @@ -923,6 +975,7 @@ GLboolean glAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *re void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) { // simplification: not taking "target" into account here + if (state.gl_batch) flush(); *params = 0; noerrorShim(); gltexture_t* bound = state.texture.bound[state.texture.active]; @@ -976,6 +1029,7 @@ void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *p extern GLuint current_fb; // from framebuffers.c void glGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid * img) { + if (state.gl_batch) flush(); if (state.texture.bound[state.texture.active]==NULL) return; // no texture bounded... if (level != 0) { @@ -1050,9 +1104,14 @@ void glClientActiveTexture( GLenum texture ) { void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * data) { //printf("glReadPixels(%i, %i, %i, %i, 0x%04X, 0x%04X, 0x%p)\n", x, y, width, height, format, type, data); + GLuint old_glbatch = state.gl_batch; + if (state.gl_batch) { + flush(); + state.gl_batch = 0; + } if (state.list.compiling && state.list.active) { errorShim(GL_INVALID_OPERATION); - return; // never in list + return; // never in list } LOAD_GLES(glReadPixels); errorGL(); @@ -1062,28 +1121,31 @@ void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format readfboBegin(); if (format == GL_RGBA && format == GL_UNSIGNED_BYTE) { - // easy passthru - gles_glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst); - readfboEnd(); - return; + // easy passthru + gles_glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst); + readfboEnd(); + state.gl_batch = old_glbatch; + return; } // grab data in GL_RGBA format GLvoid *pixels = malloc(width*height*4); gles_glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); if (! pixel_convert(pixels, &dst, width, height, GL_RGBA, GL_UNSIGNED_BYTE, format, type, 0)) { - printf("libGL ReadPixels error: (GL_RGBA, UNSIGNED_BYTE -> %#4x, %#4x )\n", - format, type); + printf("libGL ReadPixels error: (GL_RGBA, UNSIGNED_BYTE -> %#4x, %#4x )\n", + format, type); } free(pixels); readfboEnd(); + state.gl_batch = old_glbatch; return; } void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { //printf("glCopyTexSubImage2D(%i, %i, %i, %i, %i, %i, %i, %i), bounded texture=%u format/type=0x%04X, 0x%04X\n", target, level, xoffset, yoffset, x, y, width, height, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->texture:0, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->format:0, (state.texture.bound[state.texture.active])?state.texture.bound[state.texture.active]->type:0); - PUSH_IF_COMPILING(glCopyTexSubImage2D); +// PUSH_IF_COMPILING(glCopyTexSubImage2D); +if (state.gl_batch) flush(); LOAD_GLES(glCopyTexSubImage2D); errorGL(); @@ -1128,7 +1190,13 @@ void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffse void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { //printf("glCopyTexImage2D(0x%04X, %i, 0x%04X, %i, %i, %i, %i, %i), current_fb=%u\n", target, level, internalformat, x, y, width, height, border, current_fb); - PUSH_IF_COMPILING(glCopyTexImage2D); + //PUSH_IF_COMPILING(glCopyTexImage2D); + GLuint old_glbatch = state.gl_batch; + if (state.gl_batch) { + flush(); + state.gl_batch = 0; + } + errorGL(); // "Unmap" if buffer mapped... @@ -1145,6 +1213,8 @@ void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLin // "Remap" if buffer mapped... state.buffers.pack = pack; state.buffers.unpack = unpack; + + state.gl_batch = old_glbatch; } @@ -1215,6 +1285,8 @@ void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, proxy_height = (height>2048)?0:height; return; } + if (state.gl_batch) flush(); + if (state.texture.bound[state.texture.active]==NULL) { errorShim(GL_INVALID_OPERATION); return; // no texture bounded... @@ -1291,6 +1363,8 @@ void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) { + if (state.gl_batch) flush(); + if (state.texture.bound[state.texture.active]==NULL) { errorShim(GL_INVALID_OPERATION); return; // no texture bounded... @@ -1349,6 +1423,8 @@ void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint } void glGetCompressedTexImage(GLenum target, GLint lod, GLvoid *img) { + if (state.gl_batch) flush(); + printf("LIBGL: Stub GetCompressedTexImage\n"); errorShim(GL_INVALID_OPERATION); diff --git a/project/jni/glshim/src/gl/wrap/gl.c b/project/jni/glshim/src/gl/wrap/gl.c index 1d45d94d2..7bfe05c41 100755 --- a/project/jni/glshim/src/gl/wrap/gl.c +++ b/project/jni/glshim/src/gl/wrap/gl.c @@ -752,6 +752,9 @@ void glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenu state.buffers.elements = elements; } +void glDrawRangeElementsEXT(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const void *indices) { + glDrawRangeElements(mode, start, end, count, type, indices); +} void glBlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha) { // ignore buf is better than nothing... // TODO: handle buf diff --git a/project/jni/glshim/src/glx/glx.c b/project/jni/glshim/src/glx/glx.c index 6d7bc3c6d..93a69f7ee 100755 --- a/project/jni/glshim/src/glx/glx.c +++ b/project/jni/glshim/src/glx/glx.c @@ -1,6 +1,4 @@ -#ifndef ANDROID #include -#endif #include #include #include @@ -233,7 +231,8 @@ static void scan_env() { if (! first) return; /* Check for some corruption inside state.... */ - if ((state.texture.active < 0) || (state.texture.active > MAX_TEX)) { + if ((state.texture.active < 0) || (state.texture.active > MAX_TEX) || + (state.pointers.vertex.buffer!= 0) || (state.buffers.vertex != 0)) { printf("LIBGL: Warning, memory corruption detected at init, trying to compensate\n"); initialize_glshim(); } @@ -572,7 +571,10 @@ void glXSwapBuffers(Display *display, static int frames = 0; LOAD_EGL(eglSwapBuffers); - + if (gl_batch){ + flush(); + } + if (g_vsync && fbdev >= 0) { // TODO: can I just return if I don't meet vsync over multiple frames? // this will just block otherwise. @@ -586,6 +588,7 @@ void glXSwapBuffers(Display *display, blitMainFBO(); // blit the main_fbo before swap } + egl_eglSwapBuffers(eglDisplay, eglSurface); CheckEGLErrors();