diff --git a/Source/Glitch64/Glitch64.vcproj b/Source/Glitch64/Glitch64.vcproj
index e02701d25..15a142bce 100644
--- a/Source/Glitch64/Glitch64.vcproj
+++ b/Source/Glitch64/Glitch64.vcproj
@@ -145,23 +145,23 @@
Filter="*.cpp"
>
diff --git a/Source/Glitch64/OGLEScombiner.cpp b/Source/Glitch64/OGLEScombiner.cpp
new file mode 100644
index 000000000..1933230da
--- /dev/null
+++ b/Source/Glitch64/OGLEScombiner.cpp
@@ -0,0 +1,2808 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002 Dave2001
+* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifdef _WIN32
+#include
+#else // _WIN32
+#include
+#include
+#endif // _WIN32
+#include
+#include
+#include "glide.h"
+#include "main.h"
+
+void vbo_draw();
+
+static int fct[4], source0[4], operand0[4], source1[4], operand1[4], source2[4], operand2[4];
+static int fcta[4],sourcea0[4],operanda0[4],sourcea1[4],operanda1[4],sourcea2[4],operanda2[4];
+static int alpha_ref, alpha_func;
+bool alpha_test = 0;
+
+float texture_env_color[4];
+float ccolor0[4];
+float ccolor1[4];
+static float chroma_color[4];
+int fog_enabled;
+static int chroma_enabled;
+static int chroma_other_color;
+static int chroma_other_alpha;
+static int dither_enabled;
+int blackandwhite0;
+int blackandwhite1;
+
+float fogStart,fogEnd;
+float fogColor[4];
+
+#ifdef _WIN32
+static float farF;
+static float nearF;
+#endif // _WIN32
+
+int need_lambda[2];
+float lambda_color[2][4];
+
+// shaders variables
+int need_to_compile;
+
+static GLuint fragment_shader_object;
+static GLuint fragment_depth_shader_object;
+static GLuint vertex_shader_object;
+static GLuint program_object_default;
+static GLuint program_object_depth;
+static GLuint program_object;
+static int constant_color_location;
+static int ccolor0_location;
+static int ccolor1_location;
+static int first_color = 1;
+static int first_alpha = 1;
+static int first_texture0 = 1;
+static int first_texture1 = 1;
+static int tex0_combiner_ext = 0;
+static int tex1_combiner_ext = 0;
+static int c_combiner_ext = 0;
+static int a_combiner_ext = 0;
+
+#define GLSL_VERSION "100"
+
+#define SHADER_HEADER \
+"#version " GLSL_VERSION " \n" \
+"#define gl_Color vFrontColor \n" \
+"#define gl_FrontColor vFrontColor \n" \
+"#define gl_TexCoord vTexCoord \n"
+
+#define SHADER_VARYING \
+"varying highp vec4 gl_FrontColor; \n" \
+"varying highp vec4 gl_TexCoord[4]; \n"
+
+static const char* fragment_shader_header =
+SHADER_HEADER
+"precision lowp float; \n"
+"uniform sampler2D texture0; \n"
+"uniform sampler2D texture1; \n"
+"uniform sampler2D ditherTex; \n"
+"uniform vec4 constant_color; \n"
+"uniform vec4 ccolor0; \n"
+"uniform vec4 ccolor1; \n"
+"uniform vec4 chroma_color; \n"
+"uniform float lambda; \n"
+"uniform vec3 fogColor; \n"
+"uniform float alphaRef; \n"
+SHADER_VARYING
+" \n"
+"void test_chroma(vec4 ctexture1); \n"
+" \n"
+" \n"
+"void main() \n"
+"{ \n"
+;
+
+// using gl_FragCoord is terribly slow on ATI and varying variables don't work for some unknown
+// reason, so we use the unused components of the texture2 coordinates
+static const char* fragment_shader_dither =
+" float dithx = (gl_TexCoord[2].b + 1.0)*0.5*1000.0; \n"
+" float dithy = (gl_TexCoord[2].a + 1.0)*0.5*1000.0; \n"
+" if(texture2D(ditherTex, vec2((dithx-32.0*floor(dithx/32.0))/32.0, \n"
+" (dithy-32.0*floor(dithy/32.0))/32.0)).a > 0.5) discard; \n"
+;
+
+static const char* fragment_shader_default =
+" gl_FragColor = texture2D(texture0, vec2(gl_TexCoord[0])); \n"
+;
+
+static const char* fragment_shader_readtex0color =
+" vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n"
+;
+
+static const char* fragment_shader_readtex0bw =
+" vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n"
+" readtex0 = vec4(vec3(readtex0.b), \n"
+" readtex0.r + readtex0.g * 8.0 / 256.0); \n"
+;
+static const char* fragment_shader_readtex0bw_2 =
+" vec4 readtex0 = vec4(dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(1.0/3, 1.0/3, 1.0/3, 0))); \n"
+;
+
+static const char* fragment_shader_readtex1color =
+" vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n"
+;
+
+static const char* fragment_shader_readtex1bw =
+" vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n"
+" readtex1 = vec4(vec3(readtex1.b), \n"
+" readtex1.r + readtex1.g * 8.0 / 256.0); \n"
+;
+static const char* fragment_shader_readtex1bw_2 =
+" vec4 readtex1 = vec4(dot(texture2D(texture1, vec2(gl_TexCoord[1])), vec4(1.0/3, 1.0/3, 1.0/3, 0))); \n"
+;
+
+static const char* fragment_shader_fog =
+" float fog; \n"
+" fog = gl_TexCoord[0].b; \n"
+" gl_FragColor.rgb = mix(fogColor, gl_FragColor.rgb, fog); \n"
+;
+
+static const char* fragment_shader_end =
+"if(gl_FragColor.a <= alphaRef) {discard;} \n"
+" \n"
+"} \n"
+;
+
+static const char* vertex_shader =
+SHADER_HEADER
+"#define Z_MAX 65536.0 \n"
+"attribute highp vec4 aVertex; \n"
+"attribute highp vec4 aColor; \n"
+"attribute highp vec4 aMultiTexCoord0; \n"
+"attribute highp vec4 aMultiTexCoord1; \n"
+"attribute float aFog; \n"
+"uniform vec3 vertexOffset; \n" //Moved some calculations from grDrawXXX to shader
+"uniform vec4 textureSizes; \n"
+"uniform vec3 fogModeEndScale; \n" //0 = Mode, 1 = gl_Fog.end, 2 = gl_Fog.scale
+SHADER_VARYING
+" \n"
+"void main() \n"
+"{ \n"
+" float q = aVertex.w; \n"
+" float invertY = vertexOffset.z; \n" //Usually 1.0 but -1.0 when rendering to a texture (see inverted_culling grRenderBuffer)
+" gl_Position.x = (aVertex.x - vertexOffset.x) / vertexOffset.x; \n"
+" gl_Position.y = invertY *-(aVertex.y - vertexOffset.y) / vertexOffset.y; \n"
+" gl_Position.z = aVertex.z / Z_MAX; \n"
+" gl_Position.w = 1.0; \n"
+" gl_Position /= q; \n"
+" gl_FrontColor = aColor.bgra; \n"
+" \n"
+" gl_TexCoord[0] = vec4(aMultiTexCoord0.xy / q / textureSizes.xy,0,1); \n"
+" gl_TexCoord[1] = vec4(aMultiTexCoord1.xy / q / textureSizes.zw,0,1); \n"
+" \n"
+" float fogV = (1.0 / mix(q,aFog,fogModeEndScale[0])) / 255.0; \n"
+" //if(fogMode == 2) { \n"
+" // fogV = 1.0 / aFog / 255 \n"
+" //} \n"
+" \n"
+" float f = (fogModeEndScale[1] - fogV) * fogModeEndScale[2]; \n"
+" f = clamp(f, 0.0, 1.0); \n"
+" gl_TexCoord[0].b = f; \n"
+" gl_TexCoord[2].b = aVertex.x; \n"
+" gl_TexCoord[2].a = aVertex.y; \n"
+"} \n"
+;
+
+static char fragment_shader_color_combiner[1024];
+static char fragment_shader_alpha_combiner[1024];
+static char fragment_shader_texture1[1024];
+static char fragment_shader_texture0[1024];
+static char fragment_shader_chroma[1024];
+static char shader_log[2048];
+
+void check_compile(GLuint shader)
+{
+ GLint success;
+ glGetShaderiv(shader,GL_COMPILE_STATUS,&success);
+ if(!success)
+ {
+ char log[1024];
+ glGetShaderInfoLog(shader,1024,NULL,log);
+ LOGINFO(log);
+ }
+}
+
+void check_link(GLuint program)
+{
+ GLint success;
+ glGetProgramiv(program,GL_LINK_STATUS,&success);
+ if(!success)
+{
+ char log[1024];
+ glGetProgramInfoLog(program,1024,NULL,log);
+ LOGINFO(log);
+ }
+}
+
+void init_combiner()
+{
+ int texture[4] = {0, 0, 0, 0};
+
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+
+ // creating a fake texture
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ glEnable(GL_TEXTURE_2D);
+
+ int texture0_location;
+ int texture1_location;
+ char *fragment_shader;
+ int log_length;
+
+#ifndef ANDROID
+ // depth shader
+ fragment_depth_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+
+ char s[128];
+ // ZIGGY convert a 565 texture into depth component
+ sprintf(s, "gl_FragDepth = dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(31*64*32, 63*32, 31, 0))*%g + %g; \n", zscale/2/65535.0, 1-zscale/2);
+ fragment_shader = (char*)malloc(strlen(fragment_shader_header)+
+ strlen(s)+
+ strlen(fragment_shader_end)+1);
+ strcpy(fragment_shader, fragment_shader_header);
+ strcat(fragment_shader, s);
+ strcat(fragment_shader, fragment_shader_end);
+ glShaderSource(fragment_depth_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+ free(fragment_shader);
+
+ glCompileShader(fragment_depth_shader_object);
+ check_compile(fragment_depth_shader_object);
+#endif
+
+ // default shader
+ fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+
+ fragment_shader = (char*)malloc(strlen(fragment_shader_header)+
+ strlen(fragment_shader_default)+
+ strlen(fragment_shader_end)+1);
+ strcpy(fragment_shader, fragment_shader_header);
+ strcat(fragment_shader, fragment_shader_default);
+ strcat(fragment_shader, fragment_shader_end);
+ glShaderSource(fragment_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+ free(fragment_shader);
+
+ glCompileShader(fragment_shader_object);
+ check_compile(fragment_shader_object);
+
+ vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertex_shader_object, 1, &vertex_shader, NULL);
+ glCompileShader(vertex_shader_object);
+ check_compile(vertex_shader_object);
+
+ // depth program
+ program_object = glCreateProgram();
+ program_object_depth = program_object;
+ glAttachShader(program_object, fragment_depth_shader_object);
+ glAttachShader(program_object, vertex_shader_object);
+
+ glBindAttribLocation(program_object,POSITION_ATTR,"aPosition");
+ glBindAttribLocation(program_object,COLOUR_ATTR,"aColor");
+ glBindAttribLocation(program_object,TEXCOORD_0_ATTR,"aMultiTexCoord0");
+ glBindAttribLocation(program_object,TEXCOORD_1_ATTR,"aMultiTexCoord1");
+ glBindAttribLocation(program_object,FOG_ATTR,"aFog");
+
+ glLinkProgram(program_object);
+ check_link(program_object);
+ glUseProgram(program_object);
+
+ texture0_location = glGetUniformLocation(program_object, "texture0");
+ texture1_location = glGetUniformLocation(program_object, "texture1");
+ glUniform1i(texture0_location, 0);
+ glUniform1i(texture1_location, 1);
+
+ // default program
+ program_object = glCreateProgram();
+ program_object_default = program_object;
+ glAttachShader(program_object, fragment_shader_object);
+ glAttachShader(program_object, vertex_shader_object);
+
+ glBindAttribLocation(program_object,POSITION_ATTR,"aPosition");
+ glBindAttribLocation(program_object,COLOUR_ATTR,"aColor");
+ glBindAttribLocation(program_object,TEXCOORD_0_ATTR,"aMultiTexCoord0");
+ glBindAttribLocation(program_object,TEXCOORD_1_ATTR,"aMultiTexCoord1");
+ glBindAttribLocation(program_object,FOG_ATTR,"aFog");
+
+ glLinkProgram(program_object);
+ check_link(program_object);
+ glUseProgram(program_object);
+
+ texture0_location = glGetUniformLocation(program_object, "texture0");
+ texture1_location = glGetUniformLocation(program_object, "texture1");
+ glUniform1i(texture0_location, 0);
+ glUniform1i(texture1_location, 1);
+
+ strcpy(fragment_shader_color_combiner, "");
+ strcpy(fragment_shader_alpha_combiner, "");
+ strcpy(fragment_shader_texture1, "vec4 ctexture1 = texture2D(texture0, vec2(gl_TexCoord[0])); \n");
+ strcpy(fragment_shader_texture0, "");
+
+ first_color = 1;
+ first_alpha = 1;
+ first_texture0 = 1;
+ first_texture1 = 1;
+ need_to_compile = 0;
+ fog_enabled = 0;
+ chroma_enabled = 0;
+ dither_enabled = 0;
+ blackandwhite0 = 0;
+ blackandwhite1 = 0;
+}
+
+void compile_chroma_shader()
+{
+ strcpy(fragment_shader_chroma, "\nvoid test_chroma(vec4 ctexture1)\n{\n");
+
+ switch(chroma_other_alpha)
+ {
+ case GR_COMBINE_OTHER_ITERATED:
+ strcat(fragment_shader_chroma, "float alpha = gl_Color.a; \n");
+ break;
+ case GR_COMBINE_OTHER_TEXTURE:
+ strcat(fragment_shader_chroma, "float alpha = ctexture1.a; \n");
+ break;
+ case GR_COMBINE_OTHER_CONSTANT:
+ strcat(fragment_shader_chroma, "float alpha = constant_color.a; \n");
+ break;
+ default:
+ display_warning("unknown compile_choma_shader_alpha : %x", chroma_other_alpha);
+ }
+
+ switch(chroma_other_color)
+ {
+ case GR_COMBINE_OTHER_ITERATED:
+ strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(gl_Color),alpha); \n");
+ break;
+ case GR_COMBINE_OTHER_TEXTURE:
+ strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(ctexture1),alpha); \n");
+ break;
+ case GR_COMBINE_OTHER_CONSTANT:
+ strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(constant_color),alpha); \n");
+ break;
+ default:
+ display_warning("unknown compile_choma_shader_alpha : %x", chroma_other_color);
+ }
+
+ strcat(fragment_shader_chroma, "if (color.rgb == chroma_color.rgb) discard; \n");
+ strcat(fragment_shader_chroma, "}");
+}
+
+typedef struct _shader_program_key
+{
+ int color_combiner;
+ int alpha_combiner;
+ int texture0_combiner;
+ int texture1_combiner;
+ int texture0_combinera;
+ int texture1_combinera;
+ int fog_enabled;
+ int chroma_enabled;
+ int dither_enabled;
+ int blackandwhite0;
+ int blackandwhite1;
+ GLuint fragment_shader_object;
+ GLuint program_object;
+ int texture0_location;
+ int texture1_location;
+ int vertexOffset_location;
+ int textureSizes_location;
+ int fogModeEndScale_location;
+ int fogColor_location;
+ int alphaRef_location;
+ int ditherTex_location;
+ int chroma_color_location;
+} shader_program_key;
+
+static shader_program_key* shader_programs = NULL;
+static int number_of_programs = 0;
+static int color_combiner_key;
+static int alpha_combiner_key;
+static int texture0_combiner_key;
+static int texture1_combiner_key;
+static int texture0_combinera_key;
+static int texture1_combinera_key;
+
+void update_uniforms(shader_program_key prog)
+{
+ glUniform1i(prog.texture0_location, 0);
+ glUniform1i(prog.texture1_location, 1);
+
+ glUniform3f(prog.vertexOffset_location,widtho,heighto,inverted_culling ? -1.0f : 1.0f);
+ glUniform4f(prog.textureSizes_location,tex0_width,tex0_height,tex1_width,tex1_height);
+
+ glUniform3f(prog.fogModeEndScale_location,
+ fog_enabled != 2 ? 0.0f : 1.0f,
+ fogEnd,
+ 1.0f / (fogEnd - fogStart)
+ );
+
+ if(prog.fogColor_location != -1)
+ {
+ glUniform3f(prog.fogColor_location,fogColor[0],fogColor[1],fogColor[2]);
+ }
+
+ glUniform1f(prog.alphaRef_location,alpha_test ? alpha_ref/255.0f : -1.0f);
+
+ constant_color_location = glGetUniformLocation(program_object, "constant_color");
+ glUniform4f(constant_color_location, texture_env_color[0], texture_env_color[1],
+ texture_env_color[2], texture_env_color[3]);
+
+ ccolor0_location = glGetUniformLocation(program_object, "ccolor0");
+ glUniform4f(ccolor0_location, ccolor0[0], ccolor0[1], ccolor0[2], ccolor0[3]);
+
+ ccolor1_location = glGetUniformLocation(program_object, "ccolor1");
+ glUniform4f(ccolor1_location, ccolor1[0], ccolor1[1], ccolor1[2], ccolor1[3]);
+
+ glUniform4f(prog.chroma_color_location, chroma_color[0], chroma_color[1],
+ chroma_color[2], chroma_color[3]);
+
+ if(dither_enabled)
+ {
+ glUniform1i(prog.ditherTex_location, 2);
+ }
+
+ set_lambda();
+}
+
+void disable_textureSizes()
+{
+ int textureSizes_location = glGetUniformLocation(program_object_default,"textureSizes");
+ glUniform4f(textureSizes_location,1,1,1,1);
+}
+
+void compile_shader()
+{
+ int texture0_location;
+ int texture1_location;
+ int ditherTex_location;
+ int vertexOffset_location;
+ int textureSizes_location;
+ char *fragment_shader;
+ int i;
+ int chroma_color_location;
+ int log_length;
+
+ need_to_compile = 0;
+
+ for(i=0; i> 24) & 0xFF) / 255.0f;
+ texture_env_color[0] = ((value >> 16) & 0xFF) / 255.0f;
+ texture_env_color[1] = ((value >> 8) & 0xFF) / 255.0f;
+ texture_env_color[2] = (value & 0xFF) / 255.0f;
+ break;
+ case GR_COLORFORMAT_RGBA:
+ texture_env_color[0] = ((value >> 24) & 0xFF) / 255.0f;
+ texture_env_color[1] = ((value >> 16) & 0xFF) / 255.0f;
+ texture_env_color[2] = ((value >> 8) & 0xFF) / 255.0f;
+ texture_env_color[3] = (value & 0xFF) / 255.0f;
+ break;
+ default:
+ display_warning("grConstantColorValue: unknown color format : %x", lfb_color_fmt);
+ }
+
+ vbo_draw();
+
+ constant_color_location = glGetUniformLocation(program_object, "constant_color");
+ glUniform4f(constant_color_location, texture_env_color[0], texture_env_color[1],
+ texture_env_color[2], texture_env_color[3]);
+}
+
+void writeGLSLColorOther(int other)
+{
+ switch(other)
+ {
+ case GR_COMBINE_OTHER_ITERATED:
+ strcat(fragment_shader_color_combiner, "vec4 color_other = gl_Color; \n");
+ break;
+ case GR_COMBINE_OTHER_TEXTURE:
+ strcat(fragment_shader_color_combiner, "vec4 color_other = ctexture1; \n");
+ break;
+ case GR_COMBINE_OTHER_CONSTANT:
+ strcat(fragment_shader_color_combiner, "vec4 color_other = constant_color; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLColorOther : %x", other);
+ }
+}
+
+void writeGLSLColorLocal(int local)
+{
+ switch(local)
+ {
+ case GR_COMBINE_LOCAL_ITERATED:
+ strcat(fragment_shader_color_combiner, "vec4 color_local = gl_Color; \n");
+ break;
+ case GR_COMBINE_LOCAL_CONSTANT:
+ strcat(fragment_shader_color_combiner, "vec4 color_local = constant_color; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLColorLocal : %x", local);
+ }
+}
+
+void writeGLSLColorFactor(int factor, int local, int need_local, int other, int need_other)
+{
+ switch(factor)
+ {
+ case GR_COMBINE_FACTOR_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(0.0); \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL:
+ if(need_local) writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = color_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_OTHER_ALPHA:
+ if(need_other) writeGLSLColorOther(other);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(color_other.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL_ALPHA:
+ if(need_local) writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(color_local.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_TEXTURE_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(ctexture1.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_TEXTURE_RGB:
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = ctexture1; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE:
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL:
+ if(need_local) writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - color_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA:
+ if(need_other) writeGLSLColorOther(other);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(color_other.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA:
+ if(need_local) writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(color_local.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(ctexture1.a); \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLColorFactor : %x", factor);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grColorCombine(
+ GrCombineFunction_t function, GrCombineFactor_t factor,
+ GrCombineLocal_t local, GrCombineOther_t other,
+ FxBool invert )
+{
+ LOG("grColorCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert);
+ static int last_function = 0;
+ static int last_factor = 0;
+ static int last_local = 0;
+ static int last_other = 0;
+
+ if(last_function == function && last_factor == factor &&
+ last_local == local && last_other == other && first_color == 0 && !c_combiner_ext) return;
+ first_color = 0;
+ c_combiner_ext = 0;
+
+ last_function = function;
+ last_factor = factor;
+ last_local = local;
+ last_other = other;
+
+ if (invert) display_warning("grColorCombine : inverted result");
+
+ color_combiner_key = function | (factor << 4) | (local << 8) | (other << 10);
+ chroma_other_color = other;
+
+ strcpy(fragment_shader_color_combiner, "");
+ switch(function)
+ {
+ case GR_COMBINE_FUNCTION_ZERO:
+ strcat(fragment_shader_color_combiner, "gl_FragColor = vec4(0.0); \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL:
+ writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL_ALPHA:
+ writeGLSLColorLocal(local);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = vec4(color_local.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER:
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,1,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL:
+ writeGLSLColorLocal(local);
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,0,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other + color_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA:
+ writeGLSLColorLocal(local);
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,0,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other + vec4(color_local.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL:
+ writeGLSLColorLocal(local);
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,0,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLColorLocal(local);
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,0,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local) + color_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLColorLocal(local);
+ writeGLSLColorOther(other);
+ writeGLSLColorFactor(factor,local,0,other,0);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local) + vec4(color_local.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLColorLocal(local);
+ writeGLSLColorFactor(factor,local,0,other,1);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (-color_local) + color_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLColorLocal(local);
+ writeGLSLColorFactor(factor,local,0,other,1);
+ strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (-color_local) + vec4(color_local.a); \n");
+ break;
+ default:
+ strcpy(fragment_shader_color_combiner, fragment_shader_default);
+ display_warning("grColorCombine : unknown function : %x", function);
+ }
+ //compile_shader();
+ need_to_compile = 1;
+}
+
+/*
+int setOtherAlphaSource(int other)
+{
+ switch(other)
+ {
+ case GR_COMBINE_OTHER_ITERATED:
+ return GL_PRIMARY_COLOR_ARB;
+ break;
+ case GR_COMBINE_OTHER_TEXTURE:
+ return GL_PREVIOUS_ARB;
+ break;
+ case GR_COMBINE_OTHER_CONSTANT:
+ return GL_CONSTANT_ARB;
+ break;
+ default:
+ display_warning("unknwown other alpha source : %x", other);
+ }
+ return 0;
+}
+
+int setLocalAlphaSource(int local)
+{
+ switch(local)
+ {
+ case GR_COMBINE_LOCAL_ITERATED:
+ return GL_PRIMARY_COLOR_ARB;
+ break;
+ case GR_COMBINE_LOCAL_CONSTANT:
+ return GL_CONSTANT_ARB;
+ break;
+ default:
+ display_warning("unknwown local alpha source : %x", local);
+ }
+ return 0;
+}
+*/
+
+void writeGLSLAlphaOther(int other)
+{
+ switch(other)
+ {
+ case GR_COMBINE_OTHER_ITERATED:
+ strcat(fragment_shader_alpha_combiner, "float alpha_other = gl_Color.a; \n");
+ break;
+ case GR_COMBINE_OTHER_TEXTURE:
+ strcat(fragment_shader_alpha_combiner, "float alpha_other = ctexture1.a; \n");
+ break;
+ case GR_COMBINE_OTHER_CONSTANT:
+ strcat(fragment_shader_alpha_combiner, "float alpha_other = constant_color.a; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLAlphaOther : %x", other);
+ }
+}
+
+void writeGLSLAlphaLocal(int local)
+{
+ switch(local)
+ {
+ case GR_COMBINE_LOCAL_ITERATED:
+ strcat(fragment_shader_alpha_combiner, "float alpha_local = gl_Color.a; \n");
+ break;
+ case GR_COMBINE_LOCAL_CONSTANT:
+ strcat(fragment_shader_alpha_combiner, "float alpha_local = constant_color.a; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLAlphaLocal : %x", local);
+ }
+}
+
+void writeGLSLAlphaFactor(int factor, int local, int need_local, int other, int need_other)
+{
+ switch(factor)
+ {
+ case GR_COMBINE_FACTOR_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 0.0; \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL:
+ if(need_local) writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_OTHER_ALPHA:
+ if(need_other) writeGLSLAlphaOther(other);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_other; \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL_ALPHA:
+ if(need_local) writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = ctexture1.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE:
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL:
+ if(need_local) writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA:
+ if(need_other) writeGLSLAlphaOther(other);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_other; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA:
+ if(need_local) writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_local; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - ctexture1.a; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLAlphaFactor : %x", factor);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grAlphaCombine(
+ GrCombineFunction_t function, GrCombineFactor_t factor,
+ GrCombineLocal_t local, GrCombineOther_t other,
+ FxBool invert
+ )
+{
+ LOG("grAlphaCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert);
+ static int last_function = 0;
+ static int last_factor = 0;
+ static int last_local = 0;
+ static int last_other = 0;
+
+ if(last_function == function && last_factor == factor &&
+ last_local == local && last_other == other && first_alpha == 0 && !a_combiner_ext) return;
+ first_alpha = 0;
+ a_combiner_ext = 0;
+
+ last_function = function;
+ last_factor = factor;
+ last_local = local;
+ last_other = other;
+
+ if (invert) display_warning("grAlphaCombine : inverted result");
+
+ alpha_combiner_key = function | (factor << 4) | (local << 8) | (other << 10);
+ chroma_other_alpha = other;
+
+ strcpy(fragment_shader_alpha_combiner, "");
+
+ switch(function)
+ {
+ case GR_COMBINE_FUNCTION_ZERO:
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = 0.0; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL:
+ writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL_ALPHA:
+ writeGLSLAlphaLocal(local);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER:
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,1,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,0,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other + alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,0,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other + alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,0,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,0,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local) + alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaOther(other);
+ writeGLSLAlphaFactor(factor,local,0,other,0);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local) + alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaFactor(factor,local,0,other,1);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (-alpha_local) + alpha_local; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLAlphaLocal(local);
+ writeGLSLAlphaFactor(factor,local,0,other,1);
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (-alpha_local) + alpha_local; \n");
+ break;
+ default:
+ display_warning("grAlphaCombine : unknown function : %x", function);
+ }
+
+ //compile_shader();
+ need_to_compile = 1;
+}
+
+void writeGLSLTextureColorFactor(int num_tex, int factor)
+{
+ switch(factor)
+ {
+ case GR_COMBINE_FACTOR_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(0.0); \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = readtex1; \n");
+ break;
+ case GR_COMBINE_FACTOR_OTHER_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(ctexture0.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(readtex1.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(lambda); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(lambda); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - readtex1; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(ctexture0.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(readtex1.a); \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(lambda); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(lambda); \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLTextureColorFactor : %x", factor);
+ }
+}
+
+void writeGLSLTextureAlphaFactor(int num_tex, int factor)
+{
+ switch(factor)
+ {
+ case GR_COMBINE_FACTOR_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 0.0; \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = readtex1.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_OTHER_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = ctexture0.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = readtex1.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = lambda; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = lambda; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - readtex1.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - ctexture0.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - readtex1.a; \n");
+ break;
+ case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - lambda; \n");
+ else
+ strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - lambda; \n");
+ break;
+ default:
+ display_warning("unknown writeGLSLTextureAlphaFactor : %x", factor);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grTexCombine(
+ GrChipID_t tmu,
+ GrCombineFunction_t rgb_function,
+ GrCombineFactor_t rgb_factor,
+ GrCombineFunction_t alpha_function,
+ GrCombineFactor_t alpha_factor,
+ FxBool rgb_invert,
+ FxBool alpha_invert
+ )
+{
+ LOG("grTexCombine(%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, rgb_function, rgb_factor, alpha_function, alpha_factor, rgb_invert, alpha_invert);
+ int num_tex;
+
+ if (tmu == GR_TMU0) num_tex = 1;
+ else num_tex = 0;
+
+ if(num_tex == 0)
+ {
+ static int last_function = 0;
+ static int last_factor = 0;
+ static int last_afunction = 0;
+ static int last_afactor = 0;
+ static int last_rgb_invert = 0;
+
+ if(last_function == rgb_function && last_factor == rgb_factor &&
+ last_afunction == alpha_function && last_afactor == alpha_factor &&
+ last_rgb_invert == rgb_invert && first_texture0 == 0 && !tex0_combiner_ext) return;
+ first_texture0 = 0;
+ tex0_combiner_ext = 0;
+
+ last_function = rgb_function;
+ last_factor = rgb_factor;
+ last_afunction = alpha_function;
+ last_afactor = alpha_factor;
+ last_rgb_invert= rgb_invert;
+ texture0_combiner_key = rgb_function | (rgb_factor << 4) |
+ (alpha_function << 8) | (alpha_factor << 12) |
+ (rgb_invert << 16);
+ texture0_combinera_key = 0;
+ strcpy(fragment_shader_texture0, "");
+ }
+ else
+ {
+ static int last_function = 0;
+ static int last_factor = 0;
+ static int last_afunction = 0;
+ static int last_afactor = 0;
+ static int last_rgb_invert = 0;
+
+ if(last_function == rgb_function && last_factor == rgb_factor &&
+ last_afunction == alpha_function && last_afactor == alpha_factor &&
+ last_rgb_invert == rgb_invert && first_texture1 == 0 && !tex1_combiner_ext) return;
+ first_texture1 = 0;
+ tex1_combiner_ext = 0;
+
+ last_function = rgb_function;
+ last_factor = rgb_factor;
+ last_afunction = alpha_function;
+ last_afactor = alpha_factor;
+ last_rgb_invert = rgb_invert;
+
+ texture1_combiner_key = rgb_function | (rgb_factor << 4) |
+ (alpha_function << 8) | (alpha_factor << 12) |
+ (rgb_invert << 16);
+ texture1_combinera_key = 0;
+ strcpy(fragment_shader_texture1, "");
+ }
+
+ switch(rgb_function)
+ {
+ case GR_COMBINE_FUNCTION_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = vec4(0.0); \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = readtex1; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = vec4(readtex1.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0) + readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0 + readtex1; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0) + vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0 + vec4(readtex1.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0) + readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1) + readtex1; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0) + vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1) + vec4(readtex1.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (-readtex0) + readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (-readtex1) + readtex1; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLTextureColorFactor(num_tex, rgb_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (-readtex0) + vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (-readtex1) + vec4(readtex1.a); \n");
+ break;
+ default:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = readtex1; \n");
+ display_warning("grTextCombine : unknown rgb function : %x", rgb_function);
+ }
+
+ if (rgb_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0 = vec4(1.0) - ctexture0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1 = vec4(1.0) - ctexture1; \n");
+ }
+
+ switch(alpha_function)
+ {
+ case GR_COMBINE_FACTOR_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = 0.0; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_LOCAL_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0 + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a + readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0 + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a + readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a); \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a) + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a) + readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a) + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a) + readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (-readtex0.a) + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (-readtex1.a) + readtex1.a; \n");
+ break;
+ case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA:
+ writeGLSLTextureAlphaFactor(num_tex, alpha_factor);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (-readtex0.a) + readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (-readtex1.a) + readtex1.a; \n");
+ break;
+ default:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = ctexture0.a; \n");
+ display_warning("grTextCombine : unknown alpha function : %x", alpha_function);
+ }
+
+ if (alpha_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = 1.0 - ctexture0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = 1.0 - ctexture1.a; \n");
+ }
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grAlphaBlendFunction(
+ GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df,
+ GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df
+ )
+{
+ int sfactorRGB = 0, dfactorRGB = 0, sfactorAlpha = 0, dfactorAlpha = 0;
+ LOG("grAlphaBlendFunction(%d,%d,%d,%d)\r\n", rgb_sf, rgb_df, alpha_sf, alpha_df);
+
+ switch(rgb_sf)
+ {
+ case GR_BLEND_ZERO:
+ sfactorRGB = GL_ZERO;
+ break;
+ case GR_BLEND_SRC_ALPHA:
+ sfactorRGB = GL_SRC_ALPHA;
+ break;
+ case GR_BLEND_ONE:
+ sfactorRGB = GL_ONE;
+ break;
+ case GR_BLEND_ONE_MINUS_SRC_ALPHA:
+ sfactorRGB = GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ default:
+ display_warning("grAlphaBlendFunction : rgb_sf = %x", rgb_sf);
+ }
+
+ switch(rgb_df)
+ {
+ case GR_BLEND_ZERO:
+ dfactorRGB = GL_ZERO;
+ break;
+ case GR_BLEND_SRC_ALPHA:
+ dfactorRGB = GL_SRC_ALPHA;
+ break;
+ case GR_BLEND_ONE:
+ dfactorRGB = GL_ONE;
+ break;
+ case GR_BLEND_ONE_MINUS_SRC_ALPHA:
+ dfactorRGB = GL_ONE_MINUS_SRC_ALPHA;
+ break;
+ default:
+ display_warning("grAlphaBlendFunction : rgb_df = %x", rgb_df);
+ }
+
+ switch(alpha_sf)
+ {
+ case GR_BLEND_ZERO:
+ sfactorAlpha = GL_ZERO;
+ break;
+ case GR_BLEND_ONE:
+ sfactorAlpha = GL_ONE;
+ break;
+ default:
+ display_warning("grAlphaBlendFunction : alpha_sf = %x", alpha_sf);
+ }
+
+ switch(alpha_df)
+ {
+ case GR_BLEND_ZERO:
+ dfactorAlpha = GL_ZERO;
+ break;
+ case GR_BLEND_ONE:
+ dfactorAlpha = GL_ONE;
+ break;
+ default:
+ display_warning("grAlphaBlendFunction : alpha_df = %x", alpha_df);
+ }
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+/*
+ if (blend_func_separate_support)
+ glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+ else
+ glBlendFunc(sfactorRGB, dfactorRGB);
+*/
+}
+
+FX_ENTRY void FX_CALL
+grAlphaTestReferenceValue( GrAlpha_t value )
+{
+ LOG("grAlphaTestReferenceValue(%d)\r\n", value);
+ alpha_ref = value;
+ grAlphaTestFunction(alpha_func);
+}
+
+FX_ENTRY void FX_CALL
+grAlphaTestFunction( GrCmpFnc_t function )
+{
+ LOG("grAlphaTestFunction(%d)\r\n", function);
+ alpha_func = function;
+ switch(function)
+ {
+ case GR_CMP_GREATER:
+ //glAlphaFunc(GL_GREATER, alpha_ref/255.0f);
+ break;
+ case GR_CMP_GEQUAL:
+ //glAlphaFunc(GL_GEQUAL, alpha_ref/255.0f);
+ break;
+ case GR_CMP_ALWAYS:
+ //glAlphaFunc(GL_ALWAYS, alpha_ref/255.0f);
+ //glDisable(GL_ALPHA_TEST);
+ alpha_test = false;
+ return;
+ break;
+ default:
+ display_warning("grAlphaTestFunction : unknown function : %x", function);
+ }
+ //glEnable(GL_ALPHA_TEST);
+ alpha_test = true;
+}
+
+// fog
+
+FX_ENTRY void FX_CALL
+grFogMode( GrFogMode_t mode )
+{
+ LOG("grFogMode(%d)\r\n", mode);
+ switch(mode)
+ {
+ case GR_FOG_DISABLE:
+ //glDisable(GL_FOG);
+ fog_enabled = 0;
+ break;
+ case GR_FOG_WITH_TABLE_ON_Q:
+ //glEnable(GL_FOG);
+ //glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
+ fog_enabled = 1;
+ break;
+ case GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT:
+ //glEnable(GL_FOG);
+ //glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
+ fog_enabled = 2;
+ break;
+ default:
+ display_warning("grFogMode : unknown mode : %x", mode);
+ }
+ need_to_compile = 1;
+}
+
+FX_ENTRY float FX_CALL
+guFogTableIndexToW( int i )
+{
+ LOG("guFogTableIndexToW(%d)\r\n", i);
+ return (float)(pow(2.0, 3.0+(double)(i>>2)) / (8-(i&3)));
+}
+
+FX_ENTRY void FX_CALL
+guFogGenerateLinear(GrFog_t *fogtable,
+ float nearZ, float farZ )
+{
+ LOG("guFogGenerateLinear(%f,%f)\r\n", nearZ, farZ);
+/*
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
+ glFogf(GL_FOG_START, nearZ / 255.0f);
+ glFogf(GL_FOG_END, farZ / 255.0f);
+*/
+ fogStart = nearZ / 255.0f;
+ fogEnd = farZ / 255.0f;
+}
+
+FX_ENTRY void FX_CALL
+grFogTable( const GrFog_t ft[] )
+{
+ LOG("grFogTable()\r\n");
+}
+
+FX_ENTRY void FX_CALL
+grFogColorValue( GrColor_t fogcolor )
+{
+ LOG("grFogColorValue(%x)\r\n", fogcolor);
+
+ switch(lfb_color_fmt)
+ {
+ case GR_COLORFORMAT_ARGB:
+ fogColor[3] = ((fogcolor >> 24) & 0xFF) / 255.0f;
+ fogColor[0] = ((fogcolor >> 16) & 0xFF) / 255.0f;
+ fogColor[1] = ((fogcolor >> 8) & 0xFF) / 255.0f;
+ fogColor[2] = (fogcolor & 0xFF) / 255.0f;
+ break;
+ case GR_COLORFORMAT_RGBA:
+ fogColor[0] = ((fogcolor >> 24) & 0xFF) / 255.0f;
+ fogColor[1] = ((fogcolor >> 16) & 0xFF) / 255.0f;
+ fogColor[2] = ((fogcolor >> 8) & 0xFF) / 255.0f;
+ fogColor[3] = (fogcolor & 0xFF) / 255.0f;
+ break;
+ default:
+ display_warning("grFogColorValue: unknown color format : %x", lfb_color_fmt);
+ }
+
+ //glFogfv(GL_FOG_COLOR, color);
+}
+
+// chroma
+
+FX_ENTRY void FX_CALL
+grChromakeyMode( GrChromakeyMode_t mode )
+{
+ LOG("grChromakeyMode(%d)\r\n", mode);
+ switch(mode)
+ {
+ case GR_CHROMAKEY_DISABLE:
+ chroma_enabled = 0;
+ break;
+ case GR_CHROMAKEY_ENABLE:
+ chroma_enabled = 1;
+ break;
+ default:
+ display_warning("grChromakeyMode : unknown mode : %x", mode);
+ }
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grChromakeyValue( GrColor_t value )
+{
+ LOG("grChromakeyValue(%x)\r\n", value);
+ int chroma_color_location;
+
+ switch(lfb_color_fmt)
+ {
+ case GR_COLORFORMAT_ARGB:
+ chroma_color[3] = 1.0;//((value >> 24) & 0xFF) / 255.0f;
+ chroma_color[0] = ((value >> 16) & 0xFF) / 255.0f;
+ chroma_color[1] = ((value >> 8) & 0xFF) / 255.0f;
+ chroma_color[2] = (value & 0xFF) / 255.0f;
+ break;
+ case GR_COLORFORMAT_RGBA:
+ chroma_color[0] = ((value >> 24) & 0xFF) / 255.0f;
+ chroma_color[1] = ((value >> 16) & 0xFF) / 255.0f;
+ chroma_color[2] = ((value >> 8) & 0xFF) / 255.0f;
+ chroma_color[3] = 1.0;//(value & 0xFF) / 255.0f;
+ break;
+ default:
+ display_warning("grChromakeyValue: unknown color format : %x", lfb_color_fmt);
+ }
+ vbo_draw();
+ chroma_color_location = glGetUniformLocation(program_object, "chroma_color");
+ glUniform4f(chroma_color_location, chroma_color[0], chroma_color[1],
+ chroma_color[2], chroma_color[3]);
+}
+
+static void setPattern()
+{
+ int i;
+ GLubyte stip[32*4];
+ for(i=0; i<32; i++)
+ {
+ unsigned int val = (rand() << 17) | ((rand() & 1) << 16) | (rand() << 1) | (rand() & 1);
+ stip[i*4+0] = (val >> 24) & 0xFF;
+ stip[i*4+1] = (val >> 16) & 0xFF;
+ stip[i*4+2] = (val >> 8) & 0xFF;
+ stip[i*4+3] = val & 0xFF;
+ }
+ GLubyte texture[32*32*4];
+ for(i=0; i<32; i++)
+ {
+ int j;
+ for(j=0; j<4; j++)
+ {
+ texture[(i*32+j*8+0)*4+3] = ((stip[i*4+j] >> 7) & 1) ? 255 : 0;
+ texture[(i*32+j*8+1)*4+3] = ((stip[i*4+j] >> 6) & 1) ? 255 : 0;
+ texture[(i*32+j*8+2)*4+3] = ((stip[i*4+j] >> 5) & 1) ? 255 : 0;
+ texture[(i*32+j*8+3)*4+3] = ((stip[i*4+j] >> 4) & 1) ? 255 : 0;
+ texture[(i*32+j*8+4)*4+3] = ((stip[i*4+j] >> 3) & 1) ? 255 : 0;
+ texture[(i*32+j*8+5)*4+3] = ((stip[i*4+j] >> 2) & 1) ? 255 : 0;
+ texture[(i*32+j*8+6)*4+3] = ((stip[i*4+j] >> 1) & 1) ? 255 : 0;
+ texture[(i*32+j*8+7)*4+3] = ((stip[i*4+j] >> 0) & 1) ? 255 : 0;
+ }
+ }
+ glActiveTexture(GL_TEXTURE2);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 33*1024*1024);
+ glTexImage2D(GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glDisable(GL_TEXTURE_2D);
+}
+
+FX_ENTRY void FX_CALL
+grStipplePattern(
+ GrStipplePattern_t stipple)
+{
+ LOG("grStipplePattern(%x)\r\n", stipple);
+ srand(stipple);
+ setPattern();
+}
+
+FX_ENTRY void FX_CALL
+grStippleMode( GrStippleMode_t mode )
+{
+ LOG("grStippleMode(%d)\r\n", mode);
+ switch(mode)
+ {
+ case GR_STIPPLE_DISABLE:
+ dither_enabled = 0;
+ glActiveTexture(GL_TEXTURE2);
+ glDisable(GL_TEXTURE_2D);
+ break;
+ case GR_STIPPLE_PATTERN:
+ setPattern();
+ dither_enabled = 1;
+ glActiveTexture(GL_TEXTURE2);
+ glEnable(GL_TEXTURE_2D);
+ break;
+ case GR_STIPPLE_ROTATE:
+ setPattern();
+ dither_enabled = 1;
+ glActiveTexture(GL_TEXTURE2);
+ glEnable(GL_TEXTURE_2D);
+ break;
+ default:
+ display_warning("grStippleMode:%x", mode);
+ }
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grColorCombineExt(GrCCUColor_t a, GrCombineMode_t a_mode,
+ GrCCUColor_t b, GrCombineMode_t b_mode,
+ GrCCUColor_t c, FxBool c_invert,
+ GrCCUColor_t d, FxBool d_invert,
+ FxU32 shift, FxBool invert)
+{
+ LOG("grColorCombineExt(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)\r\n", a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+ if (invert) display_warning("grColorCombineExt : inverted result");
+ if (shift) display_warning("grColorCombineExt : shift = %d", shift);
+
+ color_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ c_combiner_ext = 1;
+ strcpy(fragment_shader_color_combiner, "");
+
+ switch(a)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(0.0); \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(ctexture1.a); \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(constant_color.a); \n");
+ break;
+ case GR_CMBX_CONSTANT_COLOR:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = constant_color; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = gl_Color; \n");
+ break;
+ case GR_CMBX_TEXTURE_RGB:
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = ctexture1; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : a = %x", a);
+ strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(0.0); \n");
+ }
+
+ switch(a_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(0.0); \n");
+ break;
+ case GR_FUNC_MODE_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_a = cs_a; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(1.0) - cs_a; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_a = -cs_a; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : a_mode = %x", a_mode);
+ strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(0.0); \n");
+ }
+
+ switch(b)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(0.0); \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(ctexture1.a); \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(constant_color.a); \n");
+ break;
+ case GR_CMBX_CONSTANT_COLOR:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = constant_color; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = gl_Color; \n");
+ break;
+ case GR_CMBX_TEXTURE_RGB:
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = ctexture1; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : b = %x", b);
+ strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(0.0); \n");
+ }
+
+ switch(b_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(0.0); \n");
+ break;
+ case GR_FUNC_MODE_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_b = cs_b; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(1.0) - cs_b; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ strcat(fragment_shader_color_combiner, "vec4 c_b = -cs_b; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : b_mode = %x", b_mode);
+ strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(0.0); \n");
+ }
+
+ switch(c)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(0.0); \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(ctexture1.a); \n");
+ break;
+ case GR_CMBX_ALOCAL:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(c_b.a); \n");
+ break;
+ case GR_CMBX_AOTHER:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(c_a.a); \n");
+ break;
+ case GR_CMBX_B:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = cs_b; \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(constant_color.a); \n");
+ break;
+ case GR_CMBX_CONSTANT_COLOR:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = constant_color; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = gl_Color; \n");
+ break;
+ case GR_CMBX_TEXTURE_RGB:
+ strcat(fragment_shader_color_combiner, "vec4 c_c = ctexture1; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : c = %x", c);
+ strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(0.0); \n");
+ }
+
+ if(c_invert)
+ strcat(fragment_shader_color_combiner, "c_c = vec4(1.0) - c_c; \n");
+
+ switch(d)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(0.0); \n");
+ break;
+ case GR_CMBX_ALOCAL:
+ strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(c_b.a); \n");
+ break;
+ case GR_CMBX_B:
+ strcat(fragment_shader_color_combiner, "vec4 c_d = cs_b; \n");
+ break;
+ case GR_CMBX_TEXTURE_RGB:
+ strcat(fragment_shader_color_combiner, "vec4 c_d = ctexture1; \n");
+ break;
+ case GR_CMBX_ITRGB:
+ strcat(fragment_shader_color_combiner, "vec4 c_d = gl_Color; \n");
+ break;
+ default:
+ display_warning("grColorCombineExt : d = %x", d);
+ strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(0.0); \n");
+ }
+
+ if(d_invert)
+ strcat(fragment_shader_color_combiner, "c_d = vec4(1.0) - c_d; \n");
+
+ strcat(fragment_shader_color_combiner, "gl_FragColor = (c_a + c_b) * c_c + c_d; \n");
+
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grAlphaCombineExt(GrACUColor_t a, GrCombineMode_t a_mode,
+ GrACUColor_t b, GrCombineMode_t b_mode,
+ GrACUColor_t c, FxBool c_invert,
+ GrACUColor_t d, FxBool d_invert,
+ FxU32 shift, FxBool invert)
+{
+ LOG("grAlphaCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+ if (invert) display_warning("grAlphaCombineExt : inverted result");
+ if (shift) display_warning("grAlphaCombineExt : shift = %d", shift);
+
+ alpha_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ a_combiner_ext = 1;
+ strcpy(fragment_shader_alpha_combiner, "");
+
+ switch(a)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float as_a = 0.0; \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_a = ctexture1.a; \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_a = constant_color.a; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_a = gl_Color.a; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : a = %x", a);
+ strcat(fragment_shader_alpha_combiner, "float as_a = 0.0; \n");
+ }
+
+ switch(a_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float a_a = 0.0; \n");
+ break;
+ case GR_FUNC_MODE_X:
+ strcat(fragment_shader_alpha_combiner, "float a_a = as_a; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ strcat(fragment_shader_alpha_combiner, "float a_a = 1.0 - as_a; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ strcat(fragment_shader_alpha_combiner, "float a_a = -as_a; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : a_mode = %x", a_mode);
+ strcat(fragment_shader_alpha_combiner, "float a_a = 0.0; \n");
+ }
+
+ switch(b)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float as_b = 0.0; \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_b = ctexture1.a; \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_b = constant_color.a; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_alpha_combiner, "float as_b = gl_Color.a; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : b = %x", b);
+ strcat(fragment_shader_alpha_combiner, "float as_b = 0.0; \n");
+ }
+
+ switch(b_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float a_b = 0.0; \n");
+ break;
+ case GR_FUNC_MODE_X:
+ strcat(fragment_shader_alpha_combiner, "float a_b = as_b; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ strcat(fragment_shader_alpha_combiner, "float a_b = 1.0 - as_b; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ strcat(fragment_shader_alpha_combiner, "float a_b = -as_b; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : b_mode = %x", b_mode);
+ strcat(fragment_shader_alpha_combiner, "float a_b = 0.0; \n");
+ }
+
+ switch(c)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float a_c = 0.0; \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float a_c = ctexture1.a; \n");
+ break;
+ case GR_CMBX_ALOCAL:
+ strcat(fragment_shader_alpha_combiner, "float a_c = as_b; \n");
+ break;
+ case GR_CMBX_AOTHER:
+ strcat(fragment_shader_alpha_combiner, "float a_c = as_a; \n");
+ break;
+ case GR_CMBX_B:
+ strcat(fragment_shader_alpha_combiner, "float a_c = as_b; \n");
+ break;
+ case GR_CMBX_CONSTANT_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float a_c = constant_color.a; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ strcat(fragment_shader_alpha_combiner, "float a_c = gl_Color.a; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : c = %x", c);
+ strcat(fragment_shader_alpha_combiner, "float a_c = 0.0; \n");
+ }
+
+ if(c_invert)
+ strcat(fragment_shader_alpha_combiner, "a_c = 1.0 - a_c; \n");
+
+ switch(d)
+ {
+ case GR_CMBX_ZERO:
+ strcat(fragment_shader_alpha_combiner, "float a_d = 0.0; \n");
+ break;
+ case GR_CMBX_TEXTURE_ALPHA:
+ strcat(fragment_shader_alpha_combiner, "float a_d = ctexture1.a; \n");
+ break;
+ case GR_CMBX_ALOCAL:
+ strcat(fragment_shader_alpha_combiner, "float a_d = as_b; \n");
+ break;
+ case GR_CMBX_B:
+ strcat(fragment_shader_alpha_combiner, "float a_d = as_b; \n");
+ break;
+ default:
+ display_warning("grAlphaCombineExt : d = %x", d);
+ strcat(fragment_shader_alpha_combiner, "float a_d = 0.0; \n");
+ }
+
+ if(d_invert)
+ strcat(fragment_shader_alpha_combiner, "a_d = 1.0 - a_d; \n");
+
+ strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = (a_a + a_b) * a_c + a_d; \n");
+
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grTexColorCombineExt(GrChipID_t tmu,
+ GrTCCUColor_t a, GrCombineMode_t a_mode,
+ GrTCCUColor_t b, GrCombineMode_t b_mode,
+ GrTCCUColor_t c, FxBool c_invert,
+ GrTCCUColor_t d, FxBool d_invert,
+ FxU32 shift, FxBool invert)
+{
+ int num_tex;
+ LOG("grTexColorCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+
+ if (invert) display_warning("grTexColorCombineExt : inverted result");
+ if (shift) display_warning("grTexColorCombineExt : shift = %d", shift);
+
+ if (tmu == GR_TMU0) num_tex = 1;
+ else num_tex = 0;
+
+ if(num_tex == 0)
+ {
+ texture0_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ tex0_combiner_ext = 1;
+ strcpy(fragment_shader_texture0, "");
+ }
+ else
+ {
+ texture1_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ tex1_combiner_ext = 1;
+ strcpy(fragment_shader_texture1, "");
+ }
+
+ switch(a)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(0.0); \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(gl_Color.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = gl_Color; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = gl_Color; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(readtex1.a); \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = readtex1; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(ctexture0.a); \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = ctexture0; \n");
+ break;
+ case GR_CMBX_TMU_CCOLOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = ccolor0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = ccolor1; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(ccolor0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(ccolor1.a); \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : a = %x", a);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(0.0); \n");
+ }
+
+ switch(a_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(0.0); \n");
+ break;
+ case GR_FUNC_MODE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_a = ctex0s_a; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_a = ctex1s_a; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(1.0) - ctex0s_a; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(1.0) - ctex1s_a; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_a = -ctex0s_a; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_a = -ctex1s_a; \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : a_mode = %x", a_mode);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(0.0); \n");
+ }
+
+ switch(b)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(0.0); \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(gl_Color.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = gl_Color; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = gl_Color; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(readtex1.a); \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = readtex1; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(ctexture0.a); \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = ctexture0; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(ccolor0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(ccolor1.a); \n");
+ break;
+ case GR_CMBX_TMU_CCOLOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = ccolor0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = ccolor1; \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : b = %x", b);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(0.0); \n");
+ }
+
+ switch(b_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(0.0); \n");
+ break;
+ case GR_FUNC_MODE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_b = ctex0s_b; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_b = ctex1s_b; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(1.0) - ctex0s_b; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(1.0) - ctex1s_b; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_b = -ctex0s_b; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_b = -ctex1s_b; \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : b_mode = %x", b_mode);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(0.0); \n");
+ }
+
+ switch(c)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(0.0); \n");
+ break;
+ case GR_CMBX_B:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = ctex0s_b; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = ctex1s_b; \n");
+ break;
+ case GR_CMBX_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(lambda); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(lambda); \n");
+ break;
+ case GR_CMBX_ITRGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = gl_Color; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = gl_Color; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(gl_Color.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(gl_Color.a); \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(readtex1.a); \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = readtex0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = readtex1; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(ctexture0.a); \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_RGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = ctexture0; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(ccolor0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(ccolor1.a); \n");
+ break;
+ case GR_CMBX_TMU_CCOLOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = ccolor0; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = ccolor1; \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : c = %x", c);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(0.0); \n");
+ }
+
+ if(c_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c = vec4(1.0) - ctex0_c; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c = vec4(1.0) - ctex1_c; \n");
+ }
+
+ switch(d)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(0.0); \n");
+ break;
+ case GR_CMBX_B:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_d = ctex0s_b; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_d = ctex1s_b; \n");
+ break;
+ case GR_CMBX_ITRGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_d = gl_Color; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_d = gl_Color; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(readtex0.a); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(readtex1.a); \n");
+ break;
+ default:
+ display_warning("grTexColorCombineExt : d = %x", d);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(0.0); \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(0.0); \n");
+ }
+
+ if(d_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d = vec4(1.0) - ctex0_d; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d = vec4(1.0) - ctex1_d; \n");
+ }
+
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "vec4 ctexture0 = (ctex0_a + ctex0_b) * ctex0_c + ctex0_d; \n");
+ else
+ strcat(fragment_shader_texture1, "vec4 ctexture1 = (ctex1_a + ctex1_b) * ctex1_c + ctex1_d; \n");
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grTexAlphaCombineExt(GrChipID_t tmu,
+ GrTACUColor_t a, GrCombineMode_t a_mode,
+ GrTACUColor_t b, GrCombineMode_t b_mode,
+ GrTACUColor_t c, FxBool c_invert,
+ GrTACUColor_t d, FxBool d_invert,
+ FxU32 shift, FxBool invert)
+{
+ int num_tex;
+ LOG("grTexAlphaCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+
+ if (invert) display_warning("grTexAlphaCombineExt : inverted result");
+ if (shift) display_warning("grTexAlphaCombineExt : shift = %d", shift);
+
+ if (tmu == GR_TMU0) num_tex = 1;
+ else num_tex = 0;
+
+ if(num_tex == 0)
+ {
+ texture0_combinera_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ }
+ else
+ {
+ texture1_combinera_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) |
+ ((b & 0x1F) << 7) | ((b_mode & 3) << 12) |
+ ((c & 0x1F) << 14) | ((c_invert & 1) << 19) |
+ ((d & 0x1F) << 20) | ((d_invert & 1) << 25);
+ }
+
+ switch(a)
+ {
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_a.a = gl_Color.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_a.a = gl_Color.a; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_a.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_a.a = readtex1.a; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_a.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_a.a = ctexture0.a; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_a.a = ccolor0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_a.a = ccolor1.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : a = %x", a);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_a.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_a.a = 0.0; \n");
+ }
+
+ switch(a_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_a.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_a.a = 0.0; \n");
+ break;
+ case GR_FUNC_MODE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_a.a = ctex0s_a.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_a.a = ctex1s_a.a; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_a.a = 1.0 - ctex0s_a.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_a.a = 1.0 - ctex1s_a.a; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_a.a = -ctex0s_a.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_a.a = -ctex1s_a.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : a_mode = %x", a_mode);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_a.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_a.a = 0.0; \n");
+ }
+
+ switch(b)
+ {
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_b.a = gl_Color.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_b.a = gl_Color.a; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_b.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_b.a = readtex1.a; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_b.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_b.a = ctexture0.a; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_b.a = ccolor0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_b.a = ccolor1.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : b = %x", b);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0s_b.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1s_b.a = 0.0; \n");
+ }
+
+ switch(b_mode)
+ {
+ case GR_FUNC_MODE_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_b.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_b.a = 0.0; \n");
+ break;
+ case GR_FUNC_MODE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_b.a = ctex0s_b.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_b.a = ctex1s_b.a; \n");
+ break;
+ case GR_FUNC_MODE_ONE_MINUS_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_b.a = 1.0 - ctex0s_b.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_b.a = 1.0 - ctex1s_b.a; \n");
+ break;
+ case GR_FUNC_MODE_NEGATIVE_X:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_b.a = -ctex0s_b.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_b.a = -ctex1s_b.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : b_mode = %x", b_mode);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_b.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_b.a = 0.0; \n");
+ }
+
+ switch(c)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = 0.0; \n");
+ break;
+ case GR_CMBX_B:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = ctex0s_b.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = ctex1s_b.a; \n");
+ break;
+ case GR_CMBX_DETAIL_FACTOR:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = lambda; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = lambda; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = gl_Color.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = gl_Color.a; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = readtex1.a; \n");
+ break;
+ case GR_CMBX_OTHER_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = ctexture0.a; \n");
+ break;
+ case GR_CMBX_TMU_CALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = ccolor0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = ccolor1.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : c = %x", c);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = 0.0; \n");
+ }
+
+ if(c_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_c.a = 1.0 - ctex0_c.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_c.a = 1.0 - ctex1_c.a; \n");
+ }
+
+ switch(d)
+ {
+ case GR_CMBX_ZERO:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = 0.0; \n");
+ break;
+ case GR_CMBX_B:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = ctex0s_b.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = ctex1s_b.a; \n");
+ break;
+ case GR_CMBX_ITALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = gl_Color.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = gl_Color.a; \n");
+ break;
+ case GR_CMBX_ITRGB:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = gl_Color.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = gl_Color.a; \n");
+ break;
+ case GR_CMBX_LOCAL_TEXTURE_ALPHA:
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = readtex0.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = readtex1.a; \n");
+ break;
+ default:
+ display_warning("grTexAlphaCombineExt : d = %x", d);
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = 0.0; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = 0.0; \n");
+ }
+
+ if(d_invert)
+ {
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctex0_d.a = 1.0 - ctex0_d.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctex1_d.a = 1.0 - ctex1_d.a; \n");
+ }
+
+ if(num_tex == 0)
+ strcat(fragment_shader_texture0, "ctexture0.a = (ctex0_a.a + ctex0_b.a) * ctex0_c.a + ctex0_d.a; \n");
+ else
+ strcat(fragment_shader_texture1, "ctexture1.a = (ctex1_a.a + ctex1_b.a) * ctex1_c.a + ctex1_d.a; \n");
+
+ need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL
+grConstantColorValueExt(GrChipID_t tmu,
+ GrColor_t value)
+{
+ int num_tex;
+ LOG("grConstantColorValueExt(%d,%d)\r\n", tmu, value);
+
+ if (tmu == GR_TMU0) num_tex = 1;
+ else num_tex = 0;
+
+ switch(lfb_color_fmt)
+ {
+ case GR_COLORFORMAT_ARGB:
+ if(num_tex == 0)
+ {
+ ccolor0[3] = ((value >> 24) & 0xFF) / 255.0f;
+ ccolor0[0] = ((value >> 16) & 0xFF) / 255.0f;
+ ccolor0[1] = ((value >> 8) & 0xFF) / 255.0f;
+ ccolor0[2] = (value & 0xFF) / 255.0f;
+ }
+ else
+ {
+ ccolor1[3] = ((value >> 24) & 0xFF) / 255.0f;
+ ccolor1[0] = ((value >> 16) & 0xFF) / 255.0f;
+ ccolor1[1] = ((value >> 8) & 0xFF) / 255.0f;
+ ccolor1[2] = (value & 0xFF) / 255.0f;
+ }
+ break;
+ case GR_COLORFORMAT_RGBA:
+ if(num_tex == 0)
+ {
+ ccolor0[0] = ((value >> 24) & 0xFF) / 255.0f;
+ ccolor0[1] = ((value >> 16) & 0xFF) / 255.0f;
+ ccolor0[2] = ((value >> 8) & 0xFF) / 255.0f;
+ ccolor0[3] = (value & 0xFF) / 255.0f;
+ }
+ else
+ {
+ ccolor1[0] = ((value >> 24) & 0xFF) / 255.0f;
+ ccolor1[1] = ((value >> 16) & 0xFF) / 255.0f;
+ ccolor1[2] = ((value >> 8) & 0xFF) / 255.0f;
+ ccolor1[3] = (value & 0xFF) / 255.0f;
+ }
+ break;
+ default:
+ display_warning("grConstantColorValue: unknown color format : %x", lfb_color_fmt);
+ }
+
+ vbo_draw();
+ if(num_tex == 0)
+ {
+ ccolor0_location = glGetUniformLocation(program_object, "ccolor0");
+ glUniform4f(ccolor0_location, ccolor0[0], ccolor0[1], ccolor0[2], ccolor0[3]);
+ }
+ else
+ {
+ ccolor1_location = glGetUniformLocation(program_object, "ccolor1");
+ glUniform4f(ccolor1_location, ccolor1[0], ccolor1[1], ccolor1[2], ccolor1[3]);
+ }
+}
diff --git a/Source/Glitch64/OGLESgeometry.cpp b/Source/Glitch64/OGLESgeometry.cpp
new file mode 100644
index 000000000..a1627beef
--- /dev/null
+++ b/Source/Glitch64/OGLESgeometry.cpp
@@ -0,0 +1,643 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002 Dave2001
+* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include
+#include
+#ifdef _WIN32
+#include
+#endif // _WIN32
+#include "glide.h"
+#include "main.h"
+#include "../Glide64/winlnxdefs.h"
+#include "../Glide64/rdp.h"
+
+#define Z_MAX (65536.0f)
+#define VERTEX_SIZE sizeof(VERTEX) //Size of vertex struct
+
+#ifdef ANDROID_EDITION
+#include "ae_imports.h"
+static float polygonOffsetFactor;
+static float polygonOffsetUnits;
+#endif
+
+static int xy_off;
+static int xy_en;
+static int z_en;
+static int z_off;
+static int q_off;
+static int q_en;
+static int pargb_off;
+static int pargb_en;
+static int st0_off;
+static int st0_en;
+static int st1_off;
+static int st1_en;
+static int fog_ext_off;
+static int fog_ext_en;
+
+int w_buffer_mode;
+int inverted_culling;
+int culling_mode;
+
+#define VERTEX_BUFFER_SIZE 1500 //Max amount of vertices to buffer, this seems large enough.
+static VERTEX vertex_buffer[VERTEX_BUFFER_SIZE];
+static int vertex_buffer_count = 0;
+static GLenum vertex_draw_mode;
+static bool vertex_buffer_enabled = false;
+
+void vbo_init()
+{
+
+}
+
+void vbo_draw()
+{
+ if(vertex_buffer_count)
+ {
+ glDrawArrays(vertex_draw_mode,0,vertex_buffer_count);
+ vertex_buffer_count = 0;
+ }
+}
+
+//Buffer vertices instead of glDrawArrays(...)
+void vbo_buffer(GLenum mode,GLint first,GLsizei count,void* pointers)
+{
+ if((count != 3 && mode != GL_TRIANGLES) || vertex_buffer_count + count > VERTEX_BUFFER_SIZE)
+ {
+ vbo_draw();
+ }
+
+ memcpy(&vertex_buffer[vertex_buffer_count],pointers,count * VERTEX_SIZE);
+ vertex_buffer_count += count;
+
+ if(count == 3 || mode == GL_TRIANGLES)
+ {
+ vertex_draw_mode = GL_TRIANGLES;
+ }
+ else
+ {
+ vertex_draw_mode = mode;
+ vbo_draw(); //Triangle fans and strips can't be joined as easily, just draw them straight away.
+ }
+
+
+}
+
+void vbo_enable()
+{
+ if(vertex_buffer_enabled)
+ return;
+
+ vertex_buffer_enabled = true;
+ glEnableVertexAttribArray(POSITION_ATTR);
+ glVertexAttribPointer(POSITION_ATTR, 4, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].x); //Position
+
+ glEnableVertexAttribArray(COLOUR_ATTR);
+ glVertexAttribPointer(COLOUR_ATTR, 4, GL_UNSIGNED_BYTE, true, VERTEX_SIZE, &vertex_buffer[0].b); //Colour
+
+ glEnableVertexAttribArray(TEXCOORD_0_ATTR);
+ glVertexAttribPointer(TEXCOORD_0_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[2]); //Tex0
+
+ glEnableVertexAttribArray(TEXCOORD_1_ATTR);
+ glVertexAttribPointer(TEXCOORD_1_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[0]); //Tex1
+
+ glEnableVertexAttribArray(FOG_ATTR);
+ glVertexAttribPointer(FOG_ATTR, 1, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].f); //Fog
+}
+
+void vbo_disable()
+{
+ vbo_draw();
+ vertex_buffer_enabled = false;
+}
+
+
+inline float ZCALC(const float & z, const float & q) {
+ float res = z_en ? ((z) / Z_MAX) / (q) : 1.0f;
+ return res;
+}
+
+/*
+#define zclamp (1.0f-1.0f/zscale)
+static inline void zclamp_glVertex4f(float a, float b, float c, float d)
+{
+ if (c 0.01f) continue;
+ if (z < bestz) {
+ bestz = z;
+ biasFactor = f;
+ }
+ //printf("f %g z %g\n", f, z);
+ }
+ //printf(" --> bias factor %g\n", biasFactor);
+ glPopAttrib();
+#endif
+}
+#endif
+
+FX_ENTRY void FX_CALL
+grDepthBiasLevel( FxI32 level )
+{
+ LOG("grDepthBiasLevel(%d)\r\n", level);
+ if (level)
+ {
+ #ifdef ANDROID_EDITION
+ glPolygonOffset(polygonOffsetFactor, polygonOffsetUnits);
+ #else
+ if(w_buffer_mode)
+ glPolygonOffset(1.0f, -(float)level*zscale/255.0f);
+ else
+ glPolygonOffset(0, (float)level*biasFactor);
+ #endif
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ }
+ else
+ {
+ glPolygonOffset(0,0);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ }
+}
+
+// draw
+
+FX_ENTRY void FX_CALL
+grDrawTriangle( const void *a, const void *b, const void *c )
+{
+ LOG("grDrawTriangle()\r\n\t");
+
+ if(nvidia_viewport_hack && !render_to_texture)
+ {
+ glViewport(0, viewport_offset, viewport_width, viewport_height);
+ nvidia_viewport_hack = 0;
+ }
+
+ reloadTexture();
+
+ if(need_to_compile) compile_shader();
+
+ if(vertex_buffer_count + 3 > VERTEX_BUFFER_SIZE)
+ {
+ vbo_draw();
+ }
+ vertex_draw_mode = GL_TRIANGLES;
+ memcpy(&vertex_buffer[vertex_buffer_count],a,VERTEX_SIZE);
+ memcpy(&vertex_buffer[vertex_buffer_count+1],b,VERTEX_SIZE);
+ memcpy(&vertex_buffer[vertex_buffer_count+2],c,VERTEX_SIZE);
+ vertex_buffer_count += 3;
+}
+
+FX_ENTRY void FX_CALL
+grDrawPoint( const void *pt )
+{
+/*
+ float *x = (float*)pt + xy_off/sizeof(float);
+ float *y = (float*)pt + xy_off/sizeof(float) + 1;
+ float *z = (float*)pt + z_off/sizeof(float);
+ float *q = (float*)pt + q_off/sizeof(float);
+ unsigned char *pargb = (unsigned char*)pt + pargb_off;
+ float *s0 = (float*)pt + st0_off/sizeof(float);
+ float *t0 = (float*)pt + st0_off/sizeof(float) + 1;
+ float *s1 = (float*)pt + st1_off/sizeof(float);
+ float *t1 = (float*)pt + st1_off/sizeof(float) + 1;
+ float *fog = (float*)pt + fog_ext_off/sizeof(float);
+ LOG("grDrawPoint()\r\n");
+
+ if(nvidia_viewport_hack && !render_to_texture)
+ {
+ glViewport(0, viewport_offset, viewport_width, viewport_height);
+ nvidia_viewport_hack = 0;
+ }
+
+ reloadTexture();
+
+ if(need_to_compile) compile_shader();
+
+ glBegin(GL_POINTS);
+
+ if (nbTextureUnits > 2)
+ {
+ if (st0_en)
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width,
+ ytex(0, *t0 / *q / (float)tex1_height));
+ if (st1_en)
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width,
+ ytex(1, *t1 / *q / (float)tex0_height));
+ }
+ else
+ {
+ if (st0_en)
+ glTexCoord2f(*s0 / *q / (float)tex0_width,
+ ytex(0, *t0 / *q / (float)tex0_height));
+ }
+ if (pargb_en)
+ glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f);
+ if (fog_enabled && fog_coord_support)
+ {
+ if(!fog_ext_en || fog_enabled != 2)
+ glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f);
+ else
+ glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f);
+ }
+ glVertex4f((*x - (float)widtho) / (float)(width/2) / *q,
+ -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z ,*q), 1.0f / *q);
+
+ glEnd();
+*/
+}
+
+FX_ENTRY void FX_CALL
+grDrawLine( const void *a, const void *b )
+{
+/*
+ float *a_x = (float*)a + xy_off/sizeof(float);
+ float *a_y = (float*)a + xy_off/sizeof(float) + 1;
+ float *a_z = (float*)a + z_off/sizeof(float);
+ float *a_q = (float*)a + q_off/sizeof(float);
+ unsigned char *a_pargb = (unsigned char*)a + pargb_off;
+ float *a_s0 = (float*)a + st0_off/sizeof(float);
+ float *a_t0 = (float*)a + st0_off/sizeof(float) + 1;
+ float *a_s1 = (float*)a + st1_off/sizeof(float);
+ float *a_t1 = (float*)a + st1_off/sizeof(float) + 1;
+ float *a_fog = (float*)a + fog_ext_off/sizeof(float);
+
+ float *b_x = (float*)b + xy_off/sizeof(float);
+ float *b_y = (float*)b + xy_off/sizeof(float) + 1;
+ float *b_z = (float*)b + z_off/sizeof(float);
+ float *b_q = (float*)b + q_off/sizeof(float);
+ unsigned char *b_pargb = (unsigned char*)b + pargb_off;
+ float *b_s0 = (float*)b + st0_off/sizeof(float);
+ float *b_t0 = (float*)b + st0_off/sizeof(float) + 1;
+ float *b_s1 = (float*)b + st1_off/sizeof(float);
+ float *b_t1 = (float*)b + st1_off/sizeof(float) + 1;
+ float *b_fog = (float*)b + fog_ext_off/sizeof(float);
+ LOG("grDrawLine()\r\n");
+
+ if(nvidia_viewport_hack && !render_to_texture)
+ {
+ glViewport(0, viewport_offset, viewport_width, viewport_height);
+ nvidia_viewport_hack = 0;
+ }
+
+ reloadTexture();
+
+ if(need_to_compile) compile_shader();
+
+ glBegin(GL_LINES);
+
+ if (nbTextureUnits > 2)
+ {
+ if (st0_en)
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *a_s0 / *a_q / (float)tex1_width, ytex(0, *a_t0 / *a_q / (float)tex1_height));
+ if (st1_en)
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *a_s1 / *a_q / (float)tex0_width, ytex(1, *a_t1 / *a_q / (float)tex0_height));
+ }
+ else
+ {
+ if (st0_en)
+ glTexCoord2f(*a_s0 / *a_q / (float)tex0_width, ytex(0, *a_t0 / *a_q / (float)tex0_height));
+ }
+ if (pargb_en)
+ glColor4f(a_pargb[2]/255.0f, a_pargb[1]/255.0f, a_pargb[0]/255.0f, a_pargb[3]/255.0f);
+ if (fog_enabled && fog_coord_support)
+ {
+ if(!fog_ext_en || fog_enabled != 2)
+ glSecondaryColor3f((1.0f / *a_q) / 255.0f, 0.0f, 0.0f);
+ else
+ glSecondaryColor3f((1.0f / *a_fog) / 255.0f, 0.0f, 0.0f);
+ }
+ glVertex4f((*a_x - (float)widtho) / (float)(width/2) / *a_q,
+ -(*a_y - (float)heighto) / (float)(height/2) / *a_q, ZCALC(*a_z, *a_q), 1.0f / *a_q);
+
+ if (nbTextureUnits > 2)
+ {
+ if (st0_en)
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *b_s0 / *b_q / (float)tex1_width,
+ ytex(0, *b_t0 / *b_q / (float)tex1_height));
+ if (st1_en)
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *b_s1 / *b_q / (float)tex0_width,
+ ytex(1, *b_t1 / *b_q / (float)tex0_height));
+ }
+ else
+ {
+ if (st0_en)
+ glTexCoord2f(*b_s0 / *b_q / (float)tex0_width,
+ ytex(0, *b_t0 / *b_q / (float)tex0_height));
+ }
+ if (pargb_en)
+ glColor4f(b_pargb[2]/255.0f, b_pargb[1]/255.0f, b_pargb[0]/255.0f, b_pargb[3]/255.0f);
+ if (fog_enabled && fog_coord_support)
+ {
+ if(!fog_ext_en || fog_enabled != 2)
+ glSecondaryColor3f((1.0f / *b_q) / 255.0f, 0.0f, 0.0f);
+ else
+ glSecondaryColor3f((1.0f / *b_fog) / 255.0f, 0.0f, 0.0f);
+ }
+ glVertex4f((*b_x - (float)widtho) / (float)(width/2) / *b_q,
+ -(*b_y - (float)heighto) / (float)(height/2) / *b_q, ZCALC(*b_z, *b_q), 1.0f / *b_q);
+
+ glEnd();
+*/
+}
+
+FX_ENTRY void FX_CALL
+grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers2)
+{
+ void **pointers = (void**)pointers2;
+ LOG("grDrawVertexArray(%d,%d)\r\n", mode, Count);
+
+ if(nvidia_viewport_hack && !render_to_texture)
+ {
+ glViewport(0, viewport_offset, viewport_width, viewport_height);
+ nvidia_viewport_hack = 0;
+ }
+
+ reloadTexture();
+
+ if(need_to_compile) compile_shader();
+
+ if(mode != GR_TRIANGLE_FAN)
+ {
+ display_warning("grDrawVertexArray : unknown mode : %x", mode);
+ }
+
+ vbo_enable();
+ vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers[0]);
+}
+
+FX_ENTRY void FX_CALL
+grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride)
+{
+ LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride);
+
+ if(nvidia_viewport_hack && !render_to_texture)
+ {
+ glViewport(0, viewport_offset, viewport_width, viewport_height);
+ nvidia_viewport_hack = 0;
+ }
+
+ if(stride != 156)
+ {
+ LOGINFO("Incompatible stride\n");
+ }
+
+ reloadTexture();
+
+ if(need_to_compile) compile_shader();
+
+ vbo_enable();
+
+ switch(mode)
+ {
+ case GR_TRIANGLE_STRIP:
+ vbo_buffer(GL_TRIANGLE_STRIP,0,Count,pointers);
+ break;
+ case GR_TRIANGLE_FAN:
+ vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers);
+ break;
+ default:
+ display_warning("grDrawVertexArrayContiguous : unknown mode : %x", mode);
+ }
+}
diff --git a/Source/Glitch64/OGLESglitchmain.cpp b/Source/Glitch64/OGLESglitchmain.cpp
new file mode 100644
index 000000000..f226dc391
--- /dev/null
+++ b/Source/Glitch64/OGLESglitchmain.cpp
@@ -0,0 +1,2604 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002 Dave2001
+* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define SAVE_CBUFFER
+
+#ifdef _WIN32
+#include
+#include
+#else
+#include
+#include
+#include
+#include
+#endif // _WIN32
+#include
+#include
+#include
+#include
+#include
+#include "glide.h"
+#include "g3ext.h"
+#include "main.h"
+#include "m64p.h"
+
+#include
+//#include
+
+#define OPENGL_CHECK_ERRORS { const GLenum errcode = glGetError(); if (errcode != GL_NO_ERROR) LOG("OpenGL Error code %i in '%s' line %i\n", errcode, __FILE__, __LINE__-1); }
+
+#ifdef VPDEBUG
+#include
+#endif
+
+extern void (*renderCallback)(int);
+
+wrapper_config config = {0, 0, 0, 0};
+int screen_width, screen_height;
+
+/*
+static inline void opt_glCopyTexImage2D( GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border )
+
+{
+ int w, h, fmt;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+ //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
+ if (w == (int) width && h == (int) height && fmt == (int) internalFormat) {
+ if (x+width >= screen_width) {
+ width = screen_width - x;
+ //printf("resizing w --> %d\n", width);
+ }
+ if (y+height >= screen_height+viewport_offset) {
+ height = screen_height+viewport_offset - y;
+ //printf("resizing h --> %d\n", height);
+ }
+ glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height);
+ } else {
+ //printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);
+ // glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);
+ // glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+ // printf("--> %dx%d newfmt %x\n", width, height, fmt);
+ glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
+ }
+}
+#define glCopyTexImage2D opt_glCopyTexImage2D
+*/
+
+
+#ifdef _WIN32
+PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
+PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
+PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
+PFNGLFOGCOORDFPROC glFogCoordfEXT;
+
+PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
+
+PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
+PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
+PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+
+PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+PFNGLUNIFORM1IARBPROC glUniform1iARB;
+PFNGLUNIFORM4IARBPROC glUniform4iARB;
+PFNGLUNIFORM4FARBPROC glUniform4fARB;
+PFNGLUNIFORM1FARBPROC glUniform1fARB;
+PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+
+// FXT1,DXT1,DXT5 support - Hiroshi Morii
+// NOTE: Glide64 + GlideHQ use the following formats
+// GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+// GL_COMPRESSED_RGB_FXT1_3DFX
+// GL_COMPRESSED_RGBA_FXT1_3DFX
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;
+#endif // _WIN32
+
+
+
+typedef struct
+{
+ unsigned int address;
+ int width;
+ int height;
+ unsigned int fbid;
+ unsigned int zbid;
+ unsigned int texid;
+ int buff_clear;
+} fb;
+
+int nbTextureUnits;
+int nbAuxBuffers, current_buffer;
+int width, widtho, heighto, height;
+int saved_width, saved_height;
+int blend_func_separate_support;
+int npot_support;
+int fog_coord_support;
+int render_to_texture = 0;
+int texture_unit;
+int use_fbo;
+int buffer_cleared;
+// ZIGGY
+// to allocate a new static texture name, take the value (free_texture++)
+int free_texture;
+int default_texture; // the infamous "32*1024*1024" is now configurable
+int current_texture;
+int depth_texture, color_texture;
+int glsl_support = 1;
+int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;
+int save_w, save_h;
+int lfb_color_fmt;
+float invtex[2];
+//Gonetz
+int UMAmode = 0; //support for VSA-100 UMA mode;
+
+#ifdef _WIN32
+static HDC hDC = NULL;
+static HGLRC hGLRC = NULL;
+static HWND hToolBar = NULL;
+static HWND hwnd_win = NULL;
+static unsigned long windowedExStyle, windowedStyle;
+#endif // _WIN32
+static unsigned long fullscreen;
+#ifdef _WIN32
+static RECT windowedRect;
+static HMENU windowedMenu;
+#endif // _WIN32
+
+static int savedWidtho, savedHeighto;
+static int savedWidth, savedHeight;
+unsigned int pBufferAddress;
+static int pBufferFmt;
+static int pBufferWidth, pBufferHeight;
+static fb fbs[100];
+static int nb_fb = 0;
+static unsigned int curBufferAddr = 0;
+
+struct TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };
+
+struct texbuf_t {
+ FxU32 start, end;
+ int fmt;
+};
+#define NB_TEXBUFS 128 // MUST be a power of two
+static texbuf_t texbufs[NB_TEXBUFS];
+static int texbuf_i;
+
+unsigned short frameBuffer[2048*2048];
+unsigned short depthBuffer[2048*2048];
+
+//#define VOODOO1
+
+void display_warning(const char *text, ...)
+{
+ static int first_message = 100;
+ if (first_message)
+ {
+ char buf[4096];
+
+ va_list ap;
+
+ va_start(ap, text);
+ vsprintf(buf, text, ap);
+ va_end(ap);
+ first_message--;
+ LOGINFO(buf);
+ }
+}
+
+#ifdef _WIN32
+void display_error()
+{
+ LPVOID lpMsgBuf;
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ // Handle the error.
+ return;
+ }
+ // Process any inserts in lpMsgBuf.
+ // ...
+ // Display the string.
+ MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
+
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+}
+#endif // _WIN32
+
+#ifdef LOGGING
+char out_buf[256];
+bool log_open = false;
+std::ofstream log_file;
+
+void OPEN_LOG()
+{
+ if (!log_open)
+ {
+ log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);
+ log_open = true;
+ }
+}
+
+void CLOSE_LOG()
+{
+ if (log_open)
+ {
+ log_file.close();
+ log_open = false;
+ }
+}
+
+void LOG(const char *text, ...)
+{
+#ifdef VPDEBUG
+ if (!dumping) return;
+#endif
+ if (!log_open)
+ return;
+ va_list ap;
+ va_start(ap, text);
+ vsprintf(out_buf, text, ap);
+ log_file << out_buf;
+ log_file.flush();
+ va_end(ap);
+}
+
+class LogManager {
+public:
+ LogManager() {
+ OPEN_LOG();
+ }
+ ~LogManager() {
+ CLOSE_LOG();
+ }
+};
+
+LogManager logManager;
+
+#else // LOGGING
+#define OPEN_LOG()
+#define CLOSE_LOG()
+//#define LOG
+#endif // LOGGING
+
+FX_ENTRY void FX_CALL
+grSstOrigin(GrOriginLocation_t origin)
+{
+ LOG("grSstOrigin(%d)\r\n", origin);
+ if (origin != GR_ORIGIN_UPPER_LEFT)
+ display_warning("grSstOrigin : %x", origin);
+}
+
+FX_ENTRY void FX_CALL
+grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )
+{
+ LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);
+
+ if (use_fbo && render_to_texture) {
+ if (int(minx) < 0) minx = 0;
+ if (int(miny) < 0) miny = 0;
+ if (maxx < minx) maxx = minx;
+ if (maxy < miny) maxy = miny;
+ glScissor(minx, miny, maxx - minx, maxy - miny);
+ glEnable(GL_SCISSOR_TEST);
+ return;
+ }
+
+ if (!use_fbo) {
+ int th = height;
+ if (th > screen_height)
+ th = screen_height;
+ maxy = th - maxy;
+ miny = th - miny;
+ FxU32 tmp = maxy; maxy = miny; miny = tmp;
+ if (maxx > (FxU32) width) maxx = width;
+ if (maxy > (FxU32) height) maxy = height;
+ if (int(minx) < 0) minx = 0;
+ if (int(miny) < 0) miny = 0;
+ if (maxx < minx) maxx = minx;
+ if (maxy < miny) maxy = miny;
+ glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);
+ //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
+ } else {
+ glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny);
+ }
+ glEnable(GL_SCISSOR_TEST);
+}
+
+FX_ENTRY void FX_CALL
+grColorMask( FxBool rgb, FxBool a )
+{
+ LOG("grColorMask(%d, %d)\r\n", rgb, a);
+ glColorMask(rgb, rgb, rgb, a);
+}
+
+FX_ENTRY void FX_CALL
+grGlideInit( void )
+{
+ LOG("grGlideInit()\r\n");
+}
+
+FX_ENTRY void FX_CALL
+grSstSelect( int which_sst )
+{
+ LOG("grSstSelect(%d)\r\n", which_sst);
+}
+
+int isExtensionSupported(const char *extension)
+{
+ return 0;
+ const GLubyte *extensions = NULL;
+ const GLubyte *start;
+ GLubyte *where, *terminator;
+
+ where = (GLubyte *)strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return 0;
+
+ extensions = glGetString(GL_EXTENSIONS);
+
+ start = extensions;
+ for (;;)
+ {
+ where = (GLubyte *) strstr((const char *) start, extension);
+ if (!where)
+ break;
+
+ terminator = where + strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return 1;
+
+ start = terminator;
+ }
+
+ return 0;
+}
+
+#ifdef _WIN32
+int isWglExtensionSupported(const char *extension)
+{
+ const GLubyte *extensions = NULL;
+ const GLubyte *start;
+ GLubyte *where, *terminator;
+
+ where = (GLubyte *)strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return 0;
+
+ extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
+
+ start = extensions;
+ for (;;)
+ {
+ where = (GLubyte *) strstr((const char *) start, extension);
+ if (!where)
+ break;
+
+ terminator = where + strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return 1;
+
+ start = terminator;
+ }
+
+ return 0;
+}
+#endif // _WIN32
+
+#define GrPixelFormat_t int
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpenExt(
+ HWND hWnd,
+ GrScreenResolution_t screen_resolution,
+ GrScreenRefresh_t refresh_rate,
+ GrColorFormat_t color_format,
+ GrOriginLocation_t origin_location,
+ GrPixelFormat_t pixelformat,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+ LOG("grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+ return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format,
+ origin_location, nColBuffers, nAuxBuffers);
+}
+
+#ifdef WIN32
+# include
+# ifndef ATTACH_PARENT_PROCESS
+# define ATTACH_PARENT_PROCESS ((FxU32)-1)
+# endif
+#endif
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpen(
+ HWND hWnd,
+ GrScreenResolution_t screen_resolution,
+ GrScreenRefresh_t refresh_rate,
+ GrColorFormat_t color_format,
+ GrOriginLocation_t origin_location,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+ static int show_warning = 1;
+
+ // ZIGGY
+ // allocate static texture names
+ // the initial value should be big enough to support the maximal resolution
+ free_texture = 32*2048*2048;
+ default_texture = free_texture++;
+ color_texture = free_texture++;
+ depth_texture = free_texture++;
+
+ LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+
+#ifdef _WIN32
+ if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();
+ hwnd_win = (HWND)hWnd;
+#endif // _WIN32
+ width = height = 0;
+
+ m64p_handle video_general_section;
+ printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);
+ if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)
+ {
+ printf("Could not open video settings");
+ return false;
+ }
+ width = ConfigGetParamInt(video_general_section, "ScreenWidth");
+ height = ConfigGetParamInt(video_general_section, "ScreenHeight");
+ fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");
+ int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");
+ //viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
+ // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero
+ viewport_offset = 0; //-10 //-20;
+
+ CoreVideo_Init();
+ CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);
+ CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);
+ CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);
+ // SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
+ // SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);
+
+ printf("(II) Setting video mode %dx%d...\n", width, height);
+ if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
+ {
+ printf("(EE) Error setting videomode %dx%d\n", width, height);
+ return false;
+ }
+
+ char caption[500];
+# ifdef _DEBUG
+ sprintf(caption, "Glide64mk2 debug");
+# else // _DEBUG
+ sprintf(caption, "Glide64mk2");
+# endif // _DEBUG
+ CoreVideo_SetCaption(caption);
+
+ glViewport(0, viewport_offset, width, height);
+ lfb_color_fmt = color_format;
+ if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner");
+ if (nColBuffers != 2) display_warning("number of color buffer is not 2");
+ if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1");
+
+ if (isExtensionSupported("GL_ARB_texture_env_combine") == 0 &&
+ isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&
+ show_warning)
+ display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");
+ if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_ARB_multitexture extension");
+ if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");
+ show_warning = 0;
+
+#ifdef _WIN32
+ glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
+ glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
+#endif // _WIN32
+
+ nbTextureUnits = 4;
+ //glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits);
+ if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units");
+
+ nbAuxBuffers = 4;
+ //glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
+ if (nbAuxBuffers > 0)
+ printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
+#ifdef VOODOO1
+ nbTextureUnits = 2;
+#endif
+
+ blend_func_separate_support = 1;
+ packed_pixels_support = 0;
+/*
+ if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
+ blend_func_separate_support = 0;
+ else
+ blend_func_separate_support = 1;
+
+ if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
+ packed_pixels_support = 0;
+ else {
+ printf("packed pixels extension used\n");
+ packed_pixels_support = 1;
+ }
+*/
+
+ if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
+ npot_support = 0;
+ else {
+ printf("NPOT extension used\n");
+ npot_support = 1;
+ }
+
+#ifdef _WIN32
+ glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
+#endif // _WIN32
+
+ if (isExtensionSupported("GL_EXT_fog_coord") == 0)
+ fog_coord_support = 0;
+ else
+ fog_coord_support = 1;
+
+#ifdef _WIN32
+ glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
+#endif // _WIN32
+
+#ifdef _WIN32
+ wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+#endif // _WIN32
+
+#ifdef _WIN32
+ glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
+ glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
+ glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
+ glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
+ glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
+
+ glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
+ glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
+ glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
+ glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
+ glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
+ use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);
+#else
+ use_fbo = config.fbo;
+#endif // _WIN32
+
+ LOGINFO("use_fbo %d\n", use_fbo);
+
+ if (isExtensionSupported("GL_ARB_shading_language_100") &&
+ isExtensionSupported("GL_ARB_shader_objects") &&
+ isExtensionSupported("GL_ARB_fragment_shader") &&
+ isExtensionSupported("GL_ARB_vertex_shader"))
+ {
+
+#ifdef _WIN32
+ glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
+ glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
+ glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
+ glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
+ glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
+ glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
+ glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
+ glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
+ glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
+ glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");
+ glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
+ glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
+ glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
+ glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
+ glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
+
+ glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");
+#endif // _WIN32
+ }
+
+ if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");
+ if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");
+
+#ifdef _WIN32
+ glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
+#endif
+
+
+#ifdef _WIN32
+ glViewport(0, viewport_offset, width, height);
+ viewport_width = width;
+ viewport_height = height;
+ nvidia_viewport_hack = 1;
+#else
+ glViewport(0, viewport_offset, width, height);
+ viewport_width = width;
+ viewport_height = height;
+#endif // _WIN32
+
+ // void do_benchmarks();
+ // do_benchmarks();
+
+ // VP try to resolve z precision issues
+// glMatrixMode(GL_MODELVIEW);
+// glLoadIdentity();
+// glTranslatef(0, 0, 1-zscale);
+// glScalef(1, 1, zscale);
+
+ widtho = width/2;
+ heighto = height/2;
+
+ pBufferWidth = pBufferHeight = -1;
+
+ current_buffer = GL_BACK;
+
+ texture_unit = GL_TEXTURE0;
+
+ {
+ int i;
+ for (i=0; i 0 )
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+
+ // ATI hack - certain texture formats are slow on ATI?
+ // Hmm, perhaps the internal format need to be specified explicitly...
+ {
+ GLint ifmt;
+ glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
+ if (ifmt != GL_RGB5_A1) {
+ display_warning("ATI SUCKS %x\n", ifmt);
+ ati_sucks = 1;
+ } else
+ ati_sucks = 0;
+ }
+*/
+
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grGlideShutdown( void )
+{
+ LOG("grGlideShutdown\r\n");
+}
+
+FX_ENTRY FxBool FX_CALL
+grSstWinClose( GrContext_t context )
+{
+ int i, clear_texbuff = use_fbo;
+ LOG("grSstWinClose(%d)\r\n", context);
+
+ for (i=0; i<2; i++) {
+ tmu_usage[i].min = 0xfffffff;
+ tmu_usage[i].max = 0;
+ invtex[i] = 0;
+ }
+
+ free_combiners();
+#ifndef WIN32
+ try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
+ // ZIGGY : I found the problem : it is a function pointer, when the extension isn't supported , it is then zero, so just need to check the pointer prior to do the call.
+ {
+ if (use_fbo)
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ }
+ catch (...)
+ {
+ clear_texbuff = 0;
+ }
+
+ if (clear_texbuff)
+ {
+ for (i=0; i> -aspect;
+ }
+ else
+ {
+ pBufferWidth = 1 << lodmin;
+ pBufferHeight = pBufferWidth >> aspect;
+ }
+
+ if (curBufferAddr && startAddress+1 != curBufferAddr)
+ updateTexture();
+#ifdef SAVE_CBUFFER
+ //printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
+ // save color buffer
+ if (nbAuxBuffers > 0) {
+ //glDrawBuffer(GL_AUX0);
+ //current_buffer = GL_AUX0;
+ } else {
+ int tw, th;
+ if (pBufferWidth < screen_width)
+ tw = pBufferWidth;
+ else
+ tw = screen_width;
+ if (pBufferHeight < screen_height)
+ th = pBufferHeight;
+ else
+ th = screen_height;
+ //glReadBuffer(GL_BACK);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, color_texture);
+ // save incrementally the framebuffer
+ if (save_w) {
+ if (tw > save_w && th > save_h) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
+ 0, viewport_offset+save_h, tw, th-save_h);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
+ save_w, viewport_offset, tw-save_w, save_h);
+ save_w = tw;
+ save_h = th;
+ } else if (tw > save_w) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
+ save_w, viewport_offset, tw-save_w, save_h);
+ save_w = tw;
+ } else if (th > save_h) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
+ 0, viewport_offset+save_h, save_w, th-save_h);
+ save_h = th;
+ }
+ } else {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ 0, viewport_offset, tw, th);
+ save_w = tw;
+ save_h = th;
+ }
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ }
+#endif
+
+ if (startAddress+1 != curBufferAddr ||
+ (curBufferAddr == 0L && nbAuxBuffers == 0))
+ buffer_cleared = 0;
+
+ curBufferAddr = pBufferAddress = startAddress+1;
+ pBufferFmt = fmt;
+
+ int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;
+ int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);
+ if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)
+ tmu_usage[rtmu].min = pBufferAddress;
+ if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size)
+ tmu_usage[rtmu].max = pBufferAddress+size;
+ // printf("tmu %d usage now %gMb - %gMb\n",
+ // rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
+
+
+ width = pBufferWidth;
+ height = pBufferHeight;
+
+ widtho = width/2;
+ heighto = height/2;
+
+ // this could be improved, but might be enough as long as the set of
+ // texture buffer addresses stay small
+ for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1))
+ if (texbufs[i].start == pBufferAddress)
+ break;
+ texbufs[i].start = pBufferAddress;
+ texbufs[i].end = pBufferAddress + size;
+ texbufs[i].fmt = fmt;
+ if (i == texbuf_i)
+ texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);
+ //printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
+
+ // ZIGGY it speeds things up to not delete the buffers
+ // a better thing would be to delete them *sometimes*
+ // remove_tex(pBufferAddress+1, pBufferAddress + size);
+ add_tex(pBufferAddress);
+
+ //printf("viewport %dx%d\n", width, height);
+ if (height > screen_height) {
+ glViewport( 0, viewport_offset + screen_height - height, width, height);
+ } else
+ glViewport( 0, viewport_offset, width, height);
+
+ glScissor(0, viewport_offset, width, height);
+
+
+ } else {
+ if (!render_to_texture) //initialization
+ {
+ if(!fbs_init)
+ {
+ for(i=0; i<100; i++) fbs[i].address = 0;
+ fbs_init = 1;
+ nb_fb = 0;
+ }
+ return; //no need to allocate FBO if render buffer is not texture buffer
+ }
+
+ render_to_texture = 2;
+
+ if (aspect < 0)
+ {
+ pBufferHeight = 1 << lodmin;
+ pBufferWidth = pBufferHeight >> -aspect;
+ }
+ else
+ {
+ pBufferWidth = 1 << lodmin;
+ pBufferHeight = pBufferWidth >> aspect;
+ }
+ pBufferAddress = startAddress+1;
+
+ width = pBufferWidth;
+ height = pBufferHeight;
+
+ widtho = width/2;
+ heighto = height/2;
+
+ for (i=0; i 1)
+ memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));
+ nb_fb--;
+ break;
+ }
+ }
+ }
+
+ remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
+ //create new FBO
+ glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
+ glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) );
+ glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+ fbs[nb_fb].address = pBufferAddress;
+ fbs[nb_fb].width = width;
+ fbs[nb_fb].height = height;
+ fbs[nb_fb].texid = pBufferAddress;
+ fbs[nb_fb].buff_clear = 0;
+ add_tex(fbs[nb_fb].texid);
+ glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid );
+ glViewport(0,0,width,height);
+ glScissor(0,0,width,height);
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glDepthMask(1);
+ glClear( GL_DEPTH_BUFFER_BIT );
+ CHECK_FRAMEBUFFER_STATUS();
+ curBufferAddr = pBufferAddress;
+ nb_fb++;
+ }
+}
+
+int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )
+{
+ int found, i;
+ if (!use_fbo) {
+ for (found=i=0; i<2; i++)
+ if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {
+ //printf("tmu %d == framebuffer %x\n", tmu, startAddress);
+ found = 1;
+ break;
+ }
+ } else {
+ found = i = 0;
+ while (i < nb_fb)
+ {
+ unsigned int end = fbs[i].address + fbs[i].width*fbs[i].height*2;
+ if (startAddress >= fbs[i].address && startAddress < end)
+ {
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ }
+
+ if (!use_fbo && found) {
+ int tw, th, rh, cw, ch;
+ if (info->aspectRatioLog2 < 0)
+ {
+ th = 1 << info->largeLodLog2;
+ tw = th >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ tw = 1 << info->largeLodLog2;
+ th = tw >> info->aspectRatioLog2;
+ }
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ ch = 256;
+ cw = ch >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ cw = 256;
+ ch = cw >> info->aspectRatioLog2;
+ }
+
+ if (use_fbo || th < screen_height)
+ rh = th;
+ else
+ rh = screen_height;
+
+ //printf("th %d rh %d ch %d\n", th, rh, ch);
+
+ invtex[tmu] = 1.0f - (th - rh) / (float)th;
+ } else
+ invtex[tmu] = 0;
+
+ if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) {
+ if (!found) {
+ return 0;
+ }
+ if(tmu == 0)
+ {
+ if(blackandwhite1 != found)
+ {
+ blackandwhite1 = found;
+ need_to_compile = 1;
+ }
+ }
+ else
+ {
+ if(blackandwhite0 != found)
+ {
+ blackandwhite0 = found;
+ need_to_compile = 1;
+ }
+ }
+ return 1;
+ }
+ return 0;
+
+}
+
+
+FX_ENTRY void FX_CALL
+grTextureAuxBufferExt( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLOD,
+ GrLOD_t largeLOD,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 odd_even_mask )
+{
+ LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
+ //display_warning("grTextureAuxBufferExt");
+}
+
+FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
+
+FX_ENTRY GrProc FX_CALL
+grGetProcAddress( char *procName )
+{
+ LOG("grGetProcAddress(%s)\r\n", procName);
+ if(!strcmp(procName, "grSstWinOpenExt"))
+ return (GrProc)grSstWinOpenExt;
+ if(!strcmp(procName, "grTextureBufferExt"))
+ return (GrProc)grTextureBufferExt;
+ if(!strcmp(procName, "grChromaRangeExt"))
+ return (GrProc)grChromaRangeExt;
+ if(!strcmp(procName, "grChromaRangeModeExt"))
+ return (GrProc)grChromaRangeModeExt;
+ if(!strcmp(procName, "grTexChromaRangeExt"))
+ return (GrProc)grTexChromaRangeExt;
+ if(!strcmp(procName, "grTexChromaModeExt"))
+ return (GrProc)grTexChromaModeExt;
+ // ZIGGY framebuffer copy extension
+ if(!strcmp(procName, "grFramebufferCopyExt"))
+ return (GrProc)grFramebufferCopyExt;
+ if(!strcmp(procName, "grColorCombineExt"))
+ return (GrProc)grColorCombineExt;
+ if(!strcmp(procName, "grAlphaCombineExt"))
+ return (GrProc)grAlphaCombineExt;
+ if(!strcmp(procName, "grTexColorCombineExt"))
+ return (GrProc)grTexColorCombineExt;
+ if(!strcmp(procName, "grTexAlphaCombineExt"))
+ return (GrProc)grTexAlphaCombineExt;
+ if(!strcmp(procName, "grConstantColorValueExt"))
+ return (GrProc)grConstantColorValueExt;
+ if(!strcmp(procName, "grTextureAuxBufferExt"))
+ return (GrProc)grTextureAuxBufferExt;
+ if(!strcmp(procName, "grAuxBufferExt"))
+ return (GrProc)grAuxBufferExt;
+ if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))
+ return (GrProc)grWrapperFullScreenResolutionExt;
+ if(!strcmp(procName, "grConfigWrapperExt"))
+ return (GrProc)grConfigWrapperExt;
+ if(!strcmp(procName, "grKeyPressedExt"))
+ return (GrProc)grKeyPressedExt;
+ if(!strcmp(procName, "grQueryResolutionsExt"))
+ return (GrProc)grQueryResolutionsExt;
+ if(!strcmp(procName, "grGetGammaTableExt"))
+ return (GrProc)grGetGammaTableExt;
+ display_warning("grGetProcAddress : %s", procName);
+ return 0;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grGet( FxU32 pname, FxU32 plength, FxI32 *params )
+{
+ LOG("grGet(%d,%d)\r\n", pname, plength);
+ switch(pname)
+ {
+ case GR_MAX_TEXTURE_SIZE:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 2048;
+ return 4;
+ break;
+ case GR_NUM_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ if (!nbTextureUnits)
+ {
+ grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB,
+ GR_ORIGIN_UPPER_LEFT, 2, 1);
+ grSstWinClose(0);
+ }
+#ifdef VOODOO1
+ params[0] = 1;
+#else
+ if (nbTextureUnits > 2)
+ params[0] = 2;
+ else
+ params[0] = 1;
+#endif
+ return 4;
+ break;
+ case GR_NUM_BOARDS:
+ case GR_NUM_FB:
+ case GR_REVISION_FB:
+ case GR_REVISION_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 1;
+ return 4;
+ break;
+ case GR_MEMORY_FB:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024;
+ return 4;
+ break;
+ case GR_MEMORY_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024;
+ return 4;
+ break;
+ case GR_MEMORY_UMA:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024*nbTextureUnits;
+ return 4;
+ break;
+ case GR_BITS_RGBA:
+ if (plength < 16 || params == NULL) return 0;
+ params[0] = 8;
+ params[1] = 8;
+ params[2] = 8;
+ params[3] = 8;
+ return 16;
+ break;
+ case GR_BITS_DEPTH:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16;
+ return 4;
+ break;
+ case GR_BITS_GAMMA:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 8;
+ return 4;
+ break;
+ case GR_GAMMA_TABLE_ENTRIES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 256;
+ return 4;
+ break;
+ case GR_FOG_TABLE_ENTRIES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 64;
+ return 4;
+ break;
+ case GR_WDEPTH_MIN_MAX:
+ if (plength < 8 || params == NULL) return 0;
+ params[0] = 0;
+ params[1] = 65528;
+ return 8;
+ break;
+ case GR_ZDEPTH_MIN_MAX:
+ if (plength < 8 || params == NULL) return 0;
+ params[0] = 0;
+ params[1] = 65535;
+ return 8;
+ break;
+ case GR_LFB_PIXEL_PIPE:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = FXFALSE;
+ return 4;
+ break;
+ case GR_MAX_TEXTURE_ASPECT_RATIO:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 3;
+ return 4;
+ break;
+ case GR_NON_POWER_OF_TWO_TEXTURES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = FXFALSE;
+ return 4;
+ break;
+ case GR_TEXTURE_ALIGN:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 0;
+ return 4;
+ break;
+ default:
+ display_warning("unknown pname in grGet : %x", pname);
+ }
+ return 0;
+}
+
+FX_ENTRY const char * FX_CALL
+grGetString( FxU32 pname )
+{
+ LOG("grGetString(%d)\r\n", pname);
+ switch(pname)
+ {
+ case GR_EXTENSION:
+ {
+ static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";
+ return extension;
+ }
+ break;
+ case GR_HARDWARE:
+ {
+ static char hardware[] = "Voodoo5 (tm)";
+ return hardware;
+ }
+ break;
+ case GR_VENDOR:
+ {
+ static char vendor[] = "3Dfx Interactive";
+ return vendor;
+ }
+ break;
+ case GR_RENDERER:
+ {
+ static char renderer[] = "Glide";
+ return renderer;
+ }
+ break;
+ case GR_VERSION:
+ {
+ static char version[] = "3.0";
+ return version;
+ }
+ break;
+ default:
+ display_warning("unknown grGetString selector : %x", pname);
+ }
+ return NULL;
+}
+
+static void render_rectangle(int texture_number,
+ int dst_x, int dst_y,
+ int src_width, int src_height,
+ int tex_width, int tex_height, int invert)
+{
+ LOGINFO("render_rectangle(%d,%d,%d,%d,%d,%d,%d,%d)",texture_number,dst_x,dst_y,src_width,src_height,tex_width,tex_height,invert);
+ int vertexOffset_location;
+ int textureSizes_location;
+ static float data[] = {
+ (float)((int)dst_x), //X 0
+ (float)(invert*-((int)dst_y)), //Y 0
+ 0.0f, //U 0
+ 0.0f, //V 0
+
+ (float)((int)dst_x), //X 1
+ (float)(invert*-((int)dst_y + (int)src_height)), //Y 1
+ 0.0f, //U 1
+ (float)src_height / (float)tex_height, //V 1
+
+ (float)((int)dst_x + (int)src_width),
+ (float)(invert*-((int)dst_y + (int)src_height)),
+ (float)src_width / (float)tex_width,
+ (float)src_height / (float)tex_height,
+
+ (float)((int)dst_x),
+ (float)(invert*-((int)dst_y)),
+ 0.0f,
+ 0.0f
+ };
+
+ vbo_disable();
+ glDisableVertexAttribArray(COLOUR_ATTR);
+ glDisableVertexAttribArray(TEXCOORD_1_ATTR);
+ glDisableVertexAttribArray(FOG_ATTR);
+
+ glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position
+ glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex
+
+ glEnableVertexAttribArray(COLOUR_ATTR);
+ glEnableVertexAttribArray(TEXCOORD_1_ATTR);
+ glEnableVertexAttribArray(FOG_ATTR);
+
+
+ disable_textureSizes();
+
+ glDrawArrays(GL_TRIANGLE_STRIP,0,4);
+ vbo_enable();
+
+
+/*
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBegin(GL_QUADS);
+ glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);
+ glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
+ invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);
+ glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glEnd();
+*/
+
+ compile_shader();
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+}
+
+void reloadTexture()
+{
+ if (use_fbo || !render_to_texture || buffer_cleared)
+ return;
+
+ LOG("reload texture %dx%d\n", width, height);
+ //printf("reload texture %dx%d\n", width, height);
+
+ buffer_cleared = 1;
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, pBufferAddress);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(current_buffer);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ set_copy_shader();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ int w = 0, h = 0;
+ if (height > screen_height) h = screen_height - height;
+ render_rectangle(texture_unit,
+ -w, -h,
+ width, height,
+ width, height, -1);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+}
+
+void updateTexture()
+{
+ if (!use_fbo && render_to_texture == 2) {
+ LOG("update texture %x\n", pBufferAddress);
+ //printf("update texture %x\n", pBufferAddress);
+
+ // nothing changed, don't update the texture
+ if (!buffer_cleared) {
+ LOG("update cancelled\n", pBufferAddress);
+ return;
+ }
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ // save result of render to texture into actual texture
+ //glReadBuffer(current_buffer);
+ glActiveTexture(texture_unit);
+ // ZIGGY
+ // deleting the texture before resampling it increases speed on certain old
+ // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot
+ // on newer cards.
+ //glDeleteTextures( 1, &pBufferAddress );
+ glBindTexture(GL_TEXTURE_2D, pBufferAddress);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+ 0, viewport_offset, width, height, 0);
+
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+ }
+}
+
+FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h,
+ int from, int to, int mode)
+{
+ if (mode == GR_FBCOPY_MODE_DEPTH) {
+
+ int tw = 1, th = 1;
+ if (npot_support) {
+ tw = width; th = height;
+ } else {
+ while (tw < width) tw <<= 1;
+ while (th < height) th <<= 1;
+ }
+
+ if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) {
+ //printf("save depth buffer %d\n", render_to_texture);
+ // save the depth image in a texture
+ //glReadBuffer(current_buffer);
+ glBindTexture(GL_TEXTURE_2D, depth_texture);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
+ 0, viewport_offset, tw, th, 0);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ return;
+ }
+ if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) {
+ //printf("writing to depth buffer %d\n", render_to_texture);
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(current_buffer);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, depth_texture);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ set_depth_shader();
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDisable(GL_CULL_FACE);
+ render_rectangle(texture_unit,
+ 0, 0,
+ width, height,
+ tw, th, -1);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+ return;
+ }
+
+ }
+}
+
+FX_ENTRY void FX_CALL
+grRenderBuffer( GrBuffer_t buffer )
+{
+#ifdef _WIN32
+ static HANDLE region = NULL;
+ int realWidth = pBufferWidth, realHeight = pBufferHeight;
+#endif // _WIN32
+ LOG("grRenderBuffer(%d)\r\n", buffer);
+ //printf("grRenderBuffer(%d)\n", buffer);
+
+ switch(buffer)
+ {
+ case GR_BUFFER_BACKBUFFER:
+ if(render_to_texture)
+ {
+ updateTexture();
+
+ // VP z fix
+ //glMatrixMode(GL_MODELVIEW);
+ //glLoadIdentity();
+ //glTranslatef(0, 0, 1-zscale);
+ //glScalef(1, 1, zscale);
+ inverted_culling = 0;
+ grCullMode(culling_mode);
+
+ width = savedWidth;
+ height = savedHeight;
+ widtho = savedWidtho;
+ heighto = savedHeighto;
+ if (use_fbo) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindRenderbuffer( GL_RENDERBUFFER, 0 );
+ }
+ curBufferAddr = 0;
+
+ glViewport(0, viewport_offset, width, viewport_height);
+ glScissor(0, viewport_offset, width, height);
+
+#ifdef SAVE_CBUFFER
+ if (!use_fbo && render_to_texture == 2) {
+ // restore color buffer
+ if (nbAuxBuffers > 0) {
+ //glDrawBuffer(GL_BACK);
+ current_buffer = GL_BACK;
+ } else if (save_w) {
+ int tw = 1, th = 1;
+ //printf("restore %dx%d\n", save_w, save_h);
+ if (npot_support) {
+ tw = screen_width;
+ th = screen_height;
+ } else {
+ while (tw < screen_width) tw <<= 1;
+ while (th < screen_height) th <<= 1;
+ }
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(GL_BACK);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, color_texture);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ set_copy_shader();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ render_rectangle(texture_unit,
+ 0, 0,
+ save_w, save_h,
+ tw, th, -1);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+
+ save_w = save_h = 0;
+ }
+ }
+#endif
+ render_to_texture = 0;
+ }
+ //glDrawBuffer(GL_BACK);
+ break;
+ case 6: // RENDER TO TEXTURE
+ if(!render_to_texture)
+ {
+ savedWidth = width;
+ savedHeight = height;
+ savedWidtho = widtho;
+ savedHeighto = heighto;
+ }
+
+ {
+ if (!use_fbo) {
+ //glMatrixMode(GL_MODELVIEW);
+ //glLoadIdentity();
+ //glTranslatef(0, 0, 1-zscale);
+ //glScalef(1, 1, zscale);
+ inverted_culling = 0;
+ } else {
+/*
+ float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f,-1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m);
+ // VP z fix
+ glTranslatef(0, 0, 1-zscale);
+ glScalef(1, 1*1, zscale);
+*/
+ inverted_culling = 1;
+ grCullMode(culling_mode);
+ }
+ }
+ render_to_texture = 1;
+ break;
+ default:
+ display_warning("grRenderBuffer : unknown buffer : %x", buffer);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grAuxBufferExt( GrBuffer_t buffer )
+{
+ LOG("grAuxBufferExt(%d)\r\n", buffer);
+ //display_warning("grAuxBufferExt");
+
+ if (buffer == GR_BUFFER_AUXBUFFER) {
+ invtex[0] = 0;
+ invtex[1] = 0;
+ need_to_compile = 0;
+ set_depth_shader();
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDisable(GL_CULL_FACE);
+ //glDisable(GL_ALPHA_TEST);
+ glDepthMask(GL_TRUE);
+ grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);
+ } else {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ need_to_compile = 1;
+ }
+}
+void vbo_draw();
+FX_ENTRY void FX_CALL
+grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth )
+{
+ vbo_draw();
+ LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth);
+ switch(lfb_color_fmt)
+ {
+ case GR_COLORFORMAT_ARGB:
+ glClearColor(((color >> 16) & 0xFF) / 255.0f,
+ ((color >> 8) & 0xFF) / 255.0f,
+ ( color & 0xFF) / 255.0f,
+ alpha / 255.0f);
+ break;
+ case GR_COLORFORMAT_RGBA:
+ glClearColor(((color >> 24) & 0xFF) / 255.0f,
+ ((color >> 16) & 0xFF) / 255.0f,
+ (color & 0xFF) / 255.0f,
+ alpha / 255.0f);
+ break;
+ default:
+ display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt);
+ }
+
+ if (w_buffer_mode)
+ glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
+ else
+ glClearDepthf(depth / 65535.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // ZIGGY TODO check that color mask is on
+ buffer_cleared = 1;
+
+}
+
+// #include
+FX_ENTRY void FX_CALL
+grBufferSwap( FxU32 swap_interval )
+{
+// GLuint program;
+
+ vbo_draw();
+// glFinish();
+// printf("rendercallback is %p\n", renderCallback);
+ if(renderCallback) {
+// glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*) &program);
+// glUseProgramObjectARB(0);
+ (*renderCallback)(1);
+// if (program)
+// glUseProgramObjectARB(program);
+ }
+ int i;
+ LOG("grBufferSwap(%d)\r\n", swap_interval);
+ //printf("swap\n");
+ if (render_to_texture) {
+ display_warning("swap while render_to_texture\n");
+ return;
+ }
+
+ CoreVideo_GL_SwapBuffers();
+ for (i = 0; i < nb_fb; i++)
+ fbs[i].buff_clear = 1;
+
+ // VP debugging
+#ifdef VPDEBUG
+ dump_stop();
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+case SDL_KEYDOWN:
+ switch (event.key.keysym.sym) {
+case 'd':
+ printf("Dumping !\n");
+ dump_start();
+ break;
+case 'w': {
+ static int wireframe;
+ wireframe = !wireframe;
+ glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL);
+ break;
+ }
+ }
+ break;
+ }
+ }
+#endif
+}
+
+// frame buffer
+
+FX_ENTRY FxBool FX_CALL
+grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,
+ GrOriginLocation_t origin, FxBool pixelPipeline,
+ GrLfbInfo_t *info )
+{
+ LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
+ if (type == GR_LFB_WRITE_ONLY)
+ {
+ display_warning("grLfbLock : write only");
+ }
+ else
+ {
+ unsigned char *buf;
+ int i,j;
+
+ switch(buffer)
+ {
+ case GR_BUFFER_FRONTBUFFER:
+ //glReadBuffer(GL_FRONT);
+ break;
+ case GR_BUFFER_BACKBUFFER:
+ //glReadBuffer(GL_BACK);
+ break;
+ default:
+ display_warning("grLfbLock : unknown buffer : %x", buffer);
+ }
+
+ if(buffer != GR_BUFFER_AUXBUFFER)
+ {
+ if (writeMode == GR_LFBWRITEMODE_888) {
+ //printf("LfbLock GR_LFBWRITEMODE_888\n");
+ info->lfbPtr = frameBuffer;
+ info->strideInBytes = width*4;
+ info->writeMode = GR_LFBWRITEMODE_888;
+ info->origin = origin;
+ //glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);
+ } else {
+ buf = (unsigned char*)malloc(width*height*4);
+
+ info->lfbPtr = frameBuffer;
+ info->strideInBytes = width*2;
+ info->writeMode = GR_LFBWRITEMODE_565;
+ info->origin = origin;
+ glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+ for (j=0; j> 3) << 11) |
+ ((buf[j*width*4+i*4+1] >> 2) << 5) |
+ (buf[j*width*4+i*4+2] >> 3);
+ }
+ }
+ free(buf);
+ }
+ }
+ else
+ {
+ info->lfbPtr = depthBuffer;
+ info->strideInBytes = width*2;
+ info->writeMode = GR_LFBWRITEMODE_ZA16;
+ info->origin = origin;
+ glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+ }
+ }
+
+ return FXTRUE;
+}
+
+FX_ENTRY FxBool FX_CALL
+grLfbUnlock( GrLock_t type, GrBuffer_t buffer )
+{
+ LOG("grLfbUnlock(%d,%d)\r\n", type, buffer);
+ if (type == GR_LFB_WRITE_ONLY)
+ {
+ display_warning("grLfbUnlock : write only");
+ }
+ return FXTRUE;
+}
+
+FX_ENTRY FxBool FX_CALL
+grLfbReadRegion( GrBuffer_t src_buffer,
+ FxU32 src_x, FxU32 src_y,
+ FxU32 src_width, FxU32 src_height,
+ FxU32 dst_stride, void *dst_data )
+{
+ unsigned char *buf;
+ unsigned int i,j;
+ unsigned short *frameBuffer = (unsigned short*)dst_data;
+ unsigned short *depthBuffer = (unsigned short*)dst_data;
+ LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
+
+ switch(src_buffer)
+ {
+ case GR_BUFFER_FRONTBUFFER:
+ //glReadBuffer(GL_FRONT);
+ break;
+ case GR_BUFFER_BACKBUFFER:
+ //glReadBuffer(GL_BACK);
+ break;
+ /*case GR_BUFFER_AUXBUFFER:
+ glReadBuffer(current_buffer);
+ break;*/
+ default:
+ display_warning("grReadRegion : unknown buffer : %x", src_buffer);
+ }
+
+ if(src_buffer != GR_BUFFER_AUXBUFFER)
+ {
+ buf = (unsigned char*)malloc(src_width*src_height*4);
+
+ glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+ for (j=0; j> 3) << 11) |
+ ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) << 5) |
+ (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);
+ }
+ }
+ free(buf);
+ }
+ else
+ {
+ buf = (unsigned char*)malloc(src_width*src_height*2);
+
+ glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+
+ for (j=0;j>10)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;
+ }
+ }
+ break;
+ case GR_LFBWRITEMODE_555:
+ for (j=0; j>10)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]=0xFF;
+ }
+ }
+ break;
+ case GR_LFBWRITEMODE_565:
+ for (j=0; j>11)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]=0xFF;
+ }
+ }
+ break;
+ default:
+ display_warning("grLfbWriteRegion : unknown format : %d", src_format);
+ }
+
+#ifdef VPDEBUG
+ if (dumping) {
+ ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf);
+ char name[128];
+ static int id;
+ sprintf(name, "dump/writecolor%d.png", id++);
+ ilSaveImage(name);
+ //printf("dumped gdLfbWriteRegion %s\n", name);
+ }
+#endif
+
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+ free(buf);
+
+ set_copy_shader();
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ render_rectangle(texture_number,
+ dst_x, dst_y,
+ src_width, src_height,
+ tex_width, tex_height, +1);
+
+ }
+ else
+ {
+ float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float));
+
+ if (src_format != GR_LFBWRITEMODE_ZA16)
+ display_warning("unknown depth buffer write format:%x", src_format);
+
+ if(dst_x || dst_y)
+ display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y);
+
+ for (j=0; jresolution != GR_QUERY_ANY)
+ {
+ res_inf = res_sup = resTemplate->resolution;
+ }
+ if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate");
+ if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers");
+ if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers");
+
+ if (output == NULL) return res_sup - res_inf + 1;
+ for (i=res_inf; i<=res_sup; i++)
+ {
+ output[n].resolution = i;
+ output[n].refresh = resTemplate->refresh;
+ output[n].numAuxBuffers = resTemplate->numAuxBuffers;
+ output[n].numColorBuffers = resTemplate->numColorBuffers;
+ n++;
+ }
+ return res_sup - res_inf + 1;
+}
+
+FX_ENTRY FxBool FX_CALL
+grReset( FxU32 what )
+{
+ display_warning("grReset");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grEnable( GrEnableMode_t mode )
+{
+ LOG("grEnable(%d)\r\n", mode);
+ if (mode == GR_TEXTURE_UMA_EXT)
+ UMAmode = 1;
+}
+
+FX_ENTRY void FX_CALL
+grDisable( GrEnableMode_t mode )
+{
+ LOG("grDisable(%d)\r\n", mode);
+ if (mode == GR_TEXTURE_UMA_EXT)
+ UMAmode = 0;
+}
+
+FX_ENTRY void FX_CALL
+grDisableAllEffects( void )
+{
+ display_warning("grDisableAllEffects");
+}
+
+FX_ENTRY void FX_CALL
+grErrorSetCallback( GrErrorCallbackFnc_t fnc )
+{
+ display_warning("grErrorSetCallback");
+}
+
+FX_ENTRY void FX_CALL
+grFinish(void)
+{
+ display_warning("grFinish");
+}
+
+FX_ENTRY void FX_CALL
+grFlush(void)
+{
+ display_warning("grFlush");
+}
+
+FX_ENTRY void FX_CALL
+grTexMultibase( GrChipID_t tmu,
+ FxBool enable )
+{
+ display_warning("grTexMultibase");
+}
+
+FX_ENTRY void FX_CALL
+grTexMipMapMode( GrChipID_t tmu,
+ GrMipMapMode_t mode,
+ FxBool lodBlend )
+{
+ display_warning("grTexMipMapMode");
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadTablePartial( GrTexTable_t type,
+ void *data,
+ int start,
+ int end )
+{
+ display_warning("grTexDownloadTablePartial");
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadTable( GrTexTable_t type,
+ void *data )
+{
+ display_warning("grTexDownloadTable");
+}
+
+FX_ENTRY FxBool FX_CALL
+grTexDownloadMipMapLevelPartial( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data,
+ int start,
+ int end )
+{
+ display_warning("grTexDownloadMipMapLevelPartial");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadMipMapLevel( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data )
+{
+ display_warning("grTexDownloadMipMapLevel");
+}
+
+FX_ENTRY void FX_CALL
+grTexNCCTable( GrNCCTable_t table )
+{
+ display_warning("grTexNCCTable");
+}
+
+FX_ENTRY void FX_CALL
+grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height )
+{
+ display_warning("grViewport");
+}
+
+FX_ENTRY void FX_CALL
+grDepthRange( FxFloat n, FxFloat f )
+{
+ display_warning("grDepthRange");
+}
+
+FX_ENTRY void FX_CALL
+grSplash(float x, float y, float width, float height, FxU32 frame)
+{
+ display_warning("grSplash");
+}
+
+FX_ENTRY FxBool FX_CALL
+grSelectContext( GrContext_t context )
+{
+ display_warning("grSelectContext");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grAADrawTriangle(
+ const void *a, const void *b, const void *c,
+ FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias
+ )
+{
+ display_warning("grAADrawTriangle");
+}
+
+FX_ENTRY void FX_CALL
+grAlphaControlsITRGBLighting( FxBool enable )
+{
+ display_warning("grAlphaControlsITRGBLighting");
+}
+
+FX_ENTRY void FX_CALL
+grGlideSetVertexLayout( const void *layout )
+{
+ display_warning("grGlideSetVertexLayout");
+}
+
+FX_ENTRY void FX_CALL
+grGlideGetVertexLayout( void *layout )
+{
+ display_warning("grGlideGetVertexLayout");
+}
+
+FX_ENTRY void FX_CALL
+grGlideSetState( const void *state )
+{
+ display_warning("grGlideSetState");
+}
+
+FX_ENTRY void FX_CALL
+grGlideGetState( void *state )
+{
+ display_warning("grGlideGetState");
+}
+
+FX_ENTRY void FX_CALL
+grLfbWriteColorFormat(GrColorFormat_t colorFormat)
+{
+ display_warning("grLfbWriteColorFormat");
+}
+
+FX_ENTRY void FX_CALL
+grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
+{
+ display_warning("grLfbWriteColorSwizzle");
+}
+
+FX_ENTRY void FX_CALL
+grLfbConstantDepth( FxU32 depth )
+{
+ display_warning("grLfbConstantDepth");
+}
+
+FX_ENTRY void FX_CALL
+grLfbConstantAlpha( GrAlpha_t alpha )
+{
+ display_warning("grLfbConstantAlpha");
+}
+
+FX_ENTRY void FX_CALL
+grTexMultibaseAddress( GrChipID_t tmu,
+ GrTexBaseRange_t range,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info )
+{
+ display_warning("grTexMultibaseAddress");
+}
+
+/*
+inline void MySleep(FxU32 ms)
+{
+#ifdef _WIN32
+ Sleep(ms);
+#else
+ SDL_Delay(ms);
+#endif
+}
+*/
+
+#ifdef _WIN32
+static void CorrectGamma(LPVOID apGammaRamp)
+{
+ HDC hdc = GetDC(NULL);
+ if (hdc != NULL)
+ {
+ SetDeviceGammaRamp(hdc, apGammaRamp);
+ ReleaseDC(NULL, hdc);
+ }
+}
+#else
+static void CorrectGamma(const FxU16 aGammaRamp[3][256])
+{
+ //TODO?
+ //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);
+ //LOG("SDL_SetGammaRamp returned %d\r\n", res);
+}
+#endif
+
+FX_ENTRY void FX_CALL
+grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+ LOG("grLoadGammaTable\r\n");
+ if (!fullscreen)
+ return;
+ FxU16 aGammaRamp[3][256];
+ for (int i = 0; i < 256; i++)
+ {
+ aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
+ aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
+ aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
+ }
+ CorrectGamma(aGammaRamp);
+ //MySleep(1000); //workaround for Mupen64
+}
+
+FX_ENTRY void FX_CALL
+grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+ return;
+ //TODO?
+ /*
+ LOG("grGetGammaTableExt()\r\n");
+ FxU16 aGammaRamp[3][256];
+#ifdef _WIN32
+ HDC hdc = GetDC(NULL);
+ if (hdc == NULL)
+ return;
+ if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
+ {
+ ReleaseDC(NULL, hdc);
+#else
+ if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)
+ {
+#endif
+ for (int i = 0; i < 256; i++)
+ {
+ red[i] = aGammaRamp[0][i] >> 8;
+ green[i] = aGammaRamp[1][i] >> 8;
+ blue[i] = aGammaRamp[2][i] >> 8;
+ }
+ }
+ */
+}
+
+FX_ENTRY void FX_CALL
+guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )
+{
+ LOG("guGammaCorrectionRGB()\r\n");
+ if (!fullscreen)
+ return;
+ FxU16 aGammaRamp[3][256];
+ for (int i = 0; i < 256; i++)
+ {
+ aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ }
+ CorrectGamma(aGammaRamp);
+}
+
+FX_ENTRY void FX_CALL
+grDitherMode( GrDitherMode_t mode )
+{
+ display_warning("grDitherMode");
+}
+
+void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode)
+{
+ display_warning("grChromaRangeExt");
+}
+
+void grChromaRangeModeExt(GrChromakeyMode_t mode)
+{
+ display_warning("grChromaRangeModeExt");
+}
+
+void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode)
+{
+ display_warning("grTexChromaRangeExt");
+}
+
+void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode)
+{
+ display_warning("grTexChromaRangeModeExt");
+}
+
+// VP debug
+#ifdef VPDEBUG
+int dumping = 0;
+static int tl_i;
+static int tl[10240];
+
+void dump_start()
+{
+ static int init;
+ if (!init) {
+ init = 1;
+ ilInit();
+ ilEnable(IL_FILE_OVERWRITE);
+ }
+ dumping = 1;
+ tl_i = 0;
+}
+
+void dump_stop()
+{
+ if (!dumping) return;
+
+ int i, j;
+ for (i=0; i>8;
+ ( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff;
+ }
+ }
+ ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer);
+ ilSaveImage("dump/framedepth.png");
+
+ for (i=0; i
+#else // _WIN32
+#include
+#endif // _WIN32
+#include "glide.h"
+#include "main.h"
+#include
+
+/* Napalm extensions to GrTextureFormat_t */
+#define GR_TEXFMT_ARGB_CMP_FXT1 0x11
+#define GR_TEXFMT_ARGB_8888 0x12
+#define GR_TEXFMT_YUYV_422 0x13
+#define GR_TEXFMT_UYVY_422 0x14
+#define GR_TEXFMT_AYUV_444 0x15
+#define GR_TEXFMT_ARGB_CMP_DXT1 0x16
+#define GR_TEXFMT_ARGB_CMP_DXT2 0x17
+#define GR_TEXFMT_ARGB_CMP_DXT3 0x18
+#define GR_TEXFMT_ARGB_CMP_DXT4 0x19
+#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A
+#define GR_TEXTFMT_RGB_888 0xFF
+
+int TMU_SIZE = 8*2048*2048;
+static unsigned char* texture = NULL;
+
+int packed_pixels_support = -1;
+int ati_sucks = -1;
+float largest_supported_anisotropy = 1.0f;
+
+#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#endif
+
+int tex0_width, tex0_height, tex1_width, tex1_height;
+float lambda;
+
+static int min_filter0, mag_filter0, wrap_s0, wrap_t0;
+static int min_filter1, mag_filter1, wrap_s1, wrap_t1;
+
+unsigned char *filter(unsigned char *source, int width, int height, int *width2, int *height2);
+
+typedef struct _texlist
+{
+ unsigned int id;
+ struct _texlist *next;
+} texlist;
+
+static int nbTex = 0;
+static texlist *list = NULL;
+
+#ifdef _WIN32
+extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
+extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
+#endif
+void remove_tex(unsigned int idmin, unsigned int idmax)
+{
+ unsigned int *t;
+ int n = 0;
+ texlist *aux = list;
+ int sz = nbTex;
+ if (aux == NULL) return;
+ t = (unsigned int*)malloc(sz * sizeof(int));
+ while (aux && aux->id >= idmin && aux->id < idmax)
+ {
+ if (n >= sz)
+ t = (unsigned int *) realloc(t, ++sz*sizeof(int));
+ t[n++] = aux->id;
+ aux = aux->next;
+ free(list);
+ list = aux;
+ nbTex--;
+ }
+ while (aux != NULL && aux->next != NULL)
+ {
+ if (aux->next->id >= idmin && aux->next->id < idmax)
+ {
+ texlist *aux2 = aux->next->next;
+ if (n >= sz)
+ t = (unsigned int *) realloc(t, ++sz*sizeof(int));
+ t[n++] = aux->next->id;
+ free(aux->next);
+ aux->next = aux2;
+ nbTex--;
+ }
+ aux = aux->next;
+ }
+ glDeleteTextures(n, t);
+ free(t);
+ //printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax);
+}
+
+
+void add_tex(unsigned int id)
+{
+ texlist *aux = list;
+ texlist *aux2;
+ //printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id);
+ if (list == NULL || id < list->id)
+ {
+ nbTex++;
+ list = (texlist*)malloc(sizeof(texlist));
+ list->next = aux;
+ list->id = id;
+ return;
+ }
+ while (aux->next != NULL && aux->next->id < id) aux = aux->next;
+ // ZIGGY added this test so that add_tex now accept re-adding an existing texture
+ if (aux->next != NULL && aux->next->id == id) return;
+ nbTex++;
+ aux2 = aux->next;
+ aux->next = (texlist*)malloc(sizeof(texlist));
+ aux->next->id = id;
+ aux->next->next = aux2;
+}
+
+void init_textures()
+{
+ tex0_width = tex0_height = tex1_width = tex1_height = 2;
+ // ZIGGY because remove_tex isn't called (Pj64 doesn't like it), it's better
+ // to leave these so that they'll be reused (otherwise we have a memory leak)
+ // list = NULL;
+ // nbTex = 0;
+
+ if (!texture) texture = (unsigned char*)malloc(2048*2048*4);
+}
+
+void free_textures()
+{
+#ifndef WIN32
+ // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
+ remove_tex(0x00000000, 0xFFFFFFFF);
+#endif
+ if (texture != NULL) {
+ free(texture);
+ texture = NULL;
+ }
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMinAddress( GrChipID_t tmu )
+{
+ LOG("grTexMinAddress(%d)\r\n", tmu);
+ if (UMAmode)
+ return 0;
+ else
+ return tmu*TMU_SIZE;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMaxAddress( GrChipID_t tmu )
+{
+ LOG("grTexMaxAddress(%d)\r\n", tmu);
+ if (UMAmode)
+ return TMU_SIZE*2 - 1;
+ else
+ return tmu*TMU_SIZE + TMU_SIZE - 1;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexTextureMemRequired( FxU32 evenOdd,
+ GrTexInfo *info )
+{
+ int width, height;
+ LOG("grTextureMemRequired(%d)\r\n", evenOdd);
+ if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexTextureMemRequired : loading more than one LOD");
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ height = 1 << info->largeLodLog2;
+ width = height >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ width = 1 << info->largeLodLog2;
+ height = width >> info->aspectRatioLog2;
+ }
+
+ switch(info->format)
+ {
+ case GR_TEXFMT_ALPHA_8:
+ case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+ case GR_TEXFMT_ALPHA_INTENSITY_44:
+ return width*height;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ case GR_TEXFMT_ARGB_4444:
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ case GR_TEXFMT_RGB_565:
+ return (width*height)<<1;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ return (width*height)<<2;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+ return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+ case GR_TEXFMT_ARGB_CMP_DXT3:
+ return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+ default:
+ display_warning("grTexTextureMemRequired : unknown texture format: %x", info->format);
+ }
+ return 0;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexCalcMemRequired(
+ GrLOD_t lodmin, GrLOD_t lodmax,
+ GrAspectRatio_t aspect, GrTextureFormat_t fmt)
+{
+ int width, height;
+ LOG("grTexCalcMemRequired(%d, %d, %d, %d)\r\n", lodmin, lodmax, aspect, fmt);
+ if (lodmax != lodmin) display_warning("grTexCalcMemRequired : loading more than one LOD");
+
+ if (aspect < 0)
+ {
+ height = 1 << lodmax;
+ width = height >> -aspect;
+ }
+ else
+ {
+ width = 1 << lodmax;
+ height = width >> aspect;
+ }
+
+ switch(fmt)
+ {
+ case GR_TEXFMT_ALPHA_8:
+ case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+ case GR_TEXFMT_ALPHA_INTENSITY_44:
+ return width*height;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ case GR_TEXFMT_ARGB_4444:
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ case GR_TEXFMT_RGB_565:
+ return (width*height)<<1;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ return (width*height)<<2;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+ return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+ case GR_TEXFMT_ARGB_CMP_DXT3:
+ return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+ default:
+ display_warning("grTexTextureMemRequired : unknown texture format: %x", fmt);
+ }
+ return 0;
+}
+
+int grTexFormatSize(int fmt)
+{
+ int factor = -1;
+ switch(fmt) {
+ case GR_TEXFMT_ALPHA_8:
+ case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+ factor = 1;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_44:
+ factor = 1;
+ break;
+ case GR_TEXFMT_RGB_565:
+ factor = 2;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ factor = 2;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ factor = 2;
+ break;
+ case GR_TEXFMT_ARGB_4444:
+ factor = 2;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ factor = 4;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+ factor = 8; // HACKALERT: factor holds block bytes
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
+ factor = 16; // HACKALERT: factor holds block bytes
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ factor = 16;
+ break;
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ factor = 8;
+ break;
+ default:
+ display_warning("grTexFormatSize : unknown texture format: %x", fmt);
+ }
+ return factor;
+}
+
+int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt)
+{
+ *gltexfmt = GL_RGBA;
+ *glpixfmt = GL_RGBA;
+ *glpackfmt = GL_UNSIGNED_BYTE;
+ return 0;
+/*
+ int factor = -1;
+ switch(fmt) {
+ case GR_TEXFMT_ALPHA_8:
+ factor = 1;
+ *gltexfmt = GL_INTENSITY8;
+ *glpixfmt = GL_LUMINANCE;
+ *glpackfmt = GL_UNSIGNED_BYTE;
+ break;
+ case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+ factor = 1;
+ *gltexfmt = GL_LUMINANCE8;
+ *glpixfmt = GL_LUMINANCE;
+ *glpackfmt = GL_UNSIGNED_BYTE;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_44:
+ break;
+ case GR_TEXFMT_RGB_565:
+ factor = 2;
+ *gltexfmt = GL_RGB;
+ *glpixfmt = GL_RGB;
+ *glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ if (ati_sucks > 0) return -1; // ATI sucks as usual (fixes slowdown on ATI)
+ factor = 2;
+ *gltexfmt = GL_RGB5_A1;
+ *glpixfmt = GL_BGRA;
+ *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ factor = 2;
+ *gltexfmt = GL_LUMINANCE8_ALPHA8;
+ *glpixfmt = GL_LUMINANCE_ALPHA;
+ *glpackfmt = GL_UNSIGNED_BYTE;
+ break;
+ case GR_TEXFMT_ARGB_4444:
+ factor = 2;
+ *gltexfmt = GL_RGBA4;
+ *glpixfmt = GL_BGRA;
+ *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ factor = 4;
+ *gltexfmt = GL_RGBA8;
+ *glpixfmt = GL_BGRA;
+ *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+ // HACKALERT: 3Dfx Glide uses GR_TEXFMT_ARGB_CMP_DXT1 for both opaque DXT1 and DXT1 with 1bit alpha.
+ // GlideHQ compiled with GLIDE64_DXTN option enabled, uses opaqe DXT1 only.
+ factor = 8; // HACKALERT: factor holds block bytes
+ *gltexfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // these variables aren't used
+ *glpixfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ *glpackfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT3:
+ factor = 16;
+ *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ factor = 16;
+ *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ factor = 8;
+ *gltexfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ *glpixfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ *glpackfmt = GL_COMPRESSED_RGBA_FXT1_3DFX; // XXX: what should we do about GL_COMPRESSED_RGB_FXT1_3DFX?
+ break;
+ default:
+ display_warning("grTexFormat2GLPackedFmt : unknown texture format: %x", fmt);
+ }
+ return factor;
+*/
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadMipMap( GrChipID_t tmu,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info )
+{
+ int width, height, i, j;
+ int factor;
+ int glformat = 0;
+ int gltexfmt, glpixfmt, glpackfmt;
+ LOG("grTexDownloadMipMap(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
+ if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexDownloadMipMap : loading more than one LOD");
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ height = 1 << info->largeLodLog2;
+ width = height >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ width = 1 << info->largeLodLog2;
+ height = width >> info->aspectRatioLog2;
+ }
+
+ if (!packed_pixels_support)
+ factor = -1;
+ else
+ factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
+
+ if (factor < 0) {
+
+ // VP fixed the texture conversions to be more accurate, also swapped
+ // the for i/j loops so that is is less likely to break the memory cache
+ register int n = 0, m = 0;
+ switch(info->format)
+ {
+ case GR_TEXFMT_ALPHA_8:
+ for (i=0; idata)[m];
+ texel |= (texel << 8);
+ texel |= (texel << 16);
+ ((unsigned int*)texture)[n] = texel;
+ m++;
+ n++;
+ }
+ }
+ factor = 1;
+ glformat = GL_RGBA;
+ break;
+ case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+ for (i=0; idata)[m];
+ texel |= (0xFF000000 | (texel << 16) | (texel << 8));
+ ((unsigned int*)texture)[n] = texel;
+ m++;
+ n++;
+ }
+ }
+ factor = 1;
+ glformat = GL_ALPHA;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_44:
+#if 1
+ for (i=0; idata)[m];
+#if 1
+ /* accurate conversion */
+ unsigned int texel_hi = (texel & 0x000000F0) << 20;
+ unsigned int texel_low = texel & 0x0000000F;
+ texel_low |= (texel_low << 4);
+ texel_hi |= ((texel_hi << 4) | (texel_low << 16) | (texel_low << 8) | texel_low);
+#else
+ unsigned int texel_hi = (texel & 0x000000F0) << 24;
+ unsigned int texel_low = (texel & 0x0000000F) << 4;
+ texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
+#endif
+ ((unsigned int*)texture)[n] = texel_hi;
+ m++;
+ n++;
+ }
+ }
+ factor = 1;
+ glformat = GL_LUMINANCE_ALPHA;
+#endif
+ break;
+ case GR_TEXFMT_RGB_565:
+ for (i=0; idata)[m];
+ unsigned int B = texel & 0x0000F800;
+ unsigned int G = texel & 0x000007E0;
+ unsigned int R = texel & 0x0000001F;
+#if 0
+ /* accurate conversion */
+ ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
+#else
+ ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
+#endif
+ m++;
+ n++;
+ }
+ }
+ factor = 2;
+ glformat = GL_RGB;
+ break;
+ case GR_TEXFMT_ARGB_1555:
+ for (i=0; idata)[m];
+ unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
+ unsigned int B = texel & 0x00007C00;
+ unsigned int G = texel & 0x000003E0;
+ unsigned int R = texel & 0x0000001F;
+#if 0
+ /* accurate conversion */
+ ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
+#else
+ ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
+#endif
+ m++;
+ n++;
+ }
+ }
+ factor = 2;
+ glformat = GL_RGBA;
+ break;
+ case GR_TEXFMT_ALPHA_INTENSITY_88:
+ for (i=0; idata)[m];
+ unsigned int I = (unsigned int)(AI & 0x000000FF);
+ ((unsigned int*)texture)[n] = (AI << 16) | (I << 8) | I;
+ m++;
+ n++;
+ }
+ }
+ factor = 2;
+ glformat = GL_LUMINANCE_ALPHA;
+ break;
+ case GR_TEXFMT_ARGB_4444:
+
+ for (i=0; idata)[m];
+ unsigned int A = texel & 0x0000F000;
+ unsigned int B = texel & 0x00000F00;
+ unsigned int G = texel & 0x000000F0;
+ unsigned int R = texel & 0x0000000F;
+#if 0
+ /* accurate conversion */
+ ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
+#else
+ ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
+#endif
+ m++;
+ n++;
+ }
+ }
+ factor = 2;
+ glformat = GL_RGBA;
+ break;
+ case GR_TEXFMT_ARGB_8888:
+ for (i=0; idata)[m];
+ unsigned int A = texel & 0xFF000000;
+ unsigned int B = texel & 0x00FF0000;
+ unsigned int G = texel & 0x0000FF00;
+ unsigned int R = texel & 0x000000FF;
+ ((unsigned int*)texture)[n] = A | (R << 16) | G | (B >> 16);
+ m++;
+ n++;
+ }
+ }
+ factor = 4;
+ glformat = GL_RGBA;
+ break;
+/*
+ case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+ factor = 8; // HACKALERT: factor holds block bytes
+ glformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
+ factor = 16; // HACKALERT: factor holds block bytes
+ glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ factor = 16;
+ glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ factor = 8;
+ glformat = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ break;
+*/
+ default:
+ display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format);
+ factor = 0;
+ }
+ }
+
+ if (nbTextureUnits <= 2)
+ glActiveTexture(GL_TEXTURE1);
+ else
+ glActiveTexture(GL_TEXTURE2);
+
+ switch(info->format)
+ {
+ case GR_TEXFMT_ARGB_CMP_DXT1:
+ case GR_TEXFMT_ARGB_CMP_DXT3:
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ remove_tex(startAddress+1, startAddress+1+((width*height*factor)>>4));
+ break;
+ default:
+ remove_tex(startAddress+1, startAddress+1+(width*height*factor));
+ }
+
+ add_tex(startAddress+1);
+ glBindTexture(GL_TEXTURE_2D, startAddress+1);
+
+ if (largest_supported_anisotropy > 1.0f)
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+/*
+ switch(info->format)
+ {
+ case GR_TEXFMT_ARGB_CMP_DXT1:
+ case GR_TEXFMT_ARGB_CMP_DXT3:
+ case GR_TEXFMT_ARGB_CMP_DXT5:
+ case GR_TEXFMT_ARGB_CMP_FXT1:
+ glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, (glformat ? glformat : gltexfmt), width, height, 0, (width*height*factor)>>4, info->data);
+ break;
+ default:
+ if (glformat) {
+ glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+ } else
+ glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data);
+ }
+*/
+
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+}
+
+int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info );
+
+FX_ENTRY void FX_CALL
+grTexSource( GrChipID_t tmu,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info )
+{
+ LOG("grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
+
+ if (tmu == GR_TMU1 || nbTextureUnits <= 2)
+ {
+ if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
+ glActiveTexture(GL_TEXTURE0);
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ tex0_height = 256;
+ tex0_width = tex0_height >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ tex0_width = 256;
+ tex0_height = tex0_width >> info->aspectRatioLog2;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, startAddress+1);
+#ifdef VPDEBUG
+ dump_tex(startAddress+1);
+#endif
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
+ }
+ else
+ {
+ glActiveTexture(GL_TEXTURE1);
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ tex1_height = 256;
+ tex1_width = tex1_height >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ tex1_width = 256;
+ tex1_height = tex1_width >> info->aspectRatioLog2;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, startAddress+1);
+#ifdef VPDEBUG
+ dump_tex(startAddress+1);
+#endif
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
+ }
+ if(!CheckTextureBufferFormat(tmu, startAddress+1, info))
+ {
+ if(tmu == 0 && blackandwhite1 != 0)
+ {
+ blackandwhite1 = 0;
+ need_to_compile = 1;
+ }
+ if(tmu == 1 && blackandwhite0 != 0)
+ {
+ blackandwhite0 = 0;
+ need_to_compile = 1;
+ }
+ }
+
+#if 0
+ extern int auxbuffer;
+ static int oldbuffer;
+ FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
+ if (auxbuffer == GR_BUFFER_AUXBUFFER && auxbuffer != oldbuffer)
+ grAuxBufferExt(auxbuffer);
+ oldbuffer = auxbuffer;
+#endif
+}
+
+FX_ENTRY void FX_CALL
+grTexDetailControl(
+ GrChipID_t tmu,
+ int lod_bias,
+ FxU8 detail_scale,
+ float detail_max
+ )
+{
+ LOG("grTexDetailControl(%d,%d,%d,%d)\r\n", tmu, lod_bias, detail_scale, detail_max);
+ if (lod_bias != 31 && detail_scale != 7)
+ {
+ if (!lod_bias && !detail_scale && !detail_max) return;
+ else
+ display_warning("grTexDetailControl : %d, %d, %f", lod_bias, detail_scale, detail_max);
+ }
+ lambda = detail_max;
+ if(lambda > 1.0f)
+ {
+ lambda = 1.0f - (255.0f - lambda);
+ }
+ if(lambda > 1.0f) display_warning("lambda:%f", lambda);
+
+ set_lambda();
+}
+
+FX_ENTRY void FX_CALL
+grTexLodBiasValue(GrChipID_t tmu, float bias )
+{
+ LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
+}
+
+FX_ENTRY void FX_CALL
+grTexFilterMode(
+ GrChipID_t tmu,
+ GrTextureFilterMode_t minfilter_mode,
+ GrTextureFilterMode_t magfilter_mode
+ )
+{
+ LOG("grTexFilterMode(%d,%d,%d)\r\n", tmu, minfilter_mode, magfilter_mode);
+ if (tmu == GR_TMU1 || nbTextureUnits <= 2)
+ {
+ if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
+ if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter0 = GL_NEAREST;
+ else min_filter0 = GL_LINEAR;
+
+ if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter0 = GL_NEAREST;
+ else mag_filter0 = GL_LINEAR;
+
+ glActiveTexture(GL_TEXTURE0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0);
+ }
+ else
+ {
+ if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter1 = GL_NEAREST;
+ else min_filter1 = GL_LINEAR;
+
+ if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter1 = GL_NEAREST;
+ else mag_filter1 = GL_LINEAR;
+
+ glActiveTexture(GL_TEXTURE1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grTexClampMode(
+ GrChipID_t tmu,
+ GrTextureClampMode_t s_clampmode,
+ GrTextureClampMode_t t_clampmode
+ )
+{
+ LOG("grTexClampMode(%d, %d, %d)\r\n", tmu, s_clampmode, t_clampmode);
+ if (tmu == GR_TMU1 || nbTextureUnits <= 2)
+ {
+ if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
+ switch(s_clampmode)
+ {
+ case GR_TEXTURECLAMP_WRAP:
+ wrap_s0 = GL_REPEAT;
+ break;
+ case GR_TEXTURECLAMP_CLAMP:
+ wrap_s0 = GL_CLAMP_TO_EDGE;
+ break;
+ case GR_TEXTURECLAMP_MIRROR_EXT:
+ wrap_s0 = GL_MIRRORED_REPEAT;
+ break;
+ default:
+ display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
+ }
+ switch(t_clampmode)
+ {
+ case GR_TEXTURECLAMP_WRAP:
+ wrap_t0 = GL_REPEAT;
+ break;
+ case GR_TEXTURECLAMP_CLAMP:
+ wrap_t0 = GL_CLAMP_TO_EDGE;
+ break;
+ case GR_TEXTURECLAMP_MIRROR_EXT:
+ wrap_t0 = GL_MIRRORED_REPEAT;
+ break;
+ default:
+ display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+ }
+ glActiveTexture(GL_TEXTURE0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0);
+ }
+ else
+ {
+ switch(s_clampmode)
+ {
+ case GR_TEXTURECLAMP_WRAP:
+ wrap_s1 = GL_REPEAT;
+ break;
+ case GR_TEXTURECLAMP_CLAMP:
+ wrap_s1 = GL_CLAMP_TO_EDGE;
+ break;
+ case GR_TEXTURECLAMP_MIRROR_EXT:
+ wrap_s1 = GL_MIRRORED_REPEAT;
+ break;
+ default:
+ display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode);
+ }
+ switch(t_clampmode)
+ {
+ case GR_TEXTURECLAMP_WRAP:
+ wrap_t1 = GL_REPEAT;
+ break;
+ case GR_TEXTURECLAMP_CLAMP:
+ wrap_t1 = GL_CLAMP_TO_EDGE;
+ break;
+ case GR_TEXTURECLAMP_MIRROR_EXT:
+ wrap_t1 = GL_MIRRORED_REPEAT;
+ break;
+ default:
+ display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+ }
+ glActiveTexture(GL_TEXTURE1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
+ }
+}
diff --git a/Source/Glitch64/combiner.cpp b/Source/Glitch64/OGLcombiner.cpp
similarity index 100%
rename from Source/Glitch64/combiner.cpp
rename to Source/Glitch64/OGLcombiner.cpp
diff --git a/Source/Glitch64/geometry.cpp b/Source/Glitch64/OGLgeometry.cpp
similarity index 100%
rename from Source/Glitch64/geometry.cpp
rename to Source/Glitch64/OGLgeometry.cpp
diff --git a/Source/Glitch64/glitchmain.cpp b/Source/Glitch64/OGLglitchmain.cpp
similarity index 100%
rename from Source/Glitch64/glitchmain.cpp
rename to Source/Glitch64/OGLglitchmain.cpp
diff --git a/Source/Glitch64/textures.cpp b/Source/Glitch64/OGLtextures.cpp
similarity index 100%
rename from Source/Glitch64/textures.cpp
rename to Source/Glitch64/OGLtextures.cpp