ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ati_fragment_shader.c
Go to the documentation of this file.
00001 /*
00002  * Fixed function pipeline replacement using GL_ATI_fragment_shader
00003  *
00004  * Copyright 2008 Stefan Dösinger(for CodeWeavers)
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include "config.h"
00022 
00023 #include <math.h>
00024 #include <stdio.h>
00025 
00026 #include "wined3d_private.h"
00027 
00028 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
00029 WINE_DECLARE_DEBUG_CHANNEL(d3d);
00030 
00031 /* GL locking for state handlers is done by the caller. */
00032 
00033 /* Some private defines, Constant associations, etc.
00034  * Env bump matrix and per stage constant should be independent,
00035  * a stage that bump maps can't read the per state constant
00036  */
00037 #define ATI_FFP_CONST_BUMPMAT(i) (GL_CON_0_ATI + i)
00038 #define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI
00039 #define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI
00040 #define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI
00041 #define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI
00042 #define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI
00043 #define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI
00044 #define ATI_FFP_CONST_TFACTOR   GL_CON_6_ATI
00045 
00046 /* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */
00047 struct atifs_ffp_desc
00048 {
00049     struct ffp_frag_desc parent;
00050     GLuint shader;
00051     unsigned int num_textures_used;
00052 };
00053 
00054 struct atifs_private_data
00055 {
00056     struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */
00057 };
00058 
00059 static const char *debug_dstmod(GLuint mod) {
00060     switch(mod) {
00061         case GL_NONE:               return "GL_NONE";
00062         case GL_2X_BIT_ATI:         return "GL_2X_BIT_ATI";
00063         case GL_4X_BIT_ATI:         return "GL_4X_BIT_ATI";
00064         case GL_8X_BIT_ATI:         return "GL_8X_BIT_ATI";
00065         case GL_HALF_BIT_ATI:       return "GL_HALF_BIT_ATI";
00066         case GL_QUARTER_BIT_ATI:    return "GL_QUARTER_BIT_ATI";
00067         case GL_EIGHTH_BIT_ATI:     return "GL_EIGHTH_BIT_ATI";
00068         case GL_SATURATE_BIT_ATI:   return "GL_SATURATE_BIT_ATI";
00069         default:                    return "Unexpected modifier\n";
00070     }
00071 }
00072 
00073 static const char *debug_argmod(GLuint mod) {
00074     switch(mod) {
00075         case GL_NONE:
00076             return "GL_NONE";
00077 
00078         case GL_2X_BIT_ATI:
00079             return "GL_2X_BIT_ATI";
00080         case GL_COMP_BIT_ATI:
00081             return "GL_COMP_BIT_ATI";
00082         case GL_NEGATE_BIT_ATI:
00083             return "GL_NEGATE_BIT_ATI";
00084         case GL_BIAS_BIT_ATI:
00085             return "GL_BIAS_BIT_ATI";
00086 
00087         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI:
00088             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI";
00089         case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI:
00090             return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI";
00091         case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI:
00092             return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI";
00093         case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
00094             return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
00095         case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
00096             return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
00097         case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
00098             return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
00099 
00100         case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
00101             return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
00102         case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
00103             return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
00104         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
00105             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
00106         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
00107             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
00108 
00109         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
00110             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
00111 
00112         default:
00113             return "Unexpected argmod combination\n";
00114     }
00115 }
00116 static const char *debug_register(GLuint reg) {
00117     switch(reg) {
00118         case GL_REG_0_ATI:                  return "GL_REG_0_ATI";
00119         case GL_REG_1_ATI:                  return "GL_REG_1_ATI";
00120         case GL_REG_2_ATI:                  return "GL_REG_2_ATI";
00121         case GL_REG_3_ATI:                  return "GL_REG_3_ATI";
00122         case GL_REG_4_ATI:                  return "GL_REG_4_ATI";
00123         case GL_REG_5_ATI:                  return "GL_REG_5_ATI";
00124 
00125         case GL_CON_0_ATI:                  return "GL_CON_0_ATI";
00126         case GL_CON_1_ATI:                  return "GL_CON_1_ATI";
00127         case GL_CON_2_ATI:                  return "GL_CON_2_ATI";
00128         case GL_CON_3_ATI:                  return "GL_CON_3_ATI";
00129         case GL_CON_4_ATI:                  return "GL_CON_4_ATI";
00130         case GL_CON_5_ATI:                  return "GL_CON_5_ATI";
00131         case GL_CON_6_ATI:                  return "GL_CON_6_ATI";
00132         case GL_CON_7_ATI:                  return "GL_CON_7_ATI";
00133 
00134         case GL_ZERO:                       return "GL_ZERO";
00135         case GL_ONE:                        return "GL_ONE";
00136         case GL_PRIMARY_COLOR:              return "GL_PRIMARY_COLOR";
00137         case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI";
00138 
00139         default:                            return "Unknown register\n";
00140     }
00141 }
00142 
00143 static const char *debug_swizzle(GLuint swizzle) {
00144     switch(swizzle) {
00145         case GL_SWIZZLE_STR_ATI:        return "GL_SWIZZLE_STR_ATI";
00146         case GL_SWIZZLE_STQ_ATI:        return "GL_SWIZZLE_STQ_ATI";
00147         case GL_SWIZZLE_STR_DR_ATI:     return "GL_SWIZZLE_STR_DR_ATI";
00148         case GL_SWIZZLE_STQ_DQ_ATI:     return "GL_SWIZZLE_STQ_DQ_ATI";
00149         default:                        return "unknown swizzle";
00150     }
00151 }
00152 
00153 static const char *debug_rep(GLuint rep) {
00154     switch(rep) {
00155         case GL_NONE:                   return "GL_NONE";
00156         case GL_RED:                    return "GL_RED";
00157         case GL_GREEN:                  return "GL_GREEN";
00158         case GL_BLUE:                   return "GL_BLUE";
00159         default:                        return "unknown argrep";
00160     }
00161 }
00162 
00163 static const char *debug_op(GLuint op) {
00164     switch(op) {
00165         case GL_MOV_ATI:                return "GL_MOV_ATI";
00166         case GL_ADD_ATI:                return "GL_ADD_ATI";
00167         case GL_MUL_ATI:                return "GL_MUL_ATI";
00168         case GL_SUB_ATI:                return "GL_SUB_ATI";
00169         case GL_DOT3_ATI:               return "GL_DOT3_ATI";
00170         case GL_DOT4_ATI:               return "GL_DOT4_ATI";
00171         case GL_MAD_ATI:                return "GL_MAD_ATI";
00172         case GL_LERP_ATI:               return "GL_LERP_ATI";
00173         case GL_CND_ATI:                return "GL_CND_ATI";
00174         case GL_CND0_ATI:               return "GL_CND0_ATI";
00175         case GL_DOT2_ADD_ATI:           return "GL_DOT2_ADD_ATI";
00176         default:                        return "unexpected op";
00177     }
00178 }
00179 
00180 static const char *debug_mask(GLuint mask) {
00181     switch(mask) {
00182         case GL_NONE:                           return "GL_NONE";
00183         case GL_RED_BIT_ATI:                    return "GL_RED_BIT_ATI";
00184         case GL_GREEN_BIT_ATI:                  return "GL_GREEN_BIT_ATI";
00185         case GL_BLUE_BIT_ATI:                   return "GL_BLUE_BIT_ATI";
00186         case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
00187         case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI:  return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
00188         case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
00189         case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
00190         default:                                return "Unexpected writemask";
00191     }
00192 }
00193 
00194 static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
00195         GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
00196 {
00197     if(dstMask == GL_ALPHA) {
00198         TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
00199               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
00200         GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
00201     } else {
00202         TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
00203               debug_mask(dstMask), debug_dstmod(dstMod),
00204               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod));
00205         GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
00206     }
00207 }
00208 
00209 static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
00210         GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod)
00211 {
00212     if(dstMask == GL_ALPHA) {
00213         TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
00214               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
00215               debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
00216         GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
00217     } else {
00218         TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
00219               debug_mask(dstMask), debug_dstmod(dstMod),
00220               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
00221               debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod));
00222         GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
00223     }
00224 }
00225 
00226 static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
00227         GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod,
00228         GLuint arg3, GLuint arg3Rep, GLuint arg3Mod)
00229 {
00230     if(dstMask == GL_ALPHA) {
00231         /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
00232         TRACE("glAlphaFragmentOp3ATI(%s, %s,          %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
00233               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
00234               debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
00235               debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
00236         GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
00237                                          arg1, arg1Rep, arg1Mod,
00238                                          arg2, arg2Rep, arg2Mod,
00239                                          arg3, arg3Rep, arg3Mod));
00240     } else {
00241         TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
00242               debug_mask(dstMask), debug_dstmod(dstMod),
00243               debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod),
00244               debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod),
00245               debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod));
00246         GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
00247                                          arg1, arg1Rep, arg1Mod,
00248                                          arg2, arg2Rep, arg2Mod,
00249                                          arg3, arg3Rep, arg3Mod));
00250     }
00251 }
00252 
00253 static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info,
00254         unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
00255 {
00256     GLenum ret;
00257 
00258     if(mod) *mod = GL_NONE;
00259     if(arg == ARG_UNUSED)
00260     {
00261         if (rep) *rep = GL_NONE;
00262         return -1; /* This is the marker for unused registers */
00263     }
00264 
00265     switch(arg & WINED3DTA_SELECTMASK) {
00266         case WINED3DTA_DIFFUSE:
00267             ret = GL_PRIMARY_COLOR;
00268             break;
00269 
00270         case WINED3DTA_CURRENT:
00271             /* Note that using GL_REG_0_ATI for the passed on register is safe because
00272              * texture0 is read at stage0, so in the worst case it is read in the
00273              * instruction writing to reg0. Afterwards texture0 is not used any longer.
00274              * If we're reading from current
00275              */
00276             ret = stage ? GL_REG_0_ATI : GL_PRIMARY_COLOR;
00277             break;
00278 
00279         case WINED3DTA_TEXTURE:
00280             ret = GL_REG_0_ATI + stage;
00281             break;
00282 
00283         case WINED3DTA_TFACTOR:
00284             ret = ATI_FFP_CONST_TFACTOR;
00285             break;
00286 
00287         case WINED3DTA_SPECULAR:
00288             ret = GL_SECONDARY_INTERPOLATOR_ATI;
00289             break;
00290 
00291         case WINED3DTA_TEMP:
00292             ret = tmparg;
00293             break;
00294 
00295         case WINED3DTA_CONSTANT:
00296             FIXME("Unhandled source argument WINED3DTA_TEMP\n");
00297             ret = GL_CON_0_ATI;
00298             break;
00299 
00300         default:
00301             FIXME("Unknown source argument %d\n", arg);
00302             ret = GL_ZERO;
00303     }
00304 
00305     if(arg & WINED3DTA_COMPLEMENT) {
00306         if(mod) *mod |= GL_COMP_BIT_ATI;
00307     }
00308     if(arg & WINED3DTA_ALPHAREPLICATE) {
00309         if(rep) *rep = GL_ALPHA;
00310     } else {
00311         if(rep) *rep = GL_NONE;
00312     }
00313     return ret;
00314 }
00315 
00316 static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES])
00317 {
00318     int lowest_read = -1;
00319     int lowest_write = -1;
00320     int i;
00321     BOOL tex_used[MAX_TEXTURES];
00322 
00323     memset(tex_used, 0, sizeof(tex_used));
00324     for (i = 0; i < MAX_TEXTURES; ++i)
00325     {
00326         if (op[i].cop == WINED3D_TOP_DISABLE)
00327             break;
00328 
00329         if(lowest_read == -1 &&
00330           (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP ||
00331            op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) {
00332             lowest_read = i;
00333         }
00334 
00335         if(lowest_write == -1 && op[i].dst == tempreg) {
00336             lowest_write = i;
00337         }
00338 
00339         if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE ||
00340            op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) {
00341             tex_used[i] = TRUE;
00342         }
00343     }
00344 
00345     /* Temp reg not read? We don't need it, return GL_NONE */
00346     if(lowest_read == -1) return GL_NONE;
00347 
00348     if(lowest_write >= lowest_read) {
00349         FIXME("Temp register read before being written\n");
00350     }
00351 
00352     if(lowest_write == -1) {
00353         /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */
00354         FIXME("Temp register read without being written\n");
00355         return GL_REG_1_ATI;
00356     } else if(lowest_write >= 1) {
00357         /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result.
00358          * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already
00359          * read it
00360          */
00361         return GL_REG_1_ATI;
00362     } else {
00363         /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used
00364          * for the regular result
00365          */
00366         for(i = 1; i < 6; i++) {
00367             if(!tex_used[i]) {
00368                 return GL_REG_0_ATI + i;
00369             }
00370         }
00371         /* What to do here? Report it in ValidateDevice? */
00372         FIXME("Could not find a register for the temporary register\n");
00373         return 0;
00374     }
00375 }
00376 
00377 static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info)
00378 {
00379     GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
00380     unsigned int stage;
00381     GLuint arg0, arg1, arg2, extrarg;
00382     GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
00383     GLuint rep0, rep1, rep2;
00384     GLuint swizzle;
00385     GLuint tmparg = find_tmpreg(op);
00386     GLuint dstreg;
00387 
00388     if(!ret) {
00389         ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
00390         return 0;
00391     }
00392     GL_EXTCALL(glBindFragmentShaderATI(ret));
00393     checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
00394 
00395     TRACE("glBeginFragmentShaderATI()\n");
00396     GL_EXTCALL(glBeginFragmentShaderATI());
00397     checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
00398 
00399     /* Pass 1: Generate sampling instructions for perturbation maps */
00400     for (stage = 0; stage < gl_info->limits.textures; ++stage)
00401     {
00402         if (op[stage].cop == WINED3D_TOP_DISABLE)
00403             break;
00404         if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
00405                 && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
00406             continue;
00407 
00408         TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
00409               stage, stage);
00410         GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
00411                    GL_TEXTURE0_ARB + stage,
00412                    GL_SWIZZLE_STR_ATI));
00413         if(op[stage + 1].projected == proj_none) {
00414             swizzle = GL_SWIZZLE_STR_ATI;
00415         } else if(op[stage + 1].projected == proj_count4) {
00416             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
00417         } else {
00418             swizzle = GL_SWIZZLE_STR_DR_ATI;
00419         }
00420         TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
00421               stage + 1, stage + 1, debug_swizzle(swizzle));
00422         GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
00423                    GL_TEXTURE0_ARB + stage + 1,
00424                    swizzle));
00425     }
00426 
00427     /* Pass 2: Generate perturbation calculations */
00428     for (stage = 0; stage < gl_info->limits.textures; ++stage)
00429     {
00430         GLuint argmodextra_x, argmodextra_y;
00431         struct color_fixup_desc fixup;
00432 
00433         if (op[stage].cop == WINED3D_TOP_DISABLE)
00434             break;
00435         if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
00436                 && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
00437             continue;
00438 
00439         fixup = op[stage].color_fixup;
00440         if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
00441         {
00442             FIXME("Swizzles not implemented\n");
00443             argmodextra_x = GL_NONE;
00444             argmodextra_y = GL_NONE;
00445         }
00446         else
00447         {
00448             /* Nice thing, we get the color correction for free :-) */
00449             argmodextra_x = fixup.x_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
00450             argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
00451         }
00452 
00453         wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
00454                  GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
00455                  ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
00456                  GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
00457 
00458         /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha
00459          * component of the bump matrix. Instead do this with two MADs:
00460          *
00461          * coord.a = tex.r * bump.b + coord.g
00462          * coord.g = tex.g * bump.a + coord.a
00463          *
00464          * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD.
00465          * coord.a is unused. If the perturbed texture is projected, this was already handled
00466          * in the glPassTexCoordATI above.
00467          */
00468         wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE,
00469                  GL_REG_0_ATI + stage, GL_RED, argmodextra_y,
00470                  ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE,
00471                  GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
00472         wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
00473                  GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y,
00474                  ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE,
00475                  GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE);
00476     }
00477 
00478     /* Pass 3: Generate sampling instructions for regular textures */
00479     for (stage = 0; stage < gl_info->limits.textures; ++stage)
00480     {
00481         if (op[stage].cop == WINED3D_TOP_DISABLE)
00482             break;
00483 
00484         if(op[stage].projected == proj_none) {
00485             swizzle = GL_SWIZZLE_STR_ATI;
00486         } else if(op[stage].projected == proj_count3) {
00487             swizzle = GL_SWIZZLE_STR_DR_ATI;
00488         } else {
00489             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
00490         }
00491 
00492         if ((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00493                 || (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00494                 || (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00495                 || (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00496                 || (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00497                 || (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
00498                 || op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA)
00499         {
00500             if (stage > 0
00501                     && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
00502                     || op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
00503             {
00504                 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n",
00505                       stage, stage);
00506                 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
00507                            GL_REG_0_ATI + stage,
00508                            GL_SWIZZLE_STR_ATI));
00509             } else {
00510                 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
00511                     stage, stage, debug_swizzle(swizzle));
00512                 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
00513                                         GL_TEXTURE0_ARB + stage,
00514                                         swizzle));
00515             }
00516         }
00517     }
00518 
00519     /* Pass 4: Generate the arithmetic instructions */
00520     for (stage = 0; stage < MAX_TEXTURES; ++stage)
00521     {
00522         if (op[stage].cop == WINED3D_TOP_DISABLE)
00523         {
00524             if (!stage)
00525             {
00526                 /* Handle complete texture disabling gracefully */
00527                 wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
00528                          GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
00529                 wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
00530                          GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
00531             }
00532             break;
00533         }
00534 
00535         if(op[stage].dst == tempreg) {
00536             /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place.
00537              * skip the entire stage, this saves some GPU time
00538              */
00539             if(tmparg == GL_NONE) continue;
00540 
00541             dstreg = tmparg;
00542         } else {
00543             dstreg = GL_REG_0_ATI;
00544         }
00545 
00546         arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg);
00547         arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg);
00548         arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg);
00549         dstmod = GL_NONE;
00550         argmodextra = GL_NONE;
00551         extrarg = GL_NONE;
00552 
00553         switch (op[stage].cop)
00554         {
00555             case WINED3D_TOP_SELECT_ARG2:
00556                 arg1 = arg2;
00557                 argmod1 = argmod2;
00558                 rep1 = rep2;
00559                 /* fall through */
00560             case WINED3D_TOP_SELECT_ARG1:
00561                 wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
00562                          arg1, rep1, argmod1);
00563                 break;
00564 
00565             case WINED3D_TOP_MODULATE_4X:
00566                 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
00567                 /* fall through */
00568             case WINED3D_TOP_MODULATE_2X:
00569                 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
00570                 dstmod |= GL_SATURATE_BIT_ATI;
00571                 /* fall through */
00572             case WINED3D_TOP_MODULATE:
00573                 wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
00574                          arg1, rep1, argmod1,
00575                          arg2, rep2, argmod2);
00576                 break;
00577 
00578             case WINED3D_TOP_ADD_SIGNED_2X:
00579                 dstmod = GL_2X_BIT_ATI;
00580                 /* fall through */
00581             case WINED3D_TOP_ADD_SIGNED:
00582                 argmodextra = GL_BIAS_BIT_ATI;
00583                 /* fall through */
00584             case WINED3D_TOP_ADD:
00585                 dstmod |= GL_SATURATE_BIT_ATI;
00586                 wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
00587                          arg1, rep1, argmod1,
00588                          arg2, rep2, argmodextra | argmod2);
00589                 break;
00590 
00591             case WINED3D_TOP_SUBTRACT:
00592                 dstmod |= GL_SATURATE_BIT_ATI;
00593                 wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
00594                          arg1, rep1, argmod1,
00595                          arg2, rep2, argmod2);
00596                 break;
00597 
00598             case WINED3D_TOP_ADD_SMOOTH:
00599                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
00600                 /* Dst = arg1 + * arg2(1 -arg 1)
00601                  *     = arg2 * (1 - arg1) + arg1
00602                  */
00603                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
00604                          arg2, rep2, argmod2,
00605                          arg1, rep1, argmodextra,
00606                          arg1, rep1, argmod1);
00607                 break;
00608 
00609             case WINED3D_TOP_BLEND_CURRENT_ALPHA:
00610                 if (extrarg == GL_NONE)
00611                     extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
00612                 /* fall through */
00613             case WINED3D_TOP_BLEND_FACTOR_ALPHA:
00614                 if (extrarg == GL_NONE)
00615                     extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
00616                 /* fall through */
00617             case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
00618                 if (extrarg == GL_NONE)
00619                     extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
00620                 /* fall through */
00621             case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
00622                 if (extrarg == GL_NONE)
00623                     extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
00624                 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
00625                          extrarg, GL_ALPHA, GL_NONE,
00626                          arg1, rep1, argmod1,
00627                          arg2, rep2, argmod2);
00628                 break;
00629 
00630             case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
00631                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
00632                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
00633                          arg2, rep2,  argmod2,
00634                          arg0, GL_ALPHA, GL_COMP_BIT_ATI,
00635                          arg1, rep1,  argmod1);
00636                 break;
00637 
00638             /* D3DTOP_PREMODULATE ???? */
00639 
00640             case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
00641                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
00642                 /* fall through */
00643             case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
00644                 if (!argmodextra)
00645                     argmodextra = argmod1;
00646                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
00647                          arg2, rep2,  argmod2,
00648                          arg1, GL_ALPHA, argmodextra,
00649                          arg1, rep1,  argmod1);
00650                 break;
00651 
00652             case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
00653                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
00654                 /* fall through */
00655             case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
00656                 if (!argmodextra)
00657                     argmodextra = argmod1;
00658                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
00659                          arg2, rep2,  argmod2,
00660                          arg1, rep1,  argmodextra,
00661                          arg1, GL_ALPHA, argmod1);
00662                 break;
00663 
00664             case WINED3D_TOP_DOTPRODUCT3:
00665                 wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
00666                          arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
00667                          arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
00668                 break;
00669 
00670             case WINED3D_TOP_MULTIPLY_ADD:
00671                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
00672                          arg1, rep1, argmod1,
00673                          arg2, rep2, argmod2,
00674                          arg0, rep0, argmod0);
00675                 break;
00676 
00677             case WINED3D_TOP_LERP:
00678                 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
00679                          arg0, rep0, argmod0,
00680                          arg1, rep1, argmod1,
00681                          arg2, rep2, argmod2);
00682                 break;
00683 
00684             case WINED3D_TOP_BUMPENVMAP:
00685             case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
00686                 /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */
00687                 break;
00688 
00689             default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
00690         }
00691 
00692         arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg);
00693         arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg);
00694         arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg);
00695         dstmod = GL_NONE;
00696         argmodextra = GL_NONE;
00697         extrarg = GL_NONE;
00698 
00699         switch (op[stage].aop)
00700         {
00701             case WINED3D_TOP_DISABLE:
00702                 /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
00703                 if (!stage)
00704                 {
00705                     wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE,
00706                              GL_PRIMARY_COLOR, GL_NONE, GL_NONE);
00707                 }
00708                 break;
00709 
00710             case WINED3D_TOP_SELECT_ARG2:
00711                 arg1 = arg2;
00712                 argmod1 = argmod2;
00713                 /* fall through */
00714             case WINED3D_TOP_SELECT_ARG1:
00715                 wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
00716                          arg1, GL_NONE, argmod1);
00717                 break;
00718 
00719             case WINED3D_TOP_MODULATE_4X:
00720                 if (dstmod == GL_NONE)
00721                     dstmod = GL_4X_BIT_ATI;
00722                 /* fall through */
00723             case WINED3D_TOP_MODULATE_2X:
00724                 if (dstmod == GL_NONE)
00725                     dstmod = GL_2X_BIT_ATI;
00726                 dstmod |= GL_SATURATE_BIT_ATI;
00727                 /* fall through */
00728             case WINED3D_TOP_MODULATE:
00729                 wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
00730                          arg1, GL_NONE, argmod1,
00731                          arg2, GL_NONE, argmod2);
00732                 break;
00733 
00734             case WINED3D_TOP_ADD_SIGNED_2X:
00735                 dstmod = GL_2X_BIT_ATI;
00736                 /* fall through */
00737             case WINED3D_TOP_ADD_SIGNED:
00738                 argmodextra = GL_BIAS_BIT_ATI;
00739                 /* fall through */
00740             case WINED3D_TOP_ADD:
00741                 dstmod |= GL_SATURATE_BIT_ATI;
00742                 wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
00743                          arg1, GL_NONE, argmod1,
00744                          arg2, GL_NONE, argmodextra | argmod2);
00745                 break;
00746 
00747             case WINED3D_TOP_SUBTRACT:
00748                 dstmod |= GL_SATURATE_BIT_ATI;
00749                 wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
00750                          arg1, GL_NONE, argmod1,
00751                          arg2, GL_NONE, argmod2);
00752                 break;
00753 
00754             case WINED3D_TOP_ADD_SMOOTH:
00755                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
00756                 /* Dst = arg1 + * arg2(1 -arg 1)
00757                  *     = arg2 * (1 - arg1) + arg1
00758                  */
00759                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
00760                          arg2, GL_NONE, argmod2,
00761                          arg1, GL_NONE, argmodextra,
00762                          arg1, GL_NONE, argmod1);
00763                 break;
00764 
00765             case WINED3D_TOP_BLEND_CURRENT_ALPHA:
00766                 if (extrarg == GL_NONE)
00767                     extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
00768                 /* fall through */
00769             case WINED3D_TOP_BLEND_FACTOR_ALPHA:
00770                 if (extrarg == GL_NONE)
00771                     extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
00772                 /* fall through */
00773             case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
00774                 if (extrarg == GL_NONE)
00775                     extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
00776                 /* fall through */
00777             case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
00778                 if (extrarg == GL_NONE)
00779                     extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
00780                 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
00781                          extrarg, GL_ALPHA, GL_NONE,
00782                          arg1, GL_NONE, argmod1,
00783                          arg2, GL_NONE, argmod2);
00784                 break;
00785 
00786             case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
00787                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
00788                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
00789                          arg2, GL_NONE,  argmod2,
00790                          arg0, GL_ALPHA, GL_COMP_BIT_ATI,
00791                          arg1, GL_NONE,  argmod1);
00792                 break;
00793 
00794             /* D3DTOP_PREMODULATE ???? */
00795 
00796             case WINED3D_TOP_DOTPRODUCT3:
00797                 wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI,
00798                          arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
00799                          arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
00800                 break;
00801 
00802             case WINED3D_TOP_MULTIPLY_ADD:
00803                 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
00804                          arg1, GL_NONE, argmod1,
00805                          arg2, GL_NONE, argmod2,
00806                          arg0, GL_NONE, argmod0);
00807                 break;
00808 
00809             case WINED3D_TOP_LERP:
00810                 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
00811                          arg1, GL_NONE, argmod1,
00812                          arg2, GL_NONE, argmod2,
00813                          arg0, GL_NONE, argmod0);
00814                 break;
00815 
00816             case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
00817             case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
00818             case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
00819             case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
00820             case WINED3D_TOP_BUMPENVMAP:
00821             case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
00822                 ERR("Application uses an invalid alpha operation\n");
00823                 break;
00824 
00825             default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
00826         }
00827     }
00828 
00829     TRACE("glEndFragmentShaderATI()\n");
00830     GL_EXTCALL(glEndFragmentShaderATI());
00831     checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
00832     return ret;
00833 }
00834 
00835 static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00836 {
00837     const struct wined3d_device *device = context->swapchain->device;
00838     const struct wined3d_gl_info *gl_info = context->gl_info;
00839     const struct atifs_ffp_desc *desc;
00840     struct ffp_frag_settings settings;
00841     struct atifs_private_data *priv = device->fragment_priv;
00842     DWORD mapped_stage;
00843     unsigned int i;
00844 
00845     gen_ffp_frag_op(device, state, &settings, TRUE);
00846     desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
00847     if(!desc) {
00848         struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
00849         if (!new_desc)
00850         {
00851             ERR("Out of memory\n");
00852             return;
00853         }
00854         new_desc->num_textures_used = 0;
00855         for (i = 0; i < gl_info->limits.texture_stages; ++i)
00856         {
00857             if (settings.op[i].cop == WINED3D_TOP_DISABLE)
00858                 break;
00859             new_desc->num_textures_used = i;
00860         }
00861 
00862         memcpy(&new_desc->parent.settings, &settings, sizeof(settings));
00863         new_desc->shader = gen_ati_shader(settings.op, gl_info);
00864         add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
00865         TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
00866         desc = new_desc;
00867     }
00868 
00869     /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages
00870      * used by this shader
00871      */
00872     for (i = 0; i < desc->num_textures_used; ++i)
00873     {
00874         mapped_stage = device->texUnitMap[i];
00875         if (mapped_stage != WINED3D_UNMAPPED_STAGE)
00876         {
00877             context_active_texture(context, gl_info, mapped_stage);
00878             texture_activate_dimensions(state->textures[i], gl_info);
00879         }
00880     }
00881 
00882     GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
00883 }
00884 
00885 static void state_texfactor_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00886 {
00887     const struct wined3d_gl_info *gl_info = context->gl_info;
00888     float col[4];
00889 
00890     D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
00891     GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col));
00892     checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)");
00893 }
00894 
00895 static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00896 {
00897     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
00898     const struct wined3d_gl_info *gl_info = context->gl_info;
00899     float mat[2][2];
00900 
00901     mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
00902     mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
00903     mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
00904     mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
00905     /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat
00906      * constants can be in any range. While they should stay between [-1.0 and 1.0] because
00907      * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally,
00908      * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the
00909      * shader(it is free). This might potentially reduce precision. However, if the hardware does
00910      * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway
00911      */
00912     mat[0][0] = (mat[0][0] + 1.0f) * 0.5f;
00913     mat[1][0] = (mat[1][0] + 1.0f) * 0.5f;
00914     mat[0][1] = (mat[0][1] + 1.0f) * 0.5f;
00915     mat[1][1] = (mat[1][1] + 1.0f) * 0.5f;
00916     GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), (float *) mat));
00917     checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), mat)");
00918 }
00919 
00920 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00921 {
00922     if (!isStateDirty(context, STATE_PIXELSHADER))
00923         set_tex_op_atifs(context, state, state_id);
00924 }
00925 
00926 static void atifs_apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00927 {
00928     const struct wined3d_device *device = context->swapchain->device;
00929     BOOL use_vshader = use_vs(state);
00930 
00931     context->last_was_pshader = use_ps(state);
00932     /* The ATIFS code does not support pixel shaders currently, but we have to
00933      * provide a state handler to call shader_select to select a vertex shader
00934      * if one is applied because the vertex shader state may defer calling the
00935      * shader backend if the pshader state is dirty.
00936      *
00937      * In theory the application should not be able to mark the pixel shader
00938      * dirty because it cannot create a shader, and thus has no way to set the
00939      * state to something != NULL. However, a different pipeline part may link
00940      * a different state to its pixelshader handler, thus a pshader state
00941      * exists and can be dirtified. Also the pshader is always dirtified at
00942      * startup, and blitting disables all shaders and dirtifies all shader
00943      * states. If atifs can deal with this it keeps the rest of the code
00944      * simpler. */
00945     if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative))
00946     {
00947         device->shader_backend->shader_select(context, FALSE, use_vshader);
00948 
00949         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader)
00950             context_apply_state(context, state, STATE_VERTEXSHADERCONSTANT);
00951     }
00952 }
00953 
00954 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
00955 {
00956     if (state->render_states[WINED3D_RS_SRGBWRITEENABLE])
00957         WARN("sRGB writes are not supported by this fragment pipe.\n");
00958 }
00959 
00960 static const struct StateEntryTemplate atifs_fragmentstate_template[] = {
00961     {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),              { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor_atifs   }, WINED3D_GL_EXT_NONE             },
00962     {STATE_RENDER(WINED3D_RS_FOGCOLOR),                   { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor          }, WINED3D_GL_EXT_NONE             },
00963     {STATE_RENDER(WINED3D_RS_FOGDENSITY),                 { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity        }, WINED3D_GL_EXT_NONE             },
00964     {STATE_RENDER(WINED3D_RS_FOGENABLE),                  { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_fragpart      }, WINED3D_GL_EXT_NONE             },
00965     {STATE_RENDER(WINED3D_RS_FOGTABLEMODE),               { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
00966     {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                    }, WINED3D_GL_EXT_NONE             },
00967     {STATE_RENDER(WINED3D_RS_FOGSTART),                   { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend       }, WINED3D_GL_EXT_NONE             },
00968     {STATE_RENDER(WINED3D_RS_FOGEND),                     { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                    }, WINED3D_GL_EXT_NONE             },
00969     {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),            { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           atifs_srgbwriteenable   }, WINED3D_GL_EXT_NONE             },
00970     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        set_tex_op_atifs        }, WINED3D_GL_EXT_NONE             },
00971     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00972     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00973     {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00974     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00975     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00976     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00977     {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00978     {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00979     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
00980     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00981     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00982     {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00983     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00984     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00985     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00986     {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00987     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00988     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00989     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00990     {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00991     {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00992     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
00993     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00994     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00995     {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
00996     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00997     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00998     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
00999     {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01000     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01001     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01002     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01003     {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01004     {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01005     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01006     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01007     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01008     {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01009     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01010     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01011     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01012     {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01013     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01014     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01015     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01016     {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01017     {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01018     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01019     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01020     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01021     {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01022     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01023     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01024     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01025     {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01026     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01027     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01028     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01029     {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01030     {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01031     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01032     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01033     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01034     {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01035     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01036     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01037     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01038     {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01039     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01040     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01041     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01042     {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01043     {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01044     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01045     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01046     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01047     {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01048     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01049     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01050     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01051     {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01052     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01053     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01054     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01055     {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01056     {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01057     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01058     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01059     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01060     {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01061     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01062     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01063     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01064     {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01065     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),         { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01066     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01067     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01068     {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01069     {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),       { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                    }, WINED3D_GL_EXT_NONE             },
01070     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   set_bumpmat             }, WINED3D_GL_EXT_NONE             },
01071     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01072     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01073     {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                    }, WINED3D_GL_EXT_NONE             },
01074     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01075     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01076     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01077     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01078     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01079     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01080     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01081     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
01082     {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01083     {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01084     {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01085     {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01086     {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01087     {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01088     {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01089     {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
01090     {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE             },
01091     {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
01092 };
01093 
01094 /* Context activation and GL locking are done by the caller. */
01095 static void atifs_enable(BOOL enable)
01096 {
01097     if(enable) {
01098         glEnable(GL_FRAGMENT_SHADER_ATI);
01099         checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)");
01100     } else {
01101         glDisable(GL_FRAGMENT_SHADER_ATI);
01102         checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)");
01103     }
01104 }
01105 
01106 static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
01107 {
01108     caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
01109     caps->TextureOpCaps =  WINED3DTEXOPCAPS_DISABLE                     |
01110                            WINED3DTEXOPCAPS_SELECTARG1                  |
01111                            WINED3DTEXOPCAPS_SELECTARG2                  |
01112                            WINED3DTEXOPCAPS_MODULATE4X                  |
01113                            WINED3DTEXOPCAPS_MODULATE2X                  |
01114                            WINED3DTEXOPCAPS_MODULATE                    |
01115                            WINED3DTEXOPCAPS_ADDSIGNED2X                 |
01116                            WINED3DTEXOPCAPS_ADDSIGNED                   |
01117                            WINED3DTEXOPCAPS_ADD                         |
01118                            WINED3DTEXOPCAPS_SUBTRACT                    |
01119                            WINED3DTEXOPCAPS_ADDSMOOTH                   |
01120                            WINED3DTEXOPCAPS_BLENDCURRENTALPHA           |
01121                            WINED3DTEXOPCAPS_BLENDFACTORALPHA            |
01122                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHA           |
01123                            WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA           |
01124                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM         |
01125                            WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR      |
01126                            WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA      |
01127                            WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA   |
01128                            WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR   |
01129                            WINED3DTEXOPCAPS_DOTPRODUCT3                 |
01130                            WINED3DTEXOPCAPS_MULTIPLYADD                 |
01131                            WINED3DTEXOPCAPS_LERP                        |
01132                            WINED3DTEXOPCAPS_BUMPENVMAP;
01133 
01134     /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
01135     and WINED3DTEXOPCAPS_PREMODULATE */
01136 
01137     /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards
01138      * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
01139      * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
01140      * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
01141      * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
01142      * pipeline, and almost all games are happy with that. We can however support up to 8
01143      * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
01144      * only 1 instruction.
01145      *
01146      * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
01147      * r200 series and use an ARB or GLSL shader instead
01148      */
01149     caps->MaxTextureBlendStages   = 8;
01150     caps->MaxSimultaneousTextures = 6;
01151 }
01152 
01153 static HRESULT atifs_alloc(struct wined3d_device *device)
01154 {
01155     struct atifs_private_data *priv;
01156 
01157     device->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct atifs_private_data));
01158     if (!device->fragment_priv)
01159     {
01160         ERR("Out of memory\n");
01161         return E_OUTOFMEMORY;
01162     }
01163     priv = device->fragment_priv;
01164     if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
01165     {
01166         ERR("Failed to initialize rbtree.\n");
01167         HeapFree(GetProcessHeap(), 0, device->fragment_priv);
01168         return E_OUTOFMEMORY;
01169     }
01170     return WINED3D_OK;
01171 }
01172 
01173 /* Context activation is done by the caller. */
01174 static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context)
01175 {
01176     struct wined3d_device *device = context;
01177     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
01178     struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
01179 
01180     ENTER_GL();
01181     GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
01182     checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
01183     HeapFree(GetProcessHeap(), 0, entry_ati);
01184     LEAVE_GL();
01185 }
01186 
01187 /* Context activation is done by the caller. */
01188 static void atifs_free(struct wined3d_device *device)
01189 {
01190     struct atifs_private_data *priv = device->fragment_priv;
01191 
01192     wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, device);
01193 
01194     HeapFree(GetProcessHeap(), 0, priv);
01195     device->fragment_priv = NULL;
01196 }
01197 
01198 static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup)
01199 {
01200     if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
01201     {
01202         TRACE("Checking support for fixup:\n");
01203         dump_color_fixup_desc(fixup);
01204     }
01205 
01206     /* We only support sign fixup of the first two channels. */
01207     if (fixup.x_source == CHANNEL_SOURCE_X && fixup.y_source == CHANNEL_SOURCE_Y
01208             && fixup.z_source == CHANNEL_SOURCE_Z && fixup.w_source == CHANNEL_SOURCE_W
01209             && !fixup.z_sign_fixup && !fixup.w_sign_fixup)
01210     {
01211         TRACE("[OK]\n");
01212         return TRUE;
01213     }
01214 
01215     TRACE("[FAILED]\n");
01216     return FALSE;
01217 }
01218 
01219 const struct fragment_pipeline atifs_fragment_pipeline = {
01220     atifs_enable,
01221     atifs_get_caps,
01222     atifs_alloc,
01223     atifs_free,
01224     atifs_color_fixup_supported,
01225     atifs_fragmentstate_template,
01226     TRUE /* We can disable projected textures */
01227 };

Generated on Fri May 25 2012 04:20:12 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.