Merge branch 'sdl_android' of github.com:pelya/commandergenius into sdl_android
This commit is contained in:
@@ -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
5
project/jni/glshim/CMakeLists.txt
Normal file → Executable 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user