diff --git a/Android.mk b/Android.mk index 2290e5ac2..c9adda1c8 100644 --- a/Android.mk +++ b/Android.mk @@ -88,17 +88,24 @@ LOCAL_SRC_FILES := \ src/glx/lookup.c \ src/glx/gbm.c \ src/glx/streaming.c \ + src/gl/libtxc_dxtn/txc_compress_dxtn.c \ -LOCAL_CFLAGS += -g -std=gnu99 -funwind-tables -O3 -fvisibility=hidden -include include/android_debug.h +LOCAL_CFLAGS += -std=gnu99 -funwind-tables -O3 -fvisibility=hidden -include include/android_debug.h LOCAL_CFLAGS += -DNOX11 LOCAL_CFLAGS += -DNO_GBM -#LOCAL_CFLAGS += -DNO_INIT_CONSTRUCTOR +LOCAL_CFLAGS += -DNO_INIT_CONSTRUCTOR=ON +LOCAL_CFLAGS += -DNOEGL=ON +LOCAL_CFLAGS += -DNO_LOADER=ON LOCAL_CFLAGS += -DDEFAULT_ES=2 +LOCAL_CFLAGS += -Wno-typedef-redefinition -Wno-dangling-else +LOCAL_CFLAGS += -Dasm=__asm__ -Dvolatile=__volatile__ +LOCAL_CFLAGS += -include include/gl4esinit.h + //TODO: maybe temporary? LOCAL_CFLAGS += -Wno-typedef-redefinition -Wno-dangling-else LOCAL_LDLIBS := -llog -#building as a static lib +#building as a shared lib -LOCAL_CFLAGS += -DSTATICLIB -include $(BUILD_STATIC_LIBRARY) +LOCAL_CFLAGS += -DSHAREDLIB +include $(BUILD_SHARED_LIBRARY) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca5636e29..32537890c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ endif() # Android if(ANDROID) add_definitions(-DANDROID) - add_definitions(-DNOX11 -DNO_GBM -DDEFAULT_ES=2) + add_definitions(-DNOX11 -DNO_GBM -DDEFAULT_ES=2 -o libGL.so) endif() if(USE_ANDROID_LOG) @@ -192,13 +192,13 @@ if(NOT WIN32_MSVC) if(NOT WIN32_PLATFORM) add_definitions(-fvisibility=hidden) else() - set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-all-symbols,--kill-at") + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-all-symbols,--kill-at -latomic -no-canonical-prefixes -Wl,--gc-sections -Wl,--build-id=sha1 -Wl,--no-dangling-else -Wl,--no-rosegment -Wl,--no-undefined -Wl,--fatal-warnings -Wl,--no-undefined-version -llog -landroid -lc -lm -o libGL.so") endif() elseif(CMAKE_C_COMPILER_ID MATCHES "Clang") add_definitions(-Wno-deprecated-declarations) #strdup add_definitions(-Wno-unused-function -Wno-unused-variable -Wno-dangling-else) add_definitions(-Wno-implicit-const-int-float-conversion) - add_definitions(-Wno-visibility) + add_definitions(-Wno-visibility -Wno-logical-not-parentheses) else() if(CMAKE_C_COMPILER_ID MATCHES "Intel") add_definitions(-wd1786 -wd589 -wd537 -wd118 -wd2722) diff --git a/include/GL/glext.h b/include/GL/glext.h index 22348a129..ff600e6f4 100644 --- a/include/GL/glext.h +++ b/include/GL/glext.h @@ -1507,7 +1507,7 @@ extern "C" { #define GL_CLAMP_READ_COLOR_ARB 0x891C #define GL_FIXED_ONLY_ARB 0x891D #endif - + #ifndef GL_ARB_half_float_pixel #define GL_HALF_FLOAT_ARB 0x140B #endif @@ -1663,7 +1663,7 @@ extern "C" { /* reuse GL_MAX_VARYING_COMPONENTS */ /* reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER */ #endif - + #ifndef GL_ARB_half_float_vertex #define GL_HALF_FLOAT 0x140B #endif @@ -4070,7 +4070,7 @@ extern "C" { #define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873 #define GL_PROGRAM_ERROR_STRING_NV 0x8874 #endif - + #ifndef GL_NV_half_float #define GL_HALF_FLOAT_NV 0x140B #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 388a90f93..bf72db8ac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,9 +3,9 @@ include_directories(util) #file(GLOB_RECURSE GL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gl/*.c) SET(GL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbconverter.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.c ${CMAKE_CURRENT_SOURCE_DIR}/gl/array.c ${CMAKE_CURRENT_SOURCE_DIR}/gl/blit.c ${CMAKE_CURRENT_SOURCE_DIR}/gl/blend.c @@ -66,23 +66,26 @@ SET(GL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/gl/texture_3d.c ${CMAKE_CURRENT_SOURCE_DIR}/gl/uniform.c ${CMAKE_CURRENT_SOURCE_DIR}/gl/vertexattrib.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gl4eswraps.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gles.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/glstub.c - ${CMAKE_CURRENT_SOURCE_DIR}/gl/math/matheval.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gl4eswraps.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gles.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/glstub.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/math/matheval.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/libtxc_dxtn/txc_compress_dxtn.c + ${CMAKE_CURRENT_SOURCE_DIR}/gl/libtxc_dxtn/txc_dxtn.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl/libtxc_dxtn/txc_fetch_dxtn.c ) SET(GL_H ${CMAKE_CURRENT_SOURCE_DIR}/../version.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbconverter.h - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.h - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.h - ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/array.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/blend.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/blit.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/buffers.h - ${CMAKE_CURRENT_SOURCE_DIR}/gl/build_info.h + ${CMAKE_CURRENT_SOURCE_DIR}/gl/build_info.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/const.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/debug.h ${CMAKE_CURRENT_SOURCE_DIR}/gl/decompress.h @@ -144,11 +147,11 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND NOT NO_LOADER) list(APPEND GL_SRC ${CMAKE_CURRENT_SOURCE_DIR}/glx/hardext.c ${CMAKE_CURRENT_SOURCE_DIR}/glx/gbm.c - ${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.c - ${CMAKE_CURRENT_SOURCE_DIR}/glx/glx_stubs.c - ${CMAKE_CURRENT_SOURCE_DIR}/glx/lookup.c + ${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.c + ${CMAKE_CURRENT_SOURCE_DIR}/glx/glx_stubs.c + ${CMAKE_CURRENT_SOURCE_DIR}/glx/lookup.c ${CMAKE_CURRENT_SOURCE_DIR}/glx/rpi.c - ${CMAKE_CURRENT_SOURCE_DIR}/glx/streaming.c + ${CMAKE_CURRENT_SOURCE_DIR}/glx/streaming.c ${CMAKE_CURRENT_SOURCE_DIR}/glx/utils.c ) list(APPEND GL_H @@ -221,14 +224,17 @@ else() endif() if(CMAKE_SHARED_LIBRARY_SUFFIX MATCHES ".so") - set_target_properties(GL PROPERTIES SUFFIX ".so.1") + set_target_properties(GL PROPERTIES SUFFIX ".so") endif() install(TARGETS GL LIBRARY - DESTINATION "/usr/lib/gl4es/" + DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/" ) - install(FILES "../include/gl4esinit.h" "../include/gl4eshint.h" - DESTINATION "/usr/include/gl4es/" + install(DIRECTORY "../include/" + DESTINATION "${CMAKE_INSTALL_PREFIX}/include/gl4es" + ) + install(DIRECTORY "../include/" + DESTINATION "${CMAKE_INSTALL_PREFIX}/include" ) endif() @@ -249,7 +255,7 @@ if(EGL_WRAPPER) target_link_libraries(EGL ${log-lib}) endif() if(CMAKE_SHARED_LIBRARY_SUFFIX MATCHES ".so") - set_target_properties(EGL PROPERTIES SUFFIX ".so.1") + set_target_properties(EGL PROPERTIES SUFFIX ".so") endif() endif() diff --git a/src/gl/const.h b/src/gl/const.h index fc6a1bd2f..3911f75ca 100644 --- a/src/gl/const.h +++ b/src/gl/const.h @@ -188,6 +188,7 @@ #define GL_INTENSITY16F 0x881D #define GL_INTENSITY32F 0x8817 #define GL_RGB10_A2 0x8059 +#define GL_R16F 0x822D #define GL_RGBA16F 0x881A #define GL_RGB16F 0x881B #define GL_RGBA32F 0x8814 diff --git a/src/gl/debug.c b/src/gl/debug.c index db465dea1..037610473 100644 --- a/src/gl/debug.c +++ b/src/gl/debug.c @@ -427,4 +427,4 @@ void CheckGLError(int fwd) { if(fwd) errorShim(err); } -} \ No newline at end of file +} diff --git a/src/gl/enum_info.h b/src/gl/enum_info.h index 934ccc436..7deb42708 100644 --- a/src/gl/enum_info.h +++ b/src/gl/enum_info.h @@ -168,4 +168,4 @@ static inline const GLboolean valid_vertex_type(GLenum type) { } } -#endif // _GL4ES_ENUM_INFO_H \ No newline at end of file +#endif // _GL4ES_ENUM_INFO_H diff --git a/src/gl/fpe.h b/src/gl/fpe.h index 5682f4adf..32a1a8578 100644 --- a/src/gl/fpe.h +++ b/src/gl/fpe.h @@ -217,6 +217,7 @@ typedef struct fpe_state_s { unsigned int blendeqalpha:3; uint16_t vertex_prg_id; // Id of vertex program currently binded (0 most of the time), 16bits is more than enough... uint16_t fragment_prg_id; // Id of fragment program currently binded (0 most of the time) + int16_t gamma; } fpe_state_t; #pragma pack() diff --git a/src/gl/fpe_shader.c b/src/gl/fpe_shader.c index 542c0e359..0084f26ce 100644 --- a/src/gl/fpe_shader.c +++ b/src/gl/fpe_shader.c @@ -186,7 +186,7 @@ const char* const* fpe_VertexShader(shaderconv_need_t* need, fpe_state_t *state) int cm_back_nullexp = state->cm_back_nullexp; int texgens = 0; int texmats = 0; - const char* fogp = hardext.highp?"highp":"mediump"; + const char* fogp = "highp"; for (int i=0; itexgen[i].texgen_s || state->texgen[i].texgen_t || state->texgen[i].texgen_r || state->texgen[i].texgen_q) @@ -837,7 +837,7 @@ const char* const* fpe_FragmentShader(shaderconv_need_t* need, fpe_state_t *stat int texenv_combine = 0; int texturing = 0; char buff[1024]; - const char* fogp = hardext.highp?"highp":"mediump"; + const char* fogp = "highp"; strcpy(shad, fpeshader_signature); @@ -1376,7 +1376,8 @@ const char* const* fpe_FragmentShader(shaderconv_need_t* need, fpe_state_t *stat sprintf(buff, "%s float FogF = clamp(exp(-(gl_Fog.density * fog_c)*(gl_Fog.density * fog_c)), 0., 1.);\n", fogp); break; case FPE_FOG_LINEAR: - sprintf(buff, "%s float FogF = clamp((gl_Fog.end - fog_c) %s, 0., 1.);\n", fogp, hardext.highp?"* gl_Fog.scale":"/ (gl_Fog.end - gl_Fog.start)"); + //sprintf(buff, "%s float FogF = clamp((gl_Fog.end - fog_c) %s, 0., 1.);\n", fogp, hardext.highp?"* gl_Fog.scale":"/ (gl_Fog.end - gl_Fog.start)"); + sprintf(buff, "%s float FogF = clamp((gl_Fog.end - fog_c) * gl_Fog.scale, 0., 1.);\n", fogp); break; } ShadAppend(buff); @@ -1618,6 +1619,11 @@ const char* const* fpe_FragmentShader(shaderconv_need_t* need, fpe_state_t *stat } } + if (state->gamma) { + sprintf(buff, "fColor.rgb = pow(fColor.rgb, vec3(1.0 / %.3f));\n", state->gamma / 100.0); + ShadAppend(buff); + } + //done ShadAppend("gl_FragColor = fColor;\n"); ShadAppend("}"); diff --git a/src/gl/getter.c b/src/gl/getter.c index dc500196d..140644a2d 100644 --- a/src/gl/getter.c +++ b/src/gl/getter.c @@ -110,11 +110,6 @@ void BuildExtensionsList() { "GL_EXT_draw_range_elements " "GL_EXT_bgra " "GL_ARB_texture_compression " - "GL_EXT_texture_compression_s3tc " - "GL_OES_texture_compression_S3TC " - "GL_EXT_texture_compression_dxt1 " - "GL_EXT_texture_compression_dxt3 " - "GL_EXT_texture_compression_dxt5 " "GL_ARB_point_parameters " "GL_EXT_point_parameters " "GL_EXT_stencil_wrap " @@ -133,6 +128,15 @@ void BuildExtensionsList() { "GL_NV_blend_square " // "GL_EXT_blend_logic_op " ); + + if (globals4es.dxt != 2) + strcat(extensions, "GL_EXT_texture_compression_s3tc " + "GL_OES_texture_compression_S3TC " + "GL_EXT_texture_compression_dxt1 " + "GL_EXT_texture_compression_dxt3 " + "GL_EXT_texture_compression_dxt5 "); + + if(!globals4es.notexrect) strcat(extensions, "GL_ARB_texture_rectangle "); if(globals4es.vabgra) @@ -177,9 +181,19 @@ void BuildExtensionsList() { if(hardext.floattex || (globals4es.floattex==2)) { strcat(extensions, "GL_EXT_texture_float "); strcat(extensions, "GL_ARB_texture_float "); + strcat(extensions, "GL_OES_texture_float "); + } + if(hardext.floattexlinear || (globals4es.floattex==2)) { + strcat(extensions, "GL_EXT_texture_float_linear "); + strcat(extensions, "GL_OES_texture_float_linear "); } if(hardext.halffloattex || (globals4es.floattex==2)) { strcat(extensions, "GL_EXT_texture_half_float "); + strcat(extensions, "GL_OES_texture_half_float "); + } + if(hardext.halffloattexlinear || (globals4es.floattex==2)) { + strcat(extensions, "GL_EXT_texture_half_float_linear "); + strcat(extensions, "GL_OES_texture_half_float_linear "); } if(hardext.floatfbo || (globals4es.floattex==2)) { strcat(extensions, "GL_EXT_color_buffer_float "); @@ -187,6 +201,10 @@ void BuildExtensionsList() { if(hardext.halffloatfbo || (globals4es.floattex==2)) { strcat(extensions, "GL_EXT_color_buffer_half_float "); } + if(hardext.clipcontrol) { + strcat(extensions, "GL_ARB_clip_control "); + strcat(extensions, "GL_EXT_clip_control "); + } if(hardext.depthtex) { strcat(extensions, "GL_EXT_depth_texture "); strcat(extensions, "GL_ARB_depth_texture "); diff --git a/src/gl/hint.c b/src/gl/hint.c index feef2e306..77f49777c 100644 --- a/src/gl/hint.c +++ b/src/gl/hint.c @@ -5,6 +5,7 @@ #include "loader.h" #include "gl4es.h" #include "glstate.h" +#include "fpe_cache.h" #ifdef PANDORA void pandora_set_gamma(); @@ -132,4 +133,4 @@ void APIENTRY_GL4ES gl4es_glHint(GLenum pname, GLenum mode) { gles_glHint(pname, mode); } } -AliasExport(void,glHint,,(GLenum pname, GLenum mode)); \ No newline at end of file +AliasExport(void,glHint,,(GLenum pname, GLenum mode)); diff --git a/src/gl/init.c b/src/gl/init.c index 47ad04764..935665e4f 100644 --- a/src/gl/init.c +++ b/src/gl/init.c @@ -121,6 +121,25 @@ void initialize_gl4es() { env(LIBGL_XREFRESH, globals4es.xrefresh, "xrefresh will be called on cleanup"); env(LIBGL_STACKTRACE, globals4es.stacktrace, "stacktrace will be printed on crash"); + switch(ReturnEnvVarInt("LIBGL_DXT")) { + case 1: + SHUT_LOGD("forcing software DXT decompression\n"); + globals4es.dxt = 1; + break; + case 2: + SHUT_LOGD("not exposing DXT support\n"); + globals4es.dxt = 2; + break; + case 3: + SHUT_LOGD("handling DXT as is\n"); + globals4es.dxt = 3; + break; + default: + SHUT_LOGD("using hardware DXT if supported + software fallback\n"); + globals4es.dxt = 0; + break; + } + switch(ReturnEnvVarInt("LIBGL_FB")) { case 1: @@ -626,7 +645,7 @@ void initialize_gl4es() { 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.dbgshaderconv=ReturnEnvVarIntDef("LIBGL_DBGSHADERCONV",0); + globals4es.dbgshaderconv=1;//ReturnEnvVarIntDef("LIBGL_DBGSHADERCONV",0); if(globals4es.dbgshaderconv) { if(globals4es.dbgshaderconv==1) globals4es.dbgshaderconv=15; @@ -677,6 +696,7 @@ void initialize_gl4es() { if(globals4es.nopsa==0) { cwd[0]='\0'; // TODO: What to do on ANDROID and EMSCRIPTEN? +/* const char* custom_psa = GetEnvVar("LIBGL_PSA_FOLDER"); #ifdef __linux__ const char* home = GetEnvVar("HOME"); @@ -693,8 +713,16 @@ void initialize_gl4es() { else strcpy(cwd, "PROGDIR:"); #endif + +*/ + + strcpy(cwd, GetEnvVar("OPENMW_USER_FILE_STORAGE")); + if(strlen(cwd)) { - strcat(cwd, ".gl4es.psa"); + if(globals4es.nohighp) + strcat(cwd, ".gl4es.psa-mediump"); + else + strcat(cwd, ".gl4es.psa-highp"); fpe_InitPSA(cwd); fpe_readPSA(); } diff --git a/src/gl/init.h b/src/gl/init.h index feffa5dfb..319e63610 100644 --- a/src/gl/init.h +++ b/src/gl/init.h @@ -10,6 +10,7 @@ typedef struct _globals4es { int mergelist; int xrefresh; int stacktrace; + int dxt; int usefb; int usegbm; int usefbo; diff --git a/src/gl/libtxc_dxtn/txc_compress_dxtn.c b/src/gl/libtxc_dxtn/txc_compress_dxtn.c new file mode 100644 index 000000000..0be8d4618 --- /dev/null +++ b/src/gl/libtxc_dxtn/txc_compress_dxtn.c @@ -0,0 +1,838 @@ +/* + * libtxc_dxtn + * Version: 0.1 + * + * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "txc_dxtn.h" + +/* weights used for error function, basically weights (unsquared 2/4/1) according to rgb->luminance conversion + not sure if this really reflects visual perception */ +#define REDWEIGHT 4 +#define GREENWEIGHT 16 +#define BLUEWEIGHT 1 + +#define ALPHACUT 127 + +static void fancybasecolorsearch( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], + GLint numxpixels, GLint numypixels, GLint type, GLboolean haveAlpha) +{ + /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ + + /* TODO could also try to find a better encoding for the 3-color-encoding type, this really should be done + if it's rgba_dxt1 and we have alpha in the block, currently even values which will be mapped to black + due to their alpha value will influence the result */ + GLint i, j, colors, z; + GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest; + GLint colordist, blockerrlin[2][3]; + GLubyte nrcolor[2]; + GLint pixerrorcolorbest[3]; + GLubyte enc = 0; + GLubyte cv[4][4]; + GLubyte testcolor[2][3]; + +/* fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", + bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ + if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) < + ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3)) { + testcolor[0][0] = bestcolor[0][0]; + testcolor[0][1] = bestcolor[0][1]; + testcolor[0][2] = bestcolor[0][2]; + testcolor[1][0] = bestcolor[1][0]; + testcolor[1][1] = bestcolor[1][1]; + testcolor[1][2] = bestcolor[1][2]; + } + else { + testcolor[1][0] = bestcolor[0][0]; + testcolor[1][1] = bestcolor[0][1]; + testcolor[1][2] = bestcolor[0][2]; + testcolor[0][0] = bestcolor[1][0]; + testcolor[0][1] = bestcolor[1][1]; + testcolor[0][2] = bestcolor[1][2]; + } + + for (i = 0; i < 3; i ++) { + cv[0][i] = testcolor[0][i]; + cv[1][i] = testcolor[1][i]; + cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3; + cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3; + } + + blockerrlin[0][0] = 0; + blockerrlin[0][1] = 0; + blockerrlin[0][2] = 0; + blockerrlin[1][0] = 0; + blockerrlin[1][1] = 0; + blockerrlin[1][2] = 0; + + nrcolor[0] = 0; + nrcolor[1] = 0; + + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + for (colors = 0; colors < 4; colors++) { + colordist = srccolors[j][i][0] - (cv[colors][0]); + pixerror = colordist * colordist * REDWEIGHT; + pixerrorred = colordist; + colordist = srccolors[j][i][1] - (cv[colors][1]); + pixerror += colordist * colordist * GREENWEIGHT; + pixerrorgreen = colordist; + colordist = srccolors[j][i][2] - (cv[colors][2]); + pixerror += colordist * colordist * BLUEWEIGHT; + pixerrorblue = colordist; + if (pixerror < pixerrorbest) { + enc = colors; + pixerrorbest = pixerror; + pixerrorcolorbest[0] = pixerrorred; + pixerrorcolorbest[1] = pixerrorgreen; + pixerrorcolorbest[2] = pixerrorblue; + } + } + if (enc == 0) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 3 * pixerrorcolorbest[z]; + } + nrcolor[0] += 3; + } + else if (enc == 2) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 2 * pixerrorcolorbest[z]; + } + nrcolor[0] += 2; + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 1 * pixerrorcolorbest[z]; + } + nrcolor[1] += 1; + } + else if (enc == 3) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 1 * pixerrorcolorbest[z]; + } + nrcolor[0] += 1; + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 2 * pixerrorcolorbest[z]; + } + nrcolor[1] += 2; + } + else if (enc == 1) { + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 3 * pixerrorcolorbest[z]; + } + nrcolor[1] += 3; + } + } + } + if (nrcolor[0] == 0) nrcolor[0] = 1; + if (nrcolor[1] == 0) nrcolor[1] = 1; + for (j = 0; j < 2; j++) { + for (i = 0; i < 3; i++) { + GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j]; + if (newvalue <= 0) + testcolor[j][i] = 0; + else if (newvalue >= 255) + testcolor[j][i] = 255; + else testcolor[j][i] = newvalue; + } + } + + if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) && + (abs(testcolor[0][1] - testcolor[1][1]) < 4) && + (abs(testcolor[0][2] - testcolor[1][2]) < 8)) { + /* both colors are so close they might get encoded as the same 16bit values */ + GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1; + + coldiffred = abs(testcolor[0][0] - testcolor[1][0]); + coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]); + coldiffblue = abs(testcolor[0][2] - testcolor[1][2]); + coldiffmax = coldiffred; + if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen; + if (coldiffmax < coldiffblue) coldiffmax = coldiffblue; + if (coldiffmax > 0) { + if (coldiffmax > 4) factor = 2; + else if (coldiffmax > 2) factor = 3; + else factor = 4; + /* Won't do much if the color value is near 255... */ + /* argh so many ifs */ + if (testcolor[1][1] >= testcolor[0][1]) { + ind1 = 1; ind0 = 0; + } + else { + ind1 = 0; ind0 = 1; + } + if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255) + testcolor[ind1][1] += factor * coldiffgreen; + else testcolor[ind1][1] = 255; + if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) { + if ((testcolor[ind1][0] + factor * coldiffred) <= 255) + testcolor[ind1][0] += factor * coldiffred; + else testcolor[ind1][0] = 255; + } + else { + if ((testcolor[ind0][0] + factor * coldiffred) <= 255) + testcolor[ind0][0] += factor * coldiffred; + else testcolor[ind0][0] = 255; + } + if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) { + if ((testcolor[ind1][2] + factor * coldiffblue) <= 255) + testcolor[ind1][2] += factor * coldiffblue; + else testcolor[ind1][2] = 255; + } + else { + if ((testcolor[ind0][2] + factor * coldiffblue) <= 255) + testcolor[ind0][2] += factor * coldiffblue; + else testcolor[ind0][2] = 255; + } + } + } + + if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) < + ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3) { + for (i = 0; i < 3; i++) { + bestcolor[0][i] = testcolor[0][i]; + bestcolor[1][i] = testcolor[1][i]; + } + } + else { + for (i = 0; i < 3; i++) { + bestcolor[0][i] = testcolor[1][i]; + bestcolor[1][i] = testcolor[0][i]; + } + } + +/* fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", + bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ +} + + + +static void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], + GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha) +{ + /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ + + GLint i, j, colors; + GLuint testerror, testerror2, pixerror, pixerrorbest; + GLint colordist; + GLushort color0, color1, tempcolor; + GLuint bits = 0, bits2 = 0; + GLubyte *colorptr; + GLubyte enc = 0; + GLubyte cv[4][4]; + + bestcolor[0][0] = bestcolor[0][0] & 0xf8; + bestcolor[0][1] = bestcolor[0][1] & 0xfc; + bestcolor[0][2] = bestcolor[0][2] & 0xf8; + bestcolor[1][0] = bestcolor[1][0] & 0xf8; + bestcolor[1][1] = bestcolor[1][1] & 0xfc; + bestcolor[1][2] = bestcolor[1][2] & 0xf8; + + color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3; + color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3; + if (color0 < color1) { + tempcolor = color0; color0 = color1; color1 = tempcolor; + colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr; + } + + + for (i = 0; i < 3; i ++) { + cv[0][i] = bestcolor[0][i]; + cv[1][i] = bestcolor[1][i]; + cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3; + cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3; + } + + testerror = 0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + for (colors = 0; colors < 4; colors++) { + colordist = srccolors[j][i][0] - cv[colors][0]; + pixerror = colordist * colordist * REDWEIGHT; + colordist = srccolors[j][i][1] - cv[colors][1]; + pixerror += colordist * colordist * GREENWEIGHT; + colordist = srccolors[j][i][2] - cv[colors][2]; + pixerror += colordist * colordist * BLUEWEIGHT; + if (pixerror < pixerrorbest) { + pixerrorbest = pixerror; + enc = colors; + } + } + testerror += pixerrorbest; + bits |= enc << (2 * (j * 4 + i)); + } + } + for (i = 0; i < 3; i ++) { + cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2; + /* this isn't used. Looks like the black color constant can only be used + with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees, + it will decode 3 to black even with DXT3/5), and due to how the color searching works + it won't get used even then */ + cv[3][i] = 0; + } + testerror2 = 0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3] <= ALPHACUT)) { + enc = 3; + pixerrorbest = 0; /* don't calculate error */ + } + else { + /* we're calculating the same what we have done already for colors 0-1 above... */ + for (colors = 0; colors < 3; colors++) { + colordist = srccolors[j][i][0] - cv[colors][0]; + pixerror = colordist * colordist * REDWEIGHT; + colordist = srccolors[j][i][1] - cv[colors][1]; + pixerror += colordist * colordist * GREENWEIGHT; + colordist = srccolors[j][i][2] - cv[colors][2]; + pixerror += colordist * colordist * BLUEWEIGHT; + if (pixerror < pixerrorbest) { + pixerrorbest = pixerror; + /* need to exchange colors later */ + if (colors > 1) enc = colors; + else enc = colors ^ 1; + } + } + } + testerror2 += pixerrorbest; + bits2 |= enc << (2 * (j * 4 + i)); + } + } + + + /* finally we're finished, write back colors and bits */ + if ((testerror > testerror2) || (haveAlpha)) { + *blkaddr++ = color1 & 0xff; + *blkaddr++ = color1 >> 8; + *blkaddr++ = color0 & 0xff; + *blkaddr++ = color0 >> 8; + *blkaddr++ = bits2 & 0xff; + *blkaddr++ = ( bits2 >> 8) & 0xff; + *blkaddr++ = ( bits2 >> 16) & 0xff; + *blkaddr = bits2 >> 24; + } + else { + *blkaddr++ = color0 & 0xff; + *blkaddr++ = color0 >> 8; + *blkaddr++ = color1 & 0xff; + *blkaddr++ = color1 >> 8; + *blkaddr++ = bits & 0xff; + *blkaddr++ = ( bits >> 8) & 0xff; + *blkaddr++ = ( bits >> 16) & 0xff; + *blkaddr = bits >> 24; + } +} + +static void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4], + GLint numxpixels, GLint numypixels, GLuint type ) +{ +/* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color + present in the picture as base colors */ + + /* define lowest and highest color as shortest and longest vector to 0/0/0, though the + vectors are weighted similar to their importance in rgb-luminance conversion + doesn't work too well though... + This seems to be a rather difficult problem */ + + GLubyte *bestcolor[2]; + GLubyte basecolors[2][3]; + GLubyte i, j; + GLuint lowcv, highcv, testcv; + GLboolean haveAlpha = GL_FALSE; + + lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT + + srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT + + srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT; + bestcolor[0] = bestcolor[1] = srccolors[0][0]; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* don't use this as a base color if the pixel will get black/transparent anyway */ + if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] <= ALPHACUT)) { + testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT + + srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT + + srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT; + if (testcv > highcv) { + highcv = testcv; + bestcolor[1] = srccolors[j][i]; + } + else if (testcv < lowcv) { + lowcv = testcv; + bestcolor[0] = srccolors[j][i]; + } + } + else haveAlpha = GL_TRUE; + } + } + /* make sure the original color values won't get touched... */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 3; i++) { + basecolors[j][i] = bestcolor[j][i]; + } + } + bestcolor[0] = basecolors[0]; + bestcolor[1] = basecolors[1]; + + /* try to find better base colors */ + fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); + /* find the best encoding for these colors, and store the result */ + storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); +} + +static void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2, + GLubyte alphaenc[16]) +{ + *blkaddr++ = alphabase1; + *blkaddr++ = alphabase2; + *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6); + *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7); + *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5); + *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6); + *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7); + *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5); +} + +static void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4], + GLint numxpixels, GLint numypixels) +{ + GLubyte alphabase[2], alphause[2]; + GLshort alphatest[2]; + GLuint alphablockerror1, alphablockerror2, alphablockerror3; + GLubyte i, j, aindex, acutValues[7]; + GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16]; + GLboolean alphaabsmin = GL_FALSE; + GLboolean alphaabsmax = GL_FALSE; + GLshort alphadist; + + /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */ + alphabase[0] = 0xff; alphabase[1] = 0x0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if (srccolors[j][i][3] == 0) + alphaabsmin = GL_TRUE; + else if (srccolors[j][i][3] == 255) + alphaabsmax = GL_TRUE; + else { + if (srccolors[j][i][3] > alphabase[1]) + alphabase[1] = srccolors[j][i][3]; + if (srccolors[j][i][3] < alphabase[0]) + alphabase[0] = srccolors[j][i][3]; + } + } + } + + + if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */ + /* shortcut here since it is a very common case (and also avoids later problems) */ + /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */ + /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */ + + *blkaddr++ = srccolors[0][0][3]; + blkaddr++; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; +/* fprintf(stderr, "enc0 used\n");*/ + return; + } + + /* find best encoding for alpha0 > alpha1 */ + /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */ + alphablockerror1 = 0x0; + alphablockerror2 = 0xffffffff; + alphablockerror3 = 0xffffffff; + if (alphaabsmin) alphause[0] = 0; + else alphause[0] = alphabase[0]; + if (alphaabsmax) alphause[1] = 255; + else alphause[1] = alphabase[1]; + /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */ + for (aindex = 0; aindex < 7; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14; + } + + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] > acutValues[0]) { + alphaenc1[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphause[1]; + } + else if (srccolors[j][i][3] > acutValues[1]) { + alphaenc1[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7; + } + else if (srccolors[j][i][3] > acutValues[2]) { + alphaenc1[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7; + } + else if (srccolors[j][i][3] > acutValues[3]) { + alphaenc1[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7; + } + else if (srccolors[j][i][3] > acutValues[4]) { + alphaenc1[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7; + } + else if (srccolors[j][i][3] > acutValues[5]) { + alphaenc1[4*j + i] = 6; + alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7; + } + else if (srccolors[j][i][3] > acutValues[6]) { + alphaenc1[4*j + i] = 7; + alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7; + } + else { + alphaenc1[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphause[0]; + } + alphablockerror1 += alphadist * alphadist; + } + } +/* for (i = 0; i < 16; i++) { + fprintf(stderr, "%d ", alphaenc1[i]); + } + fprintf(stderr, "cutVals "); + for (i = 0; i < 8; i++) { + fprintf(stderr, "%d ", acutValues[i]); + } + fprintf(stderr, "srcVals "); + for (j = 0; j < numypixels; j++) + for (i = 0; i < numxpixels; i++) { + fprintf(stderr, "%d ", srccolors[j][i][3]); + } + + fprintf(stderr, "\n"); + }*/ + /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax + are false but try it anyway */ + if (alphablockerror1 >= 32) { + + /* don't bother if encoding is already very good, this condition should also imply + we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */ + alphablockerror2 = 0; + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10; + } + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] == 0) { + alphaenc2[4*j + i] = 6; + alphadist = 0; + } + else if (srccolors[j][i][3] == 255) { + alphaenc2[4*j + i] = 7; + alphadist = 0; + } + else if (srccolors[j][i][3] <= acutValues[0]) { + alphaenc2[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphabase[0]; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + alphaenc2[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + alphaenc2[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + alphaenc2[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + alphaenc2[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5; + } + else { + alphaenc2[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphabase[1]; + } + alphablockerror2 += alphadist * alphadist; + } + } + + + /* skip this if the error is already very small + this encoding is MUCH better on average than #2 though, but expensive! */ + if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) { + GLshort blockerrlin1 = 0; + GLshort blockerrlin2 = 0; + GLubyte nralphainrangelow = 0; + GLubyte nralphainrangehigh = 0; + alphatest[0] = 0xff; + alphatest[1] = 0x0; + /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */ + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3] < (255 -(alphabase[1] - alphabase[0]) / 28))) + alphatest[1] = srccolors[j][i][3]; + if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28)) + alphatest[0] = srccolors[j][i][3]; + } + } + /* shouldn't happen too often, don't really care about those degenerated cases */ + if (alphatest[1] <= alphatest[0]) { + alphatest[0] = 1; + alphatest[1] = 254; +/* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/ + } + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; + } + + /* find the "average" difference between the alpha values and the next encoded value. + This is then used to calculate new base values. + Should there be some weighting, i.e. those values closer to alphatest[x] have more weight, + since they will see more improvement, and also because the values in the middle are somewhat + likely to get no improvement at all (because the base values might move in different directions)? + OTOH it would mean the values in the middle are even less likely to get an improvement + */ + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if (srccolors[j][i][3] <= alphatest[0] / 2) { + } + else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { + } + else if (srccolors[j][i][3] <= acutValues[0]) { + blockerrlin1 += (srccolors[j][i][3] - alphatest[0]); + nralphainrangelow += 1; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else { + blockerrlin2 += (srccolors[j][i][3] - alphatest[1]); + nralphainrangehigh += 1; + } + } + } + /* shouldn't happen often, needed to avoid div by zero */ + if (nralphainrangelow == 0) nralphainrangelow = 1; + if (nralphainrangehigh == 0) nralphainrangehigh = 1; + alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow); +/* fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow); + fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);*/ + /* again shouldn't really happen often... */ + if (alphatest[0] < 0) { + alphatest[0] = 0; +/* fprintf(stderr, "adj alpha base val to 0\n");*/ + } + alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh); + if (alphatest[1] > 255) { + alphatest[1] = 255; +/* fprintf(stderr, "adj alpha base val to 255\n");*/ + } + + alphablockerror3 = 0; + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; + } + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] <= alphatest[0] / 2) { + alphaenc3[4*j + i] = 6; + alphadist = srccolors[j][i][3]; + } + else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { + alphaenc3[4*j + i] = 7; + alphadist = 255 - srccolors[j][i][3]; + } + else if (srccolors[j][i][3] <= acutValues[0]) { + alphaenc3[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphatest[0]; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + alphaenc3[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + alphaenc3[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + alphaenc3[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + alphaenc3[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5; + } + else { + alphaenc3[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphatest[1]; + } + alphablockerror3 += alphadist * alphadist; + } + } + } + } + /* write the alpha values and encoding back. */ + if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) { +/* if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);*/ + writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 ); + } + else if (alphablockerror2 <= alphablockerror3) { +/* if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);*/ + writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 ); + } + else { +/* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/ + writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 ); + } +} + +static void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr, + GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) +{ + GLubyte i, j, c; + const GLchan *curaddr; + for (j = 0; j < numypixels; j++) { + curaddr = srcaddr + j * srcRowStride * comps; + for (i = 0; i < numxpixels; i++) { + for (c = 0; c < comps; c++) { + srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255); + } + } + } +} + + +void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, + GLenum destFormat, GLubyte *dest, GLint dstRowStride) +{ + GLubyte *blkaddr = dest; + GLubyte srcpixels[4][4][4]; + const GLchan *srcaddr = srcPixData; + GLint numxpixels, numypixels; + GLint i, j; + GLint dstRowDiff; + + switch (destFormat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + /* hmm we used to get called without dstRowStride... */ + dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0; +/* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 8; + } + blkaddr += dstRowDiff; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0; +/* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0); + *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0); + *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0); + *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0); + *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0); + *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0); + *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0); + *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0); + encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 8; + } + blkaddr += dstRowDiff; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0; +/* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels); + encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 16; + } + blkaddr += dstRowDiff; + } + break; + default: + fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat); + return; + } +} + + diff --git a/src/gl/libtxc_dxtn/txc_dxtn.h b/src/gl/libtxc_dxtn/txc_dxtn.h new file mode 100644 index 000000000..847083995 --- /dev/null +++ b/src/gl/libtxc_dxtn/txc_dxtn.h @@ -0,0 +1,47 @@ +/* + * libtxc_dxtn + * Version: 0.1 + * + * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +//#include +#include "../gl4es.h" + +typedef GLubyte GLchan; +#define UBYTE_TO_CHAN(b) (b) +#define CHAN_MAX 255 +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 + +void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel); +void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel); +void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel); +void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel); + +void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, + const GLubyte *srcPixData, GLenum destformat, + GLubyte *dest, GLint dstRowStride); diff --git a/src/gl/libtxc_dxtn/txc_fetch_dxtn.c b/src/gl/libtxc_dxtn/txc_fetch_dxtn.c new file mode 100644 index 000000000..1004b7cec --- /dev/null +++ b/src/gl/libtxc_dxtn/txc_fetch_dxtn.c @@ -0,0 +1,243 @@ +/* + * libtxc_dxtn + * Version: 0.1 + * + * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "txc_dxtn.h" + +#define EXP5TO8R(packedcol) \ + ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7)) + +#define EXP6TO8G(packedcol) \ + ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3)) + +#define EXP5TO8B(packedcol) \ + ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7)) + +#define EXP4TO8(col) \ + ((col) | ((col) << 4)) + +/* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */ + +static void dxt135_decode_imageblock ( const GLubyte *img_block_src, + GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) { + GLchan *rgba = (GLchan *) texel; + const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8); + const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8); + const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) | + (img_block_src[6] << 16) | (img_block_src[7] << 24); + /* What about big/little endian? */ + GLubyte bit_pos = 2 * (j * 4 + i) ; + GLubyte code = (GLubyte) ((bits >> bit_pos) & 3); + + rgba[ACOMP] = CHAN_MAX; + switch (code) { + case 0: + rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) ); + rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) ); + rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) ); + break; + case 1: + rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) ); + rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) ); + rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) ); + break; + case 2: + if (color0 > color1) { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) ); + } + else { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) ); + } + break; + case 3: + if ((dxt_type > 1) || (color0 > color1)) { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) ); + } + else { + rgba[RCOMP] = 0; + rgba[GCOMP] = 0; + rgba[BCOMP] = 0; + if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0); + } + break; + default: + /* CANNOT happen (I hope) */ + break; + } +} + + +void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) +{ + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); + dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel); +} + + +void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) +{ + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); + dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel); +} + +void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) { + + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + GLchan *rgba = (GLchan *) texel; + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); +#if 0 + /* Simple 32bit version. */ +/* that's pretty brain-dead for a single pixel, isn't it? */ + const GLubyte bit_pos = 4 * ((j&3) * 4 + (i&3)); + const GLuint alpha_low = blksrc[0] | (blksrc[1] << 8) | (blksrc[2] << 16) | (blksrc[3] << 24); + const GLuint alpha_high = blksrc[4] | (blksrc[5] << 8) | (blksrc[6] << 16) | (blksrc[7] << 24); + + dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); + if (bit_pos < 32) + rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_low >> bit_pos) & 15)) ); + else + rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_high >> (bit_pos - 32)) & 15)) ); +#endif +#if 1 +/* TODO test this! */ + const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf; + dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); + rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) ); +#endif + +} + +void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) { + + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + GLchan *rgba = (GLchan *) texel; + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); + const GLubyte alpha0 = blksrc[0]; + const GLubyte alpha1 = blksrc[1]; +#if 0 + const GLubyte bit_pos = 3 * ((j&3) * 4 + (i&3)); + /* simple 32bit version */ + const GLuint bits_low = blksrc[2] | (blksrc[3] << 8) | (blksrc[4] << 16) | (blksrc[5] << 24); + const GLuint bits_high = blksrc[6] | (blksrc[7] << 8); + GLubyte code; + + if (bit_pos < 30) + code = (GLubyte) ((bits_low >> bit_pos) & 7); + else if (bit_pos == 30) + code = (GLubyte) ((bits_low >> 30) & 3) | ((bits_high << 2) & 4); + else + code = (GLubyte) ((bits_high >> (bit_pos - 32)) & 7); +#endif +#if 1 +/* TODO test this! */ + const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3; + const GLubyte acodelow = blksrc[2 + bit_pos / 8]; + const GLubyte acodehigh = blksrc[3 + bit_pos / 8]; + const GLubyte code = (acodelow >> (bit_pos & 0x7) | + (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; +#endif + dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); +#if 0 + if (alpha0 > alpha1) { + switch (code) { + case 0: + rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); + break; + case 1: + rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); + break; + } + } + else { + switch (code) { + case 0: + rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); + break; + case 1: + rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); + break; + case 2: + case 3: + case 4: + case 5: + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); + break; + case 6: + rgba[ACOMP] = 0; + break; + case 7: + rgba[ACOMP] = CHAN_MAX; + break; + } + } +#endif +/* not sure. Which version is faster? */ +#if 1 +/* TODO test this */ + if (code == 0) + rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); + else if (code == 1) + rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); + else if (alpha0 > alpha1) + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); + else if (code < 6) + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); + else if (code == 6) + rgba[ACOMP] = 0; + else + rgba[ACOMP] = CHAN_MAX; +#endif +} diff --git a/src/gl/light.c b/src/gl/light.c index 608bbc6b6..6b0b7f2e0 100644 --- a/src/gl/light.c +++ b/src/gl/light.c @@ -77,6 +77,10 @@ void APIENTRY_GL4ES gl4es_glLightModelfv(GLenum pname, const GLfloat* params) { return; } else gl4es_flush(); switch (pname) { + case 0x4242: + if (glstate->fpe_state) + glstate->fpe_state->gamma = params[0] * 100; + return; case GL_LIGHT_MODEL_AMBIENT: if(memcmp(glstate->light.ambient, params, 4*sizeof(GLfloat))==0) { noerrorShim(); diff --git a/src/gl/shader_hacks.c b/src/gl/shader_hacks.c index aa781b4e1..514f83902 100644 --- a/src/gl/shader_hacks.c +++ b/src/gl/shader_hacks.c @@ -193,14 +193,26 @@ static const hack_t gl4es_hacks[] = { {"uniform highp \tvec2 \t\tuTcScale;", 1, {"uniform mediump vec2 \t\tuTcScale;"}}, -// for OpenMW -{"uniform bool simpleWater = false;", -1, {"uniform bool simpleWater;"}}, - // for Lethal League {"uniform vec4 Color = vec4(1.0, 1.0, 1.0, 1.0);", 1, {"uniform vec4 Color;"}}, +// openmw +{"uniform bool useAdvancedShader = false;", +1, {"uniform bool useAdvancedShader;"}}, + +{"uniform @builtinSampler omw_SamplerDepth;", +1, {"uniform highp @builtinSampler omw_SamplerDepth;"}}, + +{"uniform sampler2D orthoDepthMap;", +1, {"uniform highp sampler2D orthoDepthMap;"}}, + +{"uniform sampler2D opaqueDepthTex;", +1, {"uniform highp sampler2D opaqueDepthTex;"}}, + +{"uniform vec2 scaling = vec2(1.0, 1.0);", +1, {"uniform vec2 scaling;"}}, + // for ioQuake3 {"float c[5] = float[5](1.0, 0.9238795325, 0.7071067812, 0.3826834324, 0.0);", 1, {"float c[5]; c[0]=1.0; c[1]=0.9238795325; c[2]=0.7071067812; c[3]=0.3826834324; c[4]=0.0;"}}, diff --git a/src/gl/shaderconv.c b/src/gl/shaderconv.c index 99ced0766..ab9c3bb47 100644 --- a/src/gl/shaderconv.c +++ b/src/gl/shaderconv.c @@ -196,9 +196,9 @@ 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) +" 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_FogParametersSourceHighp = @@ -316,6 +316,9 @@ static const char* HackAltMax = "}\n" "float max(int a, float b) {\n" " return max(float(a), b);\n" +"}\n" +"int max(int a, int b) {\n" +" return int(max(float(a), float(b)));\n" "}\n"; static const char* HackAltMin = "float min(float a, int b) {\n" @@ -323,6 +326,9 @@ static const char* HackAltMin = "}\n" "float min(int a, float b) {\n" " return min(float(a), b);\n" +"}\n" +"int min(int a, int b) {\n" +" return int(min(float(a), float(b)));\n" "}\n"; static const char* HackAltClamp = "float clamp(float f, int a, int b) {\n" @@ -552,6 +558,17 @@ char* ConvertShader(const char* pEntry, int isVertex, shaderconv_need_t *need) Tmp = gl4es_inplace_insert(gl4es_getline(Tmp, headline-1), GLESFakeFragDepth, Tmp, &tmpsize); headline++; } + // openmw additions + 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); + Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "uniform sampler2d", "uniform highp sampler2d"); + Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "uniform bool useAdvancedShader = false;", "uniform bool useAdvancedShader;"); + Tmp = gl4es_inplace_replace(Tmp, &tmpsize, "uniform vec2 scaling = vec2(1.0, 1.0);", "uniform vec2 scaling;"); + // end openmw additions + 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.... @@ -919,8 +936,9 @@ char* ConvertShader(const char* pEntry, int isVertex, shaderconv_need_t *need) if(builtin_matrix[i].matrix == MAT_MV) { if(need->need_mvmatrix && !hardext.highp) ishighp = 0; - if(!hardext.highp && !isVertex) + if(/*!hardext.highp &&*/ !isVertex) need->need_mvmatrix = 1; + ishighp = 1; //force highp; } if(builtin_matrix[i].matrix == MAT_MVP) { if(need->need_mvpmatrix && !hardext.highp) diff --git a/src/gl/texture.c b/src/gl/texture.c index d94a69d95..50f5b1988 100644 --- a/src/gl/texture.c +++ b/src/gl/texture.c @@ -168,6 +168,17 @@ void internal2format_type(GLenum internalformat, GLenum *format, GLenum *type) *format = GL_DEPTH_STENCIL; *type = GL_UNSIGNED_INT_24_8; break; + case GL_R16F: + if(!hardext.rgtex) + *format = GL_RGB; + else + *format = GL_RED; + + if(!hardext.halffloattex) + *type = GL_UNSIGNED_BYTE; + else + *type = GL_HALF_FLOAT_OES; + break; case GL_RGBA16F: *format = GL_RGBA; *type = (hardext.halffloattex)?GL_HALF_FLOAT_OES:GL_UNSIGNED_BYTE; @@ -897,6 +908,15 @@ void APIENTRY_GL4ES gl4es_glTexImage2D(GLenum target, GLint level, GLint interna GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) { DBG(printf("glTexImage2D on target=%s with unpack_row_length(%i), size(%i,%i) and skip(%i,%i), format(internal)=%s(%s), type=%s, data=%p, level=%i (mipmap_need=%i, mipmap_auto=%i, base_level=%i, max_level=%i) => texture=%u (streamed=%i), glstate->list.compiling=%d\n", PrintEnum(target), glstate->texture.unpack_row_length, width, height, glstate->texture.unpack_skip_pixels, glstate->texture.unpack_skip_rows, PrintEnum(format), (internalformat==3)?"3":(internalformat==4?"4":PrintEnum(internalformat)), PrintEnum(type), data, level, glstate->texture.bound[glstate->texture.active][what_target(target)]->mipmap_need, glstate->texture.bound[glstate->texture.active][what_target(target)]->mipmap_auto, glstate->texture.bound[glstate->texture.active][what_target(target)]->base_level, glstate->texture.bound[glstate->texture.active][what_target(target)]->max_level, glstate->texture.bound[glstate->texture.active][what_target(target)]->texture, glstate->texture.bound[glstate->texture.active][what_target(target)]->streamed, glstate->list.compiling);) + + if(data==NULL && (internalformat == GL_RGB16F || internalformat == GL_RGBA16F)) + internal2format_type(internalformat, &format, &type); + + if(internalformat == GL_R16F ) internal2format_type(internalformat, &format, &type); + + if(data==NULL && (internalformat == GL_RED || internalformat == GL_RGB)) + internal2format_type(internalformat, &format, &type); + // proxy case const GLuint itarget = what_target(target); const GLuint rtarget = map_tex_target(target); diff --git a/src/gl/texture_compressed.c b/src/gl/texture_compressed.c index 25d2d742a..1ca9e90d0 100644 --- a/src/gl/texture_compressed.c +++ b/src/gl/texture_compressed.c @@ -16,6 +16,7 @@ #include "pixel.h" #include "raster.h" #include "stb_dxt_104.h" +#include "libtxc_dxtn/txc_dxtn.h" //#define DEBUG #ifdef DEBUG @@ -164,10 +165,69 @@ GLvoid *uncompressDXTc(GLsizei width, GLsizei height, GLenum format, GLsizei ima return pixels; } +GLboolean isFormatSupported(GLenum format) { + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (hardext.dxtCompression || hardext.dxt1 || hardext.dxt1angle) + return 1; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + if (hardext.dxtCompression || hardext.dxt3 || hardext.dxt3angle) + return 1; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if (hardext.dxtCompression || hardext.dxt5 || hardext.dxt5angle) + return 1; + } + return 0; +} + +GLuint computeImageSize(GLuint width, GLuint height, GLuint depth, GLenum format) +{ + switch(format) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (width < 4 && width > 0) + width = 4; + if (height < 4 && height > 0) + height = 4; + return ((width + 3) / 4) * ((height + 3) / 4) * 8 * depth; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if (width < 4 && width > 0) + width = 4; + if (height < 4 && height > 0) + height = 4; + return ((width + 3) / 4) * ((height + 3) / 4) * 16 * depth; + default: + return 0; + } + +} + +GLvoid *compressDXTc(GLsizei width, GLsizei height, GLenum format, const GLvoid *data) +{ + GLuint imageSize = computeImageSize(width,height, 1, format); + GLvoid *compressedpixels = malloc(imageSize); + + GLint dstRowStride = ((width + 3) / 4) * 16; + if (format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) + dstRowStride = ((width + 3) / 4) * 8; + + tx_compress_dxtn(4, width, height, data, format, compressedpixels, dstRowStride); + + return compressedpixels; +} + void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) { + if(!data) return; + + GLboolean generateMipmaps = (imageSize < 0) ? true : false; + if (imageSize < 0) imageSize *= -1; + const GLuint itarget = what_target(target); const GLuint rtarget = map_tex_target(target); if (target == GL_PROXY_TEXTURE_2D) { @@ -205,7 +265,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLe GLenum format = GL_RGBA; GLenum type = GL_UNSIGNED_BYTE; - if (isDXTc(internalformat)) { + if ((!isFormatSupported(internalformat) && isDXTc(internalformat)) || (globals4es.dxt == 1 && isDXTc(internalformat))) { if(level && bound->mipmap_auto==1) return; // nothing to do GLvoid *pixels, *half; @@ -295,7 +355,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLe bound->compressed = 1; bound->wanted_internal = bound->internalformat = internalformat; bound->valid = 1; - if(level) { + if(generateMipmaps) { // not automipmap yet? then set it... bound->mipmap_need = 1; // and upload higher level here... @@ -314,6 +374,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLe if(half) pixel_convert(ndata, &out, nww, nhh, GL_RGBA, GL_UNSIGNED_BYTE, format, type, 0, 1); ++leveln; + //SHUT_LOGD("generating decompressed mipmap\nlevel %i width %i height %i\n", leveln, nww, nhh); gl4es_glTexImage2D(target, leveln, new_intformat, nww, nhh, border, format, type, out); if(out!=ndata) free(out); @@ -327,6 +388,78 @@ void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLe free(half); if (pixels!=datab) free(pixels); + } else if (isDXTc(internalformat) && globals4es.dxt != 3) { + //SHUT_LOGD("level %i width %i height %i max level %i\n", level, width, height, bound->max_level); + + LOAD_GLES(glCompressedTexImage2D); + bound->alpha = (internalformat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) ? 0 : 1; + bound->format = internalformat; + //bound->type = GL_UNSIGNED_BYTE; + bound->type = (internalformat==GL_COMPRESSED_RGB_S3TC_DXT1_EXT || internalformat==GL_COMPRESSED_SRGB_S3TC_DXT1_EXT)?GL_UNSIGNED_SHORT_5_6_5:((internalformat==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)?GL_UNSIGNED_SHORT_5_5_5_1:GL_UNSIGNED_SHORT_4_4_4_4); + bound->wanted_internal = bound->internalformat = internalformat; + bound->compressed = 1; + bound->valid = 1; + + int oldalign; + gl4es_glGetIntegerv(GL_UNPACK_ALIGNMENT, &oldalign); + if (oldalign!=1) + gl4es_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if (glstate->fpe_state && glstate->fpe_bound_changed < glstate->texture.active+1) + glstate->fpe_bound_changed = glstate->texture.active+1; + gles_glCompressedTexImage2D(rtarget, level, internalformat, width, height, border, imageSize, datab); + + if (generateMipmaps) { + int simpleAlpha = 0; + int complexAlpha = 0; + int transparent0 = (internalformat==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || internalformat==GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT)?1:0; + + GLvoid *pixels; + if ((width&3) || (height&3)) { // can happens :( + GLvoid *tmp; + GLsizei nw=width; + GLsizei nh=height; + if (nw<4) nw = 4; + if (nh<4) nh = 4; + tmp = uncompressDXTc(nw, nh, internalformat, imageSize, transparent0, &simpleAlpha, &complexAlpha, datab); + pixels = malloc(4*width*height); + // crop + for (int y=0; yalpha = 1; @@ -335,6 +468,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexImage2D(GLenum target, GLint level, GLe bound->wanted_internal = bound->internalformat = internalformat; bound->compressed = 1; bound->valid = 1; + if (glstate->fpe_state && glstate->fpe_bound_changed < glstate->texture.active+1) glstate->fpe_bound_changed = glstate->texture.active+1; gles_glCompressedTexImage2D(rtarget, level, internalformat, width, height, border, imageSize, datab); @@ -347,6 +481,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexSubImage2D(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) { +//SHUT_LOGD("gl4es_glCompressedTexSubImage2D\n\n\n\n\n\n\n"); const GLuint itarget = what_target(target); FLUSH_BEGINEND; @@ -365,7 +500,7 @@ void APIENTRY_GL4ES gl4es_glCompressedTexSubImage2D(GLenum target, GLint level, int simpleAlpha = 0; int complexAlpha = 0; int transparent0 = (format==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format==GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT)?1:0; - if (isDXTc(format)) { + if ((!isFormatSupported(format) && isDXTc(format)) || (globals4es.dxt == 1 && isDXTc(format))) { if(level) { noerrorShim(); return; @@ -493,6 +628,16 @@ void APIENTRY_GL4ES gl4es_glCompressedTexSubImage3D(GLenum target, GLint level, gl4es_glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); } +void APIENTRY_GL4ES gl4es_glClipControlEXT(GLenum origin, GLenum depthMode) { + LOAD_GLES(glClipControlEXT); + gles_glClipControlEXT(origin, depthMode); +} + +void APIENTRY_GL4ES gl4es_glClipControl(GLenum origin, GLenum depthMode) { + LOAD_GLES(glClipControlEXT); + gles_glClipControlEXT(origin, depthMode); +} + //Direct wrapper AliasExport(void,glCompressedTexImage2D,,(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)); AliasExport(void,glCompressedTexImage1D,,(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data)); @@ -520,3 +665,6 @@ AliasExport(void,glCompressedTexSubImage1D,ARB,(GLenum target, GLint level, GLin AliasExport(void,glCompressedTexSubImage3D,ARB,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data)); AliasExport(void,glGetCompressedTexImage,ARB,(GLenum target, GLint lod, GLvoid *img)); +AliasExport(void,glClipControl,,(GLenum origin, GLenum depthMode)); +AliasExport(void,glClipControl,EXT,(GLenum origin, GLenum depthMode)); +AliasExport(void,glClipControl,ARB,(GLenum origin, GLenum depthMode)); diff --git a/src/gl/texture_params.c b/src/gl/texture_params.c index fe9911e9f..40eb03af8 100644 --- a/src/gl/texture_params.c +++ b/src/gl/texture_params.c @@ -237,7 +237,7 @@ GLenum get_texture_min_filter(gltexture_t* texture, glsampler_t* sampler) GLenum ret = sampler->min_filter; if ((globals4es.automipmap==3) || ((globals4es.automipmap==1) && (texture->mipmap_auto==0)) - || (texture->compressed && (texture->mipmap_auto==0))) { + /*|| (texture->compressed && (texture->mipmap_auto==0))*/) { switch (ret) { case GL_NEAREST_MIPMAP_NEAREST: case GL_NEAREST_MIPMAP_LINEAR: diff --git a/src/gl/wrap/gles.c b/src/gl/wrap/gles.c index 5168b1810..70fea018d 100644 --- a/src/gl/wrap/gles.c +++ b/src/gl/wrap/gles.c @@ -552,6 +552,20 @@ void APIENTRY_GL4ES gl4es_glDrawBuffers(GLsizei n, const GLenum * bufs) { } AliasExport(void,glDrawBuffers(,,GLsizei n, const GLenum * bufs)); #endif + + +#ifndef skip_glClipControlEXT +void APIENTRY_GL4ES gl4es_glClipControlEXT(GLenum origin, GLenum depthMode) { + LOAD_GLES_EXT(glClipControlEXT); +#ifndef direct_glClipControlEXT + PUSH_IF_COMPILING(glClipControlEXT) +#endif + gles_glClipControlEXT(origin, depthMode); +} +AliasExport(void,glClipControlEXT,,(GLenum origin, GLenum depthMode)); +#endif + + #ifndef skip_glDrawElements void APIENTRY_GL4ES gl4es_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices) { LOAD_GLES(glDrawElements); diff --git a/src/gl/wrap/gles.h b/src/gl/wrap/gles.h index b5d861fd9..5745a73e6 100644 --- a/src/gl/wrap/gles.h +++ b/src/gl/wrap/gles.h @@ -136,6 +136,7 @@ enum FORMAT { FORMAT_void_GLuint_GLfloat_GLfloat_GLfloat, FORMAT_void_GLuint_GLfloat_GLfloat_GLfloat_GLfloat, FORMAT_void_GLuint_GLint_GLenum_GLboolean_GLsizei_const_GLvoid___GENPT__, + FORMAT_void_GLenum_GLenum___GENPT__, }; typedef void (APIENTRY*FUNC_void_GLenum)(GLenum texture); @@ -3669,6 +3670,14 @@ packed_call_t* APIENTRY_GL4ES glCopyPackedCall(const packed_call_t *packed); #define glVertexAttribIPointer_INDEXED INDEXED_void_GLuint_GLint_GLenum_GLsizei_const_GLvoid___GENPT__ #define glVertexAttribIPointer_FORMAT FORMAT_void_GLuint_GLint_GLenum_GLsizei_const_GLvoid___GENPT__ +#define glClipControlEXT_INDEX 243 +#define glClipControlEXT_RETURN void +#define glClipControlEXT_ARG_NAMES origin, depthMode +#define glClipControlEXT_ARG_EXPAND GLenum origin, GLenum depthMode +#define glClipControlEXT_PACKED PACKED_void_GLenum_GLenum___GENPT__ +#define glClipControlEXT_INDEXED INDEXED_void_GLenum_GLenum___GENPT__ +#define glClipControlEXT_FORMAT FORMAT_void_GLenum_GLenum___GENPT__ + void APIENTRY_GL4ES gl4es_glActiveTexture(glActiveTexture_ARG_EXPAND); typedef void (APIENTRY_GLES * glActiveTexture_PTR)(glActiveTexture_ARG_EXPAND); void APIENTRY_GL4ES gl4es_glAlphaFunc(glAlphaFunc_ARG_EXPAND); @@ -3779,6 +3788,10 @@ void APIENTRY_GL4ES gl4es_glDrawArrays(glDrawArrays_ARG_EXPAND); typedef void (APIENTRY_GLES * glDrawArrays_PTR)(glDrawArrays_ARG_EXPAND); void APIENTRY_GL4ES gl4es_glDrawBuffers(glDrawBuffers_ARG_EXPAND); typedef void (APIENTRY_GLES * glDrawBuffers_PTR)(glDrawBuffers_ARG_EXPAND); + +void APIENTRY_GL4ES gl4es_glClipControlEXT(glClipControlEXT_ARG_EXPAND); +typedef void (APIENTRY_GLES * glClipControlEXT_PTR)(glClipControlEXT_ARG_EXPAND); + void APIENTRY_GL4ES gl4es_glDrawElements(glDrawElements_ARG_EXPAND); typedef void (APIENTRY_GLES * glDrawElements_PTR)(glDrawElements_ARG_EXPAND); void APIENTRY_GL4ES gl4es_glDrawTexf(glDrawTexf_ARG_EXPAND); @@ -4736,6 +4749,19 @@ typedef void (APIENTRY_GLES * glVertexAttribIPointer_PTR)(glVertexAttribIPointer glPushCall((void *)packed_data); \ } #endif + +#ifndef direct_glClipControlEXT +#define push_glClipControlEXT(origin, depthMode) { \ + glClipControlEXT_PACKED *packed_data = malloc(sizeof(glClipControlEXT_PACKED)); \ + packed_data->format = glClipControlEXT_FORMAT; \ + packed_data->func = gl4es_glClipControlEXT; \ + packed_data->args.a1 = (GLenum)origin; \ + packed_data->args.a2 = (GLenum)depthMode; \ + glPushCall((void *)packed_data); \ +} +#endif + + #ifndef direct_glDrawElements #define push_glDrawElements(mode, count, type, indices) { \ glDrawElements_PACKED *packed_data = malloc(sizeof(glDrawElements_PACKED)); \ diff --git a/src/gl/wrap/skips.h b/src/gl/wrap/skips.h index f709d0d55..45d049521 100644 --- a/src/gl/wrap/skips.h +++ b/src/gl/wrap/skips.h @@ -140,6 +140,7 @@ #define skip_glGetFramebufferAttachmentParameteriv #define skip_glGetRenderbufferParameteriv #define skip_glDrawBuffers +#define skip_glClipControlEXT #define skip_glFlush #define skip_glFinish diff --git a/src/glx/hardext.c b/src/glx/hardext.c index 46e35bb8b..a17c3c55b 100644 --- a/src/glx/hardext.c +++ b/src/glx/hardext.c @@ -320,9 +320,19 @@ void GetHardwareExtensions(int notest) } S("GL_OES_draw_texture ", drawtex, 1); S("GL_EXT_texture_rg ", rgtex, 1); + S("GL_EXT_clip_control ", clipcontrol, 1); + S("GL_EXT_texture_compression_s3tc ", dxtCompression, 1); + S("GL_EXT_texture_compression_dxt1 ", dxt1, 1); + S("GL_EXT_texture_compression_dxt3 ", dxt3, 1); + S("GL_EXT_texture_compression_dxt5 ", dxt5, 1); + S("GL_ANGLE_texture_compression_dxt1 ", dxt1angle, 1); + S("GL_ANGLE_texture_compression_dxt3 ", dxt3angle, 1); + S("GL_ANGLE_texture_compression_dxt5 ", dxt5angle, 1); if(globals4es.floattex) { S("GL_OES_texture_float ", floattex, 1); S("GL_OES_texture_half_float ", halffloattex, 1); + S("GL_OES_texture_float ", floattexlinear, 1); + S("GL_OES_texture_half_float ", halffloattexlinear, 1); S("GL_EXT_color_buffer_float ", floatfbo, 1); S("GL_EXT_color_buffer_half_float ", halffloatfbo, 1); } diff --git a/src/glx/hardext.h b/src/glx/hardext.h index f579bc5b7..df66d217f 100644 --- a/src/glx/hardext.h +++ b/src/glx/hardext.h @@ -35,6 +35,16 @@ typedef struct _hardext { int rgtex; // GL_EXT_texture_rg int floattex; // GL_OES_texture_float int halffloattex; // GL_OES_texture_half_float + int floattexlinear; // GL_OES_texture_float_linear + int halffloattexlinear; // GL_OES_texture_half_float_linear + int clipcontrol; // GL_EXT_clip_control + int dxtCompression; // GL_EXT_texture_compression_s3tc + int dxt1; // GL_EXT_texture_compression_dxt1 + int dxt3; // GL_EXT_texture_compression_dxt3 + int dxt5; // GL_EXT_texture_compression_dxt5 + int dxt1angle; // GL_ANGLE_texture_compression_dxt1 + int dxt3angle; // GL_ANGLE_texture_compression_dxt3 + int dxt5angle; // GL_ANGLE_texture_compression_dxt5 int floatfbo; // GL_EXT_color_buffer_float int halffloatfbo; // GL_EXT_color_buffer_half_float int rgb332; // GL_AOS4_texture_format_RGB332