mshtml: Update the German translation.
[wine] / dlls / wined3d / ati_fragment_shader.c
1 /*
2  * Fixed function pipeline replacement using GL_ATI_fragment_shader
3  *
4  * Copyright 2008 Stefan Dösinger(for CodeWeavers)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <math.h>
24 #include <stdio.h>
25
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
29
30 /* Some private defines, Constant associations, etc
31  * Env bump matrix and per stage constant should be independent,
32  * a stage that bumpmaps can't read the per state constant
33  */
34 #define ATI_FFP_CONST_BUMPMAT(i) (GL_CON_0_ATI + i)
35 #define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI
36 #define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI
37 #define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI
38 #define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI
39 #define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI
40 #define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI
41 #define ATI_FFP_CONST_TFACTOR   GL_CON_6_ATI
42
43 /* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */
44 struct atifs_ffp_desc
45 {
46     struct ffp_desc parent;
47     GLuint shader;
48 };
49
50 struct atifs_private_data
51 {
52     struct shader_arb_priv parent;
53     struct list fragment_shaders; /* A linked list to track fragment pipeline replacement shaders */
54
55 };
56
57 static const char *debug_dstmod(GLuint mod) {
58     switch(mod) {
59         case GL_NONE:               return "GL_NONE";
60         case GL_2X_BIT_ATI:         return "GL_2X_BIT_ATI";
61         case GL_4X_BIT_ATI:         return "GL_4X_BIT_ATI";
62         case GL_8X_BIT_ATI:         return "GL_8X_BIT_ATI";
63         case GL_HALF_BIT_ATI:       return "GL_HALF_BIT_ATI";
64         case GL_QUARTER_BIT_ATI:    return "GL_QUARTER_BIT_ATI";
65         case GL_EIGHTH_BIT_ATI:     return "GL_EIGHTH_BIT_ATI";
66         case GL_SATURATE_BIT_ATI:   return "GL_SATURATE_BIT_ATI";
67         default:                    return "Unexpected modifier\n";
68     }
69 }
70
71 static const char *debug_argmod(GLuint mod) {
72     switch(mod) {
73         case GL_NONE:
74             return "GL_NONE";
75
76         case GL_2X_BIT_ATI:
77             return "GL_2X_BIT_ATI";
78         case GL_COMP_BIT_ATI:
79             return "GL_COMP_BIT_ATI";
80         case GL_NEGATE_BIT_ATI:
81             return "GL_NEGATE_BIT_ATI";
82         case GL_BIAS_BIT_ATI:
83             return "GL_BIAS_BIT_ATI";
84
85         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI:
86             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI";
87         case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI:
88             return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI";
89         case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI:
90             return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI";
91         case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
92             return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
93         case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
94             return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
95         case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
96             return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
97
98         case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
99             return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
100         case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
101             return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
102         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
103             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
104         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
105             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
106
107         case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
108             return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
109
110         default:
111             return "Unexpected argmod combination\n";
112     }
113 }
114 static const char *debug_register(GLuint reg) {
115     switch(reg) {
116         case GL_REG_0_ATI:                  return "GL_REG_0_ATI";
117         case GL_REG_1_ATI:                  return "GL_REG_1_ATI";
118         case GL_REG_2_ATI:                  return "GL_REG_2_ATI";
119         case GL_REG_3_ATI:                  return "GL_REG_3_ATI";
120         case GL_REG_4_ATI:                  return "GL_REG_4_ATI";
121         case GL_REG_5_ATI:                  return "GL_REG_5_ATI";
122
123         case GL_CON_0_ATI:                  return "GL_CON_0_ATI";
124         case GL_CON_1_ATI:                  return "GL_CON_1_ATI";
125         case GL_CON_2_ATI:                  return "GL_CON_2_ATI";
126         case GL_CON_3_ATI:                  return "GL_CON_3_ATI";
127         case GL_CON_4_ATI:                  return "GL_CON_4_ATI";
128         case GL_CON_5_ATI:                  return "GL_CON_5_ATI";
129         case GL_CON_6_ATI:                  return "GL_CON_6_ATI";
130         case GL_CON_7_ATI:                  return "GL_CON_7_ATI";
131
132         case GL_ZERO:                       return "GL_ZERO";
133         case GL_ONE:                        return "GL_ONE";
134         case GL_PRIMARY_COLOR:              return "GL_PRIMARY_COLOR";
135         case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI";
136
137         default:                            return "Unknown register\n";
138     }
139 }
140
141 static const char *debug_swizzle(GLuint swizzle) {
142     switch(swizzle) {
143         case GL_SWIZZLE_STR_ATI:        return "GL_SWIZZLE_STR_ATI";
144         case GL_SWIZZLE_STQ_ATI:        return "GL_SWIZZLE_STQ_ATI";
145         case GL_SWIZZLE_STR_DR_ATI:     return "GL_SWIZZLE_STR_DR_ATI";
146         case GL_SWIZZLE_STQ_DQ_ATI:     return "GL_SWIZZLE_STQ_DQ_ATI";
147         default:                        return "unknown swizzle";
148     }
149 }
150
151 #define GLINFO_LOCATION (*gl_info)
152 static GLuint register_for_arg(DWORD arg, WineD3D_GL_Info *gl_info, unsigned int stage, GLuint *mod) {
153     GLenum ret;
154
155     if(mod) *mod = GL_NONE;
156     if(arg == 0xFFFFFFFF) return -1; /* This is the marker for unused registers */
157
158     switch(arg & WINED3DTA_SELECTMASK) {
159         case WINED3DTA_DIFFUSE:
160             ret = GL_PRIMARY_COLOR;
161             break;
162
163         case WINED3DTA_CURRENT:
164             /* Note that using GL_REG_0_ATI for the passed on register is safe because
165              * texture0 is read at stage0, so in the worst case it is read in the
166              * instruction writing to reg0. Afterwards texture0 is not used any longer.
167              * If we're reading from current
168              */
169             if(stage == 0) {
170                 ret = GL_PRIMARY_COLOR;
171             } else {
172                 ret = GL_REG_0_ATI;
173             }
174             break;
175
176         case WINED3DTA_TEXTURE:
177             ret = GL_REG_0_ATI + stage;
178             break;
179
180         case WINED3DTA_TFACTOR:
181             ret = ATI_FFP_CONST_TFACTOR;
182             break;
183
184         case WINED3DTA_SPECULAR:
185             ret = GL_SECONDARY_INTERPOLATOR_ATI;
186             break;
187
188         case WINED3DTA_TEMP:
189             FIXME("Unhandled source argument WINED3DTA_TEMP\n");
190             ret = 0;
191             break;
192
193         case WINED3DTA_CONSTANT:
194             FIXME("Unhandled source argument WINED3DTA_TEMP\n");
195             ret = GL_CON_0_ATI;
196             break;
197
198         default:
199             FIXME("Unknown source argument %d\n", arg);
200             ret = GL_ZERO;
201     }
202
203     if(arg & WINED3DTA_COMPLEMENT) {
204         if(mod) *mod |= GL_COMP_BIT_ATI;
205     }
206     if(arg & WINED3DTA_ALPHAREPLICATE) {
207         FIXME("Unhandled read modifier WINED3DTA_ALPHAREPLICATE\n");
208     }
209     return ret;
210 }
211
212 static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_GL_Info *gl_info) {
213     GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
214     unsigned int stage;
215     GLuint arg0, arg1, arg2, extrarg;
216     GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
217     GLuint swizzle;
218
219     if(!ret) {
220         ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
221         return 0;
222     }
223     GL_EXTCALL(glBindFragmentShaderATI(ret));
224     checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
225
226     TRACE("glBeginFragmentShaderATI()\n");
227     GL_EXTCALL(glBeginFragmentShaderATI());
228     checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
229
230     /* Pass 1: Generate sampling instructions for perturbation maps */
231       for(stage = 0; stage < GL_LIMITS(textures); stage++) {
232         if(op[stage].cop == WINED3DTOP_DISABLE) break;
233         if(op[stage].cop != WINED3DTOP_BUMPENVMAP &&
234            op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue;
235
236         TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
237               stage, stage);
238         GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
239                    GL_TEXTURE0_ARB + stage,
240                    GL_SWIZZLE_STR_ATI));
241         TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
242               stage + 1, stage + 1);
243         GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
244                    GL_TEXTURE0_ARB + stage + 1,
245                    GL_SWIZZLE_STR_ATI));
246
247         /* We need GL_REG_5_ATI as a temporary register to swizzle the bump matrix. So we run into
248          * issues if we're bump mapping on stage 4 or 5
249          */
250         if(stage >= 4) {
251             FIXME("Bump mapping in stage %d\n", stage);
252         }
253     }
254
255     /* Pass 2: Generate perturbation calculations */
256     for(stage = 0; stage < GL_LIMITS(textures); stage++) {
257         if(op[stage].cop == WINED3DTOP_DISABLE) break;
258         if(op[stage].cop != WINED3DTOP_BUMPENVMAP &&
259            op[stage].cop != WINED3DTOP_BUMPENVMAPLUMINANCE) continue;
260
261         /* Nice thing, we get the color correction for free :-) */
262         if(op[stage].color_correction == WINED3DFMT_V8U8) {
263             argmodextra = GL_2X_BIT_ATI | GL_BIAS_BIT_ATI;
264         } else {
265             argmodextra = 0;
266         }
267
268         TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_RED_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, ATI_FFP_CONST_BUMPMAT(%d), GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_RED, GL_NONE)\n",
269               stage + 1, stage, debug_argmod(argmodextra), stage, stage + 1);
270         GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE,
271                                          GL_REG_0_ATI + stage, GL_NONE, argmodextra,
272                                          ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
273                                          GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE));
274
275         /* FIXME: How can I make GL_DOT2_ADD_ATI read the factors from blue and alpha? It defaults to red and green,
276          * and it is fairly easy to make it read GL_BLUE or BL_ALPHA, but I can't get an R * B + G * A. So we're wasting
277          * one register and two instructions in this pass for a simple swizzling operation.
278          * For starters it might be good enough to merge the two movs into one, but even that isn't possible :-(
279          *
280          * NOTE: GL_BLUE | GL_ALPHA is not possible. It doesn't throw a compilation error, but an OR operation on the
281          * constants doesn't make sense, considering their values.
282          */
283         TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_BLUE, GL_NONE)\n", stage);
284         GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_RED_BIT_ATI, GL_NONE,
285                                          ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE));
286         TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE, ATI_FFP_CONST_BUMPMAT(%d), GL_ALPHA, GL_NONE)\n", stage);
287         GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_5_ATI, GL_GREEN_BIT_ATI, GL_NONE,
288                                         ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE));
289         TRACE("glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_%d_ATI, GL_GREEN_BIT_ATI, GL_NONE, GL_REG_%d_ATI, GL_NONE, %s, GL_REG_5_ATI, GL_NONE, GL_NONE, GL_REG_%d_ATI, GL_GREEN, GL_NONE)\n",
290               stage + 1, stage, debug_argmod(argmodextra), stage + 1);
291         GL_EXTCALL(glColorFragmentOp3ATI(GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
292                                          GL_REG_0_ATI + stage, GL_NONE, argmodextra,
293                                          GL_REG_5_ATI, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI,
294                                          GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE));
295     }
296
297     /* Pass 3: Generate sampling instructions for regular textures */
298     for(stage = 0; stage < GL_LIMITS(textures); stage++) {
299         if(op[stage].cop == WINED3DTOP_DISABLE) {
300             break;
301         }
302
303         if(op[stage].projected == proj_none) {
304             swizzle = GL_SWIZZLE_STR_ATI;
305         } else if(op[stage].projected == proj_count3) {
306             /* TODO: D3DTTFF_COUNT3 | D3DTTFF_PROJECTED would be GL_SWIZZLE_STR_DR_ATI.
307              * However, the FFP vertex processing texture transform matrix handler does
308              * some transformations in the texture matrix which makes the 3rd coordinate
309              * arrive in Q, not R in that case. This is needed for opengl fixed function
310              * fragment processing which always divides by Q. In this backend we can
311              * handle that properly and be compatible with vertex shader output and avoid
312              * side effects of the texture matrix games
313              */
314             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
315         } else {
316             swizzle = GL_SWIZZLE_STQ_DQ_ATI;
317         }
318
319         if((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
320            (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
321            (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
322            (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
323            (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
324            (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
325             op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) {
326
327             if(stage > 0 &&
328                (op[stage - 1].cop == WINED3DTOP_BUMPENVMAP ||
329                 op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) {
330                 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n",
331                       stage, stage);
332                 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
333                            GL_REG_0_ATI + stage,
334                            GL_SWIZZLE_STR_ATI));
335             } else {
336                 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
337                     stage, stage, debug_swizzle(swizzle));
338                 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
339                                         GL_TEXTURE0_ARB + stage,
340                                         swizzle));
341             }
342         }
343     }
344
345     /* Pass 4: Generate the arithmetic instructions */
346     for(stage = 0; stage < MAX_TEXTURES; stage++) {
347         if(op[stage].cop == WINED3DTOP_DISABLE) {
348             if(stage == 0) {
349                 /* Handle complete texture disabling gracefully */
350                 TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
351                 GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
352                                                  GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
353                 TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
354                 GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
355                                                  GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
356             }
357             break;
358         }
359
360         arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0);
361         arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1);
362         arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2);
363         dstmod = GL_NONE;
364         argmodextra = GL_NONE;
365         extrarg = GL_NONE;
366
367         switch(op[stage].cop) {
368             case WINED3DTOP_SELECTARG2:
369                 arg1 = arg2;
370                 argmod1 = argmod2;
371             case WINED3DTOP_SELECTARG1:
372                 TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s)\n",
373                       debug_register(arg1), debug_argmod(argmod1));
374                 GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
375                                                  arg1, GL_NONE, argmod1));
376                 break;
377
378             case WINED3DTOP_MODULATE4X:
379                 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
380             case WINED3DTOP_MODULATE2X:
381                 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
382             case WINED3DTOP_MODULATE:
383                 TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
384                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
385                 GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
386                                                  arg1, GL_NONE, argmod1,
387                                                  arg2, GL_NONE, argmod2));
388                 break;
389
390             case WINED3DTOP_ADDSIGNED2X:
391                 dstmod = GL_2X_BIT_ATI;
392             case WINED3DTOP_ADDSIGNED:
393                 argmodextra = GL_BIAS_BIT_ATI;
394             case WINED3DTOP_ADD:
395                 TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
396                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmodextra | argmod2));
397                 GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
398                            arg1, GL_NONE, argmod1,
399                            arg2, GL_NONE, argmodextra | argmod2));
400                 break;
401
402             case WINED3DTOP_SUBTRACT:
403                 TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
404                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
405                 GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
406                            arg1, GL_NONE, argmod1,
407                            arg2, GL_NONE, argmod2));
408                 break;
409
410             case WINED3DTOP_ADDSMOOTH:
411                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
412                 TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
413                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
414                 /* Dst = arg1 + * arg2(1 -arg 1)
415                  *     = arg2 * (1 - arg1) + arg1
416                  */
417                 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
418                                                  arg2, GL_NONE, argmod2,
419                                                  arg1, GL_NONE, argmodextra,
420                                                  arg1, GL_NONE, argmod1));
421                 break;
422
423             case WINED3DTOP_BLENDCURRENTALPHA:
424                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL);
425             case WINED3DTOP_BLENDFACTORALPHA:
426                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL);
427             case WINED3DTOP_BLENDTEXTUREALPHA:
428                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
429             case WINED3DTOP_BLENDDIFFUSEALPHA:
430                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL);
431                 TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
432                      debug_register(extrarg), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
433                 GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
434                                                  extrarg, GL_ALPHA, GL_NONE,
435                                                  arg1, GL_NONE, argmod1,
436                                                  arg2, GL_NONE, argmod2));
437                 break;
438
439             case WINED3DTOP_BLENDTEXTUREALPHAPM:
440                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
441                 TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n",
442                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_register(arg1), debug_argmod(argmod1));
443                 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
444                                                  arg2, GL_NONE,  argmod2,
445                                                  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
446                                                  arg1, GL_NONE,  argmod1));
447                 break;
448
449             /* D3DTOP_PREMODULATE ???? */
450
451             case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
452                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
453             case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
454                 if(!argmodextra) argmodextra = argmod1;
455                 TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, %s, %s, GL_NONE, %s)\n",
456                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(arg1));
457                 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
458                                                  arg2, GL_NONE,  argmod2,
459                                                  arg1, GL_ALPHA, argmodextra,
460                                                  arg1, GL_NONE,  argmod1));
461                 break;
462
463             case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
464                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
465             case WINED3DTOP_MODULATECOLOR_ADDALPHA:
466                 if(!argmodextra) argmodextra = argmod1;
467                 TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_ALPHA, %s)\n",
468                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
469                 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
470                                                  arg2, GL_NONE,  argmod2,
471                                                  arg1, GL_NONE,  argmodextra,
472                                                  arg1, GL_ALPHA, argmod1));
473                 break;
474
475             case WINED3DTOP_DOTPRODUCT3:
476                 TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
477                       debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
478                 GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI,
479                                                  arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
480                                                  arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
481                 break;
482
483             case WINED3DTOP_MULTIPLYADD:
484                 TRACE("glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
485                       debug_register(arg0), debug_argmod(argmod0), debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmod1));
486                 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
487                            arg0, GL_NONE, argmod0,
488                            arg2, GL_NONE, argmod2,
489                            arg1, GL_NONE, argmod1));
490                 break;
491
492             case WINED3DTOP_LERP:
493                 TRACE("glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
494                       debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_argmod(argmod0));
495                 GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
496                            arg1, GL_NONE, argmod1,
497                            arg2, GL_NONE, argmod2,
498                            arg0, GL_NONE, argmod0));
499                 break;
500
501             case WINED3DTOP_BUMPENVMAP:
502             case WINED3DTOP_BUMPENVMAPLUMINANCE:
503                 /* Those are handled in the first pass of the shader(generation pass 1 and 2) alraedy */
504                 break;
505
506             default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
507         }
508
509         arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0);
510         arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1);
511         arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2);
512         dstmod = GL_NONE;
513         argmodextra = GL_NONE;
514         extrarg = GL_NONE;
515
516         switch(op[stage].aop) {
517             case WINED3DTOP_DISABLE:
518                 /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
519                 if(stage == 0) {
520                     TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
521                     GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
522                                GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
523                 }
524                 break;
525
526             case WINED3DTOP_SELECTARG2:
527                 arg1 = arg2;
528                 argmod1 = argmod2;
529             case WINED3DTOP_SELECTARG1:
530                 TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_NONE, %s)\n",
531                       debug_register(arg1), debug_argmod(argmod1));
532                 GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
533                                                  arg1, GL_NONE, argmod1));
534                 break;
535
536             case WINED3DTOP_MODULATE4X:
537                 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
538             case WINED3DTOP_MODULATE2X:
539                 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
540             case WINED3DTOP_MODULATE:
541                 TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI,          %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
542                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
543                 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, dstmod,
544                                                  arg1, GL_NONE, argmod1,
545                                                  arg2, GL_NONE, argmod2));
546                 break;
547
548             case WINED3DTOP_ADDSIGNED2X:
549                 dstmod = GL_2X_BIT_ATI;
550             case WINED3DTOP_ADDSIGNED:
551                 argmodextra = GL_BIAS_BIT_ATI;
552             case WINED3DTOP_ADD:
553                 TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI,          %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
554                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmodextra | argmod2));
555                 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, dstmod,
556                            arg1, GL_NONE, argmod1,
557                            arg2, GL_NONE, argmodextra | argmod2));
558                 break;
559
560             case WINED3DTOP_SUBTRACT:
561                 TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
562                       debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
563                 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, dstmod,
564                            arg1, GL_NONE, argmod1,
565                            arg2, GL_NONE, argmod2));
566                 break;
567
568             case WINED3DTOP_ADDSMOOTH:
569                 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
570                 TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
571                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
572                 /* Dst = arg1 + * arg2(1 -arg 1)
573                  *     = arg2 * (1 - arg1) + arg1
574                  */
575                 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE,
576                                                  arg2, GL_NONE, argmod2,
577                                                  arg1, GL_NONE, argmodextra,
578                                                  arg1, GL_NONE, argmod1));
579                 break;
580
581             case WINED3DTOP_BLENDCURRENTALPHA:
582                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL);
583             case WINED3DTOP_BLENDFACTORALPHA:
584                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL);
585             case WINED3DTOP_BLENDTEXTUREALPHA:
586                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
587             case WINED3DTOP_BLENDDIFFUSEALPHA:
588                 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL);
589                 TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_ALPHA, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
590                       debug_register(extrarg), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
591                 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE,
592                                                  extrarg, GL_ALPHA, GL_NONE,
593                                                  arg1, GL_NONE, argmod1,
594                                                  arg2, GL_NONE, argmod2));
595                 break;
596
597             case WINED3DTOP_BLENDTEXTUREALPHAPM:
598                 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
599                 TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_NONE, %s, %s, GL_ALPHA, GL_COMP_BIT_ATI, %s, GL_NONE, %s)\n",
600                       debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_register(arg1), debug_argmod(argmod1));
601                 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE,
602                                                  arg2, GL_NONE,  argmod2,
603                                                  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
604                                                  arg1, GL_NONE,  argmod1));
605                 break;
606
607             /* D3DTOP_PREMODULATE ???? */
608
609             case WINED3DTOP_DOTPRODUCT3:
610                 TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
611                       debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
612                 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_4X_BIT_ATI,
613                                                  arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
614                                                  arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
615                 break;
616
617             case WINED3DTOP_MULTIPLYADD:
618                 TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
619                       debug_register(arg0), debug_argmod(argmod0), debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmod1));
620                 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI,          GL_NONE,
621                            arg0, GL_NONE, argmod0,
622                            arg2, GL_NONE, argmod2,
623                            arg1, GL_NONE, argmod1));
624                 break;
625
626             case WINED3DTOP_LERP:
627                 TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI,          GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
628                       debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_argmod(argmod0));
629                 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE,
630                                                  arg1, GL_NONE, argmod1,
631                                                  arg2, GL_NONE, argmod2,
632                                                  arg0, GL_NONE, argmod0));
633                 break;
634
635             case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
636             case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
637             case WINED3DTOP_MODULATECOLOR_ADDALPHA:
638             case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
639             case WINED3DTOP_BUMPENVMAP:
640             case WINED3DTOP_BUMPENVMAPLUMINANCE:
641                 ERR("Application uses an invalid alpha operation\n");
642                 break;
643
644             default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
645         }
646     }
647
648     TRACE("glEndFragmentShaderATI()\n");
649     GL_EXTCALL(glEndFragmentShaderATI());
650     checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
651     return ret;
652 }
653 #undef GLINFO_LOCATION
654
655 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
656 static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
657     IWineD3DDeviceImpl          *This = stateblock->wineD3DDevice;
658     struct atifs_ffp_desc       *desc;
659     struct texture_stage_op     op[MAX_TEXTURES];
660     struct atifs_private_data   *priv = (struct atifs_private_data *) This->shader_priv;
661
662     gen_ffp_op(stateblock, op);
663     desc = (struct atifs_ffp_desc *) find_ffp_shader(&priv->fragment_shaders, op);
664     if(!desc) {
665         desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));
666         if(!desc) {
667             ERR("Out of memory\n");
668             return;
669         }
670         memcpy(desc->parent.op, op, sizeof(op));
671         desc->shader = gen_ati_shader(op, &GLINFO_LOCATION);
672         add_ffp_shader(&priv->fragment_shaders, &desc->parent);
673         TRACE("Allocated fixed function replacement shader descriptor %p\n", desc);
674     }
675
676     GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
677 }
678
679 static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
680     float col[4];
681     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
682
683     GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col));
684     checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)");
685 }
686
687 static void set_bumpmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
688     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
689     float mat[2][2];
690
691     mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
692     mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
693     mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
694     mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
695     /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat
696      * constants can be in any range. While they should stay between [-1.0 and 1.0] because
697      * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally,
698      * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the
699      * shader(it is free). This might potentially reduce precision. However, if the hardware does
700      * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway
701      */
702     mat[0][0] = (mat[0][0] + 1.0) * 0.5;
703     mat[1][0] = (mat[1][0] + 1.0) * 0.5;
704     mat[0][1] = (mat[0][1] + 1.0) * 0.5;
705     mat[1][1] = (mat[1][1] + 1.0) * 0.5;
706     GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), (float *) mat));
707     checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), mat)");
708
709     /* FIXME: This should go away
710      * This is currently needed because atifs borrows a pixel shader implementation
711      * from somewhere else, but consumes bump map matrix change events. The other pixel
712      * shader implementation may need notification about the change to update the texbem
713      * constants. Once ATIFS supports real shaders on its own, and GLSL/ARB have a replacement
714      * pipeline this call can go away
715      *
716      * FIXME2: Even considering this workaround calling FFPStateTable directly isn't nice
717      * as well. Better would be to call the model's table we inherit from, but currently
718      * it is always the FFP table, and as soon as this changes we can remove the call anyway
719      */
720     FFPStateTable[state].apply(state, stateblock, context);
721 }
722 #undef GLINFO_LOCATION
723
724 /* our state table. Borrows lots of stuff from the base implementation */
725 struct StateEntry ATIFSStateTable[STATE_HIGHEST + 1];
726
727 static void init_state_table() {
728     unsigned int i;
729     const DWORD rep = STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP);
730     memcpy(ATIFSStateTable, FFPStateTable, sizeof(ATIFSStateTable));
731
732     for(i = 0; i < MAX_TEXTURES; i++) {
733         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply = set_tex_op_atifs;
734         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].representative = rep;
735         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG1)].apply = set_tex_op_atifs;
736         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG1)].representative = rep;
737         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG2)].apply = set_tex_op_atifs;
738         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG2)].representative = rep;
739         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG0)].apply = set_tex_op_atifs;
740         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG0)].representative = rep;
741
742         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAOP)].apply = set_tex_op_atifs;
743         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAOP)].representative = rep;
744         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG1)].apply = set_tex_op_atifs;
745         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG1)].representative = rep;
746         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG2)].apply = set_tex_op_atifs;
747         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG2)].representative = rep;
748         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].apply = set_tex_op_atifs;
749         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].representative = rep;
750
751         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00)].apply = set_bumpmat;
752         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT01)].apply = set_bumpmat;
753         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT10)].apply = set_bumpmat;
754         ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT11)].apply = set_bumpmat;
755     }
756
757     ATIFSStateTable[STATE_RENDER(WINED3DRS_TEXTUREFACTOR)].apply = state_texfactor_atifs;
758     ATIFSStateTable[STATE_RENDER(WINED3DRS_TEXTUREFACTOR)].representative = STATE_RENDER(WINED3DRS_TEXTUREFACTOR);
759 }
760
761 /* GL_ATI_fragment_shader backend.It borrows a lot from a the
762  * ARB shader backend, currently the whole vertex processing
763  * code. This code would also forward pixel shaders, but if
764  * GL_ARB_fragment_program is supported, the atifs shader backend
765  * is not used.
766  */
767 static void shader_atifs_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
768     arb_program_shader_backend.shader_select(iface, usePS, useVS);
769 }
770
771 static void shader_atifs_select_depth_blt(IWineD3DDevice *iface) {
772     arb_program_shader_backend.shader_select_depth_blt(iface);
773 }
774
775 static void shader_atifs_destroy_depth_blt(IWineD3DDevice *iface) {
776     arb_program_shader_backend.shader_destroy_depth_blt(iface);
777 }
778
779 static void shader_atifs_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {
780     arb_program_shader_backend.shader_load_constants(iface, usePS, useVS);
781 }
782
783 static void shader_atifs_cleanup(IWineD3DDevice *iface) {
784     arb_program_shader_backend.shader_cleanup(iface);
785 }
786
787 static void shader_atifs_color_correction(SHADER_OPCODE_ARG* arg) {
788     arb_program_shader_backend.shader_color_correction(arg);
789 }
790
791 static void shader_atifs_destroy(IWineD3DBaseShader *iface) {
792     arb_program_shader_backend.shader_destroy(iface);
793 }
794
795 static HRESULT shader_atifs_alloc(IWineD3DDevice *iface) {
796     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
797     HRESULT hr;
798     struct atifs_private_data *priv;
799     hr = arb_program_shader_backend.shader_alloc_private(iface);
800     if(FAILED(hr)) return hr;
801
802     This->shader_priv = HeapReAlloc(GetProcessHeap(), 0, This->shader_priv,
803                                     sizeof(struct atifs_private_data));
804     priv = (struct atifs_private_data *) This->shader_priv;
805     list_init(&priv->fragment_shaders);
806     return WINED3D_OK;
807 }
808
809 #define GLINFO_LOCATION This->adapter->gl_info
810 static void shader_atifs_free(IWineD3DDevice *iface) {
811     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
812     struct atifs_private_data *priv = (struct atifs_private_data *) This->shader_priv;
813     struct ffp_desc *entry, *entry2;
814     struct atifs_ffp_desc *entry_ati;
815
816     ENTER_GL();
817     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &priv->fragment_shaders, struct ffp_desc, entry) {
818         entry_ati = (struct atifs_ffp_desc *) entry;
819         GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
820         checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
821         list_remove(&entry->entry);
822         HeapFree(GetProcessHeap(), 0, entry);
823     }
824     LEAVE_GL();
825
826     /* Not actually needed, but revert what we've done before */
827     This->shader_priv = HeapReAlloc(GetProcessHeap(), 0, This->shader_priv,
828                                     sizeof(struct shader_arb_priv));
829     arb_program_shader_backend.shader_free_private(iface);
830 }
831 #undef GLINFO_LOCATION
832
833 static BOOL shader_atifs_dirty_const(IWineD3DDevice *iface) {
834     return arb_program_shader_backend.shader_dirtifyable_constants(iface);
835 }
836
837 static void shader_atifs_load_init(void) {
838     init_state_table();
839     arb_program_shader_backend.shader_dll_load_init();
840 }
841
842 static void shader_atifs_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *caps) {
843     arb_program_shader_backend.shader_get_caps(devtype, gl_info, caps);
844
845     caps->TextureOpCaps =  WINED3DTEXOPCAPS_DISABLE                     |
846                            WINED3DTEXOPCAPS_SELECTARG1                  |
847                            WINED3DTEXOPCAPS_SELECTARG2                  |
848                            WINED3DTEXOPCAPS_MODULATE4X                  |
849                            WINED3DTEXOPCAPS_MODULATE2X                  |
850                            WINED3DTEXOPCAPS_MODULATE                    |
851                            WINED3DTEXOPCAPS_ADDSIGNED2X                 |
852                            WINED3DTEXOPCAPS_ADDSIGNED                   |
853                            WINED3DTEXOPCAPS_ADD                         |
854                            WINED3DTEXOPCAPS_SUBTRACT                    |
855                            WINED3DTEXOPCAPS_ADDSMOOTH                   |
856                            WINED3DTEXOPCAPS_BLENDCURRENTALPHA           |
857                            WINED3DTEXOPCAPS_BLENDFACTORALPHA            |
858                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHA           |
859                            WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA           |
860                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM         |
861                            WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR      |
862                            WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA      |
863                            WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA   |
864                            WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR   |
865                            WINED3DTEXOPCAPS_DOTPRODUCT3                 |
866                            WINED3DTEXOPCAPS_MULTIPLYADD                 |
867                            WINED3DTEXOPCAPS_LERP                        |
868                            WINED3DTEXOPCAPS_BUMPENVMAP;
869
870     /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
871     and WINED3DTEXOPCAPS_PREMODULATE */
872
873     /* GL_ATI_fragment_shader only supports up to 6 textures, which was the limit on r200 cards
874      * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
875      * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
876      * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
877      * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
878      * pipeline, and almost all games are happy with that. We can however support up to 8
879      * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
880      * only 1 instruction.
881      *
882      * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
883      * r200 series and use an ARB or GLSL shader instead
884      */
885     if(caps->MaxSimultaneousTextures > 6) {
886         WARN("OpenGL fixed function supports %d simultaneous textures,\n", caps->MaxSimultaneousTextures);
887         WARN("but GL_ATI_fragment_shader limits this to 6\n");
888         caps->MaxSimultaneousTextures = 6;
889     }
890 }
891
892 static void shader_atifs_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
893     ERR("Should not get here\n");
894 }
895
896 static void shader_atifs_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) {
897     arb_program_shader_backend.shader_generate_vshader(iface, buffer);
898 }
899
900 const shader_backend_t atifs_shader_backend = {
901     shader_atifs_select,
902     shader_atifs_select_depth_blt,
903     shader_atifs_destroy_depth_blt,
904     shader_atifs_load_constants,
905     shader_atifs_cleanup,
906     shader_atifs_color_correction,
907     shader_atifs_destroy,
908     shader_atifs_alloc,
909     shader_atifs_free,
910     shader_atifs_dirty_const,
911     shader_atifs_generate_pshader,
912     shader_atifs_generate_vshader,
913     shader_atifs_get_caps,
914     shader_atifs_load_init,
915     ATIFSStateTable
916 };