ReactOS  0.4.14-dev-583-g2a1ba2c
ati_fragment_shader.c
Go to the documentation of this file.
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 #include "wine/port.h"
23 
24 #include <stdio.h>
25 
26 #include "wined3d_private.h"
27 
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
30 
31 /* Context activation for state handlers is done by the caller. */
32 
33 /* Some private defines, Constant associations, etc.
34  * Env bump matrix and per stage constant should be independent,
35  * a stage that bump maps can't read the per state constant
36  */
37 #define ATIFS_CONST_BUMPMAT(i) (GL_CON_0_ATI + i)
38 #define ATIFS_CONST_STAGE(i) (GL_CON_0_ATI + i)
39 #define ATIFS_CONST_TFACTOR GL_CON_6_ATI
40 
42 {
47 };
48 
49 /* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */
51 {
54  unsigned int num_textures_used;
56 };
57 
59 {
60  struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */
61 };
62 
64 {
65  const struct atifs_ffp_desc *last_shader;
66 };
67 
68 static const char *debug_dstmod(GLuint mod) {
69  switch(mod) {
70  case GL_NONE: return "GL_NONE";
71  case GL_2X_BIT_ATI: return "GL_2X_BIT_ATI";
72  case GL_4X_BIT_ATI: return "GL_4X_BIT_ATI";
73  case GL_8X_BIT_ATI: return "GL_8X_BIT_ATI";
74  case GL_HALF_BIT_ATI: return "GL_HALF_BIT_ATI";
75  case GL_QUARTER_BIT_ATI: return "GL_QUARTER_BIT_ATI";
76  case GL_EIGHTH_BIT_ATI: return "GL_EIGHTH_BIT_ATI";
77  case GL_SATURATE_BIT_ATI: return "GL_SATURATE_BIT_ATI";
78  default: return "Unexpected modifier\n";
79  }
80 }
81 
82 static const char *debug_argmod(GLuint mod) {
83  switch(mod) {
84  case GL_NONE:
85  return "GL_NONE";
86 
87  case GL_2X_BIT_ATI:
88  return "GL_2X_BIT_ATI";
89  case GL_COMP_BIT_ATI:
90  return "GL_COMP_BIT_ATI";
91  case GL_NEGATE_BIT_ATI:
92  return "GL_NEGATE_BIT_ATI";
93  case GL_BIAS_BIT_ATI:
94  return "GL_BIAS_BIT_ATI";
95 
97  return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI";
99  return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI";
101  return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI";
103  return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
105  return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
107  return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
108 
110  return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
112  return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
114  return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI";
116  return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI";
117 
119  return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI";
120 
121  default:
122  return "Unexpected argmod combination\n";
123  }
124 }
125 static const char *debug_register(GLuint reg) {
126  switch(reg) {
127  case GL_REG_0_ATI: return "GL_REG_0_ATI";
128  case GL_REG_1_ATI: return "GL_REG_1_ATI";
129  case GL_REG_2_ATI: return "GL_REG_2_ATI";
130  case GL_REG_3_ATI: return "GL_REG_3_ATI";
131  case GL_REG_4_ATI: return "GL_REG_4_ATI";
132  case GL_REG_5_ATI: return "GL_REG_5_ATI";
133 
134  case GL_CON_0_ATI: return "GL_CON_0_ATI";
135  case GL_CON_1_ATI: return "GL_CON_1_ATI";
136  case GL_CON_2_ATI: return "GL_CON_2_ATI";
137  case GL_CON_3_ATI: return "GL_CON_3_ATI";
138  case GL_CON_4_ATI: return "GL_CON_4_ATI";
139  case GL_CON_5_ATI: return "GL_CON_5_ATI";
140  case GL_CON_6_ATI: return "GL_CON_6_ATI";
141  case GL_CON_7_ATI: return "GL_CON_7_ATI";
142 
143  case GL_ZERO: return "GL_ZERO";
144  case GL_ONE: return "GL_ONE";
145  case GL_PRIMARY_COLOR: return "GL_PRIMARY_COLOR";
146  case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI";
147 
148  default: return "Unknown register\n";
149  }
150 }
151 
152 static const char *debug_swizzle(GLuint swizzle) {
153  switch(swizzle) {
154  case GL_SWIZZLE_STR_ATI: return "GL_SWIZZLE_STR_ATI";
155  case GL_SWIZZLE_STQ_ATI: return "GL_SWIZZLE_STQ_ATI";
156  case GL_SWIZZLE_STR_DR_ATI: return "GL_SWIZZLE_STR_DR_ATI";
157  case GL_SWIZZLE_STQ_DQ_ATI: return "GL_SWIZZLE_STQ_DQ_ATI";
158  default: return "unknown swizzle";
159  }
160 }
161 
162 static const char *debug_rep(GLuint rep) {
163  switch(rep) {
164  case GL_NONE: return "GL_NONE";
165  case GL_RED: return "GL_RED";
166  case GL_GREEN: return "GL_GREEN";
167  case GL_BLUE: return "GL_BLUE";
168  case GL_ALPHA: return "GL_ALPHA";
169  default: return "unknown argrep";
170  }
171 }
172 
173 static const char *debug_op(GLuint op) {
174  switch(op) {
175  case GL_MOV_ATI: return "GL_MOV_ATI";
176  case GL_ADD_ATI: return "GL_ADD_ATI";
177  case GL_MUL_ATI: return "GL_MUL_ATI";
178  case GL_SUB_ATI: return "GL_SUB_ATI";
179  case GL_DOT3_ATI: return "GL_DOT3_ATI";
180  case GL_DOT4_ATI: return "GL_DOT4_ATI";
181  case GL_MAD_ATI: return "GL_MAD_ATI";
182  case GL_LERP_ATI: return "GL_LERP_ATI";
183  case GL_CND_ATI: return "GL_CND_ATI";
184  case GL_CND0_ATI: return "GL_CND0_ATI";
185  case GL_DOT2_ADD_ATI: return "GL_DOT2_ADD_ATI";
186  default: return "unexpected op";
187  }
188 }
189 
190 static const char *debug_mask(GLuint mask) {
191  switch(mask) {
192  case GL_NONE: return "GL_NONE";
193  case GL_RED_BIT_ATI: return "GL_RED_BIT_ATI";
194  case GL_GREEN_BIT_ATI: return "GL_GREEN_BIT_ATI";
195  case GL_BLUE_BIT_ATI: return "GL_BLUE_BIT_ATI";
196  case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI";
197  case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI: return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI";
198  case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
199  case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI";
200  default: return "Unexpected writemask";
201  }
202 }
203 
204 static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
206 {
207  if(dstMask == GL_ALPHA) {
208  TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
210  GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod));
211  } else {
212  TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
215  GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod));
216  }
217 }
218 
219 static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
221 {
222  if(dstMask == GL_ALPHA) {
223  TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
226  GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
227  } else {
228  TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
232  GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod));
233  }
234 }
235 
236 static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod,
239 {
240  if(dstMask == GL_ALPHA) {
241  /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */
242  TRACE("glAlphaFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod),
246  GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod,
247  arg1, arg1Rep, arg1Mod,
248  arg2, arg2Rep, arg2Mod,
249  arg3, arg3Rep, arg3Mod));
250  } else {
251  TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst),
256  GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod,
257  arg1, arg1Rep, arg1Mod,
258  arg2, arg2Rep, arg2Mod,
259  arg3, arg3Rep, arg3Mod));
260  }
261 }
262 
263 static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info,
264  unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
265 {
266  GLenum ret;
267 
268  if(mod) *mod = GL_NONE;
269  if(arg == ARG_UNUSED)
270  {
271  if (rep) *rep = GL_NONE;
272  return -1; /* This is the marker for unused registers */
273  }
274 
275  switch(arg & WINED3DTA_SELECTMASK) {
276  case WINED3DTA_DIFFUSE:
278  break;
279 
280  case WINED3DTA_CURRENT:
281  /* Note that using GL_REG_0_ATI for the passed on register is safe because
282  * texture0 is read at stage0, so in the worst case it is read in the
283  * instruction writing to reg0. Afterwards texture0 is not used any longer.
284  * If we're reading from current
285  */
286  ret = stage ? GL_REG_0_ATI : GL_PRIMARY_COLOR;
287  break;
288 
289  case WINED3DTA_TEXTURE:
290  ret = GL_REG_0_ATI + stage;
291  break;
292 
293  case WINED3DTA_TFACTOR:
295  break;
296 
297  case WINED3DTA_SPECULAR:
299  break;
300 
301  case WINED3DTA_TEMP:
302  ret = tmparg;
303  break;
304 
305  case WINED3DTA_CONSTANT:
306  ret = ATIFS_CONST_STAGE(stage);
307  break;
308 
309  default:
310  FIXME("Unknown source argument %d\n", arg);
311  ret = GL_ZERO;
312  }
313 
314  if(arg & WINED3DTA_COMPLEMENT) {
315  if(mod) *mod |= GL_COMP_BIT_ATI;
316  }
318  if(rep) *rep = GL_ALPHA;
319  } else {
320  if(rep) *rep = GL_NONE;
321  }
322  return ret;
323 }
324 
326 {
327  int lowest_read = -1;
328  int lowest_write = -1;
329  int i;
330  BOOL tex_used[MAX_TEXTURES];
331 
332  memset(tex_used, 0, sizeof(tex_used));
333  for (i = 0; i < MAX_TEXTURES; ++i)
334  {
335  if (op[i].cop == WINED3D_TOP_DISABLE)
336  break;
337 
338  if(lowest_read == -1 &&
339  (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP ||
340  op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) {
341  lowest_read = i;
342  }
343 
344  if(lowest_write == -1 && op[i].dst == tempreg) {
345  lowest_write = i;
346  }
347 
348  if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE ||
349  op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) {
350  tex_used[i] = TRUE;
351  }
352  }
353 
354  /* Temp reg not read? We don't need it, return GL_NONE */
355  if(lowest_read == -1) return GL_NONE;
356 
357  if(lowest_write >= lowest_read) {
358  FIXME("Temp register read before being written\n");
359  }
360 
361  if(lowest_write == -1) {
362  /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */
363  FIXME("Temp register read without being written\n");
364  return GL_REG_1_ATI;
365  } else if(lowest_write >= 1) {
366  /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result.
367  * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already
368  * read it
369  */
370  return GL_REG_1_ATI;
371  } else {
372  /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used
373  * for the regular result
374  */
375  for(i = 1; i < 6; i++) {
376  if(!tex_used[i]) {
377  return GL_REG_0_ATI + i;
378  }
379  }
380  /* What to do here? Report it in ValidateDevice? */
381  FIXME("Could not find a register for the temporary register\n");
382  return 0;
383  }
384 }
385 
386 static const struct color_fixup_desc color_fixup_rg =
387 {
388  1, CHANNEL_SOURCE_X,
389  1, CHANNEL_SOURCE_Y,
392 };
393 static const struct color_fixup_desc color_fixup_rgl =
394 {
395  1, CHANNEL_SOURCE_X,
396  1, CHANNEL_SOURCE_Y,
397  0, CHANNEL_SOURCE_Z,
399 };
400 static const struct color_fixup_desc color_fixup_rgba =
401 {
402  1, CHANNEL_SOURCE_X,
403  1, CHANNEL_SOURCE_Y,
404  1, CHANNEL_SOURCE_Z,
406 };
407 
409 {
410  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
411  || (op->carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
412  || (op->carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
413  || (op->aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
414  || (op->aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
415  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
417 }
418 
419 static void atifs_color_fixup(const struct wined3d_gl_info *gl_info, struct color_fixup_desc fixup, GLuint reg)
420 {
421  if(is_same_fixup(fixup, color_fixup_rg))
422  {
427  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE,
429  }
430  else if(is_same_fixup(fixup, color_fixup_rgl))
431  {
434  }
435  else if (is_same_fixup(fixup, color_fixup_rgba))
436  {
437  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_NONE, GL_NONE,
439  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE,
441  }
442  else
443  {
444  /* Should not happen - atifs_color_fixup_supported refuses other fixups. */
445  ERR("Unsupported color fixup.\n");
446  }
447 }
448 
450 {
451  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
452  || (op->carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
453  || (op->carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
454  || (op->aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
455  || (op->aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
456  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
459 }
460 
462 {
463  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_CONSTANT
468  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_CONSTANT;
469 }
470 
472  const struct wined3d_gl_info *gl_info, enum atifs_constant_value *constants)
473 {
474  GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
475  unsigned int stage;
476  GLuint arg0, arg1, arg2, extrarg;
477  GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
478  GLuint rep0, rep1, rep2;
479  GLuint swizzle;
480  GLuint tmparg = find_tmpreg(op);
481  GLuint dstreg;
482  BOOL tfactor_used = FALSE;
483 
484  if(!ret) {
485  ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
486  return 0;
487  }
488  GL_EXTCALL(glBindFragmentShaderATI(ret));
489  checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
490 
491  TRACE("glBeginFragmentShaderATI()\n");
492  GL_EXTCALL(glBeginFragmentShaderATI());
493  checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
494 
495  /* Pass 1: Generate sampling instructions for perturbation maps */
496  for (stage = 0; stage < gl_info->limits.textures; ++stage)
497  {
498  if (op[stage].cop == WINED3D_TOP_DISABLE)
499  break;
500  if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
501  && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
502  continue;
503 
505 
506  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
507  stage, stage);
508  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
509  GL_TEXTURE0_ARB + stage,
511  if(op[stage + 1].projected == proj_none) {
513  } else if(op[stage + 1].projected == proj_count4) {
515  } else {
517  }
518  TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
519  stage + 1, stage + 1, debug_swizzle(swizzle));
520  GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
521  GL_TEXTURE0_ARB + stage + 1,
522  swizzle));
523  }
524 
525  /* Pass 2: Generate perturbation calculations */
526  for (stage = 0; stage < gl_info->limits.textures; ++stage)
527  {
528  GLuint argmodextra_x, argmodextra_y;
529  struct color_fixup_desc fixup;
530 
531  if (op[stage].cop == WINED3D_TOP_DISABLE)
532  break;
533  if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
534  && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
535  continue;
536 
537  fixup = op[stage].color_fixup;
538  if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
539  {
540  FIXME("Swizzles not implemented\n");
541  argmodextra_x = GL_NONE;
542  argmodextra_y = GL_NONE;
543  }
544  else
545  {
546  /* Nice thing, we get the color correction for free :-) */
547  argmodextra_x = fixup.x_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
548  argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
549  }
550 
552  GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
554  GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
555 
556  /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha
557  * component of the bump matrix. Instead do this with two MADs:
558  *
559  * coord.a = tex.r * bump.b + coord.g
560  * coord.g = tex.g * bump.a + coord.a
561  *
562  * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD.
563  * coord.a is unused. If the perturbed texture is projected, this was already handled
564  * in the glPassTexCoordATI above.
565  */
566  wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE,
567  GL_REG_0_ATI + stage, GL_RED, argmodextra_y,
569  GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
570  wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
571  GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y,
573  GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE);
574  }
575 
576  /* Pass 3: Generate sampling instructions for regular textures */
577  for (stage = 0; stage < gl_info->limits.textures; ++stage)
578  {
579  if (op[stage].cop == WINED3D_TOP_DISABLE)
580  break;
581 
582  if(op[stage].projected == proj_none) {
584  } else if(op[stage].projected == proj_count3) {
586  } else {
588  }
589 
590  if (op_reads_texture(&op[stage]))
591  {
592  if (stage > 0
593  && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
594  || op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
595  {
596  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n",
597  stage, stage);
598  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
599  GL_REG_0_ATI + stage,
601  } else {
602  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
603  stage, stage, debug_swizzle(swizzle));
604  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
605  GL_TEXTURE0_ARB + stage,
606  swizzle));
607  }
608  }
609  }
610 
611  /* Pass 4: Generate the arithmetic instructions */
612  for (stage = 0; stage < MAX_TEXTURES; ++stage)
613  {
614  if (op[stage].cop == WINED3D_TOP_DISABLE)
615  {
616  if (!stage)
617  {
618  /* Handle complete texture disabling gracefully */
623  }
624  break;
625  }
626 
627  if(op[stage].dst == tempreg) {
628  /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place.
629  * skip the entire stage, this saves some GPU time
630  */
631  if(tmparg == GL_NONE) continue;
632 
633  dstreg = tmparg;
634  } else {
635  dstreg = GL_REG_0_ATI;
636  }
637 
638  if (op[stage].cop == WINED3D_TOP_BUMPENVMAP || op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
639  {
640  /* Those are handled in the first pass of the shader (generation pass 1 and 2) already */
641  continue;
642  }
643 
644  arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg);
645  arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg);
646  arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg);
647  dstmod = GL_NONE;
648  argmodextra = GL_NONE;
649  extrarg = GL_NONE;
650 
651  if (op_reads_tfactor(&op[stage]))
652  tfactor_used = TRUE;
653 
654  if (op_reads_constant(&op[stage]))
655  {
656  if (constants[stage] != ATIFS_CONSTANT_UNUSED)
657  FIXME("Constant %u already used.\n", stage);
659  }
660 
661  if (op_reads_texture(&op[stage]) && !is_identity_fixup(op[stage].color_fixup))
662  atifs_color_fixup(gl_info, op[stage].color_fixup, GL_REG_0_ATI + stage);
663 
664  switch (op[stage].cop)
665  {
667  arg1 = arg2;
668  argmod1 = argmod2;
669  rep1 = rep2;
670  /* fall through */
672  wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
673  arg1, rep1, argmod1);
674  break;
675 
677  if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
678  /* fall through */
680  if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
681  dstmod |= GL_SATURATE_BIT_ATI;
682  /* fall through */
684  wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
685  arg1, rep1, argmod1,
686  arg2, rep2, argmod2);
687  break;
688 
690  dstmod = GL_2X_BIT_ATI;
691  /* fall through */
693  argmodextra = GL_BIAS_BIT_ATI;
694  /* fall through */
695  case WINED3D_TOP_ADD:
696  dstmod |= GL_SATURATE_BIT_ATI;
697  wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
698  arg1, rep1, argmod1,
699  arg2, rep2, argmodextra | argmod2);
700  break;
701 
703  dstmod |= GL_SATURATE_BIT_ATI;
704  wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
705  arg1, rep1, argmod1,
706  arg2, rep2, argmod2);
707  break;
708 
710  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
711  /* Dst = arg1 + * arg2(1 -arg 1)
712  * = arg2 * (1 - arg1) + arg1
713  */
714  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
715  arg2, rep2, argmod2,
716  arg1, rep1, argmodextra,
717  arg1, rep1, argmod1);
718  break;
719 
721  if (extrarg == GL_NONE)
722  extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
723  /* fall through */
725  if (extrarg == GL_NONE)
726  extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
727  /* fall through */
729  if (extrarg == GL_NONE)
730  extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
731  /* fall through */
733  if (extrarg == GL_NONE)
734  extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
735  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
736  extrarg, GL_ALPHA, GL_NONE,
737  arg1, rep1, argmod1,
738  arg2, rep2, argmod2);
739  break;
740 
742  arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
743  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
744  arg2, rep2, argmod2,
745  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
746  arg1, rep1, argmod1);
747  break;
748 
749  /* D3DTOP_PREMODULATE ???? */
750 
752  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
753  /* fall through */
755  if (!argmodextra)
756  argmodextra = argmod1;
757  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
758  arg2, rep2, argmod2,
759  arg1, GL_ALPHA, argmodextra,
760  arg1, rep1, argmod1);
761  break;
762 
764  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
765  /* fall through */
767  if (!argmodextra)
768  argmodextra = argmod1;
769  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
770  arg2, rep2, argmod2,
771  arg1, rep1, argmodextra,
772  arg1, GL_ALPHA, argmod1);
773  break;
774 
777  arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
778  arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
779  break;
780 
782  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
783  arg1, rep1, argmod1,
784  arg2, rep2, argmod2,
785  arg0, rep0, argmod0);
786  break;
787 
788  case WINED3D_TOP_LERP:
789  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
790  arg0, rep0, argmod0,
791  arg1, rep1, argmod1,
792  arg2, rep2, argmod2);
793  break;
794 
795  default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
796  }
797 
798  arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg);
799  arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg);
800  arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg);
801  dstmod = GL_NONE;
802  argmodextra = GL_NONE;
803  extrarg = GL_NONE;
804 
805  switch (op[stage].aop)
806  {
807  case WINED3D_TOP_DISABLE:
808  /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
809  if (!stage)
810  {
813  }
814  break;
815 
817  arg1 = arg2;
818  argmod1 = argmod2;
819  /* fall through */
821  wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
822  arg1, GL_NONE, argmod1);
823  break;
824 
826  if (dstmod == GL_NONE)
827  dstmod = GL_4X_BIT_ATI;
828  /* fall through */
830  if (dstmod == GL_NONE)
831  dstmod = GL_2X_BIT_ATI;
832  dstmod |= GL_SATURATE_BIT_ATI;
833  /* fall through */
835  wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
836  arg1, GL_NONE, argmod1,
837  arg2, GL_NONE, argmod2);
838  break;
839 
841  dstmod = GL_2X_BIT_ATI;
842  /* fall through */
844  argmodextra = GL_BIAS_BIT_ATI;
845  /* fall through */
846  case WINED3D_TOP_ADD:
847  dstmod |= GL_SATURATE_BIT_ATI;
848  wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
849  arg1, GL_NONE, argmod1,
850  arg2, GL_NONE, argmodextra | argmod2);
851  break;
852 
854  dstmod |= GL_SATURATE_BIT_ATI;
855  wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
856  arg1, GL_NONE, argmod1,
857  arg2, GL_NONE, argmod2);
858  break;
859 
861  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
862  /* Dst = arg1 + * arg2(1 -arg 1)
863  * = arg2 * (1 - arg1) + arg1
864  */
865  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
866  arg2, GL_NONE, argmod2,
867  arg1, GL_NONE, argmodextra,
868  arg1, GL_NONE, argmod1);
869  break;
870 
872  if (extrarg == GL_NONE)
873  extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
874  /* fall through */
876  if (extrarg == GL_NONE)
877  extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
878  /* fall through */
880  if (extrarg == GL_NONE)
881  extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
882  /* fall through */
884  if (extrarg == GL_NONE)
885  extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
886  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
887  extrarg, GL_ALPHA, GL_NONE,
888  arg1, GL_NONE, argmod1,
889  arg2, GL_NONE, argmod2);
890  break;
891 
893  arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
894  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
895  arg2, GL_NONE, argmod2,
896  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
897  arg1, GL_NONE, argmod1);
898  break;
899 
900  /* D3DTOP_PREMODULATE ???? */
901 
904  arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
905  arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
906  break;
907 
909  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
910  arg1, GL_NONE, argmod1,
911  arg2, GL_NONE, argmod2,
912  arg0, GL_NONE, argmod0);
913  break;
914 
915  case WINED3D_TOP_LERP:
917  arg1, GL_NONE, argmod1,
918  arg2, GL_NONE, argmod2,
919  arg0, GL_NONE, argmod0);
920  break;
921 
928  ERR("Application uses an invalid alpha operation\n");
929  break;
930 
931  default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
932  }
933  }
934 
936  FIXME("Texture factor constant already used.\n");
938 
939  /* Assign unused constants to avoid reloading due to unused <-> bump matrix switches. */
940  for (stage = 0; stage < MAX_TEXTURES; ++stage)
941  {
942  if (constants[stage] == ATIFS_CONSTANT_UNUSED)
944  }
945 
946  TRACE("glEndFragmentShaderATI()\n");
947  GL_EXTCALL(glEndFragmentShaderATI());
948  checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
949  return ret;
950 }
951 
952 static void atifs_tfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
953 {
954  const struct wined3d_gl_info *gl_info = context->gl_info;
955  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
956  struct wined3d_color color;
957 
958  if (!ctx_priv->last_shader
960  return;
961 
963  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_TFACTOR, &color.r));
964  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_TFACTOR, &color.r)");
965 }
966 
967 static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
968 {
969  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
970  const struct wined3d_gl_info *gl_info = context->gl_info;
971  float mat[2][2];
972  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
973 
974  if (!ctx_priv->last_shader
975  || ctx_priv->last_shader->constants[stage] != ATIFS_CONSTANT_BUMP)
976  return;
977 
978  mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
979  mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
980  mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
981  mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
982  /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat
983  * constants can be in any range. While they should stay between [-1.0 and 1.0] because
984  * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally,
985  * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the
986  * shader(it is free). This might potentially reduce precision. However, if the hardware does
987  * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway. */
988  mat[0][0] = (mat[0][0] + 1.0f) * 0.5f;
989  mat[1][0] = (mat[1][0] + 1.0f) * 0.5f;
990  mat[0][1] = (mat[0][1] + 1.0f) * 0.5f;
991  mat[1][1] = (mat[1][1] + 1.0f) * 0.5f;
992  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_BUMPMAT(stage), (float *) mat));
993  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_BUMPMAT(stage), mat)");
994 }
995 
996 static void atifs_stage_constant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
997 {
998  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
999  const struct wined3d_gl_info *gl_info = context->gl_info;
1000  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
1001  struct wined3d_color color;
1002 
1003  if (!ctx_priv->last_shader
1004  || ctx_priv->last_shader->constants[stage] != ATIFS_CONSTANT_STAGE)
1005  return;
1006 
1007  wined3d_color_from_d3dcolor(&color, state->texture_states[stage][WINED3D_TSS_CONSTANT]);
1008  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_STAGE(stage), &color.r));
1009  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_STAGE(stage), &color.r)");
1010 }
1011 
1012 static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1013 {
1014  const struct wined3d_device *device = context->device;
1015  const struct wined3d_gl_info *gl_info = context->gl_info;
1016  const struct wined3d_d3d_info *d3d_info = context->d3d_info;
1017  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
1018  const struct atifs_ffp_desc *desc, *last_shader = ctx_priv->last_shader;
1019  struct ffp_frag_settings settings;
1020  struct atifs_private_data *priv = device->fragment_priv;
1021  DWORD mapped_stage;
1022  unsigned int i;
1023 
1026  if (!desc)
1027  {
1028  struct atifs_ffp_desc *new_desc;
1029 
1030  if (!(new_desc = heap_alloc_zero(sizeof(*new_desc))))
1031  {
1032  ERR("Out of memory\n");
1033  return;
1034  }
1035  new_desc->num_textures_used = 0;
1036  for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
1037  {
1038  if (settings.op[i].cop == WINED3D_TOP_DISABLE)
1039  break;
1040  ++new_desc->num_textures_used;
1041  }
1042 
1043  new_desc->parent.settings = settings;
1044  new_desc->shader = gen_ati_shader(settings.op, gl_info, new_desc->constants);
1045  add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
1046  TRACE("Allocated fixed function replacement shader descriptor %p.\n", new_desc);
1047  desc = new_desc;
1048  }
1049 
1050  /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages
1051  * used by this shader
1052  */
1053  for (i = 0; i < desc->num_textures_used; ++i)
1054  {
1055  mapped_stage = context->tex_unit_map[i];
1056  if (mapped_stage != WINED3D_UNMAPPED_STAGE)
1057  {
1058  context_active_texture(context, gl_info, mapped_stage);
1059  texture_activate_dimensions(state->textures[i], gl_info);
1060  }
1061  }
1062 
1063  GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
1064  ctx_priv->last_shader = desc;
1065 
1066  for (i = 0; i < MAX_TEXTURES; i++)
1067  {
1068  if (last_shader && last_shader->constants[i] == desc->constants[i])
1069  continue;
1070 
1071  switch (desc->constants[i])
1072  {
1073  case ATIFS_CONSTANT_BUMP:
1075  break;
1076 
1079  break;
1080 
1081  case ATIFS_CONSTANT_STAGE:
1083  break;
1084 
1085  default:
1086  ERR("Unexpected constant type %u.\n", desc->constants[i]);
1087  }
1088  }
1089 }
1090 
1091 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1092 {
1094  set_tex_op_atifs(context, state, state_id);
1095 }
1096 
1097 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1098 {
1099  if (state->render_states[WINED3D_RS_SRGBWRITEENABLE])
1100  WARN("sRGB writes are not supported by this fragment pipe.\n");
1101 }
1102 
1248  {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
1249 };
1250 
1251 /* Context activation is done by the caller. */
1252 static void atifs_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
1253 {
1254  if (enable)
1255  {
1256  gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_SHADER_ATI);
1257  checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)");
1258  }
1259  else
1260  {
1261  gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_SHADER_ATI);
1262  checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)");
1263  }
1264 }
1265 
1266 static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
1267 {
1295 
1296  /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
1297  and WINED3DTEXOPCAPS_PREMODULATE */
1298 
1299  /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards
1300  * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
1301  * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
1302  * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
1303  * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
1304  * pipeline, and almost all games are happy with that. We can however support up to 8
1305  * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
1306  * only 1 instruction.
1307  *
1308  * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
1309  * r200 series and use an ARB or GLSL shader instead
1310  */
1312  caps->MaxSimultaneousTextures = 6;
1313 }
1314 
1315 static DWORD atifs_get_emul_mask(const struct wined3d_gl_info *gl_info)
1316 {
1318 }
1319 
1320 static void *atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
1321 {
1322  struct atifs_private_data *priv;
1323 
1324  if (!(priv = heap_alloc_zero(sizeof(*priv))))
1325  return NULL;
1326 
1328  return priv;
1329 }
1330 
1331 /* Context activation is done by the caller. */
1332 static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *cb_ctx)
1333 {
1334  const struct wined3d_gl_info *gl_info = cb_ctx;
1335  struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
1336 
1337  GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
1338  checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
1339  heap_free(entry_ati);
1340 }
1341 
1342 /* Context activation is done by the caller. */
1343 static void atifs_free(struct wined3d_device *device)
1344 {
1345  struct atifs_private_data *priv = device->fragment_priv;
1346 
1347  wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, &device->adapter->gl_info);
1348 
1349  heap_free(priv);
1350  device->fragment_priv = NULL;
1351 }
1352 
1354 {
1355  /* We only support sign fixup of the first two channels. */
1356  return is_identity_fixup(fixup) || is_same_fixup(fixup, color_fixup_rg)
1358 }
1359 
1361 {
1362  struct atifs_context_private_data *priv;
1363 
1364  if (!(priv = heap_alloc_zero(sizeof(*priv))))
1365  return FALSE;
1366  context->fragment_pipe_data = priv;
1367  return TRUE;
1368 }
1369 
1371 {
1372  heap_free(context->fragment_pipe_data);
1373 }
1374 
1376  atifs_enable,
1379  atifs_alloc,
1380  atifs_free,
1385 };
DWORD MaxTextureBlendStages
#define STATE_TEXTURESTAGE(stage, num)
#define GL_MUL_ATI
Definition: glext.h:3959
static DWORD atifs_get_emul_mask(const struct wined3d_gl_info *gl_info)
struct mke2fs_defaults settings[]
#define GL_SUB_ATI
Definition: glext.h:3960
struct wine_rb_tree fragment_shaders
#define MAX_TEXTURES
#define GL_CON_3_ATI
Definition: glext.h:3928
void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:290
unsigned short x_source
#define GL_BIAS_BIT_ATI
Definition: glext.h:3995
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2Mod
Definition: glext.h:9514
static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod)
#define TRUE
Definition: types.h:120
const struct atifs_ffp_desc * last_shader
#define GL_RED
Definition: gl.h:480
#define GL_ONE
Definition: gl.h:375
static const char * debug_dstmod(GLuint mod)
void state_fogstartend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:1112
struct opengl_funcs gl_ops
#define WINED3D_FRAGMENT_CAP_PROJ_CONTROL
#define GL_CON_4_ATI
Definition: glext.h:3929
static void atifs_free_context_data(struct wined3d_context *context)
#define GL_CND0_ATI
Definition: glext.h:3966
#define WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
Definition: wined3d.h:1165
Definition: http.c:7098
#define WINED3DTA_CONSTANT
Definition: wined3d.h:873
#define GL_REG_2_ATI
Definition: glext.h:3895
void context_active_texture(struct wined3d_context *context, const struct wined3d_gl_info *gl_info, unsigned int unit)
Definition: context.c:2717
#define WINED3DTEXOPCAPS_DISABLE
Definition: wined3d.h:1145
#define WINED3DTEXOPCAPS_BLENDCURRENTALPHA
Definition: wined3d.h:1160
#define ATIFS_CONST_BUMPMAT(i)
#define WINED3DTEXOPCAPS_ADDSIGNED
Definition: wined3d.h:1152
static void atifs_free(struct wined3d_device *device)
#define GL_REG_5_ATI
Definition: glext.h:3898
#define GL_ALPHA
Definition: gl.h:483
#define WINED3DTEXOPCAPS_MODULATE
Definition: wined3d.h:1148
static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *cb_ctx)
#define WARN(fmt,...)
Definition: debug.h:111
GLuint GLuint GLuint dstMod
Definition: glext.h:9513
#define GL_TEXTURE0_ARB
Definition: gl.h:1966
#define GL_QUARTER_BIT_ATI
Definition: glext.h:3990
#define GL_FRAGMENT_SHADER_ATI
Definition: glext.h:3892
#define WINED3DTEXOPCAPS_ADDSIGNED2X
Definition: wined3d.h:1153
#define GL_HALF_BIT_ATI
Definition: glext.h:3989
#define WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
Definition: wined3d.h:1156
static BOOL is_same_fixup(struct color_fixup_desc f1, struct color_fixup_desc f2)
#define GL_8X_BIT_ATI
Definition: glext.h:3988
static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup)
#define WINED3DTEXOPCAPS_ADDSMOOTH
Definition: wined3d.h:1155
static const MAT2 mat
Definition: font.c:66
static const char * debug_register(GLuint reg)
#define WINED3DTA_COMPLEMENT
Definition: wined3d.h:874
#define GL_CON_1_ATI
Definition: glext.h:3926
#define GL_GREEN_BIT_ATI
Definition: glext.h:3984
static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod)
#define WINED3DTEXOPCAPS_SELECTARG2
Definition: wined3d.h:1147
#define STATE_SHADER(a)
static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info, enum atifs_constant_value *constants)
void state_alpha_test(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:650
#define GL_4X_BIT_ATI
Definition: glext.h:3987
void texture_activate_dimensions(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
Definition: utils.c:6097
#define WINED3DTA_CURRENT
Definition: wined3d.h:868
#define WINED3DTEXOPCAPS_LERP
Definition: wined3d.h:1170
#define WINED3DTEXOPCAPS_BLENDFACTORALPHA
Definition: wined3d.h:1158
unsigned short x_sign_fixup
#define GL_REG_1_ATI
Definition: glext.h:3894
static BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
#define GL_SWIZZLE_STR_ATI
Definition: glext.h:3977
void state_fogcolor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:1286
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
#define STATE_COLOR_KEY
const struct fragment_pipeline atifs_fragment_pipeline
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const char * debug_argmod(GLuint mod)
GLenum GLint GLuint mask
Definition: glext.h:6028
#define ARG_UNUSED
static void atifs_stage_constant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
#define WINED3DPMISCCAPS_PERSTAGECONSTANT
Definition: wined3d.h:1105
#define GL_CON_7_ATI
Definition: glext.h:3932
static BOOL op_reads_texture(const struct texture_stage_op *op)
unsigned int BOOL
Definition: ntddk_ex.h:94
static BOOL atifs_alloc_context_data(struct wined3d_context *context)
GLuint color
Definition: glext.h:6243
Definition: devices.h:37
#define WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
Definition: wined3d.h:1164
#define ATIFS_CONST_TFACTOR
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
static const WCHAR desc[]
Definition: protectdata.c:36
#define GL_CON_0_ATI
Definition: glext.h:3925
#define GL_ZERO
Definition: gl.h:374
#define FIXME(fmt,...)
Definition: debug.h:110
#define GL_ADD_ATI
Definition: glext.h:3958
#define GL_REG_0_ATI
Definition: glext.h:3893
void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
Definition: utils.c:6083
#define WINED3DPMISCCAPS_TSSARGTEMP
Definition: wined3d.h:1101
smooth NULL
Definition: ftsmooth.c:416
static void atifs_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
#define WINED3DTA_TEXTURE
Definition: wined3d.h:869
static const struct color_fixup_desc color_fixup_rg
static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
#define GL_MOV_ATI
Definition: glext.h:3957
#define GL_RED_BIT_ATI
Definition: glext.h:3983
#define WINED3DTEXOPCAPS_DOTPRODUCT3
Definition: wined3d.h:1168
#define GL_EIGHTH_BIT_ATI
Definition: glext.h:3991
#define GL_2X_BIT_ATI
Definition: glext.h:3986
void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: utils.c:6212
static void wine_rb_init(struct wine_rb_tree *tree, wine_rb_compare_func_t compare)
Definition: rbtree.h:179
unsigned short y_sign_fixup
#define WINED3DTA_SELECTMASK
Definition: wined3d.h:866
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
Definition: glext.h:9515
static void * atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
#define GL_EXTCALL(f)
#define WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
Definition: wined3d.h:1159
GLfloat f
Definition: glext.h:7540
#define WINED3DTEXOPCAPS_MODULATE4X
Definition: wined3d.h:1150
#define TRACE(s)
Definition: solgame.cpp:4
const struct ffp_frag_desc * find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders, const struct ffp_frag_settings *settings)
Definition: utils.c:6076
#define WINED3DTEXOPCAPS_SELECTARG1
Definition: wined3d.h:1146
#define GL_REG_4_ATI
Definition: glext.h:3897
r parent
Definition: btrfs.c:2869
#define WINE_RB_ENTRY_VALUE(element, type, field)
Definition: rbtree.h:31
#define GL_LERP_ATI
Definition: glext.h:3964
static const struct color_fixup_desc color_fixup_rgba
#define WINED3DTA_DIFFUSE
Definition: wined3d.h:867
atifs_constant_value
#define WINED3DTA_SPECULAR
Definition: wined3d.h:871
#define WINED3DTEXOPCAPS_MULTIPLYADD
Definition: wined3d.h:1169
static BOOL is_identity_fixup(struct color_fixup_desc fixup)
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLuint GLuint GLuint arg1Rep
Definition: glext.h:9513
static const struct StateEntryTemplate atifs_fragmentstate_template[]
#define WINED3DTA_TFACTOR
Definition: wined3d.h:870
static const char * debug_op(GLuint op)
#define GL_SATURATE_BIT_ATI
Definition: glext.h:3992
DWORD MaxSimultaneousTextures
#define GL_NONE
Definition: gl.h:465
static BOOL op_reads_tfactor(const struct texture_stage_op *op)
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2Rep
Definition: glext.h:9514
static void wine_rb_destroy(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
Definition: rbtree.h:198
int ret
static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod)
static void atifs_color_fixup(const struct wined3d_gl_info *gl_info, struct color_fixup_desc fixup, GLuint reg)
static const char * debug_mask(GLuint mask)
#define GL_BLUE
Definition: gl.h:482
static int state
Definition: maze.c:121
GLuint GLuint dstMask
Definition: glext.h:9513
uint32_t entry
Definition: isohybrid.c:63
static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
static void atifs_tfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
unsigned int GLenum
Definition: gl.h:150
#define WINED3D_UNMAPPED_STAGE
static const char * debug_rep(GLuint rep)
unsigned int num_textures_used
void state_nop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:170
#define STATE_RENDER(a)
#define STATE_SAMPLER(num)
#define ERR(fmt,...)
Definition: debug.h:109
static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader)
#define GL_DOT4_ATI
Definition: glext.h:3962
GLuint GLuint GLuint GLuint GLuint GLuint arg1Mod
Definition: glext.h:9513
GLboolean enable
Definition: glext.h:11120
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3Mod
Definition: glext.h:9515
#define WINED3DTEXOPCAPS_MODULATE2X
Definition: wined3d.h:1149
unsigned int GLuint
Definition: gl.h:159
#define GL_CON_6_ATI
Definition: glext.h:3931
#define GL_GREEN
Definition: gl.h:481
struct wined3d_d3d_limits limits
Definition: rbtree.h:35
#define GL_DOT3_ATI
Definition: glext.h:3961
constants
Definition: resource.c:29
static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
GLenum GLenum dst
Definition: glext.h:6340
#define WINED3D_HIGHEST_TEXTURE_STATE
Definition: wined3d.h:595
#define GL_EXT_EMUL_EXT_FOG_COORD
void state_fogdensity(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:1296
#define GL_CND_ATI
Definition: glext.h:3965
#define checkGLcall(A)
int wined3d_ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
Definition: utils.c:6230
static int reg
Definition: i386-dis.c:1275
#define GL_PRIMARY_COLOR
Definition: gl.h:1846
#define WINED3DTEXOPCAPS_SUBTRACT
Definition: wined3d.h:1154
#define GL_SWIZZLE_STQ_DQ_ATI
Definition: glext.h:3980
#define GL_CON_5_ATI
Definition: glext.h:3930
#define WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
Definition: wined3d.h:1163
#define ATIFS_CONST_STAGE(i)
#define GL_MAD_ATI
Definition: glext.h:3963
#define WINED3DTA_ALPHAREPLICATE
Definition: wined3d.h:875
WINE_DECLARE_DEBUG_CHANNEL(d3d)
void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state, struct ffp_frag_settings *settings, BOOL ignore_textype)
Definition: utils.c:5751
GLuint GLenum swizzle
Definition: glext.h:9511
#define GL_SWIZZLE_STQ_ATI
Definition: glext.h:3978
void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
Definition: state.c:1128
#define GL_SWIZZLE_STR_DR_ATI
Definition: glext.h:3979
UINT op
Definition: effect.c:223
static const char * debug_swizzle(GLuint swizzle)
#define GL_DOT2_ADD_ATI
Definition: glext.h:3967
#define GL_BLUE_BIT_ATI
Definition: glext.h:3985
#define GL_REG_3_ATI
Definition: glext.h:3896
#define GL_EXT_EMUL_ARB_MULTITEXTURE
#define memset(x, y, z)
Definition: compat.h:39
#define GL_SECONDARY_INTERPOLATOR_ATI
Definition: glext.h:3968
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3Rep
Definition: glext.h:9515
struct wined3d_gl_limits limits
static BOOL op_reads_constant(const struct texture_stage_op *op)
struct ffp_frag_desc parent
#define WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
Definition: wined3d.h:1157
unsigned short y_source
#define WINED3DTEXOPCAPS_BUMPENVMAP
Definition: wined3d.h:1166
#define WINED3DTA_TEMP
Definition: wined3d.h:872
#define GL_CON_2_ATI
Definition: glext.h:3927
static void wined3d_color_from_d3dcolor(struct wined3d_color *wined3d_color, DWORD d3d_color)
static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info, unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg)
#define WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
Definition: wined3d.h:1162
#define GL_COMP_BIT_ATI
Definition: glext.h:3993
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define GL_NEGATE_BIT_ATI
Definition: glext.h:3994
static int mod
Definition: i386-dis.c:1273
#define WINED3DTEXOPCAPS_ADD
Definition: wined3d.h:1151
static const struct color_fixup_desc color_fixup_rgl
static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES])
enum atifs_constant_value constants[MAX_TEXTURES]