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