diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt
index dd9053bc..ed128745 100644
--- a/neo/CMakeLists.txt
+++ b/neo/CMakeLists.txt
@@ -631,6 +631,7 @@ if (APPLE)
)
set(src_sys_core
+ sys/glimp_ati_fragment_shader.cpp
sys/posix/posix_input.cpp
sys/osx/PickMonitor.cpp
sys/osx/PreferencesDialog.cpp
diff --git a/neo/sys/glimp_ati_fragment_shader.cpp b/neo/sys/glimp_ati_fragment_shader.cpp
new file mode 100644
index 00000000..c57cf966
--- /dev/null
+++ b/neo/sys/glimp_ati_fragment_shader.cpp
@@ -0,0 +1,570 @@
+/*
+===========================================================================
+
+Doom 3 GPL Source Code
+Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
+
+This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
+
+Doom 3 Source Code 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 3 of the License, or
+(at your option) any later version.
+
+Doom 3 Source Code 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 Doom 3 Source Code. If not, see .
+
+In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
+
+If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
+
+===========================================================================
+*/
+
+#include "sys/platform.h"
+#include "framework/Common.h"
+
+#include "sys/glimp_ati_fragment_shader.h"
+
+static GLuint sGeneratingProgram = 0;
+static int sCurrentPass;
+static char sConstString[4096];
+static char sPassString[2][4096];
+static int sOpUsed;
+static int sConstUsed;
+static int sConst[8];
+static GLfloat sConstVal[8][4];
+
+static void _endPass (void) {
+ if (!sOpUsed) return;
+ sOpUsed = 0;
+ sCurrentPass ++;
+}
+
+static GLuint glGenFragmentShadersATI (GLuint ID) {
+ qglGenProgramsARB(1, &ID);
+ return ID;
+}
+
+static void glBindFragmentShaderATI (GLuint ID) {
+ qglBindProgramARB(GL_TEXT_FRAGMENT_SHADER_ATI, ID);
+}
+
+static void glDeleteFragmentShaderATI (GLuint ID) {
+// qglDeleteProgramsARB(1, &ID);
+}
+
+static void glBeginFragmentShaderATI (void) {
+ int i;
+
+ sConstString[0] = 0;
+ for (i = 0; i < 8; i ++)
+ sConst[i] = 0;
+
+ sOpUsed = 0;
+ sPassString[0][0] = 0;
+ sPassString[1][0] = 0;
+
+ sCurrentPass = 0;
+ sGeneratingProgram = 1;
+}
+
+static void glEndFragmentShaderATI (void) {
+ GLint errPos;
+ int i;
+ char fragString[4096];
+
+ sGeneratingProgram = 0;
+
+ // header
+ strcpy(fragString, "!!ATIfs1.0\n");
+
+ // constants
+ if (sConstString[0] || sConstUsed) {
+ strcat (fragString, "StartConstants;\n");
+ if (sConstUsed) {
+ for (i = 0; i < 8; i ++) {
+ if (sConst[i] == 1) {
+ char str[128];
+ sprintf (str, " CONSTANT c%d = program.env[%d];\n", i, i);
+ strcat (fragString, str);
+ }
+ }
+ }
+ if (sConstString[0]) {
+ strcat (fragString, sConstString);
+ }
+ strcat (fragString, "EndConstants;\n\n");
+ }
+
+ if (sCurrentPass == 0) {
+ strcat(fragString, "StartOutputPass;\n");
+ strcat(fragString, sPassString[0]);
+ strcat(fragString, "EndPass;\n");
+ } else {
+ strcat(fragString, "StartPrelimPass;\n");
+ strcat(fragString, sPassString[0]);
+ strcat(fragString, "EndPass;\n\n");
+
+ strcat(fragString, "StartOutputPass;\n");
+ strcat(fragString, sPassString[1]);
+ strcat(fragString, "EndPass;\n");
+ }
+
+ qglProgramStringARB(GL_TEXT_FRAGMENT_SHADER_ATI, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragString), fragString);
+ qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
+ if(errPos != -1) {
+ const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+ common->Warning("WARNING: glError at %d:%s when compiling atiFragmentShader %s", errPos, errString, fragString);
+ }
+}
+
+
+static void glSetFragmentShaderConstantATI (GLuint num, const GLfloat *val) {
+ int constNum = num-GL_CON_0_ATI;
+ if (sGeneratingProgram) {
+ char str[128];
+ sprintf (str, " CONSTANT c%d = { %f, %f, %f, %f };\n", constNum, val[0], val[1], val[2], val[3]);
+ strcat (sConstString, str);
+ sConst[constNum] = 2;
+ }
+ else {
+ // According to Duane, frequent setting of fragment shader constants, even if they contain
+ // the same value, will cause a performance hit.
+ // According to Chris Bentley at ATI, this performance hit appears if you are using
+ // many different fragment shaders in each scene.
+ // So, we cache those values and only set the constants if they are different.
+ if (memcmp (val, sConstVal[constNum], sizeof(GLfloat)*8*4) != 0)
+ {
+ qglProgramEnvParameter4fvARB (GL_TEXT_FRAGMENT_SHADER_ATI, num-GL_CON_0_ATI, val);
+ memcpy (sConstVal[constNum], val, sizeof(GLfloat)*8*4);
+ }
+ }
+}
+
+static char *makeArgStr(GLuint arg) {
+ // Since we return "str", it needs to be static to ensure that it retains
+ // its value outside this routine.
+ static char str[128];
+
+ strcpy (str, "");
+
+ if ( arg >= GL_REG_0_ATI && arg <= GL_REG_5_ATI ) {
+ sprintf(str, "r%d", arg - GL_REG_0_ATI);
+ } else if(arg >= GL_CON_0_ATI && arg <= GL_CON_7_ATI) {
+ if(!sConst[arg - GL_CON_0_ATI]) {
+ sConstUsed = 1;
+ sConst[arg - GL_CON_0_ATI] = 1;
+ }
+ sprintf(str, "c%d", arg - GL_CON_0_ATI);
+ } else if( arg >= GL_TEXTURE0_ARB && arg <= GL_TEXTURE31_ARB ) {
+ sprintf(str, "t%d", arg - GL_TEXTURE0_ARB);
+ } else if( arg == GL_PRIMARY_COLOR_ARB ) {
+ strcpy(str, "color0");
+ } else if(arg == GL_SECONDARY_INTERPOLATOR_ATI) {
+ strcpy(str, "color1");
+ } else if (arg == GL_ZERO) {
+ strcpy(str, "0");
+ } else if (arg == GL_ONE) {
+ strcpy(str, "1");
+ } else {
+ common->Warning("makeArgStr: bad arg value\n");
+ }
+ return str;
+}
+
+static void glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle) {
+ char str[128] = "\0";
+ _endPass();
+
+ switch(swizzle) {
+ case GL_SWIZZLE_STR_ATI:
+ sprintf(str, " PassTexCoord r%d, %s.str;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
+ break;
+ case GL_SWIZZLE_STQ_ATI:
+ sprintf(str, " PassTexCoord r%d, %s.stq;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
+ break;
+ case GL_SWIZZLE_STR_DR_ATI:
+ sprintf(str, " PassTexCoord r%d, %s.str_dr;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
+ break;
+ case GL_SWIZZLE_STQ_DQ_ATI:
+ sprintf(str, " PassTexCoord r%d, %s.stq_dq;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
+ break;
+ default:
+ common->Warning("glPassTexCoordATI invalid swizzle;");
+ break;
+ }
+ strcat(sPassString[sCurrentPass], str);
+}
+
+void glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle) {
+ char str[128] = "\0";
+ _endPass();
+
+ switch(swizzle) {
+ case GL_SWIZZLE_STR_ATI:
+ sprintf(str, " SampleMap r%d, %s.str;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
+ break;
+ case GL_SWIZZLE_STQ_ATI:
+ sprintf(str, " SampleMap r%d, %s.stq;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
+ break;
+ case GL_SWIZZLE_STR_DR_ATI:
+ sprintf(str, " SampleMap r%d, %s.str_dr;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
+ break;
+ case GL_SWIZZLE_STQ_DQ_ATI:
+ sprintf(str, " SampleMap r%d, %s.stq_dq;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
+ break;
+ default:
+ common->Warning("glSampleMapATI invalid swizzle;");
+ break;
+ }
+ strcat(sPassString[sCurrentPass], str);
+}
+
+static char *makeMaskStr(GLuint mask) {
+ // Since we return "str", it needs to be static to ensure that it retains
+ // its value outside this routine.
+ static char str[128];
+
+ strcpy (str, "");
+
+ switch (mask) {
+ case GL_NONE:
+ str[0] = '\0';
+ break;
+ case GL_RGBA:
+ strcpy(str, ".rgba");
+ break;
+ case GL_RGB:
+ strcpy(str, ".rgb");
+ break;
+ case GL_RED:
+ strcpy(str, ".r");
+ break;
+ case GL_GREEN:
+ strcpy(str, ".g");
+ break;
+ case GL_BLUE:
+ strcpy(str, ".b");
+ break;
+ case GL_ALPHA:
+ strcpy(str, ".a");
+ break;
+ default:
+ strcpy(str, ".");
+ if( mask & GL_RED_BIT_ATI )
+ strcat(str, "r");
+ if( mask & GL_GREEN_BIT_ATI )
+ strcat(str, "g");
+ if( mask & GL_BLUE_BIT_ATI )
+ strcat(str, "b");
+ break;
+ }
+
+ return str;
+}
+
+static char *makeDstModStr(GLuint mod) {
+ // Since we return "str", it needs to be static to ensure that it retains
+ // its value outside this routine.
+ static char str[128];
+
+ strcpy (str, "");
+
+ if( mod == GL_NONE) {
+ str[0] = '\0';
+ return str;
+ }
+ if( mod & GL_2X_BIT_ATI) {
+ strcat(str, ".2x");
+ }
+
+ if( mod & GL_4X_BIT_ATI) {
+ strcat(str, ".4x");
+ }
+
+ if( mod & GL_8X_BIT_ATI) {
+ strcat(str, ".8x");
+ }
+
+ if( mod & GL_SATURATE_BIT_ATI) {
+ strcat(str, ".sat");
+ }
+
+ if( mod & GL_HALF_BIT_ATI) {
+ strcat(str, ".half");
+ }
+
+ if( mod & GL_QUARTER_BIT_ATI) {
+ strcat(str, ".quarter");
+ }
+
+ if( mod & GL_EIGHTH_BIT_ATI) {
+ strcat(str, ".eighth");
+ }
+
+ return str;
+}
+
+static char *makeArgModStr(GLuint mod) {
+ // Since we return "str", it needs to be static to ensure that it retains
+ // its value outside this routine.
+ static char str[128];
+
+ strcpy (str, "");
+
+ if( mod == GL_NONE) {
+ str[0] = '\0';
+ return str;
+ }
+ if( mod & GL_NEGATE_BIT_ATI) {
+ strcat(str, ".neg");
+ }
+
+ if( mod & GL_2X_BIT_ATI) {
+ strcat(str, ".2x");
+ }
+
+ if( mod & GL_BIAS_BIT_ATI) {
+ strcat(str, ".bias");
+ }
+
+ if( mod & GL_COMP_BIT_ATI) {
+ strcat(str, ".comp");
+ }
+
+ return str;
+}
+
+static void glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
+ char str[128] = "\0";
+
+ sOpUsed = 1;
+
+ switch(op) {
+ // Unary operators
+ case GL_MOV_ATI:
+ sprintf(str, " MOV r%d", dst - GL_REG_0_ATI);
+ break;
+ default:
+ common->Warning("glColorFragmentOp1ATI invalid op;\n");
+ break;
+ }
+ if(dstMask != GL_NONE) {
+ strcat(str, makeMaskStr(dstMask));
+ }
+ else {
+ strcat(str, ".rgb" );
+ }
+
+ if(dstMod != GL_NONE) {
+ strcat(str, makeDstModStr(dstMod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg1));
+ if(arg1Rep != GL_NONE) {
+ strcat(str, makeMaskStr(arg1Rep));
+ }
+ if(arg1Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg1Mod));
+ }
+ strcat(str, ";\n");
+
+ strcat(sPassString[sCurrentPass], str);
+}
+
+static void glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
+ char str[128] = "\0";
+
+ if (!sOpUsed)
+ sprintf(str,"\n");
+ sOpUsed = 1;
+
+ switch(op) {
+ // Unary operators - fall back to Op1 routine.
+ case GL_MOV_ATI:
+ glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod);
+ return;
+
+ // Binary operators
+ case GL_ADD_ATI:
+ sprintf(str, " ADD r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_MUL_ATI:
+ sprintf(str, " MUL r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_SUB_ATI:
+ sprintf(str, " SUB r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_DOT3_ATI:
+ sprintf(str, " DOT3 r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_DOT4_ATI:
+ sprintf(str, " DOT4 r%d", dst - GL_REG_0_ATI);
+ break;
+ default:
+ common->Warning("glColorFragmentOp2ATI invalid op;");
+ break;
+ }
+ if(dstMask != GL_NONE) {
+ strcat(str, makeMaskStr(dstMask));
+ }
+ else {
+ strcat(str, ".rgb" );
+ }
+ if(dstMod != GL_NONE) {
+ strcat(str, makeDstModStr(dstMod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg1));
+// if(arg1Rep != GL_NONE)
+ strcat(str, makeMaskStr(arg1Rep));
+ if(arg1Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg1Mod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg2));
+// if(arg2Rep != GL_NONE)
+ strcat(str, makeMaskStr(arg2Rep));
+ if(arg2Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg2Mod));
+ }
+ strcat(str, ";\n");
+
+ strcat(sPassString[sCurrentPass], str);
+}
+
+static void glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
+ char str[128] = "\0";
+
+ sOpUsed = 1;
+
+ switch(op) {
+ // Unary operators - fall back to Op1 routine.
+ case GL_MOV_ATI:
+ glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod);
+ return;
+
+ // Binary operators - fall back to Op2 routine.
+ case GL_ADD_ATI:
+ case GL_MUL_ATI:
+ case GL_SUB_ATI:
+ case GL_DOT3_ATI:
+ case GL_DOT4_ATI:
+ glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);
+ break;
+
+ // Ternary operators
+ case GL_MAD_ATI:
+ sprintf(str, " MAD r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_LERP_ATI:
+ sprintf(str, " LERP r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_CND_ATI:
+ sprintf(str, " CND r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_CND0_ATI:
+ sprintf(str, " CND0 r%d", dst - GL_REG_0_ATI);
+ break;
+ case GL_DOT2_ADD_ATI:
+ sprintf(str, " DOT2ADD r%d", dst - GL_REG_0_ATI);
+ break;
+ default:
+ common->Warning("glColorFragmentOp3ATI invalid op;");
+ break;
+ }
+
+ if(dstMask != GL_NONE) {
+ strcat(str, makeMaskStr(dstMask));
+ }
+ else {
+ strcat(str, ".rgb" );
+ }
+ if(dstMod != GL_NONE) {
+ strcat(str, makeDstModStr(dstMod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg1));
+ if(arg1Rep != GL_NONE) {
+ strcat(str, makeMaskStr(arg1Rep));
+ }
+ if(arg1Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg1Mod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg2));
+ if(arg2Rep != GL_NONE) {
+ strcat(str, makeMaskStr(arg2Rep));
+ }
+ if(arg2Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg2Mod));
+ }
+ strcat(str, ", ");
+
+ strcat(str, makeArgStr(arg3));
+ if(arg3Rep != GL_NONE) {
+ strcat(str, makeMaskStr(arg3Rep));
+ }
+ if(arg3Mod != GL_NONE) {
+ strcat(str, makeArgModStr(arg3Mod));
+ }
+ strcat(str, ";\n");
+
+ strcat(sPassString[sCurrentPass], str);
+}
+
+static void glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
+ glColorFragmentOp1ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod);
+}
+
+static void glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
+ glColorFragmentOp2ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);
+}
+
+static void glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
+ glColorFragmentOp3ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
+}
+
+GLExtension_t GLimp_ExtensionPointer_ATI_fragment_shader(const char *name) {
+ if (!strcmp(name, "glGenFragmentShadersATI"))
+ return (GLExtension_t)glGenFragmentShadersATI;
+ if (!strcmp(name, "glBindFragmentShaderATI"))
+ return (GLExtension_t)glBindFragmentShaderATI;
+ if (!strcmp(name, "glDeleteFragmentShaderATI"))
+ return (GLExtension_t)glDeleteFragmentShaderATI;
+ if (!strcmp(name, "glBeginFragmentShaderATI"))
+ return (GLExtension_t)glBeginFragmentShaderATI;
+ if (!strcmp(name, "glEndFragmentShaderATI"))
+ return (GLExtension_t)glEndFragmentShaderATI;
+ if (!strcmp(name, "glPassTexCoordATI"))
+ return (GLExtension_t)glPassTexCoordATI;
+ if (!strcmp(name, "glSampleMapATI"))
+ return (GLExtension_t)glSampleMapATI;
+ if (!strcmp(name, "glColorFragmentOp1ATI"))
+ return (GLExtension_t)glColorFragmentOp1ATI;
+ if (!strcmp(name, "glColorFragmentOp2ATI"))
+ return (GLExtension_t)glColorFragmentOp2ATI;
+ if (!strcmp(name, "glColorFragmentOp3ATI"))
+ return (GLExtension_t)glColorFragmentOp3ATI;
+ if (!strcmp(name, "glAlphaFragmentOp1ATI"))
+ return (GLExtension_t)glAlphaFragmentOp1ATI;
+ if (!strcmp(name, "glAlphaFragmentOp2ATI"))
+ return (GLExtension_t)glAlphaFragmentOp2ATI;
+ if (!strcmp(name, "glAlphaFragmentOp3ATI"))
+ return (GLExtension_t)glAlphaFragmentOp3ATI;
+ if (!strcmp(name, "glSetFragmentShaderConstantATI"))
+ return (GLExtension_t)glSetFragmentShaderConstantATI;
+
+ return (GLExtension_t)NULL;
+}
diff --git a/neo/sys/glimp_ati_fragment_shader.h b/neo/sys/glimp_ati_fragment_shader.h
new file mode 100644
index 00000000..337592a3
--- /dev/null
+++ b/neo/sys/glimp_ati_fragment_shader.h
@@ -0,0 +1,36 @@
+/*
+===========================================================================
+
+Doom 3 GPL Source Code
+Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
+
+This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
+
+Doom 3 Source Code 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 3 of the License, or
+(at your option) any later version.
+
+Doom 3 Source Code 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 Doom 3 Source Code. If not, see .
+
+In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
+
+If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
+
+===========================================================================
+*/
+
+#ifndef __GLIMP_ATI_FRAGMENT_SHADER__
+#define __GLIMP_ATI_FRAGMENT_SHADER__
+
+#include "renderer/qgl.h"
+
+GLExtension_t GLimp_ExtensionPointer_ATI_fragment_shader(const char *name);
+
+#endif
diff --git a/neo/sys/osx/macosx_glimp.mm b/neo/sys/osx/macosx_glimp.mm
index 4b0c54fa..c77829b5 100644
--- a/neo/sys/osx/macosx_glimp.mm
+++ b/neo/sys/osx/macosx_glimp.mm
@@ -37,6 +37,7 @@ If you have questions concerning this license or the applicable additional terms
#import "sys/platform.h"
#import "framework/Licensee.h"
#import "renderer/tr_local.h"
+#import "sys/glimp_ati_fragment_shader.h"
#import "sys/osx/macosx_glimp.h"
#import "sys/osx/macosx_local.h"
#import "sys/osx/macosx_sys.h"
@@ -605,560 +606,14 @@ void GLimp_SetGamma(unsigned short red[256],
Sys_GetGammaTable(&glw_state.inGameTable);
}
-/*****************************************************************************/
-
-static GLuint sGeneratingProgram = 0;
-static int sCurrentPass;
-static char sConstString[4096];
-static char sPassString[2][4096];
-static int sOpUsed;
-static int sConstUsed;
-static int sConst[8];
-static GLfloat sConstVal[8][4];
-
-static void _endPass (void) {
- if (!sOpUsed) return;
- sOpUsed = 0;
- sCurrentPass ++;
-}
-
-GLuint glGenFragmentShadersATI (GLuint ID) {
- qglGenProgramsARB(1, &ID);
- return ID;
-}
-
-void glBindFragmentShaderATI (GLuint ID) {
- qglBindProgramARB(GL_TEXT_FRAGMENT_SHADER_ATI, ID);
-}
-
-void glDeleteFragmentShaderATI (GLuint ID) {
-// qglDeleteProgramsARB(1, &ID);
-}
-
-void glBeginFragmentShaderATI (void) {
- int i;
-
- sConstString[0] = 0;
- for (i = 0; i < 8; i ++)
- sConst[i] = 0;
-
- sOpUsed = 0;
- sPassString[0][0] = 0;
- sPassString[1][0] = 0;
-
- sCurrentPass = 0;
- sGeneratingProgram = 1;
-}
-
-void glEndFragmentShaderATI (void) {
- GLint errPos;
- int i;
- char fragString[4096];
-
- sGeneratingProgram = 0;
-
- // header
- strcpy(fragString, "!!ATIfs1.0\n");
-
- // constants
- if (sConstString[0] || sConstUsed) {
- strcat (fragString, "StartConstants;\n");
- if (sConstUsed) {
- for (i = 0; i < 8; i ++) {
- if (sConst[i] == 1) {
- char str[128];
- sprintf (str, " CONSTANT c%d = program.env[%d];\n", i, i);
- strcat (fragString, str);
- }
- }
- }
- if (sConstString[0]) {
- strcat (fragString, sConstString);
- }
- strcat (fragString, "EndConstants;\n\n");
- }
-
- if (sCurrentPass == 0) {
- strcat(fragString, "StartOutputPass;\n");
- strcat(fragString, sPassString[0]);
- strcat(fragString, "EndPass;\n");
- } else {
- strcat(fragString, "StartPrelimPass;\n");
- strcat(fragString, sPassString[0]);
- strcat(fragString, "EndPass;\n\n");
-
- strcat(fragString, "StartOutputPass;\n");
- strcat(fragString, sPassString[1]);
- strcat(fragString, "EndPass;\n");
- }
-
- qglProgramStringARB(GL_TEXT_FRAGMENT_SHADER_ATI, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragString), fragString);
- qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
- if(errPos != -1) {
- const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
- common->Warning("WARNING: glError at %d:%s when compiling atiFragmentShader %s", errPos, errString, fragString);
- }
-}
-
-
-void glSetFragmentShaderConstantATI (GLuint num, const GLfloat *val) {
- int constNum = num-GL_CON_0_ATI;
- if (sGeneratingProgram) {
- char str[128];
- sprintf (str, " CONSTANT c%d = { %f, %f, %f, %f };\n", constNum, val[0], val[1], val[2], val[3]);
- strcat (sConstString, str);
- sConst[constNum] = 2;
- }
- else {
- // According to Duane, frequent setting of fragment shader constants, even if they contain
- // the same value, will cause a performance hit.
- // According to Chris Bentley at ATI, this performance hit appears if you are using
- // many different fragment shaders in each scene.
- // So, we cache those values and only set the constants if they are different.
- if (memcmp (val, sConstVal[constNum], sizeof(GLfloat)*8*4) != 0)
- {
- qglProgramEnvParameter4fvARB (GL_TEXT_FRAGMENT_SHADER_ATI, num-GL_CON_0_ATI, val);
- memcpy (sConstVal[constNum], val, sizeof(GLfloat)*8*4);
- }
- }
-}
-
-char *makeArgStr(GLuint arg) {
- // Since we return "str", it needs to be static to ensure that it retains
- // its value outside this routine.
- static char str[128];
-
- strcpy (str, "");
-
- if ( arg >= GL_REG_0_ATI && arg <= GL_REG_5_ATI ) {
- sprintf(str, "r%d", arg - GL_REG_0_ATI);
- } else if(arg >= GL_CON_0_ATI && arg <= GL_CON_7_ATI) {
- if(!sConst[arg - GL_CON_0_ATI]) {
- sConstUsed = 1;
- sConst[arg - GL_CON_0_ATI] = 1;
- }
- sprintf(str, "c%d", arg - GL_CON_0_ATI);
- } else if( arg >= GL_TEXTURE0_ARB && arg <= GL_TEXTURE31_ARB ) {
- sprintf(str, "t%d", arg - GL_TEXTURE0_ARB);
- } else if( arg == GL_PRIMARY_COLOR_ARB ) {
- strcpy(str, "color0");
- } else if(arg == GL_SECONDARY_INTERPOLATOR_ATI) {
- strcpy(str, "color1");
- } else if (arg == GL_ZERO) {
- strcpy(str, "0");
- } else if (arg == GL_ONE) {
- strcpy(str, "1");
- } else {
- common->Warning("makeArgStr: bad arg value\n");
- }
- return str;
-}
-
-void glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle) {
- char str[128] = "\0";
- _endPass();
-
- switch(swizzle) {
- case GL_SWIZZLE_STR_ATI:
- sprintf(str, " PassTexCoord r%d, %s.str;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
- break;
- case GL_SWIZZLE_STQ_ATI:
- sprintf(str, " PassTexCoord r%d, %s.stq;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
- break;
- case GL_SWIZZLE_STR_DR_ATI:
- sprintf(str, " PassTexCoord r%d, %s.str_dr;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
- break;
- case GL_SWIZZLE_STQ_DQ_ATI:
- sprintf(str, " PassTexCoord r%d, %s.stq_dq;\n", dst - GL_REG_0_ATI, makeArgStr(coord));
- break;
- default:
- common->Warning("glPassTexCoordATI invalid swizzle;");
- break;
- }
- strcat(sPassString[sCurrentPass], str);
-}
-
-void glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle) {
- char str[128] = "\0";
- _endPass();
-
- switch(swizzle) {
- case GL_SWIZZLE_STR_ATI:
- sprintf(str, " SampleMap r%d, %s.str;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
- break;
- case GL_SWIZZLE_STQ_ATI:
- sprintf(str, " SampleMap r%d, %s.stq;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
- break;
- case GL_SWIZZLE_STR_DR_ATI:
- sprintf(str, " SampleMap r%d, %s.str_dr;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
- break;
- case GL_SWIZZLE_STQ_DQ_ATI:
- sprintf(str, " SampleMap r%d, %s.stq_dq;\n", dst - GL_REG_0_ATI, makeArgStr(interp));
- break;
- default:
- common->Warning("glSampleMapATI invalid swizzle;");
- break;
- }
- strcat(sPassString[sCurrentPass], str);
-}
-
-char *makeMaskStr(GLuint mask) {
- // Since we return "str", it needs to be static to ensure that it retains
- // its value outside this routine.
- static char str[128];
-
- strcpy (str, "");
-
- switch (mask) {
- case GL_NONE:
- str[0] = '\0';
- break;
- case GL_RGBA:
- strcpy(str, ".rgba");
- break;
- case GL_RGB:
- strcpy(str, ".rgb");
- break;
- case GL_RED:
- strcpy(str, ".r");
- break;
- case GL_GREEN:
- strcpy(str, ".g");
- break;
- case GL_BLUE:
- strcpy(str, ".b");
- break;
- case GL_ALPHA:
- strcpy(str, ".a");
- break;
- default:
- strcpy(str, ".");
- if( mask & GL_RED_BIT_ATI )
- strcat(str, "r");
- if( mask & GL_GREEN_BIT_ATI )
- strcat(str, "g");
- if( mask & GL_BLUE_BIT_ATI )
- strcat(str, "b");
- break;
- }
-
- return str;
-}
-
-char *makeDstModStr(GLuint mod) {
- // Since we return "str", it needs to be static to ensure that it retains
- // its value outside this routine.
- static char str[128];
-
- strcpy (str, "");
-
- if( mod == GL_NONE) {
- str[0] = '\0';
- return str;
- }
- if( mod & GL_2X_BIT_ATI) {
- strcat(str, ".2x");
- }
-
- if( mod & GL_4X_BIT_ATI) {
- strcat(str, ".4x");
- }
-
- if( mod & GL_8X_BIT_ATI) {
- strcat(str, ".8x");
- }
-
- if( mod & GL_SATURATE_BIT_ATI) {
- strcat(str, ".sat");
- }
-
- if( mod & GL_HALF_BIT_ATI) {
- strcat(str, ".half");
- }
-
- if( mod & GL_QUARTER_BIT_ATI) {
- strcat(str, ".quarter");
- }
-
- if( mod & GL_EIGHTH_BIT_ATI) {
- strcat(str, ".eighth");
- }
-
- return str;
-}
-
-char *makeArgModStr(GLuint mod) {
- // Since we return "str", it needs to be static to ensure that it retains
- // its value outside this routine.
- static char str[128];
-
- strcpy (str, "");
-
- if( mod == GL_NONE) {
- str[0] = '\0';
- return str;
- }
- if( mod & GL_NEGATE_BIT_ATI) {
- strcat(str, ".neg");
- }
-
- if( mod & GL_2X_BIT_ATI) {
- strcat(str, ".2x");
- }
-
- if( mod & GL_BIAS_BIT_ATI) {
- strcat(str, ".bias");
- }
-
- if( mod & GL_COMP_BIT_ATI) {
- strcat(str, ".comp");
- }
-
- return str;
-}
-
-void glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
- char str[128] = "\0";
-
- sOpUsed = 1;
-
- switch(op) {
- // Unary operators
- case GL_MOV_ATI:
- sprintf(str, " MOV r%d", dst - GL_REG_0_ATI);
- break;
- default:
- common->Warning("glColorFragmentOp1ATI invalid op;\n");
- break;
- }
- if(dstMask != GL_NONE) {
- strcat(str, makeMaskStr(dstMask));
- }
- else {
- strcat(str, ".rgb" );
- }
-
- if(dstMod != GL_NONE) {
- strcat(str, makeDstModStr(dstMod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg1));
- if(arg1Rep != GL_NONE) {
- strcat(str, makeMaskStr(arg1Rep));
- }
- if(arg1Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg1Mod));
- }
- strcat(str, ";\n");
-
- strcat(sPassString[sCurrentPass], str);
-}
-
-void glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
- char str[128] = "\0";
-
- if (!sOpUsed)
- sprintf(str,"\n");
- sOpUsed = 1;
-
- switch(op) {
- // Unary operators - fall back to Op1 routine.
- case GL_MOV_ATI:
- glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod);
- return;
-
- // Binary operators
- case GL_ADD_ATI:
- sprintf(str, " ADD r%d", dst - GL_REG_0_ATI);
- break;
- case GL_MUL_ATI:
- sprintf(str, " MUL r%d", dst - GL_REG_0_ATI);
- break;
- case GL_SUB_ATI:
- sprintf(str, " SUB r%d", dst - GL_REG_0_ATI);
- break;
- case GL_DOT3_ATI:
- sprintf(str, " DOT3 r%d", dst - GL_REG_0_ATI);
- break;
- case GL_DOT4_ATI:
- sprintf(str, " DOT4 r%d", dst - GL_REG_0_ATI);
- break;
- default:
- common->Warning("glColorFragmentOp2ATI invalid op;");
- break;
- }
- if(dstMask != GL_NONE) {
- strcat(str, makeMaskStr(dstMask));
- }
- else {
- strcat(str, ".rgb" );
- }
- if(dstMod != GL_NONE) {
- strcat(str, makeDstModStr(dstMod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg1));
-// if(arg1Rep != GL_NONE)
- strcat(str, makeMaskStr(arg1Rep));
- if(arg1Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg1Mod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg2));
-// if(arg2Rep != GL_NONE)
- strcat(str, makeMaskStr(arg2Rep));
- if(arg2Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg2Mod));
- }
- strcat(str, ";\n");
-
- strcat(sPassString[sCurrentPass], str);
-}
-
-void glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
- char str[128] = "\0";
-
- sOpUsed = 1;
-
- switch(op) {
- // Unary operators - fall back to Op1 routine.
- case GL_MOV_ATI:
- glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod);
- return;
-
- // Binary operators - fall back to Op2 routine.
- case GL_ADD_ATI:
- case GL_MUL_ATI:
- case GL_SUB_ATI:
- case GL_DOT3_ATI:
- case GL_DOT4_ATI:
- glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);
- break;
-
- // Ternary operators
- case GL_MAD_ATI:
- sprintf(str, " MAD r%d", dst - GL_REG_0_ATI);
- break;
- case GL_LERP_ATI:
- sprintf(str, " LERP r%d", dst - GL_REG_0_ATI);
- break;
- case GL_CND_ATI:
- sprintf(str, " CND r%d", dst - GL_REG_0_ATI);
- break;
- case GL_CND0_ATI:
- sprintf(str, " CND0 r%d", dst - GL_REG_0_ATI);
- break;
- case GL_DOT2_ADD_ATI:
- sprintf(str, " DOT2ADD r%d", dst - GL_REG_0_ATI);
- break;
- default:
- common->Warning("glColorFragmentOp3ATI invalid op;");
- break;
- }
-
- if(dstMask != GL_NONE) {
- strcat(str, makeMaskStr(dstMask));
- }
- else {
- strcat(str, ".rgb" );
- }
- if(dstMod != GL_NONE) {
- strcat(str, makeDstModStr(dstMod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg1));
- if(arg1Rep != GL_NONE) {
- strcat(str, makeMaskStr(arg1Rep));
- }
- if(arg1Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg1Mod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg2));
- if(arg2Rep != GL_NONE) {
- strcat(str, makeMaskStr(arg2Rep));
- }
- if(arg2Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg2Mod));
- }
- strcat(str, ", ");
-
- strcat(str, makeArgStr(arg3));
- if(arg3Rep != GL_NONE) {
- strcat(str, makeMaskStr(arg3Rep));
- }
- if(arg3Mod != GL_NONE) {
- strcat(str, makeArgModStr(arg3Mod));
- }
- strcat(str, ";\n");
-
- strcat(sPassString[sCurrentPass], str);
-}
-
-void glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) {
- glColorFragmentOp1ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod);
-}
-
-void glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) {
- glColorFragmentOp2ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod);
-}
-
-void glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) {
- glColorFragmentOp3ATI ( op, dst, GL_ALPHA, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod);
-}
-
GLExtension_t GLimp_ExtensionPointer(const char *name) {
NSSymbol symbol;
char *symbolName;
// special case for ATI_fragment_shader calls to map to ATI_text_fragment_shader routines
- if (!strcmp(name, "glGenFragmentShadersATI")) {
- return (GLExtension_t)glGenFragmentShadersATI;
- }
- if (!strcmp(name, "glBindFragmentShaderATI")) {
- return (GLExtension_t)glBindFragmentShaderATI;
- }
- if (!strcmp(name, "glDeleteFragmentShaderATI")) {
- return (GLExtension_t)glDeleteFragmentShaderATI;
- }
- if (!strcmp(name, "glBeginFragmentShaderATI")) {
- return (GLExtension_t)glBeginFragmentShaderATI;
- }
- if (!strcmp(name, "glEndFragmentShaderATI")) {
- return (GLExtension_t)glEndFragmentShaderATI;
- }
- if (!strcmp(name, "glPassTexCoordATI")) {
- return (GLExtension_t)glPassTexCoordATI;
- }
- if (!strcmp(name, "glSampleMapATI")) {
- return (GLExtension_t)glSampleMapATI;
- }
- if (!strcmp(name, "glColorFragmentOp1ATI")) {
- return (GLExtension_t)glColorFragmentOp1ATI;
- }
- if (!strcmp(name, "glColorFragmentOp2ATI")) {
- return (GLExtension_t)glColorFragmentOp2ATI;
- }
- if (!strcmp(name, "glColorFragmentOp3ATI")) {
- return (GLExtension_t)glColorFragmentOp3ATI;
- }
- if (!strcmp(name, "glAlphaFragmentOp1ATI")) {
- return (GLExtension_t)glAlphaFragmentOp1ATI;
- }
- if (!strcmp(name, "glAlphaFragmentOp2ATI")) {
- return (GLExtension_t)glAlphaFragmentOp2ATI;
- }
- if (!strcmp(name, "glAlphaFragmentOp3ATI")) {
- return (GLExtension_t)glAlphaFragmentOp3ATI;
- }
- if (!strcmp(name, "glSetFragmentShaderConstantATI")) {
- return (GLExtension_t)glSetFragmentShaderConstantATI;
- }
+ GLExtension_t res = GLimp_ExtensionPointer_ATI_fragment_shader(name);
+ if (res)
+ return res;
// Prepend a '_' for the Unix C symbol mangling convention
symbolName = (char *)alloca(strlen(name) + 2);