diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt index b354590..bf0eb2d 100644 --- a/src/main/cpp/CMakeLists.txt +++ b/src/main/cpp/CMakeLists.txt @@ -53,6 +53,7 @@ add_library(${CMAKE_PROJECT_NAME} SHARED config/settings.cpp gl/glsl/glslconv_gl4es.cpp + gl/gl4es/gl/vgpu/shaderconv.c gl/gl4es/gl/string_utils.c gl/gl4es/gl/arbconverter.c gl/gl4es/gl/arbgenerator.c diff --git a/src/main/cpp/gl/framebuffer.cpp b/src/main/cpp/gl/framebuffer.cpp index 05144dd..deaa001 100644 --- a/src/main/cpp/gl/framebuffer.cpp +++ b/src/main/cpp/gl/framebuffer.cpp @@ -350,6 +350,13 @@ EXPORT void glFramebufferTexture3DARB(GLenum target, GLenum attachment, EXPORT void glDrawBuffersARB(GLsizei n, const GLenum *bufs) { glDrawBuffers(n, bufs); } - - +EXPORT void glFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, + GLuint texture, GLint level) { + glFramebufferTexture2D(target, attachment, GL_TEXTURE_2D, texture, level); +} +EXPORT void glFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, + GLuint texture, GLint level, GLint zoffset) { + LOG() + GLES.glFramebufferTexture3DOES(target, attachment, textarget, texture, level, zoffset); +} } \ No newline at end of file diff --git a/src/main/cpp/gl/gl4es/gl/framebuffers.c b/src/main/cpp/gl/gl4es/gl/framebuffers.c index 4c70729..fefa1f1 100644 --- a/src/main/cpp/gl/gl4es/gl/framebuffers.c +++ b/src/main/cpp/gl/gl4es/gl/framebuffers.c @@ -1497,7 +1497,7 @@ void APIENTRY_GL4ES gl4es_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX memcpy(vp, &glstate->raster.viewport, sizeof(vp)); gl4es_glViewport(0, 0, fbowidth, fboheight); // TODO: Handle the conflict between Core Profile with Compatibility Profile - gl4es_blitTexture(glname, srcX0, srcY0, srcW, srcH, nwidth, nheight, zoomx, zoomy, 0, 0, dstX0, dstY0, BLIT_OPAQUE); + //gl4es_blitTexture(glname, srcX0, srcY0, srcW, srcH, nwidth, nheight, zoomx, zoomy, 0, 0, dstX0, dstY0, BLIT_OPAQUE); gl4es_glViewport(vp[0], vp[1], vp[2], vp[3]); if(created) { gl4es_glDeleteTextures(1, &texture); diff --git a/src/main/cpp/gl/gl4es/gl/gl4es.c b/src/main/cpp/gl/gl4es/gl/gl4es.c index ca814b2..d567633 100644 --- a/src/main/cpp/gl/gl4es/gl/gl4es.c +++ b/src/main/cpp/gl/gl4es/gl/gl4es.c @@ -17,6 +17,7 @@ #include "loader.h" #include "matrix.h" #include "buffers.h" +#include "vgpu/shaderconv.h" #ifdef _WIN32 #ifdef _WINBASE_ #define GSM_CAST(c) ((LPFILETIME)c) diff --git a/src/main/cpp/gl/gl4es/gl/gl4es.h b/src/main/cpp/gl/gl4es/gl/gl4es.h index e692c74..8de2df2 100644 --- a/src/main/cpp/gl/gl4es/gl/gl4es.h +++ b/src/main/cpp/gl/gl4es/gl/gl4es.h @@ -122,6 +122,7 @@ static inline void errorGL() { // next glGetError will be from GL glstate->type_error = 1; // will need to read glGetError... } static inline void errorShim(GLenum error) { // next glGetError will be "error" from gl4es + DBG(LOGD(" -> error set: %d", error)) if(glstate->type_error && glstate->shim_error==GL_NO_ERROR) glstate->type_error = 1; if(glstate->shim_error == GL_NO_ERROR) diff --git a/src/main/cpp/gl/gl4es/gl/init.c b/src/main/cpp/gl/gl4es/gl/init.c index b909a17..1f9314c 100644 --- a/src/main/cpp/gl/gl4es/gl/init.c +++ b/src/main/cpp/gl/gl4es/gl/init.c @@ -425,11 +425,14 @@ void initialize_gl4es() { globals4es.nointovlhack = 1; SHUT_LOGD("MobileGlues-gl4es: No hack in shader converter to define overloaded function with int\n"); } + globals4es.nointovlhack = 1; if(GL4ES_IsEnvVarTrue("LIBGL_NOSHADERLOD")) { globals4es.noshaderlod = 1; SHUT_LOGD("MobileGlues-gl4es: No GL_EXT_shader_texture_lod used even if present\n"); hardext.shaderlod=0; } + hardext.shaderlod=0; + globals4es.noshaderlod = 1; int env_begin_end; if(GL4ES_GetEnvVarInt("LIBGL_BEGINEND",&env_begin_end,0)) { @@ -618,7 +621,7 @@ void initialize_gl4es() { env(LIBGL_SHADERNOGLES, globals4es.shadernogles, "Remove GLES part in shader"); env(LIBGL_NOES2COMPAT, globals4es.noes2, "Don't expose GLX_EXT_create_context_es2_profile extension"); env(LIBGL_NORMALIZE, globals4es.normalize, "Force normals to be normalized on FPE shaders"); - + globals4es.normalize=1; globals4es.dbgshaderconv=GL4ES_ReturnEnvVarIntDef("LIBGL_DBGSHADERCONV",0); if(globals4es.dbgshaderconv) { if(globals4es.dbgshaderconv==1) diff --git a/src/main/cpp/gl/gl4es/gl/program.c b/src/main/cpp/gl/gl4es/gl/program.c index 1a82197..7646a32 100644 --- a/src/main/cpp/gl/gl4es/gl/program.c +++ b/src/main/cpp/gl/gl4es/gl/program.c @@ -11,7 +11,7 @@ #include "shaderconv.h" #include "fpe_shader.h" -//#define DEBUG +#define DEBUG #ifdef DEBUG #define DBG(a) a #else @@ -46,11 +46,12 @@ void APIENTRY_GL4ES gl4es_glAttachShader(GLuint program, GLuint shader) { // send to hadware LOAD_GLES2(glAttachShader); if(gl4es_gles_glAttachShader) { - if(strstr((glshader->converted)?glshader->converted:glshader->source, "FPE")!=NULL) { - gl4es_gles_glAttachShader(glprogram->id, glshader->id); + if(glshader->is_gl4es_conv_shader) { +// gl4es_gles_glAttachShader(glprogram->id, glshader->id); + gl4es_gles_glAttachShader(program, glshader->id); + // use fronted program id? } - - {} //STUB of gl4es_gles_glAttachShader(glprogram->id, glshader->id); + errorGL(); } else noerrorShim(); @@ -795,10 +796,8 @@ void APIENTRY_GL4ES gl4es_glLinkProgram(GLuint program) { if(gl4es_gles_glLinkProgram) { LOAD_GLES(glGetError); LOAD_GLES2(glGetProgramiv); - if(strstr((glprogram->last_vert->converted)?glprogram->last_vert->converted:glprogram->last_vert->source, "FPE")!=NULL) { - gl4es_gles_glLinkProgram(glprogram->id); - } - {} //STUB of gl4es_gles_glLinkProgram(glprogram->id); + + gl4es_gles_glLinkProgram(glprogram->id); GLenum err = gl4es_gles_glGetError(); // Get Link Status gl4es_gles_glGetProgramiv(glprogram->id, GL_LINK_STATUS, &glprogram->linked); diff --git a/src/main/cpp/gl/gl4es/gl/shader.c b/src/main/cpp/gl/gl4es/gl/shader.c index fc03441..719354d 100644 --- a/src/main/cpp/gl/gl4es/gl/shader.c +++ b/src/main/cpp/gl/gl4es/gl/shader.c @@ -8,7 +8,7 @@ #include "loader.h" #include "shaderconv.h" -//#define DEBUG +#define DEBUG #ifdef DEBUG #define DBG(a) a #else @@ -110,7 +110,8 @@ void APIENTRY_GL4ES gl4es_glDeleteShader(GLuint shader) { LOAD_GLES2(glDeleteShader); if(gl4es_gles_glDeleteShader) { errorGL(); - {} //STUB of gl4es_gles_glDeleteShader(shader); + if(glshader->is_gl4es_conv_shader) + gl4es_gles_glDeleteShader(shader); } } } @@ -123,10 +124,8 @@ void APIENTRY_GL4ES gl4es_glCompileShader(GLuint shader) { glshader->compiled = 1; LOAD_GLES2(glCompileShader); if(gl4es_gles_glCompileShader) { - {} //STUB of gl4es_gles_glCompileShader(glshader->id); - if(strstr((glshader->converted)?glshader->converted:glshader->source, "FPE")!=NULL) { - gl4es_gles_glCompileShader(glshader->id); - } + gl4es_gles_glCompileShader(glshader->id); + errorGL(); if(globals4es.logshader) { // get compile status and print shaders sources if compile fail... @@ -178,9 +177,15 @@ void APIENTRY_GL4ES gl4es_glShaderSource(GLuint shader, GLsizei count, const GLc if(glstate->glsl->es2 && !strncmp(glshader->source, "#version 100", 12)) glshader->converted = strdup(glshader->source); else - glshader->converted = ConvertShader(glshader->source, glshader->type==GL_VERTEX_SHADER?1:0, &glshader->need); + glshader->converted = strdup(ConvertShaderConditionally(glshader)); // send source to GLES2 hardware if any - if(strstr((glshader->converted)?glshader->converted:glshader->source, "FPE")!=NULL) { + int getGLSLVersion(const char* glsl_code); + SHUT_LOGD("shader version: %d",getGLSLVersion(glshader->source)) + SHUT_LOGD("\nshader source: %s\n",glshader->source) + glshader->is_gl4es_conv_shader=0; + if(getGLSLVersion(glshader->source) < 140 || strstr((glshader->converted)?glshader->converted:glshader->source, "FPE")!=NULL) { + glshader->is_gl4es_conv_shader=1; + SHUT_LOGD("\nconverted and used in gl4es:\n%s\n",glshader->converted); gl4es_gles_glShaderSource(shader, 1, (const GLchar * const*)((glshader->converted)?(&glshader->converted):(&glshader->source)), NULL); } errorGL(); @@ -237,7 +242,7 @@ void redoShader(GLuint shader, shaderconv_need_t *need) { return; free(glshader->converted); memcpy(&glshader->need, need, sizeof(shaderconv_need_t)); - glshader->converted = ConvertShader(glshader->source, glshader->type==GL_VERTEX_SHADER?1:0, &glshader->need); + glshader->converted = ConvertShaderConditionally(glshader); // send source to GLES2 hardware if any gl4es_gles_glShaderSource(shader, 1, (const GLchar * const*)((glshader->converted)?(&glshader->converted):(&glshader->source)), NULL); // recompile... diff --git a/src/main/cpp/gl/gl4es/gl/shader.h b/src/main/cpp/gl/gl4es/gl/shader.h index e080eee..4d16b14 100644 --- a/src/main/cpp/gl/gl4es/gl/shader.h +++ b/src/main/cpp/gl/gl4es/gl/shader.h @@ -35,6 +35,7 @@ struct shader_s { char* converted; // converted source (or null if nothing) // shaderconv shaderconv_need_t need; // the varying need / provide of the shader + int is_gl4es_conv_shader; }; // shader_t defined in oldprogram.h KHASH_MAP_DECLARE_INT(shaderlist, struct shader_s *); diff --git a/src/main/cpp/gl/gl4es/gl/shaderconv.c b/src/main/cpp/gl/gl4es/gl/shaderconv.c index f6dbbc1..982fa10 100644 --- a/src/main/cpp/gl/gl4es/gl/shaderconv.c +++ b/src/main/cpp/gl/gl4es/gl/shaderconv.c @@ -19,51 +19,51 @@ typedef struct { } builtin_attrib_t; const builtin_attrib_t builtin_attrib[] = { - {"gl_Vertex", "_gl4es_Vertex", "vec4", "highp", ARB_VERTEX}, - {"gl_Color", "_gl4es_Color", "vec4", "lowp", ARB_COLOR}, - {"gl_MultiTexCoord0", "_gl4es_MultiTexCoord0", "vec4", "highp", ARB_MULTITEXCOORD0}, - {"gl_MultiTexCoord1", "_gl4es_MultiTexCoord1", "vec4", "highp", ARB_MULTITEXCOORD1}, - {"gl_MultiTexCoord2", "_gl4es_MultiTexCoord2", "vec4", "highp", ARB_MULTITEXCOORD2}, - {"gl_MultiTexCoord3", "_gl4es_MultiTexCoord3", "vec4", "highp", ARB_MULTITEXCOORD3}, - {"gl_MultiTexCoord4", "_gl4es_MultiTexCoord4", "vec4", "highp", ARB_MULTITEXCOORD4}, - {"gl_MultiTexCoord5", "_gl4es_MultiTexCoord5", "vec4", "highp", ARB_MULTITEXCOORD5}, - {"gl_MultiTexCoord6", "_gl4es_MultiTexCoord6", "vec4", "highp", ARB_MULTITEXCOORD6}, - {"gl_MultiTexCoord7", "_gl4es_MultiTexCoord7", "vec4", "highp", ARB_MULTITEXCOORD7}, - {"gl_MultiTexCoord8", "_gl4es_MultiTexCoord8", "vec4", "highp", ARB_MULTITEXCOORD8}, - {"gl_MultiTexCoord9", "_gl4es_MultiTexCoord9", "vec4", "highp", ARB_MULTITEXCOORD9}, - {"gl_MultiTexCoord10", "_gl4es_MultiTexCoord10", "vec4", "highp", ARB_MULTITEXCOORD10}, - {"gl_MultiTexCoord11", "_gl4es_MultiTexCoord11", "vec4", "highp", ARB_MULTITEXCOORD11}, - {"gl_MultiTexCoord12", "_gl4es_MultiTexCoord12", "vec4", "highp", ARB_MULTITEXCOORD12}, - {"gl_MultiTexCoord13", "_gl4es_MultiTexCoord13", "vec4", "highp", ARB_MULTITEXCOORD13}, - {"gl_MultiTexCoord14", "_gl4es_MultiTexCoord14", "vec4", "highp", ARB_MULTITEXCOORD14}, - {"gl_MultiTexCoord15", "_gl4es_MultiTexCoord15", "vec4", "highp", ARB_MULTITEXCOORD15}, - {"gl_SecondaryColor", "_gl4es_SecondaryColor", "vec4", "lowp", ARB_SECONDARY}, - {"gl_Normal", "_gl4es_Normal", "vec3", "highp", ARB_NORMAL}, - {"gl_FogCoord", "_gl4es_FogCoord", "float", "highp", ARB_FOGCOORD} + {"gl_Vertex", "_gl4es_Vertex", "vec4", "highp", ARB_VERTEX}, + {"gl_Color", "_gl4es_Color", "vec4", "lowp", ARB_COLOR}, + {"gl_MultiTexCoord0", "_gl4es_MultiTexCoord0", "vec4", "highp", ARB_MULTITEXCOORD0}, + {"gl_MultiTexCoord1", "_gl4es_MultiTexCoord1", "vec4", "highp", ARB_MULTITEXCOORD1}, + {"gl_MultiTexCoord2", "_gl4es_MultiTexCoord2", "vec4", "highp", ARB_MULTITEXCOORD2}, + {"gl_MultiTexCoord3", "_gl4es_MultiTexCoord3", "vec4", "highp", ARB_MULTITEXCOORD3}, + {"gl_MultiTexCoord4", "_gl4es_MultiTexCoord4", "vec4", "highp", ARB_MULTITEXCOORD4}, + {"gl_MultiTexCoord5", "_gl4es_MultiTexCoord5", "vec4", "highp", ARB_MULTITEXCOORD5}, + {"gl_MultiTexCoord6", "_gl4es_MultiTexCoord6", "vec4", "highp", ARB_MULTITEXCOORD6}, + {"gl_MultiTexCoord7", "_gl4es_MultiTexCoord7", "vec4", "highp", ARB_MULTITEXCOORD7}, + {"gl_MultiTexCoord8", "_gl4es_MultiTexCoord8", "vec4", "highp", ARB_MULTITEXCOORD8}, + {"gl_MultiTexCoord9", "_gl4es_MultiTexCoord9", "vec4", "highp", ARB_MULTITEXCOORD9}, + {"gl_MultiTexCoord10", "_gl4es_MultiTexCoord10", "vec4", "highp", ARB_MULTITEXCOORD10}, + {"gl_MultiTexCoord11", "_gl4es_MultiTexCoord11", "vec4", "highp", ARB_MULTITEXCOORD11}, + {"gl_MultiTexCoord12", "_gl4es_MultiTexCoord12", "vec4", "highp", ARB_MULTITEXCOORD12}, + {"gl_MultiTexCoord13", "_gl4es_MultiTexCoord13", "vec4", "highp", ARB_MULTITEXCOORD13}, + {"gl_MultiTexCoord14", "_gl4es_MultiTexCoord14", "vec4", "highp", ARB_MULTITEXCOORD14}, + {"gl_MultiTexCoord15", "_gl4es_MultiTexCoord15", "vec4", "highp", ARB_MULTITEXCOORD15}, + {"gl_SecondaryColor", "_gl4es_SecondaryColor", "vec4", "lowp", ARB_SECONDARY}, + {"gl_Normal", "_gl4es_Normal", "vec3", "highp", ARB_NORMAL}, + {"gl_FogCoord", "_gl4es_FogCoord", "float", "highp", ARB_FOGCOORD} }; const builtin_attrib_t builtin_attrib_compressed[] = { - {"gl_Vertex", "_gl4es_Vertex", "vec4", "highp", COMP_VERTEX}, - {"gl_Color", "_gl4es_Color", "vec4", "lowp", COMP_COLOR}, - {"gl_MultiTexCoord0", "_gl4es_MultiTexCoord0", "vec4", "highp", COMP_MULTITEXCOORD0}, - {"gl_MultiTexCoord1", "_gl4es_MultiTexCoord1", "vec4", "highp", COMP_MULTITEXCOORD1}, - {"gl_MultiTexCoord2", "_gl4es_MultiTexCoord2", "vec4", "highp", COMP_MULTITEXCOORD2}, - {"gl_MultiTexCoord3", "_gl4es_MultiTexCoord3", "vec4", "highp", COMP_MULTITEXCOORD3}, - {"gl_MultiTexCoord4", "_gl4es_MultiTexCoord4", "vec4", "highp", COMP_MULTITEXCOORD4}, - {"gl_MultiTexCoord5", "_gl4es_MultiTexCoord5", "vec4", "highp", COMP_MULTITEXCOORD5}, - {"gl_MultiTexCoord6", "_gl4es_MultiTexCoord6", "vec4", "highp", COMP_MULTITEXCOORD6}, - {"gl_MultiTexCoord7", "_gl4es_MultiTexCoord7", "vec4", "highp", COMP_MULTITEXCOORD7}, - {"gl_MultiTexCoord8", "_gl4es_MultiTexCoord8", "vec4", "highp", COMP_MULTITEXCOORD8}, - {"gl_MultiTexCoord9", "_gl4es_MultiTexCoord9", "vec4", "highp", COMP_MULTITEXCOORD9}, - {"gl_MultiTexCoord10", "_gl4es_MultiTexCoord10", "vec4", "highp", COMP_MULTITEXCOORD10}, - {"gl_MultiTexCoord11", "_gl4es_MultiTexCoord11", "vec4", "highp", COMP_MULTITEXCOORD11}, - {"gl_MultiTexCoord12", "_gl4es_MultiTexCoord12", "vec4", "highp", COMP_MULTITEXCOORD12}, - {"gl_MultiTexCoord13", "_gl4es_MultiTexCoord13", "vec4", "highp", COMP_MULTITEXCOORD13}, - {"gl_MultiTexCoord14", "_gl4es_MultiTexCoord14", "vec4", "highp", COMP_MULTITEXCOORD14}, - {"gl_MultiTexCoord15", "_gl4es_MultiTexCoord15", "vec4", "highp", COMP_MULTITEXCOORD15}, - {"gl_SecondaryColor", "_gl4es_SecondaryColor", "vec4", "lowp", COMP_SECONDARY}, - {"gl_Normal", "_gl4es_Normal", "vec3", "highp", COMP_NORMAL}, - {"gl_FogCoord", "_gl4es_FogCoord", "float", "highp", COMP_FOGCOORD} + {"gl_Vertex", "_gl4es_Vertex", "vec4", "highp", COMP_VERTEX}, + {"gl_Color", "_gl4es_Color", "vec4", "lowp", COMP_COLOR}, + {"gl_MultiTexCoord0", "_gl4es_MultiTexCoord0", "vec4", "highp", COMP_MULTITEXCOORD0}, + {"gl_MultiTexCoord1", "_gl4es_MultiTexCoord1", "vec4", "highp", COMP_MULTITEXCOORD1}, + {"gl_MultiTexCoord2", "_gl4es_MultiTexCoord2", "vec4", "highp", COMP_MULTITEXCOORD2}, + {"gl_MultiTexCoord3", "_gl4es_MultiTexCoord3", "vec4", "highp", COMP_MULTITEXCOORD3}, + {"gl_MultiTexCoord4", "_gl4es_MultiTexCoord4", "vec4", "highp", COMP_MULTITEXCOORD4}, + {"gl_MultiTexCoord5", "_gl4es_MultiTexCoord5", "vec4", "highp", COMP_MULTITEXCOORD5}, + {"gl_MultiTexCoord6", "_gl4es_MultiTexCoord6", "vec4", "highp", COMP_MULTITEXCOORD6}, + {"gl_MultiTexCoord7", "_gl4es_MultiTexCoord7", "vec4", "highp", COMP_MULTITEXCOORD7}, + {"gl_MultiTexCoord8", "_gl4es_MultiTexCoord8", "vec4", "highp", COMP_MULTITEXCOORD8}, + {"gl_MultiTexCoord9", "_gl4es_MultiTexCoord9", "vec4", "highp", COMP_MULTITEXCOORD9}, + {"gl_MultiTexCoord10", "_gl4es_MultiTexCoord10", "vec4", "highp", COMP_MULTITEXCOORD10}, + {"gl_MultiTexCoord11", "_gl4es_MultiTexCoord11", "vec4", "highp", COMP_MULTITEXCOORD11}, + {"gl_MultiTexCoord12", "_gl4es_MultiTexCoord12", "vec4", "highp", COMP_MULTITEXCOORD12}, + {"gl_MultiTexCoord13", "_gl4es_MultiTexCoord13", "vec4", "highp", COMP_MULTITEXCOORD13}, + {"gl_MultiTexCoord14", "_gl4es_MultiTexCoord14", "vec4", "highp", COMP_MULTITEXCOORD14}, + {"gl_MultiTexCoord15", "_gl4es_MultiTexCoord15", "vec4", "highp", COMP_MULTITEXCOORD15}, + {"gl_SecondaryColor", "_gl4es_SecondaryColor", "vec4", "lowp", COMP_SECONDARY}, + {"gl_Normal", "_gl4es_Normal", "vec3", "highp", COMP_NORMAL}, + {"gl_FogCoord", "_gl4es_FogCoord", "float", "highp", COMP_FOGCOORD} }; typedef struct { @@ -75,345 +75,339 @@ typedef struct { } builtin_matrix_t; const builtin_matrix_t builtin_matrix[] = { - {"gl_ModelViewMatrixInverseTranspose", "_gl4es_ITModelViewMatrix", "mat4", 0, MAT_MV_IT}, - {"gl_ModelViewMatrixInverse", "_gl4es_IModelViewMatrix", "mat4", 0, MAT_MV_I}, - {"gl_ModelViewMatrixTranspose", "_gl4es_TModelViewMatrix", "mat4", 0, MAT_MV_T}, - {"gl_ModelViewMatrix", "_gl4es_ModelViewMatrix", "mat4", 0, MAT_MV}, - {"gl_ProjectionMatrixInverseTranspose", "_gl4es_ITProjectionMatrix", "mat4", 0, MAT_P_IT}, - {"gl_ProjectionMatrixInverse", "_gl4es_IProjectionMatrix", "mat4", 0, MAT_P_I}, - {"gl_ProjectionMatrixTranspose", "_gl4es_TProjectionMatrix", "mat4", 0, MAT_P_T}, - {"gl_ProjectionMatrix", "_gl4es_ProjectionMatrix", "mat4", 0, MAT_P}, - {"gl_ModelViewProjectionMatrixInverseTranspose", "_gl4es_ITModelViewProjectionMatrix", "mat4", 0, MAT_MVP_IT}, - {"gl_ModelViewProjectionMatrixInverse", "_gl4es_IModelViewProjectionMatrix", "mat4", 0, MAT_MVP_I}, - {"gl_ModelViewProjectionMatrixTranspose", "_gl4es_TModelViewProjectionMatrix", "mat4", 0, MAT_MVP_T}, - {"gl_ModelViewProjectionMatrix", "_gl4es_ModelViewProjectionMatrix", "mat4", 0, MAT_MVP}, - // non standard version to avoid useless array of Matrix Uniform (in case the compiler as issue optimising this) - {"gl_TextureMatrix_0", "_gl4es_TextureMatrix_0", "mat4", 0, MAT_T0}, - {"gl_TextureMatrix_1", "_gl4es_TextureMatrix_1", "mat4", 0, MAT_T1}, - {"gl_TextureMatrix_2", "_gl4es_TextureMatrix_2", "mat4", 0, MAT_T2}, - {"gl_TextureMatrix_3", "_gl4es_TextureMatrix_3", "mat4", 0, MAT_T3}, - {"gl_TextureMatrix_4", "_gl4es_TextureMatrix_4", "mat4", 0, MAT_T4}, - {"gl_TextureMatrix_5", "_gl4es_TextureMatrix_5", "mat4", 0, MAT_T5}, - {"gl_TextureMatrix_6", "_gl4es_TextureMatrix_6", "mat4", 0, MAT_T6}, - {"gl_TextureMatrix_7", "_gl4es_TextureMatrix_7", "mat4", 0, MAT_T7}, - {"gl_TextureMatrix_8", "_gl4es_TextureMatrix_8", "mat4", 0, MAT_T8}, - {"gl_TextureMatrix_9", "_gl4es_TextureMatrix_9", "mat4", 0, MAT_T9}, - {"gl_TextureMatrix_10", "_gl4es_TextureMatrix_10", "mat4", 0, MAT_T10}, - {"gl_TextureMatrix_11", "_gl4es_TextureMatrix_11", "mat4", 0, MAT_T11}, - {"gl_TextureMatrix_12", "_gl4es_TextureMatrix_12", "mat4", 0, MAT_T12}, - {"gl_TextureMatrix_13", "_gl4es_TextureMatrix_13", "mat4", 0, MAT_T13}, - {"gl_TextureMatrix_14", "_gl4es_TextureMatrix_14", "mat4", 0, MAT_T14}, - {"gl_TextureMatrix_15", "_gl4es_TextureMatrix_15", "mat4", 0, MAT_T15}, - // regular texture matrix - {"gl_TextureMatrixInverseTranspose", "_gl4es_ITTextureMatrix", "mat4", 1, MAT_T0_IT}, - {"gl_TextureMatrixInverse", "_gl4es_ITextureMatrix", "mat4", 1, MAT_T0_I}, - {"gl_TextureMatrixTranspose", "_gl4es_TTextureMatrix", "mat4", 1, MAT_T0_T}, - {"gl_TextureMatrix", "_gl4es_TextureMatrix", "mat4", 1, MAT_T0}, - {"gl_NormalMatrix", "_gl4es_NormalMatrix", "mat3", 0, MAT_N} - }; + {"gl_ModelViewMatrixInverseTranspose", "_gl4es_ITModelViewMatrix", "mat4", 0, MAT_MV_IT}, + {"gl_ModelViewMatrixInverse", "_gl4es_IModelViewMatrix", "mat4", 0, MAT_MV_I}, + {"gl_ModelViewMatrixTranspose", "_gl4es_TModelViewMatrix", "mat4", 0, MAT_MV_T}, + {"gl_ModelViewMatrix", "_gl4es_ModelViewMatrix", "mat4", 0, MAT_MV}, + {"gl_ProjectionMatrixInverseTranspose", "_gl4es_ITProjectionMatrix", "mat4", 0, MAT_P_IT}, + {"gl_ProjectionMatrixInverse", "_gl4es_IProjectionMatrix", "mat4", 0, MAT_P_I}, + {"gl_ProjectionMatrixTranspose", "_gl4es_TProjectionMatrix", "mat4", 0, MAT_P_T}, + {"gl_ProjectionMatrix", "_gl4es_ProjectionMatrix", "mat4", 0, MAT_P}, + {"gl_ModelViewProjectionMatrixInverseTranspose", "_gl4es_ITModelViewProjectionMatrix", "mat4", 0, MAT_MVP_IT}, + {"gl_ModelViewProjectionMatrixInverse", "_gl4es_IModelViewProjectionMatrix", "mat4", 0, MAT_MVP_I}, + {"gl_ModelViewProjectionMatrixTranspose", "_gl4es_TModelViewProjectionMatrix", "mat4", 0, MAT_MVP_T}, + {"gl_ModelViewProjectionMatrix", "_gl4es_ModelViewProjectionMatrix", "mat4", 0, MAT_MVP}, + // non standard version to avoid useless array of Matrix Uniform (in case the compiler as issue optimising this) + {"gl_TextureMatrix_0", "_gl4es_TextureMatrix_0", "mat4", 0, MAT_T0}, + {"gl_TextureMatrix_1", "_gl4es_TextureMatrix_1", "mat4", 0, MAT_T1}, + {"gl_TextureMatrix_2", "_gl4es_TextureMatrix_2", "mat4", 0, MAT_T2}, + {"gl_TextureMatrix_3", "_gl4es_TextureMatrix_3", "mat4", 0, MAT_T3}, + {"gl_TextureMatrix_4", "_gl4es_TextureMatrix_4", "mat4", 0, MAT_T4}, + {"gl_TextureMatrix_5", "_gl4es_TextureMatrix_5", "mat4", 0, MAT_T5}, + {"gl_TextureMatrix_6", "_gl4es_TextureMatrix_6", "mat4", 0, MAT_T6}, + {"gl_TextureMatrix_7", "_gl4es_TextureMatrix_7", "mat4", 0, MAT_T7}, + {"gl_TextureMatrix_8", "_gl4es_TextureMatrix_8", "mat4", 0, MAT_T8}, + {"gl_TextureMatrix_9", "_gl4es_TextureMatrix_9", "mat4", 0, MAT_T9}, + {"gl_TextureMatrix_10", "_gl4es_TextureMatrix_10", "mat4", 0, MAT_T10}, + {"gl_TextureMatrix_11", "_gl4es_TextureMatrix_11", "mat4", 0, MAT_T11}, + {"gl_TextureMatrix_12", "_gl4es_TextureMatrix_12", "mat4", 0, MAT_T12}, + {"gl_TextureMatrix_13", "_gl4es_TextureMatrix_13", "mat4", 0, MAT_T13}, + {"gl_TextureMatrix_14", "_gl4es_TextureMatrix_14", "mat4", 0, MAT_T14}, + {"gl_TextureMatrix_15", "_gl4es_TextureMatrix_15", "mat4", 0, MAT_T15}, + // regular texture matrix + {"gl_TextureMatrixInverseTranspose", "_gl4es_ITTextureMatrix", "mat4", 1, MAT_T0_IT}, + {"gl_TextureMatrixInverse", "_gl4es_ITextureMatrix", "mat4", 1, MAT_T0_I}, + {"gl_TextureMatrixTranspose", "_gl4es_TTextureMatrix", "mat4", 1, MAT_T0_T}, + {"gl_TextureMatrix", "_gl4es_TextureMatrix", "mat4", 1, MAT_T0}, + {"gl_NormalMatrix", "_gl4es_NormalMatrix", "mat3", 0, MAT_N} +}; #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) static const char* gl4es_MaxLightsSource = -"#define _gl4es_MaxLights " STR(MAX_LIGHT) "\n"; + "#define _gl4es_MaxLights " STR(MAX_LIGHT) "\n"; static const char* gl4es_MaxClipPlanesSource = -"#define _gl4es_MaxClipPlanes " STR(MAX_CLIP_PLANES) "\n"; + "#define _gl4es_MaxClipPlanes " STR(MAX_CLIP_PLANES) "\n"; static const char* gl4es_MaxTextureUnitsSource = -"#define _gl4es_MaxTextureUnits " STR(MAX_TEX) "\n"; + "#define _gl4es_MaxTextureUnits " STR(MAX_TEX) "\n"; static const char* gl4es_MaxTextureCoordsSource = -"#define _gl4es_MaxTextureCoords " STR(MAX_TEX) "\n"; + "#define _gl4es_MaxTextureCoords " STR(MAX_TEX) "\n"; #undef STR #undef STR_HELPER -static const char* gl4es_LightSourceParametersSource = -"struct gl_LightSourceParameters\n" -"{\n" -" vec4 ambient;\n" -" vec4 diffuse;\n" -" vec4 specular;\n" -" vec4 position;\n" -" vec4 halfVector;\n" //halfVector = normalize(normalize(position) + vec3(0,0,1) if vbs==FALSE) -" vec3 spotDirection;\n" -" float spotExponent;\n" -" float spotCutoff;\n" -" float spotCosCutoff;\n" -" float constantAttenuation;\n" -" float linearAttenuation;\n" -" float quadraticAttenuation;\n" -"};\n" -"uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];\n"; +static const char* gl4es_LightSourceParametersSource = + "struct gl_LightSourceParameters\n" + "{\n" + " vec4 ambient;\n" + " vec4 diffuse;\n" + " vec4 specular;\n" + " vec4 position;\n" + " vec4 halfVector;\n" //halfVector = normalize(normalize(position) + vec3(0,0,1) if vbs==FALSE) + " vec3 spotDirection;\n" + " float spotExponent;\n" + " float spotCutoff;\n" + " float spotCosCutoff;\n" + " float constantAttenuation;\n" + " float linearAttenuation;\n" + " float quadraticAttenuation;\n" + "};\n" + "uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];\n"; static const char* gl4es_LightModelParametersSource = -"struct gl_LightModelParameters {\n" -" vec4 ambient;\n" -"};\n" -"uniform gl_LightModelParameters gl_LightModel;\n"; + "struct gl_LightModelParameters {\n" + " vec4 ambient;\n" + "};\n" + "uniform gl_LightModelParameters gl_LightModel;\n"; static const char* gl4es_MaterialParametersSource = -"struct gl_MaterialParameters\n" -"{\n" -" vec4 emission;\n" -" vec4 ambient;\n" -" vec4 diffuse;\n" -" vec4 specular;\n" -" float shininess;\n" -"};\n" -"uniform gl_MaterialParameters gl_FrontMaterial;\n" -"uniform gl_MaterialParameters gl_BackMaterial;\n"; + "struct gl_MaterialParameters\n" + "{\n" + " vec4 emission;\n" + " vec4 ambient;\n" + " vec4 diffuse;\n" + " vec4 specular;\n" + " float shininess;\n" + "};\n" + "uniform gl_MaterialParameters gl_FrontMaterial;\n" + "uniform gl_MaterialParameters gl_BackMaterial;\n"; static const char* gl4es_LightModelProductsSource = -"struct gl_LightModelProducts\n" -"{\n" -" vec4 sceneColor;\n" -"};\n" -"uniform gl_LightModelProducts gl_FrontLightModelProduct;\n" -"uniform gl_LightModelProducts gl_BackLightModelProduct;\n"; + "struct gl_LightModelProducts\n" + "{\n" + " vec4 sceneColor;\n" + "};\n" + "uniform gl_LightModelProducts gl_FrontLightModelProduct;\n" + "uniform gl_LightModelProducts gl_BackLightModelProduct;\n"; static const char* gl4es_LightProductsSource = -"struct gl_LightProducts\n" -"{\n" -" vec4 ambient;\n" -" vec4 diffuse;\n" -" vec4 specular;\n" -"};\n" -"uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];\n" -"uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];\n"; + "struct gl_LightProducts\n" + "{\n" + " vec4 ambient;\n" + " vec4 diffuse;\n" + " vec4 specular;\n" + "};\n" + "uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];\n" + "uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];\n"; static const char* gl4es_PointSpriteSource = -"struct gl_PointParameters\n" -"{\n" -" float size;\n" -" float sizeMin;\n" -" float sizeMax;\n" -" float fadeThresholdSize;\n" -" float distanceConstantAttenuation;\n" -" float distanceLinearAttenuation;\n" -" float distanceQuadraticAttenuation;\n" -"};\n" -"uniform gl_PointParameters gl_Point;\n"; + "struct gl_PointParameters\n" + "{\n" + " float size;\n" + " float sizeMin;\n" + " float sizeMax;\n" + " float fadeThresholdSize;\n" + " float distanceConstantAttenuation;\n" + " float distanceLinearAttenuation;\n" + " float distanceQuadraticAttenuation;\n" + "};\n" + "uniform gl_PointParameters gl_Point;\n"; static const char* gl4es_FogParametersSource = -"struct gl_FogParameters {\n" -" lowp vec4 color;\n" -" mediump float density;\n" -" mediump float start;\n" -" mediump float end;\n" -" mediump float scale;\n" // Derived: 1.0 / (end - start) -"};\n" -"uniform gl_FogParameters gl_Fog;\n"; + "struct gl_FogParameters {\n" + " lowp vec4 color;\n" + " mediump float density;\n" + " mediump float start;\n" + " mediump float end;\n" + " mediump float scale;\n" // Derived: 1.0 / (end - start) + "};\n" + "uniform gl_FogParameters gl_Fog;\n"; static const char* gl4es_FogParametersSourceHighp = -"struct gl_FogParameters {\n" -" lowp vec4 color;\n" -" mediump float density;\n" -" highp float start;\n" -" highp float end;\n" -" highp float scale;\n" // Derived: 1.0 / (end - start) -"};\n" -"uniform gl_FogParameters gl_Fog;\n"; + "struct gl_FogParameters {\n" + " lowp vec4 color;\n" + " mediump float density;\n" + " highp float start;\n" + " highp float end;\n" + " highp float scale;\n" // Derived: 1.0 / (end - start) + "};\n" + "uniform gl_FogParameters gl_Fog;\n"; static const char* gl4es_texenvcolorSource = -"uniform vec4 gl_TextureEnvColor[gl_MaxTextureUnits];\n"; + "uniform vec4 gl_TextureEnvColor[gl_MaxTextureUnits];\n"; static const char* gl4es_texgeneyeSource[4] = { -"uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];\n", -"uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];\n", -"uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];\n", -"uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];\n" }; + "uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];\n", + "uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];\n", + "uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];\n", + "uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];\n" }; static const char* gl4es_texgenobjSource[4] = { -"uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];\n", -"uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];\n", -"uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];\n", -"uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];\n" }; + "uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];\n", + "uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];\n", + "uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];\n", + "uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];\n" }; -static const char* gl4es_clipplanesSource = -"uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];\n"; +static const char* gl4es_clipplanesSource = + "uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];\n"; static const char* gl4es_normalscaleSource = -"uniform float gl_NormalScale;\n"; + "uniform float gl_NormalScale;\n"; static const char* gl4es_instanceID = -"#define GL_ARB_draw_instanced 1\n" -"uniform int _gl4es_InstanceID;\n"; + "#define GL_ARB_draw_instanced 1\n" + "uniform int _gl4es_InstanceID;\n"; static const char* gl4es_frontColorSource = -"varying lowp vec4 _gl4es_FrontColor;\n"; + "varying lowp vec4 _gl4es_FrontColor;\n"; static const char* gl4es_backColorSource = -"varying lowp vec4 _gl4es_BackColor;\n"; + "varying lowp vec4 _gl4es_BackColor;\n"; static const char* gl4es_frontSecondaryColorSource = -"varying lowp vec4 _gl4es_FrontSecondaryColor;\n"; + "varying lowp vec4 _gl4es_FrontSecondaryColor;\n"; static const char* gl4es_backSecondaryColorSource = -"varying lowp vec4 _gl4es_BackSecondaryColor;\n"; + "varying lowp vec4 _gl4es_BackSecondaryColor;\n"; static const char* gl4es_texcoordSource = -"varying mediump vec4 _gl4es_TexCoord[%d];\n"; + "varying mediump vec4 _gl4es_TexCoord[%d];\n"; static const char* gl4es_texcoordSourceAlt = -"varying mediump vec4 _gl4es_TexCoord_%d;\n"; + "varying mediump vec4 _gl4es_TexCoord_%d;\n"; static const char* gl4es_fogcoordSource = -"varying mediump float _gl4es_FogFragCoord;\n"; + "varying mediump float _gl4es_FogFragCoord;\n"; -static const char* gl4es_ftransformSource = -"\n" -"highp vec4 ftransform() {\n" -" return gl_ModelViewProjectionMatrix * gl_Vertex;\n" -"}\n"; +static const char* gl4es_ftransformSource = + "\n" + "highp vec4 ftransform() {\n" + " return gl_ModelViewProjectionMatrix * gl_Vertex;\n" + "}\n"; -static const char* gl4es_ClipVertex = -"vec4 gl4es_ClipVertex;\n"; - -static const char* gl4es_ClipVertexSource = -"gl4es_ClipVertex"; - -static const char* gl4es_ClipVertex_clip = -"\nif(any(lessThanEqual(gl4es_ClipVertex.xyz, vec3(-gl4es_ClipVertex.w)))" -" || any(greaterThanEqual(gl4es_ClipVertex.xyz, vec3(gl4es_ClipVertex.w)))) discard;\n"; +static const char* gl4es_dummyClipVertex = + "vec4 dummyClipVertex_%d"; static const char* gl_TexCoordSource = "gl_TexCoord["; static const char* gl_TexMatrixSources[] = { -"gl_TextureMatrixInverseTranspose[", -"gl_TextureMatrixInverse[", -"gl_TextureMatrixTranspose[", -"gl_TextureMatrix[" + "gl_TextureMatrixInverseTranspose[", + "gl_TextureMatrixInverse[", + "gl_TextureMatrixTranspose[", + "gl_TextureMatrix[" }; static const char* GLESHeader[] = { - "#version 100\n%sprecision %s float;\nprecision %s int;\n", - "#version 120\n%sprecision %s float;\nprecision %s int;\n", - "#version 310 es\n#define attribute in\n#define varying out\n%sprecision %s float;\nprecision %s int;\n", - "#version 300 es\n#define attribute in\n#define varying out\n%sprecision %s float;\nprecision %s int;\n" + "#version 100\n%sprecision %s float;\nprecision %s int;\n", + "#version 120\n%sprecision %s float;\nprecision %s int;\n", + "#version 310 es\n%sprecision %s float;\nprecision %s int;\n", + "#version 300 es\n%sprecision %s float;\nprecision %s int;\n", + "#version 320 es\n%sprecision %s float;\nprecision %s int;\n" }; static const char* gl4es_transpose = -"mat2 gl4es_transpose(mat2 m) {\n" -" return mat2(m[0][0], m[1][0],\n" -" m[0][1], m[1][1]);\n" -"}\n" -"mat3 gl4es_transpose(mat3 m) {\n" -" return mat3(m[0][0], m[1][0], m[2][0],\n" -" m[0][1], m[1][1], m[2][1],\n" -" m[0][2], m[1][2], m[2][2]);\n" -"}\n" -"mat4 gl4es_transpose(mat4 m) {\n" -" return mat4(m[0][0], m[1][0], m[2][0], m[3][0],\n" -" m[0][1], m[1][1], m[2][1], m[3][1],\n" -" m[0][2], m[1][2], m[2][2], m[3][2],\n" -" m[0][3], m[1][3], m[2][3], m[3][3]);\n" -"}\n"; + "mat2 gl4es_transpose(mat2 m) {\n" + " return mat2(m[0][0], m[0][1],\n" + " m[1][0], m[1][1]);\n" + "}\n" + "mat3 gl4es_transpose(mat3 m) {\n" + " return mat3(m[0][0], m[0][1], m[0][2],\n" + " m[1][0], m[1][1], m[1][2],\n" + " m[2][0], m[2][1], m[2][2]);\n" + "}\n" + "mat4 gl4es_transpose(mat4 m) {\n" + " return mat4(m[0][0], m[0][1], m[0][2], m[0][3],\n" + " m[1][0], m[1][1], m[1][2], m[1][3],\n" + " m[2][0], m[2][1], m[2][2], m[2][3],\n" + " m[3][0], m[3][1], m[3][2], m[3][3]);\n" + "}\n"; -static const char* HackAltPow = -"float pow(float f, int a) {\n" -" return pow(f, float(a));\n" -"}\n"; -static const char* HackAltMax = -"float max(float a, int b) {\n" -" return max(a, float(b));\n" -"}\n" -"float max(int a, float b) {\n" -" return max(float(a), b);\n" -"}\n"; -static const char* HackAltMin = -"float min(float a, int b) {\n" -" return min(a, float(b));\n" -"}\n" -"float min(int a, float b) {\n" -" return min(float(a), b);\n" -"}\n"; -static const char* HackAltClamp = -"float clamp(float f, int a, int b) {\n" -" return clamp(f, float(a), float(b));\n" -"}\n" -"float clamp(float f, float a, int b) {\n" -" return clamp(f, a, float(b));\n" -"}\n" -"float clamp(float f, int a, float b) {\n" -" return clamp(f, float(a), b);\n" -"}\n" -"vec2 clamp(vec2 f, int a, int b) {\n" -" return clamp(f, float(a), float(b));\n" -"}\n" -"vec2 clamp(vec2 f, float a, int b) {\n" -" return clamp(f, a, float(b));\n" -"}\n" -"vec2 clamp(vec2 f, int a, float b) {\n" -" return clamp(f, float(a), b);\n" -"}\n" -"vec3 clamp(vec3 f, int a, int b) {\n" -" return clamp(f, float(a), float(b));\n" -"}\n" -"vec3 clamp(vec3 f, float a, int b) {\n" -" return clamp(f, a, float(b));\n" -"}\n" -"vec3 clamp(vec3 f, int a, float b) {\n" -" return clamp(f, float(a), b);\n" -"}\n" -"vec4 clamp(vec4 f, int a, int b) {\n" -" return clamp(f, float(a), float(b));\n" -"}\n" -"vec4 clamp(vec4 f, float a, int b) {\n" -" return clamp(f, a, float(b));\n" -"}\n" -"vec4 clamp(vec4 f, int a, float b) {\n" -" return clamp(f, float(a), b);\n" -"}\n"; +static const char* HackAltPow = + "float pow(float f, int a) {\n" + " return pow(f, float(a));\n" + "}\n"; +static const char* HackAltMax = + "float max(float a, int b) {\n" + " return max(a, float(b));\n" + "}\n" + "float max(int a, float b) {\n" + " return max(float(a), b);\n" + "}\n"; +static const char* HackAltMin = + "float min(float a, int b) {\n" + " return min(a, float(b));\n" + "}\n" + "float min(int a, float b) {\n" + " return min(float(a), b);\n" + "}\n"; +static const char* HackAltClamp = + "float clamp(float f, int a, int b) {\n" + " return clamp(f, float(a), float(b));\n" + "}\n" + "float clamp(float f, float a, int b) {\n" + " return clamp(f, a, float(b));\n" + "}\n" + "float clamp(float f, int a, float b) {\n" + " return clamp(f, float(a), b);\n" + "}\n" + "vec2 clamp(vec2 f, int a, int b) {\n" + " return clamp(f, float(a), float(b));\n" + "}\n" + "vec2 clamp(vec2 f, float a, int b) {\n" + " return clamp(f, a, float(b));\n" + "}\n" + "vec2 clamp(vec2 f, int a, float b) {\n" + " return clamp(f, float(a), b);\n" + "}\n" + "vec3 clamp(vec3 f, int a, int b) {\n" + " return clamp(f, float(a), float(b));\n" + "}\n" + "vec3 clamp(vec3 f, float a, int b) {\n" + " return clamp(f, a, float(b));\n" + "}\n" + "vec3 clamp(vec3 f, int a, float b) {\n" + " return clamp(f, float(a), b);\n" + "}\n" + "vec4 clamp(vec4 f, int a, int b) {\n" + " return clamp(f, float(a), float(b));\n" + "}\n" + "vec4 clamp(vec4 f, float a, int b) {\n" + " return clamp(f, a, float(b));\n" + "}\n" + "vec4 clamp(vec4 f, int a, float b) {\n" + " return clamp(f, float(a), b);\n" + "}\n"; -static const char* HackAltMod = -"float mod(float f, int a) {\n" -" return mod(f, float(a));\n" -"}\n" -"vec2 mod(vec2 f, int a) {\n" -" return mod(f, float(a));\n" -"}\n" -"vec3 mod(vec3 f, int a) {\n" -" return mod(f, float(a));\n" -"}\n" -"vec4 mod(vec4 f, int a) {\n" -" return mod(f, float(a));\n" -"}\n"; +static const char* HackAltMod = + "float mod(float f, int a) {\n" + " return mod(f, float(a));\n" + "}\n" + "vec2 mod(vec2 f, int a) {\n" + " return mod(f, float(a));\n" + "}\n" + "vec3 mod(vec3 f, int a) {\n" + " return mod(f, float(a));\n" + "}\n" + "vec4 mod(vec4 f, int a) {\n" + " return mod(f, float(a));\n" + "}\n"; static const char* texture2DLodAlt = -"vec4 _gl4es_texture2DLod(sampler2D sampler, vec2 coord, float lod) {\n" -" return texture2D(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_texture2DLod(sampler2D sampler, vec2 coord, float lod) {\n" + " return texture2D(sampler, coord);\n" + "}\n"; static const char* texture2DProjLodAlt = -"vec4 _gl4es_texture2DProjLod(sampler2D sampler, vec3 coord, float lod) {\n" -" return texture2DProj(sampler, coord);\n" -"}\n" -"vec4 _gl4es_texture2DProjLod(sampler2D sampler, vec4 coord, float lod) {\n" -" return texture2DProj(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_texture2DProjLod(sampler2D sampler, vec3 coord, float lod) {\n" + " return texture2DProj(sampler, coord);\n" + "}\n" + "vec4 _gl4es_texture2DProjLod(sampler2D sampler, vec4 coord, float lod) {\n" + " return texture2DProj(sampler, coord);\n" + "}\n"; static const char* textureCubeLodAlt = -"vec4 _gl4es_textureCubeLod(samplerCube sampler, vec3 coord, float lod) {\n" -" return textureCube(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_textureCubeLod(samplerCube sampler, vec3 coord, float lod) {\n" + " return textureCube(sampler, coord);\n" + "}\n"; static const char* texture2DGradAlt = -"vec4 _gl4es_texture2DGrad(sampler2D sampler, vec2 coord, vec2 dPdx, vec2 dPdy) {\n" -" return texture2D(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_texture2DGrad(sampler2D sampler, vec2 coord, vec2 dPdx, vec2 dPdy) {\n" + " return texture2D(sampler, coord);\n" + "}\n"; static const char* texture2DProjGradAlt = -"vec4 _gl4es_texture2DProjGrad(sampler2D sampler, vec3 coord, vec2 dPdx, vec2 dPdy) {\n" -" return texture2DProj(sampler, coord);\n" -"}\n" -"vec4 _gl4es_texture2DProjGrad(sampler2D sampler, vec4 coord, vec2 dPdx, vec2 dPdy) {\n" -" return texture2DProj(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_texture2DProjGrad(sampler2D sampler, vec3 coord, vec2 dPdx, vec2 dPdy) {\n" + " return texture2DProj(sampler, coord);\n" + "}\n" + "vec4 _gl4es_texture2DProjGrad(sampler2D sampler, vec4 coord, vec2 dPdx, vec2 dPdy) {\n" + " return texture2DProj(sampler, coord);\n" + "}\n"; static const char* textureCubeGradAlt = -"vec4 _gl4es_textureCubeGrad(samplerCube sampler, vec3 coord, vec2 dPdx, vec2 dPdy) {\n" -" return textureCube(sampler, coord);\n" -"}\n"; + "vec4 _gl4es_textureCubeGrad(samplerCube sampler, vec3 coord, vec2 dPdx, vec2 dPdy) {\n" + " return textureCube(sampler, coord);\n" + "}\n"; static const char* useEXTDrawBuffers = -"#extension GL_EXT_draw_buffers : enable\n"; + "#extension GL_EXT_draw_buffers : enable\n"; static const char* gl_ProgramEnv = "gl_ProgramEnv"; static const char* gl_ProgramLocal= "gl_ProgramLocal"; @@ -437,838 +431,840 @@ static const char* gl4es_VertexAttrib = "_gl4es_VertexAttrib_"; char gl_VA[MAX_VATTRIB][32] = {0}; char gl4es_VA[MAX_VATTRIB][32] = {0}; -char* ConvertShader(const char* pEntry, int isVertex, shaderconv_need_t *need) +void AppendToEnd(char **str, const char *suffix); +void InsertAtBeginning(char **str, const char *prefix); + +char * InplaceReplaceByIndex(char* pBuffer, int* size, int startIndex, int endIndex, const char* replacement); +char * InplaceInsertByIndex(char * source, int *sourceLength, int insertPoint, const char *insertedString); + +extern const char* FindString(const char* pBuffer, const char* S); +extern char* FindStringNC(char* pBuffer, const char* S); +extern int CountString(const char* pBuffer, const char* S); +extern char* ResizeIfNeeded(char* pBuffer, int *size, int addsize); +extern char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D); +extern char* Append(char* pBuffer, int* size, const char* S); +extern char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size); +extern char* GetLine(char* pBuffer, int num); +extern int CountLine(const char* pBuffer); +extern int GetLineFor(const char* pBuffer, const char* S); +extern char* StrNext(char *pBuffer, const char* S); +extern char* NextStr(char* pBuffer); +extern char* PrevStr(char* Str, char* pBuffer); +extern char* NextBlank(char* pBuffer); +extern char* NextLine(char* pBuffer); +extern const char* GetNextStr(char* pBuffer); +extern int CountStringSimple(char* pBuffer, const char* S); +extern char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D); + + +char* ConvertShader(const char* pEntry, int isVertex, shaderconv_need_t *need, int forwardPort) { - #define ShadAppend(S) Tmp = gl4es_append(Tmp, &tmpsize, S) - - if(gl_VA[0][0]=='\0') { - for (int i=0; ineed_texcoord = -1; - need->need_clean = 1; // no hack, this is a dummy need structure - } - int notexarray = globals4es.notexarray || need->need_notexarray || fpeShader; - - //const char* GLESUseFragHighp = "#extension GL_OES_fragment_precision_high : enable\n"; // is this needed? - char GLESFullHeader[512]; - int wanthighp = !fpeShader; - if(wanthighp && !hardext.highp) wanthighp = 0; - int versionHeader = 0; - #if 0 - // support for higher glsl require much more work - // around some keyword - // like in/out that depends on the shader being vertex or fragment - // and a few other little things... - if(versionString && strcmp(versionString, "120")==0) - version120 = 1; - if(version120) { - if(hardext.glsl120) versionHeader = 1; - else if(hardext.glsl310es) versionHeader = 2; - else if(hardext.glsl300es) { versionHeader = 3; /* location on uniform not supported ! */ } - /* else no location or in / out are supported */ - } - #endif - //sprintf(GLESFullHeader, GLESHeader, (wanthighp && hardext.highp==1 && !isVertex)?GLESUseFragHighp:"", (wanthighp)?"highp":"mediump", (wanthighp)?"highp":"mediump"); - sprintf(GLESFullHeader, GLESHeader[versionHeader], "", (wanthighp)?"highp":"mediump", (wanthighp)?"highp":"mediump"); - - int tmpsize = strlen(pBuffer)*2+strlen(GLESFullHeader)+100; - char* Tmp = (char*)calloc(1, tmpsize); - strcpy(Tmp, pBuffer); - - // and now change the version header, and add default precision - char* newptr; - newptr=strstr(Tmp, "#version"); - if (!newptr) { - Tmp = gl4es_inplace_insert(Tmp, GLESFullHeader, Tmp, &tmpsize); - } else { - while(*newptr!=0x0a) newptr++; - newptr++; - memmove(Tmp, newptr, strlen(newptr)+1); - Tmp = gl4es_inplace_insert(Tmp, GLESFullHeader, Tmp, &tmpsize); - } - int headline = 3; - // move all "#extension in header zone" - while (strstr(Tmp, "#extension") && strstr(Tmp, "#extension")>gl4es_getline(Tmp, headline-2)) { - char* ext = strstr(Tmp, "#extension"); - size_t l = (uintptr_t)strstr(ext, "\n")-(uintptr_t)ext + sizeof("\n"); -#ifndef _MSC_VER - char e[l]; -#else - char* e = _alloca(l); -#endif - memset(e, 0, l); - strncpy(e, ext, l-1); - Tmp = gl4es_inplace_replace_simple(Tmp, &tmpsize, e, ""); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline-2), e, Tmp, &tmpsize); - ++headline; - } - // check if gl_FragDepth is used - int fragdepth = (strstr(pBuffer, "gl_FragDepth"))?1:0; - const char* GLESUseFragDepth = "#extension GL_EXT_frag_depth : enable\n"; - const char* GLESFakeFragDepth = "mediump float fakeFragDepth = 0.0;\n"; - if (fragdepth) { - /* If #extension is used, it should be placed before the second line of the header. */ - if(hardext.fragdepth) - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 1), GLESUseFragDepth, Tmp, &tmpsize); - else - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline-1), GLESFakeFragDepth, Tmp, &tmpsize); - headline++; - } - - const char* GLESUseShaderNonConstantGlobalInitialzers = "#extension GL_EXT_shader_non_constant_global_initializers : enable\n"; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 1), GLESUseShaderNonConstantGlobalInitialzers, Tmp, &tmpsize); - ++headline; - - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline-1), "#define GL4ES\n", Tmp, &tmpsize); - - int derivatives = (strstr(pBuffer, "dFdx(") || strstr(pBuffer, "dFdy(") || strstr(pBuffer, "fwidth("))?1:0; - const char* GLESUseDerivative = "#extension GL_OES_standard_derivatives : enable\n"; - // complete fake value... A better thing should be use.... - const char* GLESFakeDerivative = "float dFdx(float p) {return 0.0001;}\nvec2 dFdx(vec2 p) {return vec2(0.0001);}\nvec3 dFdx(vec3 p) {return vec3(0.0001);}\n" - "float dFdy(float p) {return 0.0001;}\nvec2 dFdy(vec2 p) {return vec2(0.0001);}\nvec3 dFdy(vec3 p) {return vec3(0.0001);}\n" - "float fwidth(float p) {return abs(dFdx(p))+abs(dFdy(p));}\nvec2 fwidth(vec2 p) {return abs(dFdx(p))+abs(dFdy(p));}\n" - "vec3 fwidth(vec3 p) {return abs(dFdx(p))+abs(dFdy(p));}\n"; - if (derivatives) { - /* If #extension is used, it should be placed before the second line of the header. */ - if(hardext.derivatives) - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 1), GLESUseDerivative, Tmp, &tmpsize); - else - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline-1), GLESFakeDerivative, Tmp, &tmpsize); - headline++; - } - // check if draw_buffers may be used (no fallback here :( ) - if(hardext.maxdrawbuffers>1 && strstr(pBuffer, "gl_FragData[")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 1), useEXTDrawBuffers, Tmp, &tmpsize); - } - // if some functions are used, add some int/float alternative - if(!fpeShader && !globals4es.nointovlhack) { - if(strstr(Tmp, "pow(") || strstr(Tmp, "pow (")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), HackAltPow, Tmp, &tmpsize); - } - if(strstr(Tmp, "max(") || strstr(Tmp, "max (")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), HackAltMax, Tmp, &tmpsize); - } - if(strstr(Tmp, "min(") || strstr(Tmp, "min (")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), HackAltMin, Tmp, &tmpsize); - } - if(strstr(Tmp, "clamp(") || strstr(Tmp, "clamp (")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), HackAltClamp, Tmp, &tmpsize); - } - if(strstr(Tmp, "mod(") || strstr(Tmp, "mod (")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), HackAltMod, Tmp, &tmpsize); - } - } - if(!isVertex && hardext.shaderlod && - (gl4es_find_string(Tmp, "texture2DLod") || gl4es_find_string(Tmp, "texture2DProjLod") - || gl4es_find_string(Tmp, "textureCubeLod") - || gl4es_find_string(Tmp, "texture2DGradARB") || gl4es_find_string(Tmp, "texture2DProjGradARB")|| gl4es_find_string(Tmp, "textureCubeGradARB") - )) { - const char* GLESUseShaderLod = "#extension GL_EXT_shader_texture_lod : enable\n"; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 1), GLESUseShaderLod, Tmp, &tmpsize); - } - if(!isVertex && (gl4es_find_string(Tmp, "texture2DLod"))) { - if(hardext.shaderlod) { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DLod", "texture2DLodEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DLod", "_gl4es_texture2DLod"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), texture2DLodAlt, Tmp, &tmpsize); - } - } - if(!isVertex && (gl4es_find_string(Tmp, "texture2DProjLod"))) { - if(hardext.shaderlod) { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DProjLod", "texture2DProjLodEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DProjLod", "_gl4es_texture2DProjLod"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), texture2DProjLodAlt, Tmp, &tmpsize); - } - } - if(!isVertex && (gl4es_find_string(Tmp, "textureCubeLod"))) { - if(hardext.shaderlod) { - if(!hardext.cubelod) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "textureCubeLod", "textureCubeLodEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "textureCubeLod", "_gl4es_textureCubeLod"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), textureCubeLodAlt, Tmp, &tmpsize); - } - } - if(!isVertex && (gl4es_find_string(Tmp, "texture2DGradARB"))) { - if(hardext.shaderlod) { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DGradARB", "texture2DGradEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DGradARB", "_gl4es_texture2DGrad"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), texture2DGradAlt, Tmp, &tmpsize); - } - } - if(!isVertex && (gl4es_find_string(Tmp, "texture2DProjGradARB"))) { - if(hardext.shaderlod) { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DProjGradARB", "texture2DProjGradEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "texture2DProjGradARB", "_gl4es_texture2DProjGrad"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), texture2DProjGradAlt, Tmp, &tmpsize); - } - } - if(!isVertex && (gl4es_find_string(Tmp, "textureCubeGradARB"))) { - if(hardext.shaderlod) { - if(!hardext.cubelod) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "textureCubeGradARB", "textureCubeGradEXT"); - } else { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "textureCubeGradARB", "_gl4es_textureCubeGrad"); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), textureCubeGradAlt, Tmp, &tmpsize); - } - } - - // Some drivers have troubles with "\\\r\n" or "\\\n" sequences on preprocessor macros - newptr = Tmp; - while (*newptr!=0x00) { - if (*newptr == '\\') { - if (*(newptr+1) == '\r' && *(newptr+2) == '\n') - memmove(newptr, newptr+3, strlen(newptr+3)+1); - else if (*(newptr+1) == '\n') - memmove(newptr, newptr+2, strlen(newptr+2)+1); - } - - newptr++; - } - - // now check to remove trailling "f" after float, as it's not supported too - newptr = Tmp; - // simple state machine... - int state = 0; - while (*newptr!=0x00) { - switch(state) { - case 0: - if ((*newptr >= '0') && (*newptr <= '9')) - state = 1; // integer part - else if (*newptr == '.') - state = 2; // fractional part - else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) - state = 0; // separator - else - state = 3; // something else - break; - case 1: // integer part - if ((*newptr >= '0') && (*newptr <= '9')) - state = 1; // integer part - else if (*newptr == '.') - state = 2; // fractional part - else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) - state = 0; // separator - else if (*newptr == 'f' ) { - // remove that f - memmove(newptr, newptr+1, strlen(newptr+1)+1); - newptr--; - } else - state = 3; - break; - case 2: // fractionnal part - if ((*newptr >= '0') && (*newptr <= '9')) - state = 2; - else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) - state = 0; // separator - else if (*newptr == 'f' ) { - // remove that f - memmove(newptr, newptr+1, strlen(newptr+1)+1); - newptr--; - } else - state = 3; - break; - case 3: - if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) - state = 0; // separator - else - state = 3; - break; - } - newptr++; - } - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FragDepth", (hardext.fragdepth)?"gl_FragDepthEXT":"fakeFragDepth"); - // builtin attribs - if(isVertex) { - // check for ftransform function - if(strstr(Tmp, "ftransform(")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_ftransformSource, Tmp, &tmpsize); - // don't increment headline count, as all variying and attributes should be created before - } - // check for builtin OpenGL attributes... - int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); - for (int i=0; ineed_color) { - if(need->need_color<1) need->need_color = 1; - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_Color", (need->need_color==1)?"gl_FrontColor":"(gl_FrontFacing?gl_FrontColor:gl_BackColor)"); - } - if(strstr(Tmp, "gl_FrontColor") || need->need_color) { - if(need->need_color<1) need->need_color = 1; - nvarying+=1; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_frontColorSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_frontColorSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FrontColor", "_gl4es_FrontColor"); - } - if(strstr(Tmp, "gl_BackColor") || (need->need_color==2)) { - need->need_color = 2; - nvarying+=1; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_backColorSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_backColorSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_BackColor", "_gl4es_BackColor"); - } - if(strstr(Tmp, "gl_SecondaryColor") || need->need_secondary) { - if(need->need_secondary<1) need->need_secondary = 1; - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_SecondaryColor", (need->need_secondary==1)?"gl_FrontSecondaryColor":"(gl_FrontFacing?gl_FrontSecondaryColor:gl_BackSecondaryColor)"); - } - if(strstr(Tmp, "gl_FrontSecondaryColor") || need->need_secondary) { - if(need->need_secondary<1) need->need_secondary = 1; - nvarying+=1; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_frontSecondaryColorSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_frontSecondaryColorSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FrontSecondaryColor", "_gl4es_FrontSecondaryColor"); - } - if(strstr(Tmp, "gl_BackSecondaryColor") || (need->need_secondary==2)) { - need->need_secondary = 2; - nvarying+=1; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_backSecondaryColorSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_backSecondaryColorSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_BackSecondaryColor", "_gl4es_BackSecondaryColor"); - } - if(strstr(Tmp, "gl_FogFragCoord") || need->need_fogcoord) { - need->need_fogcoord = 1; - nvarying+=1; - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_fogcoordSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_fogcoordSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FogFragCoord", "_gl4es_FogFragCoord"); - } - // Get the max_texunit and the calc notexarray - if(strstr(Tmp, "gl_TexCoord") || need->need_texcoord!=-1) { - int ntex = need->need_texcoord; - // Try to determine max gl_TexCoord used - char* p = Tmp; - int notexarray_ok = 1; - while((p=strstr(p, gl_TexCoordSource))) { - p+=strlen(gl_TexCoordSource); - if(*p>='0' && *p<='9') { - int n = (*p) - '0'; - if(p[1]>='0' && p[1]<='9') - n = n*10 + (p[1] - '0'); - if (ntexhardext.maxvarying && !need->need_clean && notexarray_ok) { - notexarray = 1; - need->need_notexarray = 1; + int fpeShader = (strstr(pEntry, fpeshader_signature)!=NULL)?1:0; + int maskbefore = 4|(isVertex?1:2); + int maskafter = 8|(isVertex?1:2); + if((globals4es.dbgshaderconv&maskbefore)==maskbefore) { + printf("Shader source%s:\n%s\n", pEntry, fpeShader?" (FPEShader generated)":""); } - // prefer notexarray... - if(!isVertex && notexarray_ok && !need->need_clean) { - notexarray = 1; - need->need_notexarray = 1; - } - // check constraints - if (!notexarray && ntex+nvarying>hardext.maxvarying) ntex = hardext.maxvarying - nvarying; - need->need_texcoord = ntex; - char d[100]; - if(notexarray) { - for (int k=0; kneed_texs |= (1<need_texcoord = -1; + need->need_clean = 1; // no hack, this is a dummy need structure + } + int notexarray = globals4es.notexarray || need->need_notexarray || fpeShader; + + //const char* GLESUseFragHighp = "#extension GL_OES_fragment_precision_high : enable\n"; // does this one is needed? + char GLESFullHeader[512]; + int wanthighp = !fpeShader; + if(wanthighp && !hardext.highp) wanthighp = 0; + int versionHeader = 0; + printf("version string: %s", versionString); + if(versionString && (strcmp(versionString, "120")==0 || strcmp(versionString, "110")==0 || strstr(versionString, "150") != NULL)) + version120 = forwardPort ? 1 : 0; + if(version120) { + if(hardext.glsl120) versionHeader = 1; + else if(1) versionHeader = 4; + else if(hardext.glsl310es) versionHeader = 2; + else if(hardext.glsl300es) { versionHeader = 3; /* location on uniform not supported ! */ } + /* else no location or in / out are supported */ + } + //sprintf(GLESFullHeader, GLESHeader, (wanthighp && hardext.highp==1 && !isVertex)?GLESUseFragHighp:"", (wanthighp)?"highp":"mediump", (wanthighp)?"highp":"mediump"); + sprintf(GLESFullHeader, GLESHeader[versionHeader], "", (wanthighp)?"highp":"mediump", (wanthighp)?"highp":"mediump"); + + int tmpsize = strlen(pBuffer)*2+strlen(GLESFullHeader)+100; + char* Tmp = (char*)calloc(1, tmpsize); + strcpy(Tmp, pBuffer); + + // and now change the version header, and add default precision + char* newptr; + newptr=strstr(Tmp, "#version"); + if (!newptr) { + Tmp = InplaceInsert(Tmp, GLESFullHeader, Tmp, &tmpsize); } else { - sprintf(d, gl4es_texcoordSource, ntex+1); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), d, Tmp, &tmpsize); - headline+=gl4es_countline(d); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_TexCoord", "_gl4es_TexCoord"); - // set textures as all ntex used - for (int k=0; kneed_texs |= (1<='0' && *p<='9') { - int n = 0; - while(*p>='0' && *p<='9') - n = n*10 + (*(p++) - '0'); - - if (ntexneed_texcoord; else ++ntex; - // change gl_TextureMatrix[X] to gl_TextureMatrix_X if possible - int change_textmat = notexarray; - if(!change_textmat) { - change_textmat = 1; - char* p = Tmp; - while(change_textmat && (p=strstr(p, "gl_TextureMatrix["))) { - p += strlen("gl_TextureMatrix["); - while((*p)>='0' && (*p)<='9') ++p; - if((*p)!=']') - change_textmat = 0; - } - } - if(change_textmat) { - for (int k=0; kneed_normalmatrix && !hardext.highp) - ishighp = 0; - if(!hardext.highp && !isVertex) - need->need_normalmatrix = 1; - } - if(builtin_matrix[i].matrix == MAT_MV) { - if(need->need_mvmatrix && !hardext.highp) - ishighp = 0; - if(!hardext.highp && !isVertex) - need->need_mvmatrix = 1; - } - if(builtin_matrix[i].matrix == MAT_MVP) { - if(need->need_mvpmatrix && !hardext.highp) - ishighp = 0; - if(!hardext.highp && !isVertex) - need->need_mvpmatrix = 1; - } - if(builtin_matrix[i].texarray) - sprintf(def, "uniform %s%s %s[%d];\n", (ishighp)?"highp ":"mediump ", builtin_matrix[i].type, builtin_matrix[i].name, ntex); - else - sprintf(def, "uniform %s%s %s;\n", (ishighp)?"highp ":"mediump ", builtin_matrix[i].type, builtin_matrix[i].name); - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline++), def, Tmp, &tmpsize); - } - } + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESUseTexture3D, Tmp, &tmpsize); + headline++; } - } - // Handling of gl_LightSource[x].halfVector => normalize(gl_LightSource[x].position - gl_Vertex), but what if in the FragShader ? + // check if gl_FragDepth is used + int fragdepth = (strstr(pBuffer, "gl_FragDepth"))?1:0; + const char* GLESUseFragDepth = "#extension GL_EXT_frag_depth : enable\n"; + const char* GLESFakeFragDepth = "mediump float fakeFragDepth = 0.0;\n"; + if (fragdepth) { + /* If #extension is used, it should be placed before the second line of the header. */ + if(hardext.fragdepth) + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESUseFragDepth, Tmp, &tmpsize); + else + Tmp = InplaceInsert(GetLine(Tmp, headline-1), GLESFakeFragDepth, Tmp, &tmpsize); + headline++; + } + // check if the shader uses 3D textures + int threed_texture = (strstr(pBuffer, "sampler3D"))?1:0; + const char* GLESUse3DTexture = "#extension GL_OES_texture_3D : enable\n"; + if(threed_texture) { + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESUse3DTexture, Tmp, &tmpsize); // no fallback possible if device does not support 3D textures + } + + int derivatives = (strstr(pBuffer, "dFdx(") || strstr(pBuffer, "dFdy(") || strstr(pBuffer, "fwidth("))?1:0; + const char* GLESUseDerivative = "#extension GL_OES_standard_derivatives : enable\n"; + // complete fake value... A better thing should be use.... + const char* GLESFakeDerivative = "float dFdx(float p) {return 0.0001;}\nvec2 dFdx(vec2 p) {return vec2(0.0001);}\nvec3 dFdx(vec3 p) {return vec3(0.0001);}\n" + "float dFdy(float p) {return 0.0001;}\nvec2 dFdy(vec2 p) {return vec2(0.0001);}\nvec3 dFdy(vec3 p) {return vec3(0.0001);}\n" + "float fwidth(float p) {return abs(dFdx(p))+abs(dFdy(p));}\nvec2 fwidth(vec2 p) {return abs(dFdx(p))+abs(dFdy(p));}\n" + "vec3 fwidth(vec3 p) {return abs(dFdx(p))+abs(dFdy(p));}\n"; + if (derivatives) { + /* If #extension is used, it should be placed before the second line of the header. */ + if(hardext.derivatives) + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESUseDerivative, Tmp, &tmpsize); + else + Tmp = InplaceInsert(GetLine(Tmp, headline-1), GLESFakeDerivative, Tmp, &tmpsize); + headline++; + } + // check if draw_buffers may be used (no fallback here :( ) + if(hardext.maxdrawbuffers>1 && strstr(pBuffer, "gl_FragData[")) { + Tmp = InplaceInsert(GetLine(Tmp, 1), useEXTDrawBuffers, Tmp, &tmpsize); + } + // if some functions are used, add some int/float alternative + if(!fpeShader && !globals4es.nointovlhack) { + if(strstr(Tmp, "pow(") || strstr(Tmp, "pow (")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), HackAltPow, Tmp, &tmpsize); + } + if(strstr(Tmp, "max(") || strstr(Tmp, "max (")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), HackAltMax, Tmp, &tmpsize); + } + if(strstr(Tmp, "min(") || strstr(Tmp, "min (")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), HackAltMin, Tmp, &tmpsize); + } + if(strstr(Tmp, "clamp(") || strstr(Tmp, "clamp (")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), HackAltClamp, Tmp, &tmpsize); + } + if(strstr(Tmp, "mod(") || strstr(Tmp, "mod (")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), HackAltMod, Tmp, &tmpsize); + } + } + if(!isVertex && hardext.shaderlod && + (FindString(Tmp, "tLod") || FindString(Tmp, "texture2DProjLod") + || FindString(Tmp, "textureCubeLod") + || FindString(Tmp, "texture2DGradARB") || FindString(Tmp, "texture2DProjGradARB")|| FindString(Tmp, "textureCubeGradARB") + )) { + const char* GLESUseShaderLod = "#extension GL_EXT_shader_texture_lod : enable\n"; + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESUseShaderLod, Tmp, &tmpsize); + } + if(!isVertex && (FindString(Tmp, "texture2DLod"))) { + if(hardext.shaderlod) { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DLod", "texture2DLodEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DLod", "_gl4es_texture2DLod"); + Tmp = InplaceInsert(GetLine(Tmp, headline), texture2DLodAlt, Tmp, &tmpsize); + } + } + if(!isVertex && (FindString(Tmp, "texture2DProjLod"))) { + if(hardext.shaderlod) { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DProjLod", "texture2DProjLodEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DProjLod", "_gl4es_texture2DProjLod"); + Tmp = InplaceInsert(GetLine(Tmp, headline), texture2DProjLodAlt, Tmp, &tmpsize); + } + } + if(!isVertex && (FindString(Tmp, "textureCubeLod"))) { + if(hardext.shaderlod) { + if(!hardext.cubelod) + Tmp = InplaceReplace(Tmp, &tmpsize, "textureCubeLod", "textureCubeLodEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "textureCubeLod", "_gl4es_textureCubeLod"); + Tmp = InplaceInsert(GetLine(Tmp, headline), textureCubeLodAlt, Tmp, &tmpsize); + } + } + if(!isVertex && (FindString(Tmp, "texture2DGradARB"))) { + if(hardext.shaderlod) { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DGradARB", "texture2DGradEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DGradARB", "_gl4es_texture2DGrad"); + Tmp = InplaceInsert(GetLine(Tmp, headline), texture2DGradAlt, Tmp, &tmpsize); + } + } + if(!isVertex && (FindString(Tmp, "texture2DProjGradARB"))) { + if(hardext.shaderlod) { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DProjGradARB", "texture2DProjGradEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "texture2DProjGradARB", "_gl4es_texture2DProjGrad"); + Tmp = InplaceInsert(GetLine(Tmp, headline), texture2DProjGradAlt, Tmp, &tmpsize); + } + } + if(!isVertex && (FindString(Tmp, "textureCubeGradARB"))) { + if(hardext.shaderlod) { + if(!hardext.cubelod) + Tmp = InplaceReplace(Tmp, &tmpsize, "textureCubeGradARB", "textureCubeGradEXT"); + } else { + Tmp = InplaceReplace(Tmp, &tmpsize, "textureCubeGradARB", "_gl4es_textureCubeGrad"); + Tmp = InplaceInsert(GetLine(Tmp, headline), textureCubeGradAlt, Tmp, &tmpsize); + } + } + // now check to remove trailling "f" after float, as it's not supported too + newptr = Tmp; + // simple state machine... + int state = 0; + while (*newptr!=0x00) { + switch(state) { + case 0: + if ((*newptr >= '0') && (*newptr <= '9')) + state = 1; // integer part + else if (*newptr == '.') + state = 2; // fractional part + else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) + state = 0; // separator + else + state = 3; // something else + break; + case 1: // integer part + if ((*newptr >= '0') && (*newptr <= '9')) + state = 1; // integer part + else if (*newptr == '.') + state = 2; // fractional part + else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) + state = 0; // separator + else if (*newptr == 'f' ) { + // remove that f + memmove(newptr, newptr+1, strlen(newptr+1)+1); + newptr--; + } else + state = 3; + break; + case 2: // fractionnal part + if ((*newptr >= '0') && (*newptr <= '9')) + state = 2; + else if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) + state = 0; // separator + else if (*newptr == 'f' ) { + // remove that f + memmove(newptr, newptr+1, strlen(newptr+1)+1); + newptr--; + } else + state = 3; + break; + case 3: + if ((*newptr==' ') || (*newptr==0x0d) || (*newptr==0x0a) || (*newptr=='-') || (*newptr=='+') || (*newptr=='*') || (*newptr=='/') || (*newptr=='(') || (*newptr==')' || (*newptr=='>') || (*newptr=='<'))) + state = 0; // separator + else + state = 3; + break; + } + newptr++; + } + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FragDepth", (hardext.fragdepth)?"gl_FragDepthEXT":"fakeFragDepth"); + // builtin attribs + if(isVertex) { + // ANGLE already has ftransform, so skip it +#ifndef __APPLE__ + // check for ftransform function + if(strstr(Tmp, "ftransform(")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_ftransformSource, Tmp, &tmpsize); + // don't increment headline count, as all variying and attributes should be created before + } +#endif + // check for builtin OpenGL attributes... + int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); + for (int i=0; ineed_color) { + if(need->need_color<1) need->need_color = 1; + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_Color", (need->need_color==1)?"gl_FrontColor":"(gl_FrontFacing?gl_FrontColor:gl_BackColor)"); + } + if(strstr(Tmp, "gl_FrontColor") || need->need_color) { + if(need->need_color<1) need->need_color = 1; + nvarying+=1; + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_frontColorSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_frontColorSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FrontColor", "_gl4es_FrontColor"); + } + if(strstr(Tmp, "gl_BackColor") || (need->need_color==2)) { + need->need_color = 2; + nvarying+=1; + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_backColorSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_backColorSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_BackColor", "_gl4es_BackColor"); + } + if(strstr(Tmp, "gl_SecondaryColor") || need->need_secondary) { + if(need->need_secondary<1) need->need_secondary = 1; + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_SecondaryColor", (need->need_secondary==1)?"gl_FrontSecondaryColor":"(gl_FrontFacing?gl_FrontSecondaryColor:gl_BackSecondaryColor)"); + } + if(strstr(Tmp, "gl_FrontSecondaryColor") || need->need_secondary) { + if(need->need_secondary<1) need->need_secondary = 1; + nvarying+=1; + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_frontSecondaryColorSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_frontSecondaryColorSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FrontSecondaryColor", "_gl4es_FrontSecondaryColor"); + } + if(strstr(Tmp, "gl_BackSecondaryColor") || (need->need_secondary==2)) { + need->need_secondary = 2; + nvarying+=1; + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_backSecondaryColorSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_backSecondaryColorSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_BackSecondaryColor", "_gl4es_BackSecondaryColor"); + } + if(strstr(Tmp, "gl_FogFragCoord") || need->need_fogcoord) { + need->need_fogcoord = 1; + nvarying+=1; + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_fogcoordSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_fogcoordSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FogFragCoord", "_gl4es_FogFragCoord"); + } + // Get the max_texunit and the calc notexarray + if(strstr(Tmp, "gl_TexCoord") || need->need_texcoord!=-1) { + int ntex = need->need_texcoord; + // Try to determine max gl_TexCoord used + char* p = Tmp; + int notexarray_ok = 1; + while((p=strstr(p, gl_TexCoordSource))) { + p+=strlen(gl_TexCoordSource); + if(*p>='0' && *p<='9') { + int n = (*p) - '0'; + if(p[1]>='0' && p[1]<='9') + n = n*10 + (p[1] - '0'); + if (ntexhardext.maxvarying && !need->need_clean && notexarray_ok) { + notexarray = 1; + need->need_notexarray = 1; + } + // prefer notexarray... + if(!isVertex && notexarray_ok && !need->need_clean) { + notexarray = 1; + need->need_notexarray = 1; + } + // check constaints + if (!notexarray && ntex+nvarying>hardext.maxvarying) ntex = hardext.maxvarying - nvarying; + need->need_texcoord = ntex; + char d[100]; + if(notexarray) { + for (int k=0; kneed_texs |= (1<need_texs |= (1<='0' && *p<='9') { + int n = 0; + while(*p>='0' && *p<='9') + n = n*10 + (*(p++) - '0'); + + if (ntexneed_texcoord; else ++ntex; + // change gl_TextureMatrix[X] to gl_TextureMatrix_X if possible + int change_textmat = notexarray; + if(!change_textmat) { + change_textmat = 1; + char* p = Tmp; + while(change_textmat && (p=strstr(p, "gl_TextureMatrix["))) { + p += strlen("gl_TextureMatrix["); + while((*p)>='0' && (*p)<='9') ++p; + if((*p)!=']') + change_textmat = 0; + } + } + if(change_textmat) { + for (int k=0; kneed_normalmatrix && !hardext.highp) + ishighp = 0; + if(!hardext.highp && !isVertex) + need->need_normalmatrix = 1; + } + if(builtin_matrix[i].matrix == MAT_MV) { + if(need->need_mvmatrix && !hardext.highp) + ishighp = 0; + if(!hardext.highp && !isVertex) + need->need_mvmatrix = 1; + } + if(builtin_matrix[i].matrix == MAT_MVP) { + if(need->need_mvpmatrix && !hardext.highp) + ishighp = 0; + if(!hardext.highp && !isVertex) + need->need_mvpmatrix = 1; + } + if(builtin_matrix[i].texarray) + sprintf(def, "uniform %s%s %s[%d];\n", (ishighp)?"highp ":"mediump ", builtin_matrix[i].type, builtin_matrix[i].name, ntex); + else + sprintf(def, "uniform %s%s %s;\n", (ishighp)?"highp ":"mediump ", builtin_matrix[i].type, builtin_matrix[i].name); + Tmp = InplaceInsert(GetLine(Tmp, headline++), def, Tmp, &tmpsize); + } + } + } + } + // Handling of gl_LightSource[x].halfVector => normalize(gl_LightSource[x].position - gl_Vertex), but what if in the FragShader ? /* if(strstr(Tmp, "halfVector")) { char *p = Tmp; while((p=strstr(p, "gl_LightSource["))) { char *p2 = strchr(p, ']'); if (p2 && !strncmp(p2, "].halfVector", strlen("].halfVector"))) { - // found an occurrence, lets change + // found an occurence, lets change char p3[500]; strncpy(p3,p, (p2-p)+1); p3[(p2-p)+1]='\0'; char p4[500], p5[500]; sprintf(p4, "%s.halfVector", p3); sprintf(p5, "normalize(normalize(%s.position.xyz) + vec3(0., 0., 1.))", p3); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, p4, p5); + Tmp = InplaceReplace(Tmp, &tmpsize, p4, p5); p = Tmp; } else ++p; } }*/ - // cleaning up the "centroid" keyword... - if(strstr(Tmp, "centroid")) - { - char *p = Tmp; - while((p=strstr(p, "centroid"))!=NULL) + // cleaning up the "centroid" keyword... + if(strstr(Tmp, "centroid")) { - if(p[8]==' ' || p[8]=='\t') { // what next... - const char* p2 = gl4es_get_next_str(p+8); - if(strcmp(p2, "uniform")==0 || strcmp(p2, "varying")==0) { - memset(p, ' ', 8); // erase the keyword... + char *p = Tmp; + while((p=strstr(p, "centroid"))!=NULL) + { + if(p[8]==' ' || p[8]=='\t') { // what next... + const char* p2 = GetNextStr(p+8); + if(strcmp(p2, "uniform")==0 || strcmp(p2, "varying")==0) { + memset(p, ' ', 8); // erase the keyword... + } + } + p+=8; } - } - p+=8; } - } - - // check for builtin OpenGL gl_LightSource & friends - if(strstr(Tmp, "gl_LightSourceParameters") || strstr(Tmp, "gl_LightSource")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_LightSourceParametersSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_LightSourceParametersSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightSourceParameters", "_gl4es_LightSourceParameters"); - } - if(strstr(Tmp, "gl_LightModelParameters") || strstr(Tmp, "gl_LightModel")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_LightModelParametersSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_LightModelParametersSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightModelParameters", "_gl4es_LightModelParameters"); - } - if(strstr(Tmp, "gl_LightModelProducts") || strstr(Tmp, "gl_FrontLightModelProduct") || strstr(Tmp, "gl_BackLightModelProduct")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_LightModelProductsSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_LightModelProductsSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightModelProducts", "_gl4es_LightModelProducts"); - } - if(strstr(Tmp, "gl_LightProducts") || strstr(Tmp, "gl_FrontLightProduct") || strstr(Tmp, "gl_BackLightProduct")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_LightProductsSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_LightProductsSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightProducts", "_gl4es_LightProducts"); - } - if(strstr(Tmp, "gl_MaterialParameters ") || (strstr(Tmp, "gl_FrontMaterial")) || strstr(Tmp, "gl_BackMaterial")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_MaterialParametersSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_MaterialParametersSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_MaterialParameters", "_gl4es_MaterialParameters"); - } - if(strstr(Tmp, "gl_LightSource")) { - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightSource", "_gl4es_LightSource"); - } - if(strstr(Tmp, "gl_LightModel")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_LightModel", "_gl4es_LightModel"); - if(strstr(Tmp, "gl_FrontLightModelProduct")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FrontLightModelProduct", "_gl4es_FrontLightModelProduct"); - if(strstr(Tmp, "gl_BackLightModelProduct")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_BackLightModelProduct", "_gl4es_BackLightModelProduct"); - if(strstr(Tmp, "gl_FrontLightProduct")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FrontLightProduct", "_gl4es_FrontLightProduct"); - if(strstr(Tmp, "gl_BackLightProduct")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_BackLightProduct", "_gl4es_BackLightProduct"); - if(strstr(Tmp, "gl_FrontMaterial")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FrontMaterial", "_gl4es_FrontMaterial"); - if(strstr(Tmp, "gl_BackMaterial")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_BackMaterial", "_gl4es_BackMaterial"); - if(strstr(Tmp, "gl_MaxLights")) - { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_MaxLightsSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_MaxLightsSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_MaxLights", "_gl4es_MaxLights"); - } - if(strstr(Tmp, "gl_NormalScale")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_normalscaleSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_normalscaleSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_NormalScale", "_gl4es_NormalScale"); - } - if(strstr(Tmp, "gl_InstanceID") || strstr(Tmp, "gl_InstanceIDARB")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_instanceID, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_instanceID); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_InstanceIDARB", "_gl4es_InstanceID"); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_InstanceID", "_gl4es_InstanceID"); - } - if(strstr(Tmp, "gl_ClipPlane")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_clipplanesSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_clipplanesSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ClipPlane", "_gl4es_ClipPlane"); - } - if(strstr(Tmp, "gl_MaxClipPlanes")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_MaxClipPlanesSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_MaxClipPlanesSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_MaxClipPlanes", "_gl4es_MaxClipPlanes"); - } - if(strstr(Tmp, "gl_PointParameters") || strstr(Tmp, "gl_Point")) + // check for builtin OpenGL gl_LightSource & friends + if(strstr(Tmp, "gl_LightSourceParameters") || strstr(Tmp, "gl_LightSource")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_PointSpriteSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_PointSpriteSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_PointParameters", "_gl4es_PointParameters"); + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_LightSourceParametersSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_LightSourceParametersSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightSourceParameters", "_gl4es_LightSourceParameters"); } - if(strstr(Tmp, "gl_Point")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_Point", "_gl4es_Point"); - if(strstr(Tmp, "gl_FogParameters") || strstr(Tmp, "gl_Fog")) + if(strstr(Tmp, "gl_LightModelParameters") || strstr(Tmp, "gl_LightModel")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), hardext.highp?gl4es_FogParametersSourceHighp:gl4es_FogParametersSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_FogParametersSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_FogParameters", "_gl4es_FogParameters"); + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_LightModelParametersSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_LightModelParametersSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightModelParameters", "_gl4es_LightModelParameters"); + } + if(strstr(Tmp, "gl_LightModelProducts") || strstr(Tmp, "gl_FrontLightModelProduct") || strstr(Tmp, "gl_BackLightModelProduct")) + { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_LightModelProductsSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_LightModelProductsSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightModelProducts", "_gl4es_LightModelProducts"); + } + if(strstr(Tmp, "gl_LightProducts") || strstr(Tmp, "gl_FrontLightProduct") || strstr(Tmp, "gl_BackLightProduct")) + { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_LightProductsSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_LightProductsSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightProducts", "_gl4es_LightProducts"); + } + if(strstr(Tmp, "gl_MaterialParameters ") || (strstr(Tmp, "gl_FrontMaterial")) || strstr(Tmp, "gl_BackMaterial")) + { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_MaterialParametersSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_MaterialParametersSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_MaterialParameters", "_gl4es_MaterialParameters"); + } + if(strstr(Tmp, "gl_LightSource")) { + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightSource", "_gl4es_LightSource"); + } + if(strstr(Tmp, "gl_LightModel")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_LightModel", "_gl4es_LightModel"); + if(strstr(Tmp, "gl_FrontLightModelProduct")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FrontLightModelProduct", "_gl4es_FrontLightModelProduct"); + if(strstr(Tmp, "gl_BackLightModelProduct")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_BackLightModelProduct", "_gl4es_BackLightModelProduct"); + if(strstr(Tmp, "gl_FrontLightProduct")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FrontLightProduct", "_gl4es_FrontLightProduct"); + if(strstr(Tmp, "gl_BackLightProduct")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_BackLightProduct", "_gl4es_BackLightProduct"); + if(strstr(Tmp, "gl_FrontMaterial")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_FrontMaterial", "_gl4es_FrontMaterial"); + if(strstr(Tmp, "gl_BackMaterial")) + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_BackMaterial", "_gl4es_BackMaterial"); + if(strstr(Tmp, "gl_MaxLights")) + { + Tmp = InplaceInsert(GetLine(Tmp, 2), gl4es_MaxLightsSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_MaxLightsSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_MaxLights", "_gl4es_MaxLights"); + } + if(strstr(Tmp, "gl_NormalScale")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_normalscaleSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_normalscaleSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_NormalScale", "_gl4es_NormalScale"); + } + if(strstr(Tmp, "gl_InstanceID") || strstr(Tmp, "gl_InstanceIDARB")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_instanceID, Tmp, &tmpsize); + headline+=CountLine(gl4es_instanceID); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_InstanceIDARB", "_gl4es_InstanceID"); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_InstanceID", "_gl4es_InstanceID"); + } + if(strstr(Tmp, "gl_ClipPlane")) { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_clipplanesSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_clipplanesSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_ClipPlane", "_gl4es_ClipPlane"); + } + if(strstr(Tmp, "gl_MaxClipPlanes")) { + Tmp = InplaceInsert(GetLine(Tmp, 2), gl4es_MaxClipPlanesSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_MaxClipPlanesSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_MaxClipPlanes", "_gl4es_MaxClipPlanes"); } - if(strstr(Tmp, "gl_Fog")) - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_Fog", "_gl4es_Fog"); - if(strstr(Tmp, "gl_TextureEnvColor")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texenvcolorSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texenvcolorSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_TextureEnvColor", "_gl4es_TextureEnvColor"); - } - if(strstr(Tmp, "gl_EyePlaneS")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgeneyeSource[0], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgeneyeSource[0]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_EyePlaneS", "_gl4es_EyePlaneS"); - } - if(strstr(Tmp, "gl_EyePlaneT")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgeneyeSource[1], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgeneyeSource[1]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_EyePlaneT", "_gl4es_EyePlaneT"); - } - if(strstr(Tmp, "gl_EyePlaneR")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgeneyeSource[2], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgeneyeSource[2]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_EyePlaneR", "_gl4es_EyePlaneR"); - } - if(strstr(Tmp, "gl_EyePlaneQ")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgeneyeSource[3], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgeneyeSource[3]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_EyePlaneQ", "_gl4es_EyePlaneQ"); - } - if(strstr(Tmp, "gl_ObjectPlaneS")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgenobjSource[0], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgenobjSource[0]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ObjectPlaneS", "_gl4es_ObjectPlaneS"); - } - if(strstr(Tmp, "gl_ObjectPlaneT")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgenobjSource[1], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgenobjSource[1]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ObjectPlaneT", "_gl4es_ObjectPlaneT"); - } - if(strstr(Tmp, "gl_ObjectPlaneR")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgenobjSource[2], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgenobjSource[2]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ObjectPlaneR", "_gl4es_ObjectPlaneR"); - } - if(strstr(Tmp, "gl_ObjectPlaneQ")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline), gl4es_texgenobjSource[3], Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_texgenobjSource[3]); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ObjectPlaneQ", "_gl4es_ObjectPlaneQ"); - } - if(strstr(Tmp, "gl_MaxTextureUnits")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_MaxTextureUnitsSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_MaxTextureUnitsSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_MaxTextureUnits", "_gl4es_MaxTextureUnits"); - } - if(strstr(Tmp, "gl_MaxTextureCoords")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_MaxTextureCoordsSource, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_MaxTextureCoordsSource); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_MaxTextureCoords", "_gl4es_MaxTextureCoords"); - } - if(strstr(Tmp, "gl_ClipVertex")) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_ClipVertex, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_ClipVertex); - Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "gl_ClipVertex", gl4es_ClipVertexSource); - need->need_clipvertex = 1; - } else if(isVertex && need && need->need_clipvertex) { - Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, 2), gl4es_ClipVertex, Tmp, &tmpsize); - headline+=gl4es_countline(gl4es_ClipVertex); - char *p = strchr(gl4es_find_string_nc(Tmp, "main"), '{'); // find the openning curly bracket of main - if(p) { - // add regular clipping at start of main - Tmp = gl4es_inplace_insert(p+1, gl4es_ClipVertex_clip, Tmp, &tmpsize); + if(strstr(Tmp, "gl_PointParameters") || strstr(Tmp, "gl_Point")) + { + Tmp = InplaceInsert(GetLine(Tmp, headline), gl4es_PointSpriteSource, Tmp, &tmpsize); + headline+=CountLine(gl4es_PointSpriteSource); + Tmp = InplaceReplace(Tmp, &tmpsize, "gl_PointParameters", "_gl4es_PointParameters"); } - } - //oldprogram uniforms... - if(gl4es_find_string(Tmp, gl_ProgramEnv)) { - // check if array can be removed - int maxind = -1; - int noarray_ok = 1; - char* p = Tmp; - while(noarray_ok && (p=gl4es_find_string_nc(p, gl_ProgramEnv))) { - p+=strlen(gl_ProgramEnv); - if(*p=='[') { - ++p; - if(*p>='0' && *p<='9') { - int n = (*p) - '0'; - if(p[1]>='0' && p[1]<='9') - n = n*10 + (p[1] - '0'); - if (maxind='0' && *p<='9') { + int n = (*p) - '0'; + if(p[1]>='0' && p[1]<='9') + n = n*10 + (p[1] - '0'); + if (maxind='0' && *p<='9') { - int n = (*p) - '0'; - if(p[1]>='0' && p[1]<='9') - n = n*10 + (p[1] - '0'); - if (maxind='0' && *p<='9') { + int n = (*p) - '0'; + if(p[1]>='0' && p[1]<='9') + n = n*10 + (p[1] - '0'); + if (maxind 1) { + const char* GLESBackport = "#define texture2D texture\n#define attribute in\n#define varying out\n"; + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESBackport, Tmp, &tmpsize); + }else { + const char* GLESForwardPort = "#define texture texture2D\n #define textureProj texture2DProj\n #define mod(a,b) (int(a) - int(b) * int(a/b))\n"; + Tmp = InplaceInsert(GetLine(Tmp, 1), GLESForwardPort, Tmp, &tmpsize); + } + + // finish + if((globals4es.dbgshaderconv&maskafter)==maskafter) { + printf("New Shader source:\n%s\n", Tmp); + } + // clean preproc'd source + if(pEntry!=pBuffer) + free(pBuffer); + return Tmp; } int isBuiltinAttrib(const char* name) { @@ -1286,15 +1282,15 @@ int isBuiltinMatrix(const char* name) { for (int i=0; i='0' && name[l+2]<='9') - n = n*10 + name[l+2]-'0'; + n = n*10 + name[l+2]-'0'; ret+=n*4; } } @@ -1305,61 +1301,61 @@ int isBuiltinMatrix(const char* name) { const char* hasBuiltinAttrib(const char* vertexShader, int Att) { if(!vertexShader) // can happens (like if the shader is a pure GLES2 one) - return NULL; + return NULL; // first search for the string const char* ret = NULL; if(hardext.maxvattrib>8) { - int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); - for (int i=0; i='0' && name[l]<='9') - n = n*10 + name[l++]-'0'; - return gl_VA[n]; - } - return name; + // no need to check for compressed array here... + int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); + for(int i=0; i='0' && name[l]<='9') + n = n*10 + name[l++]-'0'; + return gl_VA[n]; + } + return name; } const char* builtinAttribInternalName(const char* name) { - // no need to check for compressed array here... - int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); - for(int i=0; i='0' && name[l]<='9') - n = n*10 + name[l++]-'0'; - return gl4es_VA[n]; - } - return name; + // no need to check for compressed array here... + int n = sizeof(builtin_attrib)/sizeof(builtin_attrib_t); + for(int i=0; i='0' && name[l]<='9') + n = n*10 + name[l++]-'0'; + return gl4es_VA[n]; + } + return name; } diff --git a/src/main/cpp/gl/gl4es/gl/shaderconv.h b/src/main/cpp/gl/gl4es/gl/shaderconv.h index ff6ed4c..b3aebfe 100644 --- a/src/main/cpp/gl/gl4es/gl/shaderconv.h +++ b/src/main/cpp/gl/gl4es/gl/shaderconv.h @@ -4,7 +4,8 @@ #include "gles.h" #include "program.h" -char* ConvertShader(const char* pBuffer, int isVertex, shaderconv_need_t *need); +char * ConvertShaderConditionally(struct shader_s * shader_source); +char* ConvertShader(const char* pBuffer, int isVertex, shaderconv_need_t *need, int forwardPort); int isBuiltinAttrib(const char* name); int isBuiltinMatrix(const char* name); diff --git a/src/main/cpp/gl/gl4es/gl/string_utils.c b/src/main/cpp/gl/gl4es/gl/string_utils.c index fb04824..95c445c 100644 --- a/src/main/cpp/gl/gl4es/gl/string_utils.c +++ b/src/main/cpp/gl/gl4es/gl/string_utils.c @@ -8,6 +8,67 @@ const char* AllSeparators = " \t\n\r.,;()[]{}-<>+*/%&\\\"'^$=!:?"; char* gl4es_resize_if_needed(char* pBuffer, int *size, int addsize); +void AppendToEnd(char **str, const char *suffix) { + size_t len = strlen(*str); + size_t suffixLen = strlen(suffix); + char *newStr = (char *)malloc(len + suffixLen + 1); + if (newStr == NULL) { + return; + } + strcpy(newStr, *str); + strcpy(newStr + len, suffix); + free(*str); + *str = newStr; +} +void InsertAtBeginning(char **str, const char *prefix) { + size_t len = strlen(*str); + size_t prefixLen = strlen(prefix); + char *newStr = (char *)malloc(len + prefixLen + 1); + strcpy(newStr, prefix); + strcpy(newStr + prefixLen, *str); + free(*str); + *str = newStr; +} + + +char * InplaceReplaceByIndex(char* pBuffer, int* size, const int startIndex, const int endIndex, const char* replacement) +{ + //printf("BY INDEX: %s", replacement); + //printf("BY INDEX: %i", strlen(replacement)); + int length_difference; + if(endIndex < startIndex) + length_difference = strlen(replacement) + (endIndex - startIndex); + else if(endIndex == startIndex) + length_difference = strlen(replacement) - 1; // The initial char gets replaced + else + length_difference = strlen(replacement) - (endIndex - startIndex); // Can be negative if repl is smaller + pBuffer = gl4es_resize_if_needed(pBuffer, size, length_difference); + //printf("BEFORE MOVING: \n%s", pBuffer); + // Move the end of the string + memmove(pBuffer + startIndex + strlen(replacement) , pBuffer + endIndex + 1, strlen(pBuffer) - endIndex + 1); + //printf("AFTER MOVING 1: \n%s", pBuffer); + // Insert the replacement + memcpy(pBuffer + startIndex, replacement, strlen(replacement)); + //strncpy(pBuffer + startIndex, replacement, strlen(replacement)); + //printf("AFTER MOVING 2: \n%s", pBuffer); + return pBuffer; +} +/** + * Insert the string at the index, pushing "every chars to the right" + * @param source The shader as a string + * @param sourceLength The ALLOCATED length of the shader + * @param insertPoint The index at which the string is inserted. + * @param insertedString The string to insert + * @return The shader as a string, maybe in a different memory location + */ +char * InplaceInsertByIndex(char * source, int *sourceLength, const int insertPoint, const char *insertedString){ + int insertLength = strlen(insertedString); + source = gl4es_resize_if_needed(source, sourceLength, insertLength); + memmove(source + insertPoint + insertLength, source + insertPoint, strlen(source) - insertPoint + 1); + memcpy(source + insertPoint, insertedString, insertLength); + return source; +} + char* gl4es_inplace_replace(char* pBuffer, int* size, const char* S, const char* D) { int lS = strlen(S), lD = strlen(D); @@ -26,7 +87,7 @@ char* gl4es_inplace_replace(char* pBuffer, int* size, const char* S, const char* p+=lD; } else p+=lS; } - + return pBuffer; } @@ -129,13 +190,21 @@ char* gl4es_resize_if_needed(char* pBuffer, int *size, int addsize) { char* p = pBuffer; int newsize = strlen(pBuffer)+addsize+1; if (newsize>*size) { - newsize += 100; + //newsize += 100; p = (char*)realloc(pBuffer, newsize); *size=newsize; } return p; } +int isDigit(char value){ + return (value >= '0' && value <= '9'); +} + +int isValidFunctionName(char value){ + return ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value == '_')); +} + char* gl4es_append(char* pBuffer, int* size, const char* S) { char* p =pBuffer; p = gl4es_resize_if_needed(pBuffer, size, strlen(S)); @@ -243,6 +312,27 @@ char* gl4es_inplace_replace_simple(char* pBuffer, int* size, const char* S, cons // next p+=lD; } - + return pBuffer; } + + +// for vgpu/shaderconv.c +const char* FindString(const char* pBuffer, const char* S) __attribute__((alias("gl4es_find_string"))); +char* FindStringNC(char* pBuffer, const char* S) __attribute__((alias("gl4es_find_string_nc"))); +int CountString(const char* pBuffer, const char* S) __attribute__((alias("gl4es_count_string"))); +char* ResizeIfNeeded(char* pBuffer, int *size, int addsize) __attribute__((alias("gl4es_resize_if_needed"))); +char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D) __attribute__((alias("gl4es_inplace_replace"))); +char* Append(char* pBuffer, int* size, const char* S) __attribute__((alias("gl4es_append"))); +char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size) __attribute__((alias("gl4es_inplace_insert"))); +char* GetLine(char* pBuffer, int num) __attribute__((alias("gl4es_getline"))); +int CountLine(const char* pBuffer) __attribute__((alias("gl4es_countline"))); +int GetLineFor(const char* pBuffer, const char* S) __attribute__((alias("gl4es_getline_for"))); +char* StrNext(char *pBuffer, const char* S) __attribute__((alias("gl4es_str_next"))); +char* NextStr(char* pBuffer) __attribute__((alias("gl4es_next_str"))); +char* PrevStr(char* Str, char* pBuffer) __attribute__((alias("gl4es_prev_str"))); +char* NextBlank(char* pBuffer) __attribute__((alias("gl4es_next_blank"))); +char* NextLine(char* pBuffer) __attribute__((alias("gl4es_next_line"))); +const char* GetNextStr(char* pBuffer) __attribute__((alias("gl4es_get_next_str"))); +int CountStringSimple(char* pBuffer, const char* S) __attribute__((alias("gl4es_countstring_simple"))); +char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D) __attribute__((alias("gl4es_inplace_replace_simple"))); \ No newline at end of file diff --git a/src/main/cpp/gl/gl4es/gl/string_utils.h b/src/main/cpp/gl/gl4es/gl/string_utils.h index ed01890..be88093 100644 --- a/src/main/cpp/gl/gl4es/gl/string_utils.h +++ b/src/main/cpp/gl/gl4es/gl/string_utils.h @@ -20,11 +20,40 @@ char* gl4es_prev_str(char* Str, char* pBuffer); // go to previous non "blank" char* gl4es_next_blank(char* pBuffer); // go to next "blank" char* gl4es_next_line(char* pBuffer); // go to next new line (crlf not included) + const char* gl4es_get_next_str(char* pBuffer); // get a (static) copy of next str (until next separator), can be a simple number or separator also // those function don't try to be smart with separators... int gl4es_countstring_simple(char* pBuffer, const char* S); char* gl4es_inplace_replace_simple(char* pBuffer, int* size, const char* S, const char* D); +// dare not to change their names into gl4es_xxx :( +int isDigit(char value); +int isValidFunctionName(char value); +void AppendToEnd(char **str, const char *suffix); +void InsertAtBeginning(char **str, const char *prefix); + +char * InplaceReplaceByIndex(char* pBuffer, int* size, int startIndex, int endIndex, const char* replacement); +char * InplaceInsertByIndex(char * source, int *sourceLength, int insertPoint, const char *insertedString); + +extern const char* FindString(const char* pBuffer, const char* S); +extern char* FindStringNC(char* pBuffer, const char* S); +extern int CountString(const char* pBuffer, const char* S); +extern char* ResizeIfNeeded(char* pBuffer, int *size, int addsize); +extern char* InplaceReplace(char* pBuffer, int* size, const char* S, const char* D); +extern char* Append(char* pBuffer, int* size, const char* S); +extern char* InplaceInsert(char* pBuffer, const char* S, char* master, int* size); +extern char* GetLine(char* pBuffer, int num); +extern int CountLine(const char* pBuffer); +extern int GetLineFor(const char* pBuffer, const char* S); +extern char* StrNext(char *pBuffer, const char* S); +extern char* NextStr(char* pBuffer); +extern char* PrevStr(char* Str, char* pBuffer); +extern char* NextBlank(char* pBuffer); +extern char* NextLine(char* pBuffer); +extern const char* GetNextStr(char* pBuffer); +extern int CountStringSimple(char* pBuffer, const char* S); +extern char* InplaceReplaceSimple(char* pBuffer, int* size, const char* S, const char* D); + #endif // _GL4ES_STRING_UTILS_H_ diff --git a/src/main/cpp/gl/gl4es/gl/texture_params.c b/src/main/cpp/gl/gl4es/gl/texture_params.c index e36bc61..a55d741 100644 --- a/src/main/cpp/gl/gl4es/gl/texture_params.c +++ b/src/main/cpp/gl/gl4es/gl/texture_params.c @@ -400,7 +400,7 @@ void APIENTRY_GL4ES gl4es_glTexParameterf(GLenum target, GLenum pname, GLfloat p gl4es_glTexParameterfv(target, pname, ¶m); } void gl4es_glTexParameterf_real(GLenum target, GLenum pname, GLfloat param) { - DBG(SHUT_LOGD("MobileGlues-gl4es: glTexParameterfv(%s, %s, [%f(%s)...])\n", PrintEnum(target), PrintEnum(pname), params[0], PrintEnum(params[0]));) + DBG(SHUT_LOGD("MobileGlues-gl4es: glTexParameterfv(%s, %s, [%f(%s)...])\n", PrintEnum(target), PrintEnum(pname), param, PrintEnum(param));) GLfloat* params = ¶m; if(!glstate->list.pending) { PUSH_IF_COMPILING(glTexParameterfv); @@ -462,7 +462,7 @@ void APIENTRY_GL4ES gl4es_glTexParameteri(GLenum target, GLenum pname, GLint par gl4es_glTexParameterfv(target, pname, &fparam); } void gl4es_glTexParameteri_real(GLenum target, GLenum pname, GLint param) { - DBG(SHUT_LOGD("MobileGlues-gl4es: glTexParameterfv(%s, %s, [%f(%s)...])\n", PrintEnum(target), PrintEnum(pname), params[0], PrintEnum(params[0]));) + DBG(SHUT_LOGD("MobileGlues-gl4es: glTexParameterfv(%s, %s, [%f(%s)...])\n", PrintEnum(target), PrintEnum(pname), param, PrintEnum(param));) if(!glstate->list.pending) { GLfloat *params = ¶m; PUSH_IF_COMPILING(glTexParameterfv); diff --git a/src/main/cpp/gl/gl4es/gl/uniform.c b/src/main/cpp/gl/gl4es/gl/uniform.c index 60465c1..ba756d4 100644 --- a/src/main/cpp/gl/gl4es/gl/uniform.c +++ b/src/main/cpp/gl/gl4es/gl/uniform.c @@ -1,3 +1,4 @@ +#include #include "uniform.h" #include "../glx/hardext.h" @@ -227,6 +228,10 @@ void GoUniformiv(program_t *glprogram, GLint location, int size, int count, cons return; } m = kh_value(glprogram->uniform, k); + if(m->type == GL_FLOAT && count == 1) { + glUniform1f(location, (float)*value); + return; + } if(size != n_uniform(m->type) || !is_uniform_int(m->type) || count>m->size) { errorShim(GL_INVALID_OPERATION); return; diff --git a/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.c b/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.c new file mode 100644 index 0000000..643400c --- /dev/null +++ b/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.c @@ -0,0 +1,1358 @@ +// +// Created by serpentspirale on 13/01/2022. +// +#include +#include +#include +#include "shaderconv.h" +#include "../string_utils.h" +#include "../logs.h" +#include "../const.h" +#include "../../glx/hardext.h" +#include "../shaderconv.h" +#include "../gl4es.h" +#include "../loader.h" + +int NO_OPERATOR_VALUE = 9999; + + +#include +#include +#include +#include +#include + +int testGenericShader(struct shader_s* shader_source) { + // check the current shader is valid for compilation + LOAD_GLES2(glCreateShader); + LOAD_GLES2(glShaderSource); + LOAD_GLES2(glCompileShader); + LOAD_GLES2(glGetShaderiv); + LOAD_GLES2(glDeleteShader); + + GLuint shad = gl4es_gles_glCreateShader(shader_source->type); + gl4es_gles_glShaderSource(shad, 1, (const GLchar *const *)(&shader_source->converted), NULL); + gl4es_gles_glCompileShader(shad); + GLint compiled; + gl4es_gles_glGetShaderiv(shad, GL_COMPILE_STATUS, &compiled); + /* + if(!compiled) { + LOAD_GLES2(glGetShaderInfoLog) + char buff[500]; + gl4es_gles_glGetShaderInfoLog(shad, 500, NULL, buff); + SHUT_LOGD("LIBGL: \"%s\" failed, message:\n%s\n", version, buff); + } + */ + gl4es_gles_glDeleteShader(shad); + + return compiled; +} + +int startsWith(char* str, char* prefix) { + return strncmp(str, prefix, strlen(prefix)) == 0; +} + +char* process_uniform_declarations_for_c(char* glslCode); + +/** + * Makes more and more destructive conversions to make the shader compile + * @return The shader as a string + */ +char * ConvertShaderConditionally(struct shader_s * shader_source){ + int shaderCompileStatus; + + // First, vanilla gl4es, no forward port + shader_source->converted = ConvertShader(shader_source->source, shader_source->type == GL_VERTEX_SHADER ? 1 : 0,&shader_source->need, 0); + shaderCompileStatus = testGenericShader(shader_source); + + // Then, attempt back porting if desired of constrained to do so + if(!shaderCompileStatus) { + shader_source->converted = ConvertShader(shader_source->source, shader_source->type == GL_VERTEX_SHADER ? 1 : 0,&shader_source->need, 0); + shader_source->converted = ConvertShaderVgpu(shader_source); + shaderCompileStatus = testGenericShader(shader_source); + } + + // At last resort, use forward porting + if(!shaderCompileStatus && hardext.glsl300es){ + shader_source->converted = ConvertShader(shader_source->source, shader_source->type == GL_VERTEX_SHADER ? 1 : 0, &shader_source->need, 1); + shader_source->converted = ConvertShaderVgpu(shader_source); + } + + // Process uniform declarations + shader_source->converted = process_uniform_declarations_for_c(shader_source->converted); + return shader_source->converted; +} + + +/** Convert the shader through multiple steps + * @param source The start of the shader as a string*/ +char * ConvertShaderVgpu(struct shader_s * shader_source){ + + if (0){ + SHUT_LOGD("New VGPU Shader source:\n%s\n", shader_source->converted); + } + + // Get the shader source + char * source = shader_source->converted; + int sourceLength = strlen(source) + 1; + // For now, skip stuff + if(FindString(source, "#version 100")){ + if(0 || 1){ + if (shader_source->type == GL_VERTEX_SHADER){ + source = ReplaceVariableName(source, &sourceLength, "in", "attribute"); + source = ReplaceVariableName(source, &sourceLength, "out", "varying"); + }else{ + source = ReplaceVariableName(source, &sourceLength, "in", "varying"); + source = ReplaceFragmentOut(source, &sourceLength); + } + + // Well, we don't have gl_VertexID on OPENGL 1 + source = ReplaceVariableName(source, &sourceLength, "gl_VertexID", "0"); + source = InplaceReplaceSimple(source, &sourceLength, "ivec", "vec"); + source = InplaceReplaceSimple(source, &sourceLength, "bvec", "vec"); + source = InplaceReplaceSimple(source, &sourceLength, "flat ", ""); + + source = BackportConstArrays(source, &sourceLength); + int insertPoint = FindPositionAfterVersion(source); + source = InplaceInsertByIndex(source, &sourceLength, insertPoint + 1, "#define texelFetch(a, b, c) vec4(1.0,1.0,1.0,1.0) \n"); + + source = ReplaceModOperator(source, &sourceLength); + + if (0){ + SHUT_LOGD("New VGPU Shader conversion:\n%s\n", source); + } + + return source; + } + + // Else, skip the conversion + if (0){ + SHUT_LOGD("SKIPPING OLD SHADER CONVERSION \n%s\n", source); + } + return source; + } + + + // Remove 'const' storage qualifier + //printf("REMOVING CONST qualifiers"); + //source = RemoveConstInsideBlocks(source, &sourceLength); + //source = ReplaceVariableName(source, &sourceLength, "const", " "); + + + + + // Avoid keyword clash with gl4es #define blocks + //printf("REPLACING KEYWORDS"); + source = InplaceReplaceSimple(source, &sourceLength, "#define texture2D texture\n", ""); + source = ReplaceVariableName(source, &sourceLength, "sample", "vgpu_Sample"); + source = ReplaceVariableName(source, &sourceLength, "texture", "vgpu_texture"); + + source = ReplaceFunctionName(source, &sourceLength, "texture2D", "texture"); + source = ReplaceFunctionName(source, &sourceLength, "texture3D", "texture"); + source = ReplaceFunctionName(source, &sourceLength, "texture2DLod", "textureLod"); + + + //printf("REMOVING \" CHARS "); + // " not really supported here + source = InplaceReplaceSimple(source, &sourceLength, "\"", ""); + + // For now let's hope no extensions are used + // TODO deal with extensions but properly + //printf("REMOVING EXTENSIONS"); + //source = RemoveUnsupportedExtensions(source); + + // OpenGL natively supports non const global initializers, not OPENGL ES except if we add an extension + //printf("ADDING EXTENSIONS\n"); + source = InsertExtensions(source, &sourceLength); + + //printf("REPLACING mod OPERATORS"); + // No support for % operator, so we replace it + source = ReplaceModOperator(source, &sourceLength); + + //printf("COERCING INT TO FLOATS"); + // Hey we don't want to deal with implicit type stuff + source = CoerceIntToFloat(source, &sourceLength); + + //printf("FIXING ARRAY ACCESS"); + // Avoid any weird type trying to be an index for an array + source = ForceIntegerArrayAccess(source, &sourceLength); + + //printf("WRAPPING FUNCTION"); + // Since everything is a float, we need to overload WAY TOO MANY functions + source = WrapIvecFunctions(source, &sourceLength); + + //printf("REMOVING DUBIOUS DEFINES"); + source = InplaceReplaceSimple(source, &sourceLength, "#define texture texture2D\n", ""); + source = InplaceReplaceSimple(source, &sourceLength, "#define attribute in\n", ""); + source = InplaceReplaceSimple(source, &sourceLength, "#define varying out\n", ""); + + if (shader_source->type == GL_VERTEX_SHADER){ + source = ReplaceVariableName(source, &sourceLength, "attribute", "in"); + source = ReplaceVariableName(source, &sourceLength, "varying", "out"); + }else{ + source = ReplaceVariableName(source, &sourceLength, "varying", "in"); + } + + // Draw buffers aren't dealt the same on OPEN GL|ES + if(shader_source->type == GL_FRAGMENT_SHADER && doesShaderVersionContainsES(source) ){ + //printf("REPLACING FRAG DATA"); + source = ReplaceGLFragData(source, &sourceLength); + //printf("REPLACING FRAG COLOR"); + source = ReplaceGLFragColor(source, &sourceLength); + } + + //printf("FUCKING UP PRECISION"); + source = ReplacePrecisionQualifiers(source, &sourceLength, shader_source->type == GL_VERTEX_SHADER); + + source = ProcessSwitchCases(source, &sourceLength); + + if (0){ + SHUT_LOGD("New VGPU Shader conversion:\n%s\n", source); + } + + return source; +} + +static const char* switch_template = " switch (%n%[^)] { "; +static const char* case_template = " case %n%[^:] "; +static const char* declaration_template = " const float %s = %s ;"; + +#define VARIABLE_SIZE 1024 +#define MODE_SWITCH 0 +#define MODE_CASE 1 + + +/** + * Convert switches or cases to be usable with the current int to float conversion + * @param source The shader as a string + * @param sourceLength The shader allocated length + * @param mode Whether to scan and fix switches or cases + * @return The shader as a string, converted appropriately, maybe in a different memory location +*/ +char* FindAndCorrect(char* source, int* length, int mode) { + const char* template = mode == MODE_SWITCH ? switch_template : mode == MODE_CASE ? case_template : NULL; + char* scan_source = source; + char template_string[VARIABLE_SIZE]; + size_t string_offset; + size_t offset = 0; + unsigned char rewind = 0; + while(1) { + int scan_result = sscanf(scan_source, template, &string_offset, &template_string); + if(scan_result == 0) { + scan_source++; + continue; + }else if(scan_result == EOF) { + break; + } + offset = string_offset + (strstr(scan_source, mode == MODE_SWITCH ? "{" : mode == MODE_CASE ? ":" : 0) - scan_source); // find it by hand cause sscanf has trouble with two %n operators + string_offset += (scan_source - source); // convert it from relative to scan to relative to base + if(mode == MODE_SWITCH && !strstr(template_string, "int(") ) { // already cast to int, skip + size_t insert_end_offset = string_offset + strlen(template_string); + source = InplaceInsertByIndex(source, length, insert_end_offset, ")"); + source = InplaceInsertByIndex(source, length, string_offset, "int("); + rewind = 1; + } + if(mode == MODE_CASE) { + if(!isdigit(template_string[0])) { // cant have a number without the first digit, and the standard doesnt permit variable names starting with numbers + char decltemplate_formatted[VARIABLE_SIZE]; + float declared_value = 99; + snprintf(decltemplate_formatted, VARIABLE_SIZE, declaration_template, template_string, "%f"); + SHUT_LOGD("Scanning with template %s\n", decltemplate_formatted); + char* scanbase = source; + while(1) { + int result = sscanf(scanbase, decltemplate_formatted, &declared_value); + if(result == 0) { + scanbase++; + continue; + }else if(result == EOF) { + SHUT_LOGD("Scanned the whole shader and didn't find declaration for %s with template \"%s\"\n", template_string, decltemplate_formatted); + abort(); + } + break; + } + char integer[VARIABLE_SIZE]; + snprintf(integer, VARIABLE_SIZE, "%i", (int)declared_value); + size_t replace_end_offset = string_offset + strlen(template_string)-1; + source = InplaceReplaceByIndex(source, length, string_offset, replace_end_offset, integer); + rewind = 1; + } + } + if(rewind) { + scan_source = source; // since inplace replacement operations are destructive, the scan will be rewound after doing them + rewind = 0; + }else scan_source += offset; + } + return source; +} + +/** + *Convert switches and cases in the shader to be usable with the current int to float coercion + * @param source The shader as a string + * @param sourceLength The shader allocated length + * @return The shader as a string, converted appropriately, maybe in a different memory location +*/ + +char* ProcessSwitchCases(char* source, int* length) { + source = FindAndCorrect(source, length, MODE_SWITCH); + source = FindAndCorrect(source, length, MODE_CASE); + return source; +} + +/** + * Turn const arrays and its accesses into a function and function calls + * @param source The shader as a string + * @param sourceLength The shader allocated length + * @return The shader as a string, maybe in a different memory location + */ +char * BackportConstArrays(char *source, int * sourceLength){ + unsigned long startPoint = strstrPos(source, "const"); + if(startPoint == 0){ + return source; + } + int constStart, constStop; + GetNextWord(source, startPoint, &constStart, &constStop); // Catch the "const" + + int typeStart, typeStop; + GetNextWord(source, constStop, &typeStart, &typeStop); // Catch the type, without [] + + int variableNameStart, variableNameStop; + GetNextWord(source, typeStop, &variableNameStart, &variableNameStop); // Catch the var name + char * variableName = ExtractString(source, variableNameStart, variableNameStop); + + //Now, verify the data type is actually an array + char * tokenStart = strstr(source + typeStop, "["); + if( tokenStart != NULL && (tokenStart - source) < variableNameStart){ + // We've found an array. So we need to get to the starting parenthesis and isolate each member + int startArray = GetNextTokenPosition(source, variableNameStop, '(', ""); + int endArray = GetClosingTokenPosition(source, startArray); + + // First pass, to count the amount of entries in the array + int arrayEntryCount = -1; + int currentPoint = startArray; + while (currentPoint < endArray){ + ++arrayEntryCount; + currentPoint = GetClosingTokenPositionTokenOverride(source, currentPoint, ','); + } + if(currentPoint == endArray){ + ++arrayEntryCount; + } + + // Now we know how many entries we have, we can copy data + int entryStart = startArray + 1; + int entryEnd; + for(int j=0; j= 300; +} + +char * WrapIvecFunctions(char * source, int * sourceLength){ + source = WrapFunction(source, sourceLength, "texelFetch", "vgpu_texelFetch", "\nvec4 vgpu_texelFetch(sampler2D sampler, vec2 P, float lod){return texelFetch(sampler, ivec2(int(P.x), int(P.y)), int(lod));}\n" + "vec4 vgpu_texelFetch(sampler3D sampler, vec3 P, float lod){return texelFetch(sampler, ivec3(int(P.x), int(P.y), int(P.z)), int(lod));}\n" + "vec4 vgpu_texelFetch(sampler2DArray sampler, vec3 P, float lod){return texelFetch(sampler, ivec3(int(P.x), int(P.y), int(P.z)), int(lod));}\n" + "#ifdef GL_EXT_texture_buffer\n" + "vec4 vgpu_texelFetch(samplerBuffer sampler, float P){return texelFetch(sampler, int(P));}\n" + "#endif\n" + "#ifdef GL_OES_texture_storage_multisample_2d_array\n" + "vec4 vgpu_texelFetch(sampler2DMS sampler, vec2 P, float _sample){return texelFetch(sampler, ivec2(int(P.x), int(P.y)), int(_sample));}\n" + "vec4 vgpu_texelFetch(sampler2DMSArray sampler, vec3 P, float _sample){return texelFetch(sampler, ivec3(int(P.x), int(P.y), int(P.z)), int(_sample));}\n" + "#endif\n"); + + source = WrapFunction(source, sourceLength, "textureSize", "vgpu_textureSize", "\nvec2 vgpu_textureSize(sampler2D sampler, float lod){ivec2 size = textureSize(sampler, int(lod));return vec2(size.x, size.y);}\n" + "vec3 vgpu_textureSize(sampler3D sampler, float lod){ivec3 size = textureSize(sampler, int(lod));return vec3(size.x, size.y, size.z);}\n" + "vec2 vgpu_textureSize(samplerCube sampler, float lod){ivec2 size = textureSize(sampler, int(lod));return vec2(size.x, size.y);}\n" + "vec2 vgpu_textureSize(sampler2DShadow sampler, float lod){ivec2 size = textureSize(sampler, int(lod));return vec2(size.x, size.y);}\n" + "vec2 vgpu_textureSize(samplerCubeShadow sampler, float lod){ivec2 size = textureSize(sampler, int(lod));return vec2(size.x, size.y);}\n" + "#ifdef GL_EXT_texture_cube_map_array\n" + "vec3 vgpu_textureSize(samplerCubeArray sampler, float lod){ivec3 size = textureSize(sampler, int(lod));return vec3(size.x, size.y, size.z);}\n" + "vec3 vgpu_textureSize(samplerCubeArrayShadow sampler, float lod){ivec3 size = textureSize(sampler, int(lod));return vec3(size.x, size.y, size.z);}\n" + "#endif\n" + "vec3 vgpu_textureSize(sampler2DArray sampler, float lod){ivec3 size = textureSize(sampler, int(lod));return vec3(size.x, size.y, size.z);}\n" + "vec3 vgpu_textureSize(sampler2DArrayShadow sampler, float lod){ivec3 size = textureSize(sampler, int(lod));return vec3(size.x, size.y, size.z);}\n" + "#ifdef GL_EXT_texture_buffer\n" + "float vgpu_textureSize(samplerBuffer sampler){return float(textureSize(sampler));}\n" + "#endif\n" + "#ifdef GL_OES_texture_storage_multisample_2d_array\n" + "vec2 vgpu_textureSize(sampler2DMS sampler){ivec2 size = textureSize(sampler);return vec2(size.x, size.y);}\n" + "vec3 vgpu_textureSize(sampler2DMSArray sampler){ivec3 size = textureSize(sampler);return vec3(size.x, size.y, size.z);}\n" + "#endif\n"); + + source = WrapFunction(source, sourceLength, "textureOffset", "vgpu_textureOffset", "\nvec4 vgpu_textureOffset(sampler2D tex, vec2 P, vec2 offset, float bias){ivec2 Size = textureSize(tex, 0);return texture(tex, P+offset/vec2(float(Size.x), float(Size.y)), bias);}\n" + "vec4 vgpu_textureOffset(sampler2D tex, vec2 P, vec2 offset){return vgpu_textureOffset(tex, P, offset, 0.0);}\n" + "vec4 vgpu_textureOffset(sampler3D tex, vec3 P, vec3 offset, float bias){ivec3 Size = textureSize(tex, 0);return texture(tex, P+offset/vec3(float(Size.x), float(Size.y), float(Size.z)), bias);}\n" + "vec4 vgpu_textureOffset(sampler3D tex, vec3 P, vec3 offset){return vgpu_textureOffset(tex, P, offset, 0.0);}\n" + "float vgpu_textureOffset(sampler2DShadow tex, vec3 P, vec2 offset, float bias){ivec2 Size = textureSize(tex, 0);return texture(tex, P+vec3(offset.x, offset.y, 0)/vec3(float(Size.x), float(Size.y), 1.0), bias);}\n" + "float vgpu_textureOffset(sampler2DShadow tex, vec3 P, vec2 offset){return vgpu_textureOffset(tex, P, offset, 0.0);}\n" + "vec4 vgpu_textureOffset(sampler2DArray tex, vec3 P, vec2 offset, float bias){ivec3 Size = textureSize(tex, 0);return texture(tex, P+vec3(offset.x, offset.y, 0)/vec3(float(Size.x), float(Size.y), float(Size.z)), bias);}\n" + "vec4 vgpu_textureOffset(sampler2DArray tex, vec3 P, vec2 offset){return vgpu_textureOffset(tex, P, offset, 0.0);}\n"); + + source = WrapFunction(source, sourceLength, "shadow2D", "vgpu_shadow2D", "\nvec4 vgpu_shadow2D(sampler2DShadow shadow, vec3 coord){return vec4(texture(shadow, coord), 0.0, 0.0, 0.0);}\n" + "vec4 vgpu_shadow2D(sampler2DShadow shadow, vec3 coord, float bias){return vec4(texture(shadow, coord, bias), 0.0, 0.0, 0.0);}\n"); + return source; +} + +/** + * Replace a function and its calls by a wrapper version, only if needed + * @param source The shader code as a string + * @param functionName The function to be replaced + * @param wrapperFunctionName The replacing function name + * @param function The wrapper function itself + * @return The shader as a string, maybe in a different memory location + */ +char * WrapFunction(char * source, int * sourceLength, char * functionName, char * wrapperFunctionName, char * wrapperFunction){ + int originalSize = strlen(source); + source = ReplaceFunctionName(source, sourceLength, functionName, wrapperFunctionName); + // If some calls got replaced, add the wrapper + if(originalSize != strlen(source)){ + int insertPoint = FindPositionAfterDirectives(source); + source = InplaceInsertByIndex(source, sourceLength, insertPoint + 1, wrapperFunction); + } + + return source; +} + +/** + * Replace the % operator with a mathematical equivalent (x - y * floor(x/y)) + * @param source The shader as a string + * @return The shader as a string, maybe in a different memory location + */ +char * ReplaceModOperator(char * source, int * sourceLength){ + char * modelString = " mod(x, y) "; + int startIndex, endIndex = 0; + int * startPtr = &startIndex, *endPtr = &endIndex; + + for(int i=0;i<*sourceLength; ++i){ + if(source[i] != '%') continue; + // A mod operator is found ! + char * leftOperand = GetOperandFromOperator(source, i, 0, startPtr); + char * rightOperand = GetOperandFromOperator(source, i, 1, endPtr); + + // Generate a model string to be inserted + char * replacementString = malloc(strlen(modelString) + 1); + strcpy(replacementString, modelString); + int replacementSize = strlen(replacementString); + replacementString = InplaceReplace(replacementString, &replacementSize, "x", leftOperand); + replacementString = InplaceReplace(replacementString, &replacementSize, "y", rightOperand); + + // Insert the new string + source = InplaceReplaceByIndex(source, sourceLength, startIndex, endIndex, replacementString); + + // Free all the temporary strings + free(leftOperand); + free(rightOperand); + free(replacementString); + } + + return source; +} + +/** + * Change all (u)ints to floats. + * This is a hack to avoid dealing with implicit conversions on common operators + * @param source The shader as a string + * @return The shader as a string, maybe in a new memory location + * @see ForceIntegerArrayAccess + */ +char * CoerceIntToFloat(char * source, int * sourceLength){ + // Let's go the "freestyle way" + + // Step 1 is to translate keywords + // Attempt and loop unrolling -> worked well, time to fix my shit I guess + source = ReplaceVariableName(source, sourceLength, "int", "float"); + source = WrapFunction(source, sourceLength, "int", "float", "\n "); + source = ReplaceVariableName(source, sourceLength, "uint", "float"); + source = WrapFunction(source, sourceLength, "uint", "float", "\n "); + + // TODO Yes I could just do the same as above but I'm lazy at times + source = InplaceReplaceSimple(source, sourceLength, "ivec", "vec"); + source = InplaceReplaceSimple(source, sourceLength, "uvec", "vec"); + + source = InplaceReplaceSimple(source, sourceLength, "isampleBuffer", "sampleBuffer"); + source = InplaceReplaceSimple(source, sourceLength, "usampleBuffer", "sampleBuffer"); + + source = InplaceReplaceSimple(source, sourceLength, "isampler", "sampler"); + source = InplaceReplaceSimple(source, sourceLength, "usampler", "sampler"); + + + // Step 3 is slower. + // We need to parse hardcoded values like 1 and turn it into 1.(0) + for(int i=0; i<*sourceLength; ++i){ + + // Avoid version/line directives + if(source[i] == '#' && (source[i + 1] == 'v' || source[i + 1] == 'l') ){ + // Look for the next line + while (source[i] != '\n' && source[i] != '\0'){ + i++; + } + } + + if(!isDigit(source[i])){ continue; } + // So there is a few situations that we have to distinguish: + // functionName1 ( ----- meaning there is SOMETHING on its left side that is related to the number + // function(1, ----- there is something, and it ISN'T related to the number + // float test=3; ----- something on both sides, not related to the number. + // float test=X.2 ----- There is a dot, so it is part of a float already + // float test = 0.00000 ----- I have to backtrack to find the dot + + if(source[i-1] == '.' || source[i+1] == '.') continue;// Number part of a float + if(isValidFunctionName(source[i - 1])) continue; // Char attached to something related + if(isDigit(source[i+1])) continue; // End of number not reached + if(isDigit(source[i-1])){ + // Backtrack to check if the number is floating point + int shouldBeCoerced = 0; + for(int j=1; 1; ++j){ + if(isDigit(source[i-j])) continue; + if(isValidFunctionName(source[i-j])) break; // Function or variable name, don't coerce + if(source[i-j] == '.' || ((source[i-j] == '+' || source[i-j] == '-') && (source[i-j-1] == 'e'|| source[i-j-1] == 'E') )) break; // No coercion, float or scientific notation already + // Nothing found, should be coerced then + shouldBeCoerced = 1; + break; + } + + if(!shouldBeCoerced) continue; + } + + // Now we know there is nothing related to the digit, turn it into a float + source = InplaceInsertByIndex(source, sourceLength, i+1, ".0"); + } + + // TODO Hacks for special built in values and typecasts ? + source = InplaceReplaceSimple(source, sourceLength, "gl_VertexID", "float(gl_VertexID)"); + source = InplaceReplaceSimple(source, sourceLength, "gl_InstanceID", "float(gl_InstanceID)"); + + return source; +} + +/** Force all array accesses to use integers by adding an explicit typecast + * @param source The shader as a string + * @return The shader as a string, maybe at a new memory location */ +char * ForceIntegerArrayAccess(char* source, int * sourceLength){ + char * markerStart = "$"; + char * markerEnd = "`"; + + // Step 1, we need to mark all [] that are empty and must not be changed + int leftCharIndex = 0; + for(int i=0; i< *sourceLength; ++i){ + if(source[i] == '['){ + leftCharIndex = i; + continue; + } + // If a start has been found + if(leftCharIndex){ + if(source[i] == ' ' || source[i] == '\n'){ + continue; + } + // We find the other side and mark both ends + if(source[i] == ']'){ + source[leftCharIndex] = *markerStart; + source[i] = *markerEnd; + } + } + //Something else is there, abort the marking phase for this one + leftCharIndex = 0; + } + + // Step 2, replace the array accesses with a forced typecast version + source = InplaceReplaceSimple(source, sourceLength, "]", ")]"); + source = InplaceReplaceSimple(source, sourceLength, "[", "[int("); + + // Step 3, restore all marked empty [] + source = InplaceReplaceSimple(source, sourceLength, markerStart, "["); + source = InplaceReplaceSimple(source, sourceLength, markerEnd, "]"); + + return source; +} + + +/** Small helper to help evaluate whether to continue or not I guess + * Values over 9900 are not for real operators, more like stop indicators*/ +int GetOperatorValue(char operator){ + if(operator == ',' || operator == ';') return 9998; + if(operator == '=') return 9997; + if(operator == '+' || operator == '-') return 3; + if(operator == '*' || operator == '/' || operator == '%') return 2; + return NO_OPERATOR_VALUE; // Meaning no value; +} + +/** Get the left or right operand, given the last index of the operator + * It bases its ability to get operands by evaluating the priority of operators. + * @param source The shader as a string + * @param operatorIndex The index the operator is found + * @param rightOperand Whether we get the right or left operator + * @param limit The left or right index of the operand + * @return newly allocated string with the operand + */ +char* GetOperandFromOperator(char* source, int operatorIndex, int rightOperand, int * limit){ + int parserState = 0; + int parserDirection = rightOperand ? 1 : -1; + int operandStartIndex = 0, operandEndIndex = 0; + int parenthesesLeft = 0, hasFoundParentheses = 0; + int operatorValue = GetOperatorValue(source[operatorIndex]); + int lastOperator = 0; // Used to determine priority for unary operators + + char parenthesesStart = rightOperand ? '(' : ')'; + char parenthesesEnd = rightOperand ? ')' : '('; + int stringIndex = operatorIndex; + + // Get to the operand + while (parserState == 0){ + stringIndex += parserDirection; + if(source[stringIndex] != ' '){ + parserState = 1; + // Place the mark + if(rightOperand){ + operandStartIndex = stringIndex; + }else{ + operandEndIndex = stringIndex; + } + + // Special case for unary operator when parsing to the right + if(GetOperatorValue(source[stringIndex]) == 3 ){ // 3 is +- operators + stringIndex += parserDirection; + } + } + } + + // Get to the other side of the operand, the twist is here. + while (parenthesesLeft > 0 || parserState == 1){ + + // Look for parentheses + if(source[stringIndex] == parenthesesStart){ + hasFoundParentheses = 1; + parenthesesLeft += 1; + stringIndex += parserDirection; + continue; + } + + if(source[stringIndex] == parenthesesEnd){ + hasFoundParentheses = 1; + parenthesesLeft -= 1; + + // Likely to happen in a function call + if(parenthesesLeft < 0){ + parserState = 3; + if(rightOperand){ + operandEndIndex = stringIndex - 1; + }else{ + operandStartIndex = stringIndex + 1; + } + continue; + } + stringIndex += parserDirection; + continue; + } + + // Small optimisation + if(parenthesesLeft > 0){ + stringIndex += parserDirection; + continue; + } + + // So by now the following assumptions are made + // 1 - We aren't between parentheses + // 2 - No implicit multiplications are present + // 3 - No fuckery with operators like "test = +-+-+-+-+-+-+-+-3;" although I attempt to support them + + // Higher value operators have less priority + int currentValue = GetOperatorValue(source[stringIndex]); + + + // The condition is different due to the evaluation order which is left to right, aside from the unary operators + if((rightOperand ? currentValue >= operatorValue: currentValue > operatorValue)){ + if(currentValue == NO_OPERATOR_VALUE){ + if(source[stringIndex] == ' '){ + stringIndex += parserDirection; + continue; + } + + // Found an operand, so reset the operator eval for unary + if(rightOperand) lastOperator = NO_OPERATOR_VALUE; + + // maybe it is the start of a function ? + if(hasFoundParentheses){ + parserState = 2; + continue; + } + // If no full () set is found, assume we didn't fully travel the operand + stringIndex += parserDirection; + continue; + } + + // Special case when parsing unary operator to the right + if(rightOperand && operatorValue == 3 && lastOperator < currentValue){ + stringIndex += parserDirection; + continue; + } + + // Stop, we found an operator of same worth. + parserState = 3; + if(rightOperand){ + operandEndIndex = stringIndex - 1; + }else{ + operandStartIndex = stringIndex + 1; + } + } + + // Special case for unary operators from the right + if(rightOperand && operatorValue == 3) { // 3 is + - operators + lastOperator = currentValue; + } // Special case for unary operators from the left + if(!rightOperand && operatorValue < 3 && currentValue == 3){ + lastOperator = NO_OPERATOR_VALUE; + for(int j=1; 1; ++j){ + int subCurrentValue = GetOperatorValue(source[stringIndex - j]); + if(subCurrentValue != NO_OPERATOR_VALUE){ + lastOperator = subCurrentValue; + continue; + } + + // No operator value, can be almost anything + if(source[stringIndex - j] == ' ') continue; + // Else we found something. Did we found a high priority operator ? + if(lastOperator <= operatorValue){ // If so, we allow continuing and going out of the loop + stringIndex -= j; + parserState = 1; + break; + } + // No other operator found + operandStartIndex = stringIndex; + parserState = 3; + break; + } + } + stringIndex += parserDirection; + } + + // Status when we get the name of a function and nothing else. + while (parserState == 2){ + if(source[stringIndex] != ' '){ + stringIndex += parserDirection; + continue; + } + if(rightOperand){ + operandEndIndex = stringIndex - 1; + }else{ + operandStartIndex = stringIndex + 1; + } + parserState = 3; + } + + // At this point, we know both the start and end point of our operand, let's copy it + char * operand = malloc(operandEndIndex - operandStartIndex + 2); + memcpy(operand, source+operandStartIndex, operandEndIndex - operandStartIndex + 1); + // Make sure the string is null terminated + operand[operandEndIndex - operandStartIndex + 1] = '\0'; + + // Send back the limitIndex + *limit = rightOperand ? operandEndIndex : operandStartIndex; + + return operand; +} + +/** + * Replace any gl_FragData[n] reference by creating an out variable with the manual layout binding + * @param source The shader source as a string + * @return The shader as a string, maybe at a different memory location + */ +char * ReplaceGLFragData(char * source, int * sourceLength){ + + // 10 is arbitrary, but I don't expect the shader to use so many + // TODO I guess the array could be accessed with one or more spaces :think: + // TODO wait they can access via a variable ! + for (int i = 0; i < 10; ++i) { + // Check for 2 forms on the glFragData and take the first one found + char needle[30]; + sprintf(needle, "gl_FragData[%i]", i); + + // Skip if the draw buffer isn't used at this index + char * useFragData = strstr(source, &needle[0]); + if(useFragData == NULL){ + sprintf(needle, "gl_FragData[int(%i.0)]", i); + useFragData = strstr(source, &needle[0]); + if(useFragData == NULL) continue; + } + + // Construct replacement string + char replacement[20]; + char replacementLine[70]; + sprintf(replacement, "vgpu_FragData%i", i); + sprintf(replacementLine, "\nlayout(location = %i) out mediump vec4 %s;\n", i, replacement); + int insertPoint = FindPositionAfterDirectives(source); + + // And place them into the shader + source = InplaceReplaceSimple(source, sourceLength, &needle[0], &replacement[0]); + source = InplaceInsertByIndex(source, sourceLength, insertPoint + 1, &replacementLine[0]); + } + return source; +} + +/** + * Replace the gl_FragColor + * @param source The shader as a string + * @return The shader a a string, maybe in a different memory location + */ +char * ReplaceGLFragColor(char * source, int * sourceLength){ + if(strstr(source, "gl_FragColor")){ + source = InplaceReplaceSimple(source, sourceLength, "gl_FragColor", "vgpu_FragColor"); + int insertPoint = FindPositionAfterDirectives(source); + source = InplaceInsertByIndex(source, sourceLength, insertPoint + 1, "out mediump vec4 vgpu_FragColor;\n"); + } + return source; +} + +/** + * Remove all extensions right now by replacing them with spaces + * @param source The shader as a string + * @return The shader as a string, maybe in a different memory location + */ +char * RemoveUnsupportedExtensions(char * source){ + //TODO remove only specific extensions ? + for(char * extensionPtr = strstr(source, "#extension "); extensionPtr; extensionPtr = strstr(source, "#extension ")){ + int i = 0; + while(extensionPtr[i] != '\n'){ + extensionPtr[i] = ' '; + ++i; + } + } + return source; +} + +/** + * Replace the variable name in a shader, mostly used to avoid keyword clashing + * @param source The shader as a string + * @param initialName The initial name for the variable + * @param newName The new name for the variable + * @return The shader as a string, maybe in a different memory location + */ +char * ReplaceVariableName(char * source, int * sourceLength, char * initialName, char* newName) { + + char * toReplace = malloc(strlen(initialName) + 3); + char * replacement = malloc(strlen(newName) + 3); + char * charBefore = "{}([];+-*/~!%<>,&| \n\t"; + char * charAfter = ")[];+-*/%<>;,|&. \n\t"; + + // Prepare the fixed part of the strings + strcpy(toReplace+1, initialName); + toReplace[strlen(initialName)+2] = '\0'; + + strcpy(replacement+1, newName); + replacement[strlen(newName)+2] = '\0'; + + for (int i = 0; i < strlen(charBefore); ++i) { + for (int j = 0; j < strlen(charAfter); ++j) { + // Prepare the string to replace + toReplace[0] = charBefore[i]; + toReplace[strlen(initialName)+1] = charAfter[j]; + + // Prepare the replacement string + replacement[0] = charBefore[i]; + replacement[strlen(newName)+1] = charAfter[j]; + + source = InplaceReplaceSimple(source, sourceLength, toReplace, replacement); + } + } + + free(toReplace); + free(replacement); + + return source; +} + +/** + * Replace a function definition and calls to the function to another name + * @param source The shader as a string + * @param sourceLength The shader length + * @param initialName The name be to changed + * @param finalName The name to use instead + * @return The shader as a string, maybe in a different memory location + */ +char * ReplaceFunctionName(char * source, int * sourceLength, char * initialName, char * finalName){ + for(unsigned long currentPosition = 0; 1; currentPosition += strlen(initialName)){ + unsigned long newPosition = strstrPos(source + currentPosition, initialName); + if(newPosition == 0) // No more calls + break; + + // Check if that is indeed a function call on the right side + if (source[GetNextTokenPosition(source, currentPosition + newPosition + strlen(initialName), '(', " \n\t")] != '('){ + currentPosition += newPosition; + continue; // Skip to the next potential call + } + + // Check the naming on the left side + if (isValidFunctionName(source[currentPosition + newPosition - 1])){ + currentPosition += newPosition; + continue; // Skip to the next potential call + } + + // This is a valid function call/definition, replace it + source = InplaceReplaceByIndex(source, sourceLength, currentPosition + newPosition, currentPosition + newPosition + strlen(initialName) - 1, finalName); + currentPosition += newPosition; + } + return source; +} + +/** Remove 'const ' storage qualifier from variables inside {..} blocks + * @param source The pointer to the start of the shader */ +char * RemoveConstInsideBlocks(char* source, int * sourceLength){ + int insideBlock = 0; + char * keyword = "const \0"; + int keywordLength = strlen(keyword); + + + for(int i=0; i< *sourceLength+1; ++i){ + // Step 1, look for a block + if(source[i] == '{'){ + insideBlock += 1; + continue; + } + if(!insideBlock) continue; + + // A block has been found, look for the keyword + if(source[i] == keyword[0]){ + int keywordMatch = 1; + int j = 1; + while (j < keywordLength){ + if (source[i+j] != keyword[j]){ + keywordMatch = 0; + break; + } + j +=1; + } + // A match is found, remove it + if(keywordMatch){ + source = InplaceReplaceByIndex(source, sourceLength, i, i+j - 1, " "); + continue; + } + } + + // Look for an exit + if(source[i] == '}'){ + insideBlock -= 1; + continue; + } + } + return source; +} + +/** Find the first point which is right after most shader directives + * @param source The shader as a string + * @return The index position after the #version line, start of the shader if not found + */ +int FindPositionAfterDirectives(char * source){ + const char * position = FindString(source, "#version"); + if (position == NULL) return 0; + for(int i=7; 1; ++i){ + if(position[i] == '\n'){ + if(position[i+1] == '#') continue; // a directive is present right after, skip + return i; + } + } +} + +int FindPositionAfterVersion(char * source){ + const char * position = FindString(source, "#version"); + if (position == NULL) return 0; + for(int i=7; 1; ++i){ + if(position[i] == '\n'){ + return i; + } + } +} + +/** + * Replace and inserts precision qualifiers as necessary, see LIBGL_VGPU_PRECISION + * @param source The shader as a string + * @param sourceLength The length of the string + * @return The shader as a string, maybe in a different memory location + */ +char * ReplacePrecisionQualifiers(char * source, int * sourceLength, int isVertex){ + + if(!doesShaderVersionContainsES(source)){ + if (0) { + SHUT_LOGD("\nSKIPPING the replacement qualifiers step\n"); + } + return source; + } + + // Step 1 is to remove any "precision" qualifiers + for(unsigned long currentPosition=strstrPos(source, "precision "); currentPosition>0;currentPosition=strstrPos(source, "precision ")){ + // Once a qualifier is found, get to the end of the instruction and replace + int endPosition = GetNextTokenPosition(source, currentPosition, ';', ""); + source = InplaceReplaceByIndex(source, sourceLength, currentPosition, endPosition,""); + } + + // Step 2 is to insert precision qualifiers, even the ones we think are defaults, since there are defaults only for some types + + int insertPoint = FindPositionAfterDirectives(source); + source = InplaceInsertByIndex(source, sourceLength, insertPoint, + "\nprecision lowp sampler2D;\n" + "precision lowp sampler3D;\n" + "precision lowp sampler2DShadow;\n" + "precision lowp samplerCubeShadow;\n" + "precision lowp sampler2DArray;\n" + "precision lowp sampler2DArrayShadow;\n" + "precision lowp samplerCube;\n" + "#ifdef GL_EXT_texture_buffer\n" + "precision lowp samplerBuffer;\n" + "precision lowp imageBuffer;\n" + "#endif\n" + "#ifdef GL_EXT_texture_cube_map_array\n" + "precision lowp imageCubeArray;\n" + "precision lowp samplerCubeArray;\n" + "precision lowp samplerCubeArrayShadow;\n" + "#endif\n" + "#ifdef GL_OES_texture_storage_multisample_2d_array\n" + "precision lowp sampler2DMS;\n" + "precision lowp sampler2DMSArray;\n" + "#endif\n"); + + if(GetShaderVersion(source) > 300){ + source = InplaceInsertByIndex(source, sourceLength,insertPoint, + "\nprecision lowp image2D;\n" + "precision lowp image2DArray;\n" + "precision lowp image3D;\n" + "precision lowp imageCube;\n"); + } + int supportHighp = ((isVertex || hardext.highp) ? 1 : 0); + source = InplaceInsertByIndex(source, sourceLength, insertPoint, supportHighp ? "\nprecision highp float;\n" : "\nprecision medium float;\n"); + + if (1 != 0){ + char * target_precision; + switch (1) { + case 1: target_precision = "highp"; break; + case 2: target_precision = "mediump"; break; + case 3: target_precision = "lowp"; break; + default: target_precision = "highp"; + } + source = ReplaceVariableName(source, sourceLength, "highp", target_precision); + source = ReplaceVariableName(source, sourceLength, "mediump", target_precision); + source = ReplaceVariableName(source, sourceLength, "lowp", target_precision); + } + + return source; +} + +/** + * @param openingToken The opening token + * @return All closing tokens, if available + */ +char * GetClosingTokens(char openingToken){ + switch (openingToken) { + case '(': return ")"; + case '[': return "]"; + case ',': return ",)"; + case '{': return "}"; + case ';': return ";"; + + default: return ""; + } +} + +/** + * @param openingToken The opening token + * @return Whether the token is an opening token + */ +int isOpeningToken(char openingToken){ + return openingToken != ',' && strlen(GetClosingTokens(openingToken)) != 0; +} + +int GetClosingTokenPosition(const char * source, int initialTokenPosition){ + return GetClosingTokenPositionTokenOverride(source, initialTokenPosition, source[initialTokenPosition]); +} + +/** + * Get the index of the closing token within a string, same as initialTokenPosition if not found + * @param source The string to look into + * @param initialTokenPosition The opening token position + * @return The closing token position + */ +int GetClosingTokenPositionTokenOverride(const char * source, int initialTokenPosition, char initialToken){ + // Step 1: Determine the closing token + char openingToken = initialToken; + char * closingTokens = GetClosingTokens(openingToken); + SHUT_LOGD("Closing tokens: %s", closingTokens); + if (strlen(closingTokens) == 0){ + SHUT_LOGD("No closing tokens, somehow \n"); + return initialTokenPosition; + } + + // Step 2: Go through the string to find what we want + for(int i=initialTokenPosition+1; i 0){ + for(int j=0; j< strlen(acceptedChars); ++j){ + if (source[i] == acceptedChars[j]) break; // No tripping, continue + } + return initialPosition; // Tripped, meaning the token is not found + } + + if (source[i] == token){ + return i; + } + } + return initialPosition; +} + +/** + * @param haystack + * @param needle + * @return The position of the first occurence of the needle in the haystack + */ +unsigned long strstrPos(const char * haystack, const char * needle){ + char * substr = strstr(haystack, needle); + if (substr == NULL) return 0; + return (substr - haystack); +} + +/** + * Inserts int(...) on a specific argument from each call to the function + * @param source The shader as a string + * @param functionName The name of the function to manipulate + * @param argumentPosition The position of the argument to manipulate, from 0. If not found, no changes are made. + * @return The shader as a string, maybe in a different memory location + */ +char * insertIntAtFunctionCall(char * source, int * sourceSize, const char * functionName, int argumentPosition){ + //TODO a less naive function for edge-cases ? + unsigned long functionCallPosition = strstrPos(source, functionName); + while(functionCallPosition != 0){ + int openingTokenPosition = GetNextTokenPosition(source, functionCallPosition + strlen(functionName), '(', " \n\r\t"); + if (source[openingTokenPosition] == '('){ + // Function call found, determine the start and end of the argument + int endArgPos = openingTokenPosition; + int startArgPos = openingTokenPosition; + + // Note the additional check to see we aren't at the end of a function + for(int argCount=0; argCount<=argumentPosition && source[startArgPos] != ')'; ++argCount){ + endArgPos = GetClosingTokenPositionTokenOverride(source, endArgPos, ','); + if (argCount == argumentPosition){ + // Argument found, insert the int(...) + source = InplaceInsertByIndex(source, sourceSize, endArgPos+1, ")"); + source = InplaceInsertByIndex(source, sourceSize, startArgPos+1, "int("); + break; + } + // Not the arg we want, got to the next one + startArgPos = endArgPos; + } + } + + // Get the next function call + unsigned long offset = strstrPos(source + functionCallPosition + strlen(functionName), functionName); + if (offset == 0) break; // No more function calls + functionCallPosition += offset + strlen(functionName); + } + return source; +} + +/** + * @param source The shader as a string + * @return The shader version: eg. 310 for #version 310 es + */ +int GetShaderVersion(const char * source){ + // Oh yeah, I won't care much about this function + if(FindString(source, "#version 320 es")){return 320;} + if(FindString(source, "#version 310 es")){return 310;} + if(FindString(source, "#version 300 es")){return 300;} + + // Check for core profile versions + if (FindString(source, "#version 460 core")) return 460; + if (FindString(source, "#version 450 core")) return 450; + if (FindString(source, "#version 440 core")) return 440; + if (FindString(source, "#version 430 core")) return 430; + if (FindString(source, "#version 420 core")) return 420; + if (FindString(source, "#version 410 core")) return 410; + if (FindString(source, "#version 400 core")) return 400; + if (FindString(source, "#version 330 core")) return 330; + if (FindString(source, "#version 150 core")) return 150; + + // Check for compatibility profile versions + if (FindString(source, "#version 460")) return 460; + if (FindString(source, "#version 450")) return 450; + if (FindString(source, "#version 440")) return 440; + if (FindString(source, "#version 430")) return 430; + if (FindString(source, "#version 420")) return 420; + if (FindString(source, "#version 410")) return 410; + if (FindString(source, "#version 400")) return 400; + if (FindString(source, "#version 330")) return 330; + if (FindString(source, "#version 150")) return 150; + if (FindString(source, "#version 140")) return 140; + if (FindString(source, "#version 130")) return 130; + if (FindString(source, "#version 120")) return 120; + if (FindString(source, "#version 110")) return 110; + if (FindString(source, "#version 100")) return 100; + return 100; +} diff --git a/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.h b/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.h new file mode 100644 index 0000000..4bb08f9 --- /dev/null +++ b/src/main/cpp/gl/gl4es/gl/vgpu/shaderconv.h @@ -0,0 +1,47 @@ +// +// Created by serpentspirale on 13/01/2022. +// + +#ifndef UNTITLED_SHADERCONV_H +#define UNTITLED_SHADERCONV_H + +#include "../shader.h" + +char* ConvertShaderVgpu(struct shader_s* shader_source); + +char * GLSLHeader(char* source); +char * RemoveConstInsideBlocks(char* source, int * sourceLength); +char * ForceIntegerArrayAccess(char* source, int * sourceLength); +char * CoerceIntToFloat(char * source, int * sourceLength); +char * ReplaceModOperator(char * source, int * sourceLength); +char * WrapIvecFunctions(char * source, int * sourceLength); +char * WrapFunction(char * source, int * sourceLength, char * functionName, char * wrapperFunctionName, char * wrapperFunction); +int FindPositionAfterDirectives(char * source); +int FindPositionAfterVersion(char * source); +char * ReplaceGLFragData(char * source, int * sourceLength); +char * ReplaceGLFragColor(char * source, int * sourceLength); +char * ReplaceVariableName(char * source, int * sourceLength, char * initialName, char* newName); +char * ReplaceFunctionName(char * source, int * sourceLength, char * initialName, char * finalName); +char * RemoveUnsupportedExtensions(char * source); +int doesShaderVersionContainsES(const char * source); +char *ReplacePrecisionQualifiers(char *source, int *sourceLength, int isVertex); +char * GetClosingTokens(char openingToken); +int isOpeningToken(char openingToken); +int GetClosingTokenPosition(const char * source, int initialTokenPosition); +int GetClosingTokenPositionTokenOverride(const char * source, int initialTokenPosition, char initialToken); +int GetNextTokenPosition(const char * source, int initialPosition, char token, const char * acceptedChars); +void GetNextWord(char *source, int startPoint, int * startWord, int * endWord); +unsigned long strstrPos(const char * haystack, const char * needle); +char * insertIntAtFunctionCall(char * source, int * sourceSize, const char * functionName, int argumentPosition); +char * InsertExtension(char * source, int * sourceLength, int insertPoint, const char * extension); +char * InsertExtensions(char *source, int *sourceLength); +int GetShaderVersion(const char * source); +char * ReplaceFragmentOut(char * source, int *sourceLength); +char * BackportConstArrays(char *source, int * sourceLength); +char * ExtractString(char * source, int startString, int endString); +char* ProcessSwitchCases(char* source, int* length); + + +char* GetOperandFromOperator(char* source, int operatorIndex, int rightOperand, int * limit); + +#endif //UNTITLED_SHADERCONV_H diff --git a/src/main/cpp/gl/gl4es/glx/hardext.c b/src/main/cpp/gl/gl4es/glx/hardext.c index 1c9cf60..ec5f576 100644 --- a/src/main/cpp/gl/gl4es/glx/hardext.c +++ b/src/main/cpp/gl/gl4es/glx/hardext.c @@ -424,23 +424,29 @@ void GetHardwareExtensions(int notest) hardext.vendor = VEND_ARM; else if(strstr(vendor, "Imagination Technologies")) hardext.vendor = VEND_IMGTEC; - if(hardext.esversion>1) { - if(testGLSL("#version 120", 1)) - hardext.glsl120 = 1; - if(testGLSL("#version 300 es", 0)) - hardext.glsl300es = 1; - if(testGLSL("#version 310 es", 1)) - hardext.glsl310es = 1; - } - if(hardext.glsl120) { - SHUT_LOGD("MobileGlues-gl4es: GLSL 120 supported and used\n"); - } - if(hardext.glsl300es) { - SHUT_LOGD("MobileGlues-gl4es: GLSL 300 es supported%s\n", (hardext.glsl120||hardext.glsl310es)?"":" and used"); - } - if(hardext.glsl310es) { - SHUT_LOGD("MobileGlues-gl4es: GLSL 310 es supported%s\n", hardext.glsl120?"":" and used"); - } + + hardext.glsl120 = 0; + hardext.glsl300es = 1; + hardext.glsl310es = 1; + // TODO: Check gles caps + + //if(hardext.esversion>1) { + // if(testGLSL("#version 120", 1)) + // hardext.glsl120 = 1; + // if(testGLSL("#version 300 es", 0)) + // hardext.glsl300es = 1; + // if(testGLSL("#version 310 es", 1)) + // hardext.glsl310es = 1; + //} + //if(hardext.glsl120) { + // SHUT_LOGD("MobileGlues-gl4es: GLSL 120 supported and used\n"); + //} + //if(hardext.glsl300es) { + // SHUT_LOGD("MobileGlues-gl4es: GLSL 300 es supported%s\n", (hardext.glsl120||hardext.glsl310es)?"":" and used"); + //} + //if(hardext.glsl310es) { + // SHUT_LOGD("MobileGlues-gl4es: GLSL 310 es supported%s\n", hardext.glsl120?"":" and used"); + //} #ifndef NOEGL if(strstr(gl4es_egl_eglQueryString(eglDisplay, EGL_EXTENSIONS), "EGL_KHR_gl_colorspace")) { diff --git a/src/main/cpp/gl/gl_native.cpp b/src/main/cpp/gl/gl_native.cpp index 710ed51..9748e4a 100644 --- a/src/main/cpp/gl/gl_native.cpp +++ b/src/main/cpp/gl/gl_native.cpp @@ -32,13 +32,13 @@ NATIVE_FUNCTION_HEAD(void, glClearColor, GLfloat red, GLfloat green, GLfloat blu NATIVE_FUNCTION_HEAD(void, glClearDepthf, GLfloat d) NATIVE_FUNCTION_END_NO_RETURN(void, glClearDepthf, d) NATIVE_FUNCTION_HEAD(void, glClearStencil, GLint s) NATIVE_FUNCTION_END_NO_RETURN(void, glClearStencil, s) NATIVE_FUNCTION_HEAD(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) NATIVE_FUNCTION_END_NO_RETURN(void, glColorMask, red,green,blue,alpha) -NATIVE_FUNCTION_HEAD(void, glCompileShader, GLuint shader) NATIVE_FUNCTION_END_NO_RETURN(void, glCompileShader, shader) +//NATIVE_FUNCTION_HEAD(void, glCompileShader, GLuint shader) NATIVE_FUNCTION_END_NO_RETURN(void, glCompileShader, shader) NATIVE_FUNCTION_HEAD(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) NATIVE_FUNCTION_END_NO_RETURN(void, glCompressedTexImage2D, target,level,internalformat,width,height,border,imageSize,data) NATIVE_FUNCTION_HEAD(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) NATIVE_FUNCTION_END_NO_RETURN(void, glCompressedTexSubImage2D, target,level,xoffset,yoffset,width,height,format,imageSize,data) //NATIVE_FUNCTION_HEAD(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) NATIVE_FUNCTION_END_NO_RETURN(void, glCopyTexImage2D, target,level,internalformat,x,y,width,height,border) //NATIVE_FUNCTION_HEAD(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) NATIVE_FUNCTION_END_NO_RETURN(void, glCopyTexSubImage2D, target,level,xoffset,yoffset,x,y,width,height) -NATIVE_FUNCTION_HEAD(GLuint, glCreateProgram) NATIVE_FUNCTION_END(GLuint, glCreateProgram) -NATIVE_FUNCTION_HEAD(GLuint, glCreateShader, GLenum type) NATIVE_FUNCTION_END(GLuint, glCreateShader, type) +//NATIVE_FUNCTION_HEAD(GLuint, glCreateProgram) NATIVE_FUNCTION_END(GLuint, glCreateProgram) +//NATIVE_FUNCTION_HEAD(GLuint, glCreateShader, GLenum type) NATIVE_FUNCTION_END(GLuint, glCreateShader, type) NATIVE_FUNCTION_HEAD(void, glCullFace, GLenum mode) NATIVE_FUNCTION_END_NO_RETURN(void, glCullFace, mode) //NATIVE_FUNCTION_HEAD(void, glDeleteBuffers, GLsizei n, const GLuint *buffers) NATIVE_FUNCTION_END_NO_RETURN(void, glDeleteBuffers, n,buffers) NATIVE_FUNCTION_HEAD(void, glDeleteFramebuffers, GLsizei n, const GLuint *framebuffers) NATIVE_FUNCTION_END_NO_RETURN(void, glDeleteFramebuffers, n,framebuffers) diff --git a/src/main/cpp/gl/gl_stub.cpp b/src/main/cpp/gl/gl_stub.cpp index 9600479..5c781bc 100644 --- a/src/main/cpp/gl/gl_stub.cpp +++ b/src/main/cpp/gl/gl_stub.cpp @@ -943,7 +943,7 @@ STUB_FUNCTION_HEAD(void, glEvaluateDepthValuesARB,void); STUB_FUNCTION_END_NO_RE //STUB_FUNCTION_HEAD(void, glGetObjectParameterfvARB, GLhandleARB obj, GLenum pname, GLfloat* params); STUB_FUNCTION_END_NO_RETURN(void, glGetObjectParameterfvARB,obj,pname,params) //STUB_FUNCTION_HEAD(void, glGetObjectParameterivARB, GLhandleARB obj, GLenum pname, GLint* params); STUB_FUNCTION_END_NO_RETURN(void, glGetObjectParameterivARB,obj,pname,params) STUB_FUNCTION_HEAD(void, glGetInfoLogARB, GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog); STUB_FUNCTION_END_NO_RETURN(void, glGetInfoLogARB,obj,maxLength,length,infoLog) -STUB_FUNCTION_HEAD(void, glGetAttachedObjectsARB, GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB* obj); STUB_FUNCTION_END_NO_RETURN(void, glGetAttachedObjectsARB,containerObj,maxCount,count,obj) +//STUB_FUNCTION_HEAD(void, ,glGetAttachedObjectsARB GLhandleARB containerObj, GLsizei maxCount, GLsizei* count, GLhandleARB* obj); STUB_FUNCTION_END_NO_RETURN(void, glGetAttachedObjectsARB,containerObj,maxCount,count,obj) STUB_FUNCTION_HEAD(void, glNamedStringARB, GLenum type, GLint namelen, const GLchar* name, GLint stringlen, const GLchar* string); STUB_FUNCTION_END_NO_RETURN(void, glNamedStringARB,type,namelen,name,stringlen,string) STUB_FUNCTION_HEAD(void, glDeleteNamedStringARB, GLint namelen, const GLchar* name); STUB_FUNCTION_END_NO_RETURN(void, glDeleteNamedStringARB,namelen,name) STUB_FUNCTION_HEAD(void, glCompileShaderIncludeARB, GLuint shader, GLsizei count, const GLchar* const*path, const GLint* length); STUB_FUNCTION_END_NO_RETURN(void, glCompileShaderIncludeARB,shader,count,path,length) @@ -1627,8 +1627,8 @@ STUB_FUNCTION_HEAD(void, glFogCoordfvEXT,const GLfloat* coord); STUB_FUNCTION_EN STUB_FUNCTION_HEAD(void, glFogCoorddEXT, GLdouble coord); STUB_FUNCTION_END_NO_RETURN(void, glFogCoorddEXT,coord) STUB_FUNCTION_HEAD(void, glFogCoorddvEXT,const GLdouble* coord); STUB_FUNCTION_END_NO_RETURN(void, glFogCoorddvEXT,coord) STUB_FUNCTION_HEAD(void, glFogCoordPointerEXT, GLenum type, GLsizei stride, const void* pointer); STUB_FUNCTION_END_NO_RETURN(void, glFogCoordPointerEXT,type,stride,pointer) -STUB_FUNCTION_HEAD(void, glFramebufferTexture1DEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); STUB_FUNCTION_END_NO_RETURN(void, glFramebufferTexture1DEXT,target,attachment,textarget,texture,level) -STUB_FUNCTION_HEAD(void, glFramebufferTexture3DEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); STUB_FUNCTION_END_NO_RETURN(void, glFramebufferTexture3DEXT,target,attachment,textarget,texture,level,zoffset) +//STUB_FUNCTION_HEAD(void, glFramebufferTexture1DEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); STUB_FUNCTION_END_NO_RETURN(void, glFramebufferTexture1DEXT,target,attachment,textarget,texture,level) +//STUB_FUNCTION_HEAD(void, glFramebufferTexture3DEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); STUB_FUNCTION_END_NO_RETURN(void, glFramebufferTexture3DEXT,target,attachment,textarget,texture,level,zoffset) STUB_FUNCTION_HEAD(void, glProgramEnvParameters4fvEXT, GLenum target, GLuint index, GLsizei count, const GLfloat* params); STUB_FUNCTION_END_NO_RETURN(void, glProgramEnvParameters4fvEXT,target,index,count,params) STUB_FUNCTION_HEAD(void, glProgramLocalParameters4fvEXT, GLenum target, GLuint index, GLsizei count, const GLfloat* params); STUB_FUNCTION_END_NO_RETURN(void, glProgramLocalParameters4fvEXT,target,index,count,params) //STUB_FUNCTION_HEAD(void, glBindFragDataLocationEXT, GLuint program, GLuint color, const GLchar* name); STUB_FUNCTION_END_NO_RETURN(void, glBindFragDataLocationEXT,program,color,name) diff --git a/src/main/cpp/gl/glsl/glsl_for_es.cpp b/src/main/cpp/gl/glsl/glsl_for_es.cpp index 723fa20..0aab106 100644 --- a/src/main/cpp/gl/glsl/glsl_for_es.cpp +++ b/src/main/cpp/gl/glsl/glsl_for_es.cpp @@ -705,6 +705,11 @@ std::string process_uniform_declarations(const std::string& glslCode) { return result; } +extern "C" char* process_uniform_declarations_for_c(char* glslCode) { + std::string glslCode_str(glslCode); + return strdup(process_uniform_declarations(glslCode_str).c_str()); +} + std::string processOutColorLocations(const std::string& glslCode) { const static std::regex pattern(R"(\n(out highp vec4 outColor)(\d+);)"); const std::string replacement = "\nlayout(location=$2) $1$2;"; @@ -732,13 +737,7 @@ std::string GLSLtoGLSLES(const char* glsl_code, GLenum glsl_type, uint essl_vers } int return_code = -1; - //std::string converted = /*glsl_version<140? GLSLtoGLSLES_1(glsl_code, glsl_type, essl_version, return_code):*/GLSLtoGLSLES_2(glsl_code, glsl_type, essl_version, return_code); - std::string converted; - if (glsl_version<140) { - converted = GLSLtoGLSLES_3(glsl_code, glsl_type, essl_version, return_code); - } else { - converted = GLSLtoGLSLES_2(glsl_code, glsl_type, essl_version, return_code); - } + std::string converted = /*glsl_version<140? GLSLtoGLSLES_1(glsl_code, glsl_type, essl_version, return_code):*/GLSLtoGLSLES_2(glsl_code, glsl_type, essl_version, return_code); if (return_code == 0 && !converted.empty()) { converted = process_uniform_declarations(converted); Cache::get_instance().put(sha256_string.c_str(), converted.c_str()); @@ -750,6 +749,7 @@ std::string GLSLtoGLSLES(const char* glsl_code, GLenum glsl_type, uint essl_vers std::string GLSLtoGLSLES_3(const char *glsl_code, GLenum glsl_type, uint essl_version, int& return_code) { LOG_W("Warning: use gl4es shaderconv to convert shader.") + /* gl4es_code::GL4ES_shaderconv_need_t need; need.need_texcoord = -1; int shaderCompileStatus; @@ -775,6 +775,7 @@ std::string GLSLtoGLSLES_3(const char *glsl_code, GLenum glsl_type, uint essl_ve LOG_D("converted:\n%s", converted) return_code = 0; return std::string(converted); + */ } std::string replace_line_starting_with(const std::string& glslCode, const std::string& starting, const std::string& substitution = "") { diff --git a/src/main/cpp/gl/glsl/glsl_for_es.h b/src/main/cpp/gl/glsl/glsl_for_es.h index fb25a0f..9624908 100644 --- a/src/main/cpp/gl/glsl/glsl_for_es.h +++ b/src/main/cpp/gl/glsl/glsl_for_es.h @@ -21,6 +21,6 @@ std::string GLSLtoGLSLES(const char *glsl_code, GLenum glsl_type, uint esversion std::string GLSLtoGLSLES_1(const char *glsl_code, GLenum glsl_type, uint esversion, int& return_code); std::string GLSLtoGLSLES_2(const char *glsl_code, GLenum glsl_type, uint essl_version, int& return_code); std::string GLSLtoGLSLES_3(const char *glsl_code, GLenum glsl_type, uint essl_version, int& return_code); -int getGLSLVersion(const char* glsl_code); +extern "C" int getGLSLVersion(const char* glsl_code); #endif \ No newline at end of file diff --git a/src/main/cpp/gl/glsl/glslconv_gl4es.cpp b/src/main/cpp/gl/glsl/glslconv_gl4es.cpp index 4d77974..518546d 100644 --- a/src/main/cpp/gl/glsl/glslconv_gl4es.cpp +++ b/src/main/cpp/gl/glsl/glslconv_gl4es.cpp @@ -12,7 +12,7 @@ #include #include -#define DEBUG 1 +#define DEBUG 0 namespace gl4es_code { diff --git a/src/main/cpp/gl/program.cpp b/src/main/cpp/gl/program.cpp index 0aa3068..b3ff436 100644 --- a/src/main/cpp/gl/program.cpp +++ b/src/main/cpp/gl/program.cpp @@ -88,10 +88,15 @@ void glBindFragDataLocation(GLuint program, GLuint color, const GLchar *name) { shaderInfo.frag_data_changed = 1; } +extern "C" EXPORT GLuint glCreateProgram() { + LOG() + GLuint program = gl4es_glCreateProgram(); + CHECK_GL_ERROR + return program; +} + void glLinkProgram(GLuint program) { LOG() - GET_GL4ES_FUNC(void, glLinkProgram, GLuint program) - CALL_GL4ES_FUNC(glLinkProgram, program) LOG_D("glLinkProgram(%d)", program) if (!shaderInfo.converted.empty() && shaderInfo.frag_data_changed) { GLES.glShaderSource(shaderInfo.id, 1, (const GLchar * const*) &shaderInfo.frag_data_changed_converted, nullptr); @@ -111,7 +116,9 @@ void glLinkProgram(GLuint program) { shaderInfo.converted = ""; shaderInfo.frag_data_changed_converted = nullptr; shaderInfo.frag_data_changed = 0; - GLES.glLinkProgram(program); + //GLES.glLinkProgram(program); + GET_GL4ES_FUNC(void, glLinkProgram, GLuint program) + CALL_GL4ES_FUNC(glLinkProgram, program) CHECK_GL_ERROR } @@ -191,4 +198,13 @@ EXPORT GLint glGetProgramResourceLocationIndex(GLuint program, GLenum programInt } EXPORT void glGetProgramResourceLocationIndexARB(GLuint program, GLenum programInterface, const char *name) __attribute__((alias("glGetProgramResourceLocationIndex"))); +EXPORT void glGetAttachedObjectsARB(GLhandleARB program, GLsizei maxCount, GLsizei* count, GLhandleARB* objects) { + if (program == 0 || glIsProgram(program) == GL_FALSE) { + return; + } + glGetAttachedShaders(program, maxCount, count, (GLuint*)objects); +} + +EXPORT GLhandleARB glCreateProgramARB() { return glCreateProgram(); } + } \ No newline at end of file diff --git a/src/main/cpp/gl/shader.cpp b/src/main/cpp/gl/shader.cpp index 860436a..b5d3adc 100644 --- a/src/main/cpp/gl/shader.cpp +++ b/src/main/cpp/gl/shader.cpp @@ -40,10 +40,22 @@ bool is_direct_shader(const char *glsl) return es3_ability; } +extern "C" EXPORT GLuint glCreateShader(GLenum type) { + LOG() + GLuint shader = gl4es_glCreateShader(type); + CHECK_GL_ERROR + return shader; +} + +extern "C" EXPORT void glCompileShader(GLuint shader) { + LOG() + gl4es_glCompileShader(shader); + CHECK_GL_ERROR +} + void glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint *length) { LOG() - GET_GL4ES_FUNC(void, glShaderSource, GLuint shader, GLsizei count, const GLchar *const* string, const GLint *length) - CALL_GL4ES_FUNC(glShaderSource, shader, count, string, length) + gl4es_glShaderSource(shader,count,string,length); shaderInfo.id = 0; shaderInfo.converted = ""; shaderInfo.frag_data_changed = 0; @@ -69,6 +81,7 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, c essl_src = glsl_src; } else { int glsl_version = getGLSLVersion(glsl_src.c_str()); + if (glsl_version < 140) { LOG_D("Shader won't be processed in mg shaderconv."); return; } // will be converted in gl4es LOG_D("[INFO] [Shader] Shader source: ") LOG_D("%s", glsl_src.c_str()) GLint shaderType; @@ -87,9 +100,7 @@ void glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, c shaderInfo.converted = essl_src; const char* s[] = { essl_src.c_str() }; GLES.glShaderSource(shader, count, s, nullptr); - } - else - LOG_E("Failed to convert glsl.") + } else LOG_E("Failed to convert glsl.") CHECK_GL_ERROR } else { LOG_E("No GLES.glShaderSource") @@ -209,6 +220,9 @@ EXPORT void glVertexAttrib4ubvARB(GLuint index, const GLubyte *v) { glVertexAttr EXPORT void glVertexAttrib4usvARB(GLuint index, const GLushort *v) { glVertexAttrib4fv(index, (GLfloat*)v); } EXPORT void glVertexAttrib4uivARB(GLuint index, const GLuint *v) { glVertexAttrib4fv(index, (GLfloat*)v); } +EXPORT void glCompileShaderARB(GLhandleARB shader) { glCompileShader(shader); } +EXPORT GLhandleARB glCreateShaderARB(GLenum shaderType) { return glCreateShader(shaderType); } + //EXPORT void glVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { // glVertexAttribPointer(index, size, type, normalized, stride, pointer); //} diff --git a/src/main/cpp/gles/gles.h b/src/main/cpp/gles/gles.h index 5fbe770..613e41c 100644 --- a/src/main/cpp/gles/gles.h +++ b/src/main/cpp/gles/gles.h @@ -526,6 +526,8 @@ GL_FUNC_TYPEDEF(void, glMultiDrawArraysIndirectEXT, GLenum mode, const void *ind GL_FUNC_TYPEDEF(void, glMultiDrawElementsIndirectEXT, GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride) GL_FUNC_TYPEDEF(void, glBruh) GL_FUNC_TYPEDEF(void, glMultiDrawElementsBaseVertexEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex) +GL_FUNC_TYPEDEF(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, + GLuint texture, GLint level, GLint layer) #define GL_FUNC_DECL(name) \ name##_PTR name; @@ -903,6 +905,8 @@ struct gles_func_t { GL_FUNC_DECL(glMultiDrawElementsBaseVertexEXT) GL_FUNC_DECL(glBruh) + + GL_FUNC_DECL(glFramebufferTexture3DOES) }; extern struct gles_func_t g_gles_func; diff --git a/src/main/cpp/gles/loader.cpp b/src/main/cpp/gles/loader.cpp index 53f5590..e4ad877 100644 --- a/src/main/cpp/gles/loader.cpp +++ b/src/main/cpp/gles/loader.cpp @@ -580,6 +580,8 @@ void init_target_gles() { INIT_GLES_FUNC(glMultiDrawArraysIndirectEXT) INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT) INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT) + + INIT_GLES_FUNC(glFramebufferTexture3DOES) // INIT_GLES_FUNC(glBruh) LOG_D("glMultiDrawArraysIndirectEXT() @ 0x%x", GLES.glMultiDrawArraysIndirectEXT)