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
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 */
42 struct ffp_desc parent
;
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
) {
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
) {
73 return "GL_2X_BIT_ATI";
75 return "GL_COMP_BIT_ATI";
76 case GL_NEGATE_BIT_ATI
:
77 return "GL_NEGATE_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";
107 return "Unexpected argmod combination\n";
110 static const char *debug_register(GLuint 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
) {
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
) {
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
;
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
166 ret
= GL_PRIMARY_COLOR
;
172 case WINED3DTA_TEXTURE
:
173 ret
= GL_REG_0_ATI
+ stage
;
176 case WINED3DTA_TFACTOR
:
177 ret
= ATI_FFP_CONST_TFACTOR
;
180 case WINED3DTA_SPECULAR
:
181 ret
= GL_SECONDARY_INTERPOLATOR_ATI
;
185 FIXME("Unhandled source argument WINED3DTA_TEMP\n");
189 case WINED3DTA_CONSTANT
:
190 FIXME("Unhandled source argument WINED3DTA_TEMP\n");
195 FIXME("Unknown source argument %d\n", arg
);
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");
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));
211 GLuint arg0
, arg1
, arg2
, extrarg
;
212 GLuint dstmod
, argmod0
, argmod1
, argmod2
, argmodextra
;
216 ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
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
) {
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
;
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
,
265 for(stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
266 if(op
[stage
].cop
== WINED3DTOP_DISABLE
) {
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
));
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
);
283 argmodextra
= GL_NONE
;
286 switch(op
[stage
].cop
) {
287 case WINED3DTOP_SELECTARG2
:
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
));
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
));
309 case WINED3DTOP_ADDSIGNED2X
:
310 dstmod
= GL_2X_BIT_ATI
;
311 case WINED3DTOP_ADDSIGNED
:
312 argmodextra
= GL_BIAS_BIT_ATI
;
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
);
427 argmodextra
= 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 */
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
));
440 case WINED3DTOP_SELECTARG2
:
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
));
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
));
462 case WINED3DTOP_ADDSIGNED2X
:
463 dstmod
= GL_2X_BIT_ATI
;
464 case WINED3DTOP_ADDSIGNED
:
465 argmodextra
= GL_BIAS_BIT_ATI
;
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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");
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())");
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
);
579 desc
= HeapAlloc(GetProcessHeap(), 0, sizeof(*desc
));
581 ERR("Out of memory\n");
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
) {
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() {
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
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
;
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
);
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
;
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
);
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) {
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
= {
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
,
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
,