Merge branch 'sdl_android' of github.com:pelya/commandergenius into sdl_android

This commit is contained in:
Sergii Pylypenko
2015-02-17 22:36:59 +02:00
19 changed files with 902 additions and 277 deletions

View File

@@ -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

5
project/jni/glshim/CMakeLists.txt Normal file → Executable file
View File

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

View File

@@ -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

View File

@@ -1,4 +1,5 @@
#include "framebuffers.h"
#ifndef ANDROID
#include <execinfo.h>
#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();

View File

@@ -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; i<list->len*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<MAX_TEX; aa++)
shift_pointer(tex_coord[aa], tex_coord_array[aa]);
shift_pointer(normal, normal_array);
#undef shift_pointer
if (state.polygon_mode == GL_LINE && mode>=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; aa<MAX_TEX; aa++) {
shift_pointer(tex_coord[aa], tex_coord_array[aa]);
}
shift_pointer(normal, normal_array);
#undef shift_pointer
GLenum mode_init = mode;
if (mode == GL_QUAD_STRIP)
mode = GL_TRIANGLE_STRIP;
@@ -715,7 +730,7 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
mode = GL_TRIANGLE_FAN;
if (state.render_mode == GL_SELECT) {
select_glDrawArrays(mode, first, count);
select_glDrawArrays(&state.pointers.vertex, mode, first, count);
} else {
// setup the Array Pointers
// secondary color...
@@ -727,7 +742,8 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
final_colors[i]+=seconds_colors[i];
gles_glColorPointer(4, GL_FLOAT, 0, final_colors);
free(seconds_colors);
} else if (state.enable.color_array && (state.pointers.color.size != 4)) {
} else if ((state.enable.color_array && (state.pointers.color.size != 4))
|| (state.enable.color_array && (state.pointers.color.stride!=0) && (state.pointers.color.type != GL_FLOAT))) {
// Pandora doesn't like Color Pointer with size != 4
final_colors=copy_gl_pointer_color(&state.pointers.color, 4, 0, count+first, 0);
gles_glColorPointer(4, GL_FLOAT, 0, final_colors);
@@ -783,11 +799,7 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
// secondary color
if (final_colors) {
free(final_colors);
//gles_glColorPointer(old_color.size, old_color.type, old_color.stride, old_color.pointer);
}
}
}
// if (state.buffers.vertex) {
#define shift_pointer(a, b) \
if (state.enable.b && state.pointers.a.buffer) state.pointers.a.pointer = state.pointers.a.pointer - (uintptr_t)state.pointers.a.buffer->data;
@@ -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; a<MAX_TEX; a++)
if (state.enable.texture_2d[a] && (state.list.active->tex[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);
}

View File

@@ -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;
}

View File

@@ -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; a<MAX_TEX; a++)
list->tex[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; i<MAX_TEX; i++)
if ((a->tex[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; i<ilen; i++) {
a->indices[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; i<ilen-1; i++) {
a->indices[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; i<ilen; i++) {
a->indices[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; i<len; i++) {
a->indices[(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; i<len; i++) {
a->indices[(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; i<len; i+=4) {
a->indices[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; i<MAX_TEX; i++)
realloc_sublist(a->tex[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; i<MAX_TEX; i++)
if (a->tex[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; i<b->ilen; 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; i<ilen; i+=3) {
ind_line[k++] = indices[i+0]; ind_line[k++] = indices[i+1];
ind_line[k++] = indices[i+1]; ind_line[k++] = indices[i+2];
ind_line[k++] = indices[i+2]; ind_line[k++] = indices[i+0];
}
break;
case GL_TRIANGLE_STRIP:
n = 3;
s = 1;
// first 3 points a triangle, then a 2 lines per new point
if (ilen>2) {
ind_line[k++] = indices[0]; ind_line[k++] = indices[1];
}
for (int i = 2; i<ilen; i++) {
ind_line[k++] = indices[i-2]; ind_line[k++] = indices[i];
ind_line[k++] = indices[i-1]; ind_line[k++] = indices[i];
}
break;
case GL_TRIANGLE_FAN: // wrong here...
n = list->ilen;
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; i<ilen; i++) {
ind_line[k++] = indices[0]; ind_line[k++] = indices[i];
ind_line[k++] = indices[i-1]; ind_line[k++] = indices[i];
}
break;
case GL_QUADS:
n = 4;
s = 4;
// 4 lines per quads, but dest may already be a triangles list...
if (list->mode == 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; i<ilen; i+=6) {
ind_line[k++] = indices[i+0]; ind_line[k++] = indices[i+1];
ind_line[k++] = indices[i+1]; ind_line[k++] = indices[i+2];
ind_line[k++] = indices[i+2]; ind_line[k++] = indices[i+5];
ind_line[k++] = indices[i+5]; ind_line[k++] = indices[i+0];
}
}
break;
case GL_QUAD_STRIP:
n = 4;
s = 1;
// first 4 points is a quad, then 2 points per new quad
if (ilen>2) {
ind_line[k++] = indices[0]; ind_line[k++] = indices[1];
}
for (int i = 2; i<ilen; i+=2) {
ind_line[k++] = indices[i-1]; ind_line[k++] = indices[i];
ind_line[k++] = indices[i-2]; ind_line[k++] = indices[i+1];
ind_line[k++] = indices[i+0]; ind_line[k++] = indices[i+1];
}
break;
default: // Polygon and other?
n = list->ilen;
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; i<ilen; i++) {
ind_line[k++] = indices[i-1]; ind_line[k++] = indices[i];
}
if (ilen) {
ind_line[k++] = indices[ilen-1]; ind_line[k++] = indices[0];
}
break;
}
int k = 0;
for (int i=n; i<=list->ilen; 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; j<n; j++)
ind_line[k++]=i-n+j;
//gles_glDrawArrays(mode, i-n, n);
switch (list->mode_init) {
case GL_TRIANGLES:
// 1 triangle -> 3 lines
for (int i = 0; i<len; i+=3) {
ind_line[k++] = i+0; ind_line[k++] = i+1;
ind_line[k++] = i+1; ind_line[k++] = i+2;
ind_line[k++] = i+2; ind_line[k++] = i+0;
}
break;
case GL_TRIANGLE_STRIP:
// first 3 points a triangle, then a 2 lines per new point
if (len>2) {
ind_line[k++] = 0; ind_line[k++] = 1;
}
for (int i = 2; i<len; i++) {
ind_line[k++] = i-2; ind_line[k++] = i;
ind_line[k++] = i-1; ind_line[k++] = i;
}
break;
case GL_TRIANGLE_FAN:
// first 3 points a triangle, then a 2 lines per new point too
if (len>2) {
ind_line[k++] = 0; ind_line[k++] = 1;
}
for (int i = 2; i<len; i++) {
ind_line[k++] = 0; ind_line[k++] = i;
ind_line[k++] = i-1; ind_line[k++] = i;
}
break;
case GL_QUADS:
// 4 lines per quads, QUAD without indices means 1 single quad
if (list->mode == 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; i<len; i+=2) {
ind_line[k++] = i-1; ind_line[k++] = i;
ind_line[k++] = i-2; ind_line[k++] = i+1;
ind_line[k++] = i+0; ind_line[k++] = i+1;
}
break;
case GL_POLYGON:
// if polygons have been merged, then info is lost...
if (len) {
ind_line[k++] = 0; ind_line[k++] = 1;
}
for (int i = 1; i<len; i++) {
ind_line[k++] = i-1; ind_line[k++] = i;
}
if (len) {
ind_line[k++] = len-1; ind_line[k++] = 0;
}
break;
}
gles_glDrawElements(mode, k, GL_UNSIGNED_SHORT, ind_line);
} else {
gles_glDrawArrays(mode, 0, len);
@@ -739,6 +1082,13 @@ void rlBindTexture(renderlist_t *list, GLenum target, GLuint texture) {
list->set_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) {

View File

@@ -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

View File

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

View File

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

View File

@@ -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

View File

@@ -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; a<MAX_TEX; a++) {
cur->tex_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);
}

View File

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

View File

@@ -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

View File

@@ -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++)

View File

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

View File

@@ -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<<level)>2048)?0:width;
proxy_height = ((height<<level)>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<<level)>2048)?0:width;
proxy_height = ((height<<level)>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);

View File

@@ -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

View File

@@ -1,6 +1,4 @@
#ifndef ANDROID
#include <execinfo.h>
#endif
#include <fcntl.h>
#include <linux/fb.h>
#include <signal.h>
@@ -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();