ReactOS  0.4.13-dev-99-g7e18b6d
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].tmp_dst)
345  lowest_write = i;
346 
347  if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE ||
348  op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) {
349  tex_used[i] = TRUE;
350  }
351  }
352 
353  /* Temp reg not read? We don't need it, return GL_NONE */
354  if(lowest_read == -1) return GL_NONE;
355 
356  if(lowest_write >= lowest_read) {
357  FIXME("Temp register read before being written\n");
358  }
359 
360  if(lowest_write == -1) {
361  /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */
362  FIXME("Temp register read without being written\n");
363  return GL_REG_1_ATI;
364  } else if(lowest_write >= 1) {
365  /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result.
366  * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already
367  * read it
368  */
369  return GL_REG_1_ATI;
370  } else {
371  /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used
372  * for the regular result
373  */
374  for(i = 1; i < 6; i++) {
375  if(!tex_used[i]) {
376  return GL_REG_0_ATI + i;
377  }
378  }
379  /* What to do here? Report it in ValidateDevice? */
380  FIXME("Could not find a register for the temporary register\n");
381  return 0;
382  }
383 }
384 
385 static const struct color_fixup_desc color_fixup_rg =
386 {
387  1, CHANNEL_SOURCE_X,
388  1, CHANNEL_SOURCE_Y,
391 };
392 static const struct color_fixup_desc color_fixup_rgl =
393 {
394  1, CHANNEL_SOURCE_X,
395  1, CHANNEL_SOURCE_Y,
396  0, CHANNEL_SOURCE_Z,
398 };
399 static const struct color_fixup_desc color_fixup_rgba =
400 {
401  1, CHANNEL_SOURCE_X,
402  1, CHANNEL_SOURCE_Y,
403  1, CHANNEL_SOURCE_Z,
405 };
406 
408 {
409  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
410  || (op->carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
411  || (op->carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
412  || (op->aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
413  || (op->aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
414  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
416 }
417 
418 static void atifs_color_fixup(const struct wined3d_gl_info *gl_info, struct color_fixup_desc fixup, GLuint reg)
419 {
420  if(is_same_fixup(fixup, color_fixup_rg))
421  {
426  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE,
428  }
429  else if(is_same_fixup(fixup, color_fixup_rgl))
430  {
433  }
434  else if (is_same_fixup(fixup, color_fixup_rgba))
435  {
436  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_NONE, GL_NONE,
438  wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE,
440  }
441  else
442  {
443  /* Should not happen - atifs_color_fixup_supported refuses other fixups. */
444  ERR("Unsupported color fixup.\n");
445  }
446 }
447 
449 {
450  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
451  || (op->carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
452  || (op->carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
453  || (op->aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
454  || (op->aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
455  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TFACTOR
458 }
459 
461 {
462  return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_CONSTANT
467  || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_CONSTANT;
468 }
469 
471  const struct wined3d_gl_info *gl_info, enum atifs_constant_value *constants)
472 {
473  GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1));
474  unsigned int stage;
475  GLuint arg0, arg1, arg2, extrarg;
476  GLuint dstmod, argmod0, argmod1, argmod2, argmodextra;
477  GLuint rep0, rep1, rep2;
478  GLuint swizzle;
479  GLuint tmparg = find_tmpreg(op);
480  GLuint dstreg;
481  BOOL tfactor_used = FALSE;
482 
483  if(!ret) {
484  ERR("Failed to generate a GL_ATI_fragment_shader shader id\n");
485  return 0;
486  }
487  GL_EXTCALL(glBindFragmentShaderATI(ret));
488  checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))");
489 
490  TRACE("glBeginFragmentShaderATI()\n");
491  GL_EXTCALL(glBeginFragmentShaderATI());
492  checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())");
493 
494  /* Pass 1: Generate sampling instructions for perturbation maps */
495  for (stage = 0; stage < gl_info->limits.textures; ++stage)
496  {
497  if (op[stage].cop == WINED3D_TOP_DISABLE)
498  break;
499  if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
500  && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
501  continue;
502 
504 
505  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n",
506  stage, stage);
507  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, GL_TEXTURE0_ARB + stage, GL_SWIZZLE_STR_ATI));
508  if (op[stage + 1].projected == WINED3D_PROJECTION_NONE)
510  else if (op[stage + 1].projected == WINED3D_PROJECTION_COUNT4)
512  else
514  TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
515  stage + 1, stage + 1, debug_swizzle(swizzle));
516  GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1,
517  GL_TEXTURE0_ARB + stage + 1,
518  swizzle));
519  }
520 
521  /* Pass 2: Generate perturbation calculations */
522  for (stage = 0; stage < gl_info->limits.textures; ++stage)
523  {
524  GLuint argmodextra_x, argmodextra_y;
525  struct color_fixup_desc fixup;
526 
527  if (op[stage].cop == WINED3D_TOP_DISABLE)
528  break;
529  if (op[stage].cop != WINED3D_TOP_BUMPENVMAP
530  && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE)
531  continue;
532 
533  fixup = op[stage].color_fixup;
534  if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y)
535  {
536  FIXME("Swizzles not implemented\n");
537  argmodextra_x = GL_NONE;
538  argmodextra_y = GL_NONE;
539  }
540  else
541  {
542  /* Nice thing, we get the color correction for free :-) */
543  argmodextra_x = fixup.x_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
544  argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE;
545  }
546 
548  GL_REG_0_ATI + stage, GL_NONE, argmodextra_x,
550  GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE);
551 
552  /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha
553  * component of the bump matrix. Instead do this with two MADs:
554  *
555  * coord.a = tex.r * bump.b + coord.g
556  * coord.g = tex.g * bump.a + coord.a
557  *
558  * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD.
559  * coord.a is unused. If the perturbed texture is projected, this was already handled
560  * in the glPassTexCoordATI above.
561  */
562  wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE,
563  GL_REG_0_ATI + stage, GL_RED, argmodextra_y,
565  GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE);
566  wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE,
567  GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y,
569  GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE);
570  }
571 
572  /* Pass 3: Generate sampling instructions for regular textures */
573  for (stage = 0; stage < gl_info->limits.textures; ++stage)
574  {
575  if (op[stage].cop == WINED3D_TOP_DISABLE)
576  break;
577 
578  if (op[stage].projected == WINED3D_PROJECTION_NONE)
580  else if (op[stage].projected == WINED3D_PROJECTION_COUNT3)
582  else
584 
585  if (op_reads_texture(&op[stage]))
586  {
587  if (stage > 0
588  && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP
589  || op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE))
590  {
591  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n",
592  stage, stage);
593  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
594  GL_REG_0_ATI + stage,
596  } else {
597  TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n",
598  stage, stage, debug_swizzle(swizzle));
599  GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage,
600  GL_TEXTURE0_ARB + stage,
601  swizzle));
602  }
603  }
604  }
605 
606  /* Pass 4: Generate the arithmetic instructions */
607  for (stage = 0; stage < MAX_TEXTURES; ++stage)
608  {
609  if (op[stage].cop == WINED3D_TOP_DISABLE)
610  {
611  if (!stage)
612  {
613  /* Handle complete texture disabling gracefully */
618  }
619  break;
620  }
621 
622  if (op[stage].tmp_dst)
623  {
624  /* If we're writing to D3DTA_TEMP, but never reading from it we
625  * don't have to write there in the first place. Skip the entire
626  * stage, this saves some GPU time. */
627  if (tmparg == GL_NONE)
628  continue;
629 
630  dstreg = tmparg;
631  }
632  else
633  {
634  dstreg = GL_REG_0_ATI;
635  }
636 
637  if (op[stage].cop == WINED3D_TOP_BUMPENVMAP || op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
638  {
639  /* Those are handled in the first pass of the shader (generation pass 1 and 2) already */
640  continue;
641  }
642 
643  arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg);
644  arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg);
645  arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg);
646  dstmod = GL_NONE;
647  argmodextra = GL_NONE;
648  extrarg = GL_NONE;
649 
650  if (op_reads_tfactor(&op[stage]))
651  tfactor_used = TRUE;
652 
653  if (op_reads_constant(&op[stage]))
654  {
655  if (constants[stage] != ATIFS_CONSTANT_UNUSED)
656  FIXME("Constant %u already used.\n", stage);
658  }
659 
660  if (op_reads_texture(&op[stage]) && !is_identity_fixup(op[stage].color_fixup))
661  atifs_color_fixup(gl_info, op[stage].color_fixup, GL_REG_0_ATI + stage);
662 
663  switch (op[stage].cop)
664  {
666  arg1 = arg2;
667  argmod1 = argmod2;
668  rep1 = rep2;
669  /* fall through */
671  wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE,
672  arg1, rep1, argmod1);
673  break;
674 
676  if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI;
677  /* fall through */
679  if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI;
680  dstmod |= GL_SATURATE_BIT_ATI;
681  /* fall through */
683  wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod,
684  arg1, rep1, argmod1,
685  arg2, rep2, argmod2);
686  break;
687 
689  dstmod = GL_2X_BIT_ATI;
690  /* fall through */
692  argmodextra = GL_BIAS_BIT_ATI;
693  /* fall through */
694  case WINED3D_TOP_ADD:
695  dstmod |= GL_SATURATE_BIT_ATI;
696  wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod,
697  arg1, rep1, argmod1,
698  arg2, rep2, argmodextra | argmod2);
699  break;
700 
702  dstmod |= GL_SATURATE_BIT_ATI;
703  wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod,
704  arg1, rep1, argmod1,
705  arg2, rep2, argmod2);
706  break;
707 
709  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
710  /* Dst = arg1 + * arg2(1 -arg 1)
711  * = arg2 * (1 - arg1) + arg1
712  */
713  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
714  arg2, rep2, argmod2,
715  arg1, rep1, argmodextra,
716  arg1, rep1, argmod1);
717  break;
718 
720  if (extrarg == GL_NONE)
721  extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
722  /* fall through */
724  if (extrarg == GL_NONE)
725  extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
726  /* fall through */
728  if (extrarg == GL_NONE)
729  extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
730  /* fall through */
732  if (extrarg == GL_NONE)
733  extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
734  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
735  extrarg, GL_ALPHA, GL_NONE,
736  arg1, rep1, argmod1,
737  arg2, rep2, argmod2);
738  break;
739 
741  arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
742  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE,
743  arg2, rep2, argmod2,
744  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
745  arg1, rep1, argmod1);
746  break;
747 
748  /* D3DTOP_PREMODULATE ???? */
749 
751  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
752  /* fall through */
754  if (!argmodextra)
755  argmodextra = argmod1;
756  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
757  arg2, rep2, argmod2,
758  arg1, GL_ALPHA, argmodextra,
759  arg1, rep1, argmod1);
760  break;
761 
763  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
764  /* fall through */
766  if (!argmodextra)
767  argmodextra = argmod1;
768  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
769  arg2, rep2, argmod2,
770  arg1, rep1, argmodextra,
771  arg1, GL_ALPHA, argmod1);
772  break;
773 
776  arg1, rep1, argmod1 | GL_BIAS_BIT_ATI,
777  arg2, rep2, argmod2 | GL_BIAS_BIT_ATI);
778  break;
779 
781  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI,
782  arg1, rep1, argmod1,
783  arg2, rep2, argmod2,
784  arg0, rep0, argmod0);
785  break;
786 
787  case WINED3D_TOP_LERP:
788  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE,
789  arg0, rep0, argmod0,
790  arg1, rep1, argmod1,
791  arg2, rep2, argmod2);
792  break;
793 
794  default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage);
795  }
796 
797  arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg);
798  arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg);
799  arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg);
800  dstmod = GL_NONE;
801  argmodextra = GL_NONE;
802  extrarg = GL_NONE;
803 
804  switch (op[stage].aop)
805  {
806  case WINED3D_TOP_DISABLE:
807  /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */
808  if (!stage)
809  {
812  }
813  break;
814 
816  arg1 = arg2;
817  argmod1 = argmod2;
818  /* fall through */
820  wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE,
821  arg1, GL_NONE, argmod1);
822  break;
823 
825  if (dstmod == GL_NONE)
826  dstmod = GL_4X_BIT_ATI;
827  /* fall through */
829  if (dstmod == GL_NONE)
830  dstmod = GL_2X_BIT_ATI;
831  dstmod |= GL_SATURATE_BIT_ATI;
832  /* fall through */
834  wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod,
835  arg1, GL_NONE, argmod1,
836  arg2, GL_NONE, argmod2);
837  break;
838 
840  dstmod = GL_2X_BIT_ATI;
841  /* fall through */
843  argmodextra = GL_BIAS_BIT_ATI;
844  /* fall through */
845  case WINED3D_TOP_ADD:
846  dstmod |= GL_SATURATE_BIT_ATI;
847  wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod,
848  arg1, GL_NONE, argmod1,
849  arg2, GL_NONE, argmodextra | argmod2);
850  break;
851 
853  dstmod |= GL_SATURATE_BIT_ATI;
854  wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod,
855  arg1, GL_NONE, argmod1,
856  arg2, GL_NONE, argmod2);
857  break;
858 
860  argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI;
861  /* Dst = arg1 + * arg2(1 -arg 1)
862  * = arg2 * (1 - arg1) + arg1
863  */
864  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
865  arg2, GL_NONE, argmod2,
866  arg1, GL_NONE, argmodextra,
867  arg1, GL_NONE, argmod1);
868  break;
869 
871  if (extrarg == GL_NONE)
872  extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1);
873  /* fall through */
875  if (extrarg == GL_NONE)
876  extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1);
877  /* fall through */
879  if (extrarg == GL_NONE)
880  extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
881  /* fall through */
883  if (extrarg == GL_NONE)
884  extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1);
885  wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE,
886  extrarg, GL_ALPHA, GL_NONE,
887  arg1, GL_NONE, argmod1,
888  arg2, GL_NONE, argmod2);
889  break;
890 
892  arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1);
893  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE,
894  arg2, GL_NONE, argmod2,
895  arg0, GL_ALPHA, GL_COMP_BIT_ATI,
896  arg1, GL_NONE, argmod1);
897  break;
898 
899  /* D3DTOP_PREMODULATE ???? */
900 
903  arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI,
904  arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI);
905  break;
906 
908  wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI,
909  arg1, GL_NONE, argmod1,
910  arg2, GL_NONE, argmod2,
911  arg0, GL_NONE, argmod0);
912  break;
913 
914  case WINED3D_TOP_LERP:
916  arg1, GL_NONE, argmod1,
917  arg2, GL_NONE, argmod2,
918  arg0, GL_NONE, argmod0);
919  break;
920 
927  ERR("Application uses an invalid alpha operation\n");
928  break;
929 
930  default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage);
931  }
932  }
933 
935  FIXME("Texture factor constant already used.\n");
937 
938  /* Assign unused constants to avoid reloading due to unused <-> bump matrix switches. */
939  for (stage = 0; stage < MAX_TEXTURES; ++stage)
940  {
941  if (constants[stage] == ATIFS_CONSTANT_UNUSED)
943  }
944 
945  TRACE("glEndFragmentShaderATI()\n");
946  GL_EXTCALL(glEndFragmentShaderATI());
947  checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())");
948  return ret;
949 }
950 
951 static void atifs_tfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
952 {
953  const struct wined3d_gl_info *gl_info = context->gl_info;
954  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
955  struct wined3d_color color;
956 
957  if (!ctx_priv->last_shader
959  return;
960 
962  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_TFACTOR, &color.r));
963  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_TFACTOR, &color.r)");
964 }
965 
966 static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
967 {
968  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
969  const struct wined3d_gl_info *gl_info = context->gl_info;
970  float mat[2][2];
971  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
972 
973  if (!ctx_priv->last_shader
974  || ctx_priv->last_shader->constants[stage] != ATIFS_CONSTANT_BUMP)
975  return;
976 
977  mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
978  mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
979  mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
980  mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
981  /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat
982  * constants can be in any range. While they should stay between [-1.0 and 1.0] because
983  * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally,
984  * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the
985  * shader(it is free). This might potentially reduce precision. However, if the hardware does
986  * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway. */
987  mat[0][0] = (mat[0][0] + 1.0f) * 0.5f;
988  mat[1][0] = (mat[1][0] + 1.0f) * 0.5f;
989  mat[0][1] = (mat[0][1] + 1.0f) * 0.5f;
990  mat[1][1] = (mat[1][1] + 1.0f) * 0.5f;
991  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_BUMPMAT(stage), (float *) mat));
992  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_BUMPMAT(stage), mat)");
993 }
994 
995 static void atifs_stage_constant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
996 {
997  DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
998  const struct wined3d_gl_info *gl_info = context->gl_info;
999  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
1000  struct wined3d_color color;
1001 
1002  if (!ctx_priv->last_shader
1003  || ctx_priv->last_shader->constants[stage] != ATIFS_CONSTANT_STAGE)
1004  return;
1005 
1006  wined3d_color_from_d3dcolor(&color, state->texture_states[stage][WINED3D_TSS_CONSTANT]);
1007  GL_EXTCALL(glSetFragmentShaderConstantATI(ATIFS_CONST_STAGE(stage), &color.r));
1008  checkGLcall("glSetFragmentShaderConstantATI(ATIFS_CONST_STAGE(stage), &color.r)");
1009 }
1010 
1011 static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1012 {
1013  const struct wined3d_device *device = context->device;
1014  const struct wined3d_gl_info *gl_info = context->gl_info;
1015  const struct wined3d_d3d_info *d3d_info = context->d3d_info;
1016  struct atifs_context_private_data *ctx_priv = context->fragment_pipe_data;
1017  const struct atifs_ffp_desc *desc, *last_shader = ctx_priv->last_shader;
1018  struct ffp_frag_settings settings;
1019  struct atifs_private_data *priv = device->fragment_priv;
1020  DWORD mapped_stage;
1021  unsigned int i;
1022 
1025  if (!desc)
1026  {
1027  struct atifs_ffp_desc *new_desc;
1028 
1029  if (!(new_desc = heap_alloc_zero(sizeof(*new_desc))))
1030  {
1031  ERR("Out of memory\n");
1032  return;
1033  }
1034  new_desc->num_textures_used = 0;
1035  for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
1036  {
1037  if (settings.op[i].cop == WINED3D_TOP_DISABLE)
1038  break;
1039  ++new_desc->num_textures_used;
1040  }
1041 
1042  new_desc->parent.settings = settings;
1043  new_desc->shader = gen_ati_shader(settings.op, gl_info, new_desc->constants);
1044  add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
1045  TRACE("Allocated fixed function replacement shader descriptor %p.\n", new_desc);
1046  desc = new_desc;
1047  }
1048 
1049  /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages
1050  * used by this shader
1051  */
1052  for (i = 0; i < desc->num_textures_used; ++i)
1053  {
1054  mapped_stage = context->tex_unit_map[i];
1055  if (mapped_stage != WINED3D_UNMAPPED_STAGE)
1056  {
1057  context_active_texture(context, gl_info, mapped_stage);
1058  texture_activate_dimensions(state->textures[i], gl_info);
1059  }
1060  }
1061 
1062  GL_EXTCALL(glBindFragmentShaderATI(desc->shader));
1063  ctx_priv->last_shader = desc;
1064 
1065  for (i = 0; i < MAX_TEXTURES; i++)
1066  {
1067  if (last_shader && last_shader->constants[i] == desc->constants[i])
1068  continue;
1069 
1070  switch (desc->constants[i])
1071  {
1072  case ATIFS_CONSTANT_BUMP:
1074  break;
1075 
1078  break;
1079 
1080  case ATIFS_CONSTANT_STAGE:
1082  break;
1083 
1084  default:
1085  ERR("Unexpected constant type %u.\n", desc->constants[i]);
1086  }
1087  }
1088 }
1089 
1090 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1091 {
1093  set_tex_op_atifs(context, state, state_id);
1094 }
1095 
1096 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1097 {
1098  if (state->render_states[WINED3D_RS_SRGBWRITEENABLE])
1099  WARN("sRGB writes are not supported by this fragment pipe.\n");
1100 }
1101 
1247  {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
1248 };
1249 
1250 /* Context activation is done by the caller. */
1251 static void atifs_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
1252 {
1253  if (enable)
1254  {
1255  gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_SHADER_ATI);
1256  checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)");
1257  }
1258  else
1259  {
1260  gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_SHADER_ATI);
1261  checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)");
1262  }
1263 }
1264 
1265 static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
1266 {
1294 
1295  /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
1296  and WINED3DTEXOPCAPS_PREMODULATE */
1297 
1298  /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards
1299  * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program).
1300  * If the current card has more than 8 fixed function textures in OpenGL's regular fixed
1301  * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This
1302  * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp
1303  * pipeline, and almost all games are happy with that. We can however support up to 8
1304  * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use
1305  * only 1 instruction.
1306  *
1307  * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the
1308  * r200 series and use an ARB or GLSL shader instead
1309  */
1311  caps->MaxSimultaneousTextures = 6;
1312 }
1313 
1314 static DWORD atifs_get_emul_mask(const struct wined3d_gl_info *gl_info)
1315 {
1317 }
1318 
1319 static void *atifs_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
1320 {
1321  struct atifs_private_data *priv;
1322 
1323  if (!(priv = heap_alloc_zero(sizeof(*priv))))
1324  return NULL;
1325 
1327  return priv;
1328 }
1329 
1330 /* Context activation is done by the caller. */
1331 static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *cb_ctx)
1332 {
1333  const struct wined3d_gl_info *gl_info = cb_ctx;
1334  struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry);
1335 
1336  GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader));
1337  checkGLcall("glDeleteFragmentShaderATI(entry->shader)");
1338  heap_free(entry_ati);
1339 }
1340 
1341 /* Context activation is done by the caller. */
1342 static void atifs_free(struct wined3d_device *device)
1343 {
1344  struct atifs_private_data *priv = device->fragment_priv;
1345 
1346  wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, &device->adapter->gl_info);
1347 
1348  heap_free(priv);
1349  device->fragment_priv = NULL;
1350 }
1351 
1353 {
1354  /* We only support sign fixup of the first two channels. */
1355  return is_identity_fixup(fixup) || is_same_fixup(fixup, color_fixup_rg)
1357 }
1358 
1360 {
1361  struct atifs_context_private_data *priv;
1362 
1363  if (!(priv = heap_alloc_zero(sizeof(*priv))))
1364  return FALSE;
1365  context->fragment_pipe_data = priv;
1366  return TRUE;
1367 }
1368 
1370 {
1371  heap_free(context->fragment_pipe_data);
1372 }
1373 
1375  atifs_enable,
1378  atifs_alloc,
1379  atifs_free,
1384 };
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:289
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:1111
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:1167
Definition: http.c:6587
#define WINED3DTA_CONSTANT
Definition: wined3d.h:882
#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:2486
#define WINED3DTEXOPCAPS_DISABLE
Definition: wined3d.h:1147
#define WINED3DTEXOPCAPS_BLENDCURRENTALPHA
Definition: wined3d.h:1162
#define ATIFS_CONST_BUMPMAT(i)
#define WINED3DTEXOPCAPS_ADDSIGNED
Definition: wined3d.h:1154
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:1150
uint8_t entry
Definition: isohybrid.c:63
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:1155
#define GL_HALF_BIT_ATI
Definition: glext.h:3989
#define WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
Definition: wined3d.h:1158
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:1157
static const MAT2 mat
Definition: font.c:66
static const char * debug_register(GLuint reg)
#define WINED3DTA_COMPLEMENT
Definition: wined3d.h:883
#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:1149
#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:649
#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:6035
#define WINED3DTA_CURRENT
Definition: wined3d.h:877
#define WINED3DTEXOPCAPS_LERP
Definition: wined3d.h:1172
#define WINED3DTEXOPCAPS_BLENDFACTORALPHA
Definition: wined3d.h:1160
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:1285
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:1107
#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:1166
#define ATIFS_CONST_TFACTOR
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
#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
const struct builtin_class_descr * desc
Definition: regcontrol.c:48
#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:6021
#define WINED3DPMISCCAPS_TSSARGTEMP
Definition: wined3d.h:1103
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:878
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:1170
#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:6122
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:875
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:1161
GLfloat f
Definition: glext.h:7540
#define WINED3DTEXOPCAPS_MODULATE4X
Definition: wined3d.h:1152
#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:6014
#define WINED3DTEXOPCAPS_SELECTARG1
Definition: wined3d.h:1148
#define GL_REG_4_ATI
Definition: glext.h:3897
r parent
Definition: btrfs.c:2659
#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:876
atifs_constant_value
#define WINED3DTA_SPECULAR
Definition: wined3d.h:880
#define WINED3DTEXOPCAPS_MULTIPLYADD
Definition: wined3d.h:1171
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:879
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
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:169
#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:1151
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:604
#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:1295
#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:6140
static int reg
Definition: i386-dis.c:1275
#define GL_PRIMARY_COLOR
Definition: gl.h:1846
#define WINED3DTEXOPCAPS_SUBTRACT
Definition: wined3d.h:1156
#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:1165
#define ATIFS_CONST_STAGE(i)
#define GL_MAD_ATI
Definition: glext.h:3963
#define WINED3DTA_ALPHAREPLICATE
Definition: wined3d.h:884
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:5693
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:1127
#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:1159
unsigned short y_source
#define WINED3DTEXOPCAPS_BUMPENVMAP
Definition: wined3d.h:1168
#define WINED3DTA_TEMP
Definition: wined3d.h:881
#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:1164
#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:1153
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]