wined3d: Fragment processing using GL_ATI_fragment_shader.
[wine.git] / dlls / wined3d / ati_fragment_shader.c
blobd1a4a8b35418c41ffce020d4c436f71a0990f43e
1 /*
2 * Fixed function pipeline replacement using GL_ATI_fragment_shader
4 * Copyright 2008 Stefan Dösinger(for CodeWeavers)
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.
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.
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdio.h>
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
30 /* Some private defines, Constant associations, etc */
31 #define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI
32 #define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI
33 #define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI
34 #define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI
35 #define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI
36 #define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI
37 #define ATI_FFP_CONST_TFACTOR GL_CON_6_ATI
39 /* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */
40 struct atifs_ffp_desc
42 struct ffp_desc parent;
43 GLuint shader;
46 struct atifs_private_data
48 struct shader_arb_priv parent;
49 struct list fragment_shaders; /* A linked list to track fragment pipeline replacement shaders */
53 static const char *debug_dstmod(GLuint mod) {
54 switch(mod) {
55 case GL_NONE: return "GL_NONE";
56 case GL_2X_BIT_ATI: return "GL_2X_BIT_ATI";
57 case GL_4X_BIT_ATI: return "GL_4X_BIT_ATI";
58 case GL_8X_BIT_ATI: return "GL_8X_BIT_ATI";
59 case GL_HALF_BIT_ATI: return "GL_HALF_BIT_ATI";
60 case GL_QUARTER_BIT_ATI: return "GL_QUARTER_BIT_ATI";
61 case GL_EIGHTH_BIT_ATI: return "GL_EIGHTH_BIT_ATI";
62 case GL_SATURATE_BIT_ATI: return "GL_SATURATE_BIT_ATI";
63 default: return "Unexpected modifier\n";
67 static const char *debug_argmod(GLuint mod) {
68 switch(mod) {
69 case GL_NONE:
70 return "GL_NONE";
72 case GL_2X_BIT_ATI:
73 return "GL_2X_BIT_ATI";
74 case GL_COMP_BIT_ATI:
75 return "GL_COMP_BIT_ATI";
76 case GL_NEGATE_BIT_ATI:
77 return "GL_NEGATE_BIT_ATI";
78 case GL_BIAS_BIT_ATI:
79 return "GL_BIAS_BIT_ATI";
81 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI:
82 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI";
83 case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI:
84 return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI";
85 case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI:
86 return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI";
87 case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
88 return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
89 case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
90 return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
91 case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
92 return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
94 case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
95 return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
96 case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
97 return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
98 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI:
99 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
100 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI:
101 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
103 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI:
104 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
106 default:
107 return "Unexpected argmod combination\n";
110 static const char *debug_register(GLuint reg) {
111 switch(reg) {
112 case GL_REG_0_ATI: return "GL_REG_0_ATI";
113 case GL_REG_1_ATI: return "GL_REG_1_ATI";
114 case GL_REG_2_ATI: return "GL_REG_2_ATI";
115 case GL_REG_3_ATI: return "GL_REG_3_ATI";
116 case GL_REG_4_ATI: return "GL_REG_4_ATI";
117 case GL_REG_5_ATI: return "GL_REG_5_ATI";
119 case GL_CON_0_ATI: return "GL_CON_0_ATI";
120 case GL_CON_1_ATI: return "GL_CON_1_ATI";
121 case GL_CON_2_ATI: return "GL_CON_2_ATI";
122 case GL_CON_3_ATI: return "GL_CON_3_ATI";
123 case GL_CON_4_ATI: return "GL_CON_4_ATI";
124 case GL_CON_5_ATI: return "GL_CON_5_ATI";
125 case GL_CON_6_ATI: return "GL_CON_6_ATI";
126 case GL_CON_7_ATI: return "GL_CON_7_ATI";
128 case GL_ZERO: return "GL_ZERO";
129 case GL_ONE: return "GL_ONE";
130 case GL_PRIMARY_COLOR: return "GL_PRIMARY_COLOR";
131 case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI";
133 default: return "Unknown register\n";
137 static const char *debug_swizzle(GLuint swizzle) {
138 switch(swizzle) {
139 case GL_SWIZZLE_STR_ATI: return "GL_SWIZZLE_STR_ATI";
140 case GL_SWIZZLE_STQ_ATI: return "GL_SWIZZLE_STQ_ATI";
141 case GL_SWIZZLE_STR_DR_ATI: return "GL_SWIZZLE_STR_DR_ATI";
142 case GL_SWIZZLE_STQ_DQ_ATI: return "GL_SWIZZLE_STQ_DQ_ATI";
143 default: return "unknown swizzle";
147 #define GLINFO_LOCATION (*gl_info)
148 static GLuint register_for_arg(DWORD arg, WineD3D_GL_Info *gl_info, unsigned int stage, GLuint *mod) {
149 GLenum ret;
151 if(mod) *mod = GL_NONE;
152 if(arg == 0xFFFFFFFF) return -1; /* This is the marker for unused registers */
154 switch(arg & WINED3DTA_SELECTMASK) {
155 case WINED3DTA_DIFFUSE:
156 ret = GL_PRIMARY_COLOR;
157 break;
159 case WINED3DTA_CURRENT:
160 /* Note that using GL_REG_0_ATI for the passed on register is safe because
161 * texture0 is read at stage0, so in the worst case it is read in the
162 * instruction writing to reg0. Afterwards texture0 is not used any longer.
163 * If we're reading from current
165 if(stage == 0) {
166 ret = GL_PRIMARY_COLOR;
167 } else {
168 ret = GL_REG_0_ATI;
170 break;
172 case WINED3DTA_TEXTURE:
173 ret = GL_REG_0_ATI + stage;
174 break;
176 case WINED3DTA_TFACTOR:
177 ret = ATI_FFP_CONST_TFACTOR;
178 break;
180 case WINED3DTA_SPECULAR:
181 ret = GL_SECONDARY_INTERPOLATOR_ATI;
182 break;
184 case WINED3DTA_TEMP:
185 FIXME("Unhandled source argument WINED3DTA_TEMP\n");
186 ret = 0;
187 break;
189 case WINED3DTA_CONSTANT:
190 FIXME("Unhandled source argument WINED3DTA_TEMP\n");
191 ret = GL_CON_0_ATI;
192 break;
194 default:
195 FIXME("Unknown source argument %d\n", arg);
196 ret = GL_ZERO;
199 if(arg & WINED3DTA_COMPLEMENT) {
200 if(mod) *mod |= GL_COMP_BIT_ATI;
202 if(arg & WINED3DTA_ALPHAREPLICATE) {
203 FIXME("Unhandled read modifier WINED3DTA_ALPHAREPLICATE\n");
205 return ret;
208 static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_GL_Info *gl_info) {
209 GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
210 unsigned int stage;
211 GLuint arg0, arg1, arg2, extrarg;
212 GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
213 GLuint swizzle;
215 if(!ret) {
216 ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
217 return 0;
219 GL_EXTCALL(glBindFragmentShaderATI(ret));
220 checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
222 TRACE("glBeginFragmentShaderATI()\n");
223 GL_EXTCALL(glBeginFragmentShaderATI());
224 checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
226 for(stage = 0; stage < GL_LIMITS(textures); stage++) {
227 if(op[stage].cop == WINED3DTOP_DISABLE) {
228 break;
231 if(op[stage].projected == proj_none) {
232 swizzle = GL_SWIZZLE_STR_ATI;
233 } else if(op[stage].projected == proj_count3) {
234 /* TODO: D3DTTFF_COUNT3 | D3DTTFF_PROJECTED would be GL_SWIZZLE_STR_DR_ATI.
235 * However, the FFP vertex processing texture transform matrix handler does
236 * some transformations in the texture matrix which makes the 3rd coordinate
237 * arrive in Q, not R in that case. This is needed for opengl fixed function
238 * fragment processing which always divides by Q. In this backend we can
239 * handle that properly and be compatible with vertex shader output and avoid
240 * side effects of the texture matrix games
242 swizzle = GL_SWIZZLE_STQ_DQ_ATI;
243 } else {
244 swizzle = GL_SWIZZLE_STQ_DQ_ATI;
247 if((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
248 (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
249 (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
250 (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
251 (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
252 (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE ||
253 op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) {
254 /* TODO 1: Handle bump mapping. In this case we have to generate a first pass,
255 * and use GL_REG_x_ATI as source instead of GL_TEXTURE_x.
257 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
258 stage, stage, debug_swizzle(swizzle));
259 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
260 GL_TEXTURE0_ARB + stage,
261 swizzle));
265 for(stage = 0; stage < MAX_TEXTURES; stage++) {
266 if(op[stage].cop == WINED3DTOP_DISABLE) {
267 if(stage == 0) {
268 /* Handle complete texture disabling gracefully */
269 TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
270 GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
271 GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
272 TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
273 GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
274 GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
276 break;
279 arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0);
280 arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1);
281 arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2);
282 dstmod = GL_NONE;
283 argmodextra = GL_NONE;
284 extrarg = GL_NONE;
286 switch(op[stage].cop) {
287 case WINED3DTOP_SELECTARG2:
288 arg1 = arg2;
289 argmod1 = argmod2;
290 case WINED3DTOP_SELECTARG1:
291 TRACE("glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, %s, GL_NONE, %s)\n",
292 debug_register(arg1), debug_argmod(argmod1));
293 GL_EXTCALL(glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
294 arg1, GL_NONE, argmod1));
295 break;
297 case WINED3DTOP_MODULATE4X:
298 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
299 case WINED3DTOP_MODULATE2X:
300 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
301 case WINED3DTOP_MODULATE:
302 TRACE("glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
303 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
304 GL_EXTCALL(glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
305 arg1, GL_NONE, argmod1,
306 arg2, GL_NONE, argmod2));
307 break;
309 case WINED3DTOP_ADDSIGNED2X:
310 dstmod = GL_2X_BIT_ATI;
311 case WINED3DTOP_ADDSIGNED:
312 argmodextra = GL_BIAS_BIT_ATI;
313 case WINED3DTOP_ADD:
314 TRACE("glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
315 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmodextra | argmod2));
316 GL_EXTCALL(glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
317 arg1, GL_NONE, argmod1,
318 arg2, GL_NONE, argmodextra | argmod2));
319 break;
321 case WINED3DTOP_SUBTRACT:
322 TRACE("glColorFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
323 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
324 GL_EXTCALL(glColorFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
325 arg1, GL_NONE, argmod1,
326 arg2, GL_NONE, argmod2));
327 break;
329 case WINED3DTOP_ADDSMOOTH:
330 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
331 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",
332 debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
333 /* Dst = arg1 + * arg2(1 -arg 1)
334 * = arg2 * (1 - arg1) + arg1
336 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
337 arg2, GL_NONE, argmod2,
338 arg1, GL_NONE, argmodextra,
339 arg1, GL_NONE, argmod1));
340 break;
342 case WINED3DTOP_BLENDCURRENTALPHA:
343 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL);
344 case WINED3DTOP_BLENDFACTORALPHA:
345 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL);
346 case WINED3DTOP_BLENDTEXTUREALPHA:
347 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
348 case WINED3DTOP_BLENDDIFFUSEALPHA:
349 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL);
350 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",
351 debug_register(extrarg), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
352 GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
353 extrarg, GL_ALPHA, GL_NONE,
354 arg1, GL_NONE, argmod1,
355 arg2, GL_NONE, argmod2));
356 break;
358 case WINED3DTOP_BLENDTEXTUREALPHAPM:
359 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
360 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",
361 debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_register(arg1), debug_argmod(argmod1));
362 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
363 arg2, GL_NONE, argmod2,
364 arg0, GL_ALPHA, GL_COMP_BIT_ATI,
365 arg1, GL_NONE, argmod1));
366 break;
368 /* D3DTOP_PREMODULATE ???? */
370 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
371 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
372 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
373 if(!argmodextra) argmodextra = argmod1;
374 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",
375 debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(arg1));
376 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
377 arg2, GL_NONE, argmod2,
378 arg1, GL_ALPHA, argmodextra,
379 arg1, GL_NONE, argmod1));
380 break;
382 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
383 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
384 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
385 if(!argmodextra) argmodextra = argmod1;
386 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",
387 debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
388 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
389 arg2, GL_NONE, argmod2,
390 arg1, GL_NONE, argmodextra,
391 arg1, GL_ALPHA, argmod1));
392 break;
394 case WINED3DTOP_DOTPRODUCT3:
395 TRACE("glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
396 debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
397 GL_EXTCALL(glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI,
398 arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
399 arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
400 break;
402 case WINED3DTOP_MULTIPLYADD:
403 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",
404 debug_register(arg0), debug_argmod(argmod0), debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmod1));
405 GL_EXTCALL(glColorFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
406 arg0, GL_NONE, argmod0,
407 arg2, GL_NONE, argmod2,
408 arg1, GL_NONE, argmod1));
409 break;
411 case WINED3DTOP_LERP:
412 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",
413 debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_argmod(argmod0));
414 GL_EXTCALL(glColorFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
415 arg1, GL_NONE, argmod1,
416 arg2, GL_NONE, argmod2,
417 arg0, GL_NONE, argmod0));
418 break;
420 default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
423 arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0);
424 arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1);
425 arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2);
426 dstmod = GL_NONE;
427 argmodextra = GL_NONE;
428 extrarg = GL_NONE;
430 switch(op[stage].aop) {
431 case WINED3DTOP_DISABLE:
432 /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
433 if(stage == 0) {
434 TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_PRIMARY_COLOR, GL_NONE, GL_NONE)\n");
435 GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
436 GL_PRIMARY_COLOR, GL_NONE, GL_NONE));
438 break;
440 case WINED3DTOP_SELECTARG2:
441 arg1 = arg2;
442 argmod1 = argmod2;
443 case WINED3DTOP_SELECTARG1:
444 TRACE("glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, %s, GL_NONE, %s)\n",
445 debug_register(arg1), debug_argmod(argmod1));
446 GL_EXTCALL(glAlphaFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE,
447 arg1, GL_NONE, argmod1));
448 break;
450 case WINED3DTOP_MODULATE4X:
451 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
452 case WINED3DTOP_MODULATE2X:
453 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
454 case WINED3DTOP_MODULATE:
455 TRACE("glAlphaFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
456 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
457 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, dstmod,
458 arg1, GL_NONE, argmod1,
459 arg2, GL_NONE, argmod2));
460 break;
462 case WINED3DTOP_ADDSIGNED2X:
463 dstmod = GL_2X_BIT_ATI;
464 case WINED3DTOP_ADDSIGNED:
465 argmodextra = GL_BIAS_BIT_ATI;
466 case WINED3DTOP_ADD:
467 TRACE("glAlphaFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
468 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmodextra | argmod2));
469 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, dstmod,
470 arg1, GL_NONE, argmod1,
471 arg2, GL_NONE, argmodextra | argmod2));
472 break;
474 case WINED3DTOP_SUBTRACT:
475 TRACE("glAlphaFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
476 debug_dstmod(dstmod), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
477 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_SUB_ATI, GL_REG_0_ATI, dstmod,
478 arg1, GL_NONE, argmod1,
479 arg2, GL_NONE, argmod2));
480 break;
482 case WINED3DTOP_ADDSMOOTH:
483 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
484 TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
485 debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmodextra), debug_register(arg1), debug_argmod(argmod1));
486 /* Dst = arg1 + * arg2(1 -arg 1)
487 * = arg2 * (1 - arg1) + arg1
489 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE,
490 arg2, GL_NONE, argmod2,
491 arg1, GL_NONE, argmodextra,
492 arg1, GL_NONE, argmod1));
493 break;
495 case WINED3DTOP_BLENDCURRENTALPHA:
496 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL);
497 case WINED3DTOP_BLENDFACTORALPHA:
498 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL);
499 case WINED3DTOP_BLENDTEXTUREALPHA:
500 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
501 case WINED3DTOP_BLENDDIFFUSEALPHA:
502 if(extrarg == GL_NONE) extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL);
503 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",
504 debug_register(extrarg), debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2));
505 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE,
506 extrarg, GL_ALPHA, GL_NONE,
507 arg1, GL_NONE, argmod1,
508 arg2, GL_NONE, argmod2));
509 break;
511 case WINED3DTOP_BLENDTEXTUREALPHAPM:
512 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL);
513 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",
514 debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_register(arg1), debug_argmod(argmod1));
515 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE,
516 arg2, GL_NONE, argmod2,
517 arg0, GL_ALPHA, GL_COMP_BIT_ATI,
518 arg1, GL_NONE, argmod1));
519 break;
521 /* D3DTOP_PREMODULATE ???? */
523 case WINED3DTOP_DOTPRODUCT3:
524 TRACE("glAlphaFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_NONE, GL_4X_BIT_ATI, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
525 debug_register(arg1), debug_argmod(argmod1 | GL_BIAS_BIT_ATI), debug_register(arg2), debug_argmod(argmod2 | GL_BIAS_BIT_ATI));
526 GL_EXTCALL(glAlphaFragmentOp2ATI(GL_DOT3_ATI, GL_REG_0_ATI, GL_4X_BIT_ATI,
527 arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
528 arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI));
529 break;
531 case WINED3DTOP_MULTIPLYADD:
532 TRACE("glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
533 debug_register(arg0), debug_argmod(argmod0), debug_register(arg2), debug_argmod(argmod2), debug_register(arg1), debug_argmod(argmod1));
534 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_MAD_ATI, GL_REG_0_ATI, GL_NONE,
535 arg0, GL_NONE, argmod0,
536 arg2, GL_NONE, argmod2,
537 arg1, GL_NONE, argmod1));
538 break;
540 case WINED3DTOP_LERP:
541 TRACE("glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE, %s, GL_NONE, %s, %s, GL_NONE, %s, %s, GL_NONE, %s)\n",
542 debug_register(arg1), debug_argmod(argmod1), debug_register(arg2), debug_argmod(argmod2), debug_register(arg0), debug_argmod(argmod0));
543 GL_EXTCALL(glAlphaFragmentOp3ATI(GL_LERP_ATI, GL_REG_0_ATI, GL_NONE,
544 arg1, GL_NONE, argmod1,
545 arg2, GL_NONE, argmod2,
546 arg0, GL_NONE, argmod0));
547 break;
549 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
550 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
551 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
552 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
553 case WINED3DTOP_BUMPENVMAP:
554 case WINED3DTOP_BUMPENVMAPLUMINANCE:
555 ERR("Application uses an invalid alpha operation\n");
556 break;
558 default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
562 TRACE("glEndFragmentShaderATI()\n");
563 GL_EXTCALL(glEndFragmentShaderATI());
564 checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
565 return ret;
567 #undef GLINFO_LOCATION
569 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
570 static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
571 IWineD3DDeviceImpl *This = stateblock->wineD3DDevice;
572 struct atifs_ffp_desc *desc;
573 struct texture_stage_op op[MAX_TEXTURES];
574 struct atifs_private_data *priv = (struct atifs_private_data *) This->shader_priv;
576 gen_ffp_op(stateblock, op);
577 desc = (struct atifs_ffp_desc *) find_ffp_shader(&priv->fragment_shaders, op);
578 if(!desc) {
579 desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));
580 if(!desc) {
581 ERR("Out of memory\n");
582 return;
584 memcpy(desc->parent.op, op, sizeof(op));
585 desc->shader = gen_ati_shader(op, &GLINFO_LOCATION);
586 add_ffp_shader(&priv->fragment_shaders, &desc->parent);
587 TRACE("Allocated fixed function replacement shader descriptor %p\n", desc);
590 GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
593 static void state_texfactor_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
594 float col[4];
595 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
597 GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col));
598 checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)");
601 #undef GLINFO_LOCATION
603 /* our state table. Borrows lots of stuff from the base implementation */
604 struct StateEntry ATIFSStateTable[STATE_HIGHEST + 1];
606 static void init_state_table() {
607 unsigned int i;
608 const DWORD rep = STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP);
609 memcpy(ATIFSStateTable, FFPStateTable, sizeof(ATIFSStateTable));
611 for(i = 0; i < MAX_TEXTURES; i++) {
612 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply = set_tex_op_atifs;
613 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].representative = rep;
614 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG1)].apply = set_tex_op_atifs;
615 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG1)].representative = rep;
616 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG2)].apply = set_tex_op_atifs;
617 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG2)].representative = rep;
618 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG0)].apply = set_tex_op_atifs;
619 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLORARG0)].representative = rep;
621 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAOP)].apply = set_tex_op_atifs;
622 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAOP)].representative = rep;
623 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG1)].apply = set_tex_op_atifs;
624 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG1)].representative = rep;
625 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG2)].apply = set_tex_op_atifs;
626 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG2)].representative = rep;
627 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].apply = set_tex_op_atifs;
628 ATIFSStateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_ALPHAARG0)].representative = rep;
631 ATIFSStateTable[STATE_RENDER(WINED3DRS_TEXTUREFACTOR)].apply = state_texfactor_atifs;
632 ATIFSStateTable[STATE_RENDER(WINED3DRS_TEXTUREFACTOR)].representative = STATE_RENDER(WINED3DRS_TEXTUREFACTOR);
635 /* GL_ATI_fragment_shader backend.It borrows a lot from a the
636 * ARB shader backend, currently the whole vertex processing
637 * code. This code would also forward pixel shaders, but if
638 * GL_ARB_fragment_program is supported, the atifs shader backend
639 * is not used.
641 static void shader_atifs_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
642 arb_program_shader_backend.shader_select(iface, usePS, useVS);
645 static void shader_atifs_select_depth_blt(IWineD3DDevice *iface) {
646 arb_program_shader_backend.shader_select_depth_blt(iface);
649 static void shader_atifs_destroy_depth_blt(IWineD3DDevice *iface) {
650 arb_program_shader_backend.shader_destroy_depth_blt(iface);
653 static void shader_atifs_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {
654 arb_program_shader_backend.shader_load_constants(iface, usePS, useVS);
657 static void shader_atifs_cleanup(IWineD3DDevice *iface) {
658 arb_program_shader_backend.shader_cleanup(iface);
661 static void shader_atifs_color_correction(SHADER_OPCODE_ARG* arg) {
662 arb_program_shader_backend.shader_color_correction(arg);
665 static void shader_atifs_destroy(IWineD3DBaseShader *iface) {
666 arb_program_shader_backend.shader_destroy(iface);
669 static HRESULT shader_atifs_alloc(IWineD3DDevice *iface) {
670 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
671 HRESULT hr;
672 struct atifs_private_data *priv;
673 hr = arb_program_shader_backend.shader_alloc_private(iface);
674 if(FAILED(hr)) return hr;
676 This->shader_priv = HeapReAlloc(GetProcessHeap(), 0, This->shader_priv,
677 sizeof(struct atifs_private_data));
678 priv = (struct atifs_private_data *) This->shader_priv;
679 list_init(&priv->fragment_shaders);
680 return WINED3D_OK;
683 #define GLINFO_LOCATION This->adapter->gl_info
684 static void shader_atifs_free(IWineD3DDevice *iface) {
685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
686 struct atifs_private_data *priv = (struct atifs_private_data *) This->shader_priv;
687 struct ffp_desc *entry, *entry2;
688 struct atifs_ffp_desc *entry_ati;
690 ENTER_GL();
691 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &priv->fragment_shaders, struct ffp_desc, entry) {
692 entry_ati = (struct atifs_ffp_desc *) entry;
693 GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
694 checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
695 list_remove(&entry->entry);
696 HeapFree(GetProcessHeap(), 0, entry);
698 LEAVE_GL();
700 /* Not actually needed, but revert what we've done before */
701 This->shader_priv = HeapReAlloc(GetProcessHeap(), 0, This->shader_priv,
702 sizeof(struct shader_arb_priv));
703 arb_program_shader_backend.shader_free_private(iface);
705 #undef GLINFO_LOCATION
707 static BOOL shader_atifs_dirty_const(IWineD3DDevice *iface) {
708 return arb_program_shader_backend.shader_dirtifyable_constants(iface);
711 static void shader_atifs_load_init(void) {
712 init_state_table();
713 arb_program_shader_backend.shader_dll_load_init();
716 static void shader_atifs_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *caps) {
717 arb_program_shader_backend.shader_get_caps(devtype, gl_info, caps);
719 caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE |
720 WINED3DTEXOPCAPS_SELECTARG1 |
721 WINED3DTEXOPCAPS_SELECTARG2 |
722 WINED3DTEXOPCAPS_MODULATE4X |
723 WINED3DTEXOPCAPS_MODULATE2X |
724 WINED3DTEXOPCAPS_MODULATE |
725 WINED3DTEXOPCAPS_ADDSIGNED2X |
726 WINED3DTEXOPCAPS_ADDSIGNED |
727 WINED3DTEXOPCAPS_ADD |
728 WINED3DTEXOPCAPS_SUBTRACT |
729 WINED3DTEXOPCAPS_ADDSMOOTH |
730 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
731 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
732 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
733 WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
734 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM |
735 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
736 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
737 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |
738 WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
739 WINED3DTEXOPCAPS_DOTPRODUCT3 |
740 WINED3DTEXOPCAPS_MULTIPLYADD |
741 WINED3DTEXOPCAPS_LERP;
743 /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAP, WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
744 and WINED3DTEXOPCAPS_PREMODULATE */
746 /* GL_ATI_fragment_shader only supports up to 6 textures, which was the limit on r200 cards
747 * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
748 * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
749 * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
750 * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
751 * pipeline, and almost all games are happy with that. We can however support up to 8
752 * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
753 * only 1 instruction.
755 * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
756 * r200 series and use an ARB or GLSL shader instead
758 if(caps->MaxSimultaneousTextures > 6) {
759 WARN("OpenGL fixed function supports %d simultaneous textures,\n", caps->MaxSimultaneousTextures);
760 WARN("but GL_ATI_fragment_shader limits this to 6\n");
761 caps->MaxSimultaneousTextures = 6;
765 static void shader_atifs_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
766 ERR("Should not get here\n");
769 static void shader_atifs_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) {
770 arb_program_shader_backend.shader_generate_vshader(iface, buffer);
773 const shader_backend_t atifs_shader_backend = {
774 shader_atifs_select,
775 shader_atifs_select_depth_blt,
776 shader_atifs_destroy_depth_blt,
777 shader_atifs_load_constants,
778 shader_atifs_cleanup,
779 shader_atifs_color_correction,
780 shader_atifs_destroy,
781 shader_atifs_alloc,
782 shader_atifs_free,
783 shader_atifs_dirty_const,
784 shader_atifs_generate_pshader,
785 shader_atifs_generate_vshader,
786 shader_atifs_get_caps,
787 shader_atifs_load_init,
788 ATIFSStateTable