From 8df54ffad26acf43c41a72a8a904b32bfc2f883f Mon Sep 17 00:00:00 2001 From: dhewg Date: Sat, 31 Dec 2011 16:15:47 +0100 Subject: [PATCH] Move OSX ATI_fragment_shader functions Move the software implementation to sys/glimp_ati_fragment_shader.cpp in preparation to move to the SDL based GLimp and events. --- neo/CMakeLists.txt | 1 + neo/sys/glimp_ati_fragment_shader.cpp | 570 ++++++++++++++++++++++++++ neo/sys/glimp_ati_fragment_shader.h | 36 ++ neo/sys/osx/macosx_glimp.mm | 553 +------------------------ 4 files changed, 611 insertions(+), 549 deletions(-) create mode 100644 neo/sys/glimp_ati_fragment_shader.cpp create mode 100644 neo/sys/glimp_ati_fragment_shader.h 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);