Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenati_fragment_shader.c
Go to the documentation of this file.
00001 /* 00002 * Fixed function pipeline replacement using GL_ATI_fragment_shader 00003 * 00004 * Copyright 2008 Stefan Dösinger(for CodeWeavers) 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include <math.h> 00024 #include <stdio.h> 00025 00026 #include "wined3d_private.h" 00027 00028 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); 00029 WINE_DECLARE_DEBUG_CHANNEL(d3d); 00030 00031 /* GL locking for state handlers is done by the caller. */ 00032 00033 /* Some private defines, Constant associations, etc. 00034 * Env bump matrix and per stage constant should be independent, 00035 * a stage that bump maps can't read the per state constant 00036 */ 00037 #define ATI_FFP_CONST_BUMPMAT(i) (GL_CON_0_ATI + i) 00038 #define ATI_FFP_CONST_CONSTANT0 GL_CON_0_ATI 00039 #define ATI_FFP_CONST_CONSTANT1 GL_CON_1_ATI 00040 #define ATI_FFP_CONST_CONSTANT2 GL_CON_2_ATI 00041 #define ATI_FFP_CONST_CONSTANT3 GL_CON_3_ATI 00042 #define ATI_FFP_CONST_CONSTANT4 GL_CON_4_ATI 00043 #define ATI_FFP_CONST_CONSTANT5 GL_CON_5_ATI 00044 #define ATI_FFP_CONST_TFACTOR GL_CON_6_ATI 00045 00046 /* GL_ATI_fragment_shader specific fixed function pipeline description. "Inherits" from the common one */ 00047 struct atifs_ffp_desc 00048 { 00049 struct ffp_frag_desc parent; 00050 GLuint shader; 00051 unsigned int num_textures_used; 00052 }; 00053 00054 struct atifs_private_data 00055 { 00056 struct wine_rb_tree fragment_shaders; /* A rb-tree to track fragment pipeline replacement shaders */ 00057 }; 00058 00059 static const char *debug_dstmod(GLuint mod) { 00060 switch(mod) { 00061 case GL_NONE: return "GL_NONE"; 00062 case GL_2X_BIT_ATI: return "GL_2X_BIT_ATI"; 00063 case GL_4X_BIT_ATI: return "GL_4X_BIT_ATI"; 00064 case GL_8X_BIT_ATI: return "GL_8X_BIT_ATI"; 00065 case GL_HALF_BIT_ATI: return "GL_HALF_BIT_ATI"; 00066 case GL_QUARTER_BIT_ATI: return "GL_QUARTER_BIT_ATI"; 00067 case GL_EIGHTH_BIT_ATI: return "GL_EIGHTH_BIT_ATI"; 00068 case GL_SATURATE_BIT_ATI: return "GL_SATURATE_BIT_ATI"; 00069 default: return "Unexpected modifier\n"; 00070 } 00071 } 00072 00073 static const char *debug_argmod(GLuint mod) { 00074 switch(mod) { 00075 case GL_NONE: 00076 return "GL_NONE"; 00077 00078 case GL_2X_BIT_ATI: 00079 return "GL_2X_BIT_ATI"; 00080 case GL_COMP_BIT_ATI: 00081 return "GL_COMP_BIT_ATI"; 00082 case GL_NEGATE_BIT_ATI: 00083 return "GL_NEGATE_BIT_ATI"; 00084 case GL_BIAS_BIT_ATI: 00085 return "GL_BIAS_BIT_ATI"; 00086 00087 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI: 00088 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI"; 00089 case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI: 00090 return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI"; 00091 case GL_2X_BIT_ATI | GL_BIAS_BIT_ATI: 00092 return "GL_2X_BIT_ATI | GL_BIAS_BIT_ATI"; 00093 case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI: 00094 return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI"; 00095 case GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI: 00096 return "GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI"; 00097 case GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: 00098 return "GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; 00099 00100 case GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: 00101 return "GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; 00102 case GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: 00103 return "GL_2X_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; 00104 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI: 00105 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_BIAS_BIT_ATI"; 00106 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI: 00107 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI"; 00108 00109 case GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI: 00110 return "GL_2X_BIT_ATI | GL_COMP_BIT_ATI | GL_NEGATE_BIT_ATI | GL_BIAS_BIT_ATI"; 00111 00112 default: 00113 return "Unexpected argmod combination\n"; 00114 } 00115 } 00116 static const char *debug_register(GLuint reg) { 00117 switch(reg) { 00118 case GL_REG_0_ATI: return "GL_REG_0_ATI"; 00119 case GL_REG_1_ATI: return "GL_REG_1_ATI"; 00120 case GL_REG_2_ATI: return "GL_REG_2_ATI"; 00121 case GL_REG_3_ATI: return "GL_REG_3_ATI"; 00122 case GL_REG_4_ATI: return "GL_REG_4_ATI"; 00123 case GL_REG_5_ATI: return "GL_REG_5_ATI"; 00124 00125 case GL_CON_0_ATI: return "GL_CON_0_ATI"; 00126 case GL_CON_1_ATI: return "GL_CON_1_ATI"; 00127 case GL_CON_2_ATI: return "GL_CON_2_ATI"; 00128 case GL_CON_3_ATI: return "GL_CON_3_ATI"; 00129 case GL_CON_4_ATI: return "GL_CON_4_ATI"; 00130 case GL_CON_5_ATI: return "GL_CON_5_ATI"; 00131 case GL_CON_6_ATI: return "GL_CON_6_ATI"; 00132 case GL_CON_7_ATI: return "GL_CON_7_ATI"; 00133 00134 case GL_ZERO: return "GL_ZERO"; 00135 case GL_ONE: return "GL_ONE"; 00136 case GL_PRIMARY_COLOR: return "GL_PRIMARY_COLOR"; 00137 case GL_SECONDARY_INTERPOLATOR_ATI: return "GL_SECONDARY_INTERPOLATOR_ATI"; 00138 00139 default: return "Unknown register\n"; 00140 } 00141 } 00142 00143 static const char *debug_swizzle(GLuint swizzle) { 00144 switch(swizzle) { 00145 case GL_SWIZZLE_STR_ATI: return "GL_SWIZZLE_STR_ATI"; 00146 case GL_SWIZZLE_STQ_ATI: return "GL_SWIZZLE_STQ_ATI"; 00147 case GL_SWIZZLE_STR_DR_ATI: return "GL_SWIZZLE_STR_DR_ATI"; 00148 case GL_SWIZZLE_STQ_DQ_ATI: return "GL_SWIZZLE_STQ_DQ_ATI"; 00149 default: return "unknown swizzle"; 00150 } 00151 } 00152 00153 static const char *debug_rep(GLuint rep) { 00154 switch(rep) { 00155 case GL_NONE: return "GL_NONE"; 00156 case GL_RED: return "GL_RED"; 00157 case GL_GREEN: return "GL_GREEN"; 00158 case GL_BLUE: return "GL_BLUE"; 00159 default: return "unknown argrep"; 00160 } 00161 } 00162 00163 static const char *debug_op(GLuint op) { 00164 switch(op) { 00165 case GL_MOV_ATI: return "GL_MOV_ATI"; 00166 case GL_ADD_ATI: return "GL_ADD_ATI"; 00167 case GL_MUL_ATI: return "GL_MUL_ATI"; 00168 case GL_SUB_ATI: return "GL_SUB_ATI"; 00169 case GL_DOT3_ATI: return "GL_DOT3_ATI"; 00170 case GL_DOT4_ATI: return "GL_DOT4_ATI"; 00171 case GL_MAD_ATI: return "GL_MAD_ATI"; 00172 case GL_LERP_ATI: return "GL_LERP_ATI"; 00173 case GL_CND_ATI: return "GL_CND_ATI"; 00174 case GL_CND0_ATI: return "GL_CND0_ATI"; 00175 case GL_DOT2_ADD_ATI: return "GL_DOT2_ADD_ATI"; 00176 default: return "unexpected op"; 00177 } 00178 } 00179 00180 static const char *debug_mask(GLuint mask) { 00181 switch(mask) { 00182 case GL_NONE: return "GL_NONE"; 00183 case GL_RED_BIT_ATI: return "GL_RED_BIT_ATI"; 00184 case GL_GREEN_BIT_ATI: return "GL_GREEN_BIT_ATI"; 00185 case GL_BLUE_BIT_ATI: return "GL_BLUE_BIT_ATI"; 00186 case GL_RED_BIT_ATI | GL_GREEN_BIT_ATI: return "GL_RED_BIT_ATI | GL_GREEN_BIT_ATI"; 00187 case GL_RED_BIT_ATI | GL_BLUE_BIT_ATI: return "GL_RED_BIT_ATI | GL_BLUE_BIT_ATI"; 00188 case GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI:return "GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI"; 00189 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"; 00190 default: return "Unexpected writemask"; 00191 } 00192 } 00193 00194 static void wrap_op1(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, 00195 GLuint arg1, GLuint arg1Rep, GLuint arg1Mod) 00196 { 00197 if(dstMask == GL_ALPHA) { 00198 TRACE("glAlphaFragmentOp1ATI(%s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), 00199 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod)); 00200 GL_EXTCALL(glAlphaFragmentOp1ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod)); 00201 } else { 00202 TRACE("glColorFragmentOp1ATI(%s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), 00203 debug_mask(dstMask), debug_dstmod(dstMod), 00204 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod)); 00205 GL_EXTCALL(glColorFragmentOp1ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod)); 00206 } 00207 } 00208 00209 static void wrap_op2(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, 00210 GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod) 00211 { 00212 if(dstMask == GL_ALPHA) { 00213 TRACE("glAlphaFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), 00214 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod), 00215 debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod)); 00216 GL_EXTCALL(glAlphaFragmentOp2ATI(op, dst, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod)); 00217 } else { 00218 TRACE("glColorFragmentOp2ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), 00219 debug_mask(dstMask), debug_dstmod(dstMod), 00220 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod), 00221 debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod)); 00222 GL_EXTCALL(glColorFragmentOp2ATI(op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod)); 00223 } 00224 } 00225 00226 static void wrap_op3(const struct wined3d_gl_info *gl_info, GLuint op, GLuint dst, GLuint dstMask, GLuint dstMod, 00227 GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, 00228 GLuint arg3, GLuint arg3Rep, GLuint arg3Mod) 00229 { 00230 if(dstMask == GL_ALPHA) { 00231 /* Leave some free space to fit "GL_NONE, " in to align most alpha and color op lines */ 00232 TRACE("glAlphaFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), debug_dstmod(dstMod), 00233 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod), 00234 debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod), 00235 debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod)); 00236 GL_EXTCALL(glAlphaFragmentOp3ATI(op, dst, dstMod, 00237 arg1, arg1Rep, arg1Mod, 00238 arg2, arg2Rep, arg2Mod, 00239 arg3, arg3Rep, arg3Mod)); 00240 } else { 00241 TRACE("glColorFragmentOp3ATI(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n", debug_op(op), debug_register(dst), 00242 debug_mask(dstMask), debug_dstmod(dstMod), 00243 debug_register(arg1), debug_rep(arg1Rep), debug_argmod(arg1Mod), 00244 debug_register(arg2), debug_rep(arg2Rep), debug_argmod(arg2Mod), 00245 debug_register(arg3), debug_rep(arg3Rep), debug_argmod(arg3Mod)); 00246 GL_EXTCALL(glColorFragmentOp3ATI(op, dst, dstMask, dstMod, 00247 arg1, arg1Rep, arg1Mod, 00248 arg2, arg2Rep, arg2Mod, 00249 arg3, arg3Rep, arg3Mod)); 00250 } 00251 } 00252 00253 static GLuint register_for_arg(DWORD arg, const struct wined3d_gl_info *gl_info, 00254 unsigned int stage, GLuint *mod, GLuint *rep, GLuint tmparg) 00255 { 00256 GLenum ret; 00257 00258 if(mod) *mod = GL_NONE; 00259 if(arg == ARG_UNUSED) 00260 { 00261 if (rep) *rep = GL_NONE; 00262 return -1; /* This is the marker for unused registers */ 00263 } 00264 00265 switch(arg & WINED3DTA_SELECTMASK) { 00266 case WINED3DTA_DIFFUSE: 00267 ret = GL_PRIMARY_COLOR; 00268 break; 00269 00270 case WINED3DTA_CURRENT: 00271 /* Note that using GL_REG_0_ATI for the passed on register is safe because 00272 * texture0 is read at stage0, so in the worst case it is read in the 00273 * instruction writing to reg0. Afterwards texture0 is not used any longer. 00274 * If we're reading from current 00275 */ 00276 ret = stage ? GL_REG_0_ATI : GL_PRIMARY_COLOR; 00277 break; 00278 00279 case WINED3DTA_TEXTURE: 00280 ret = GL_REG_0_ATI + stage; 00281 break; 00282 00283 case WINED3DTA_TFACTOR: 00284 ret = ATI_FFP_CONST_TFACTOR; 00285 break; 00286 00287 case WINED3DTA_SPECULAR: 00288 ret = GL_SECONDARY_INTERPOLATOR_ATI; 00289 break; 00290 00291 case WINED3DTA_TEMP: 00292 ret = tmparg; 00293 break; 00294 00295 case WINED3DTA_CONSTANT: 00296 FIXME("Unhandled source argument WINED3DTA_TEMP\n"); 00297 ret = GL_CON_0_ATI; 00298 break; 00299 00300 default: 00301 FIXME("Unknown source argument %d\n", arg); 00302 ret = GL_ZERO; 00303 } 00304 00305 if(arg & WINED3DTA_COMPLEMENT) { 00306 if(mod) *mod |= GL_COMP_BIT_ATI; 00307 } 00308 if(arg & WINED3DTA_ALPHAREPLICATE) { 00309 if(rep) *rep = GL_ALPHA; 00310 } else { 00311 if(rep) *rep = GL_NONE; 00312 } 00313 return ret; 00314 } 00315 00316 static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES]) 00317 { 00318 int lowest_read = -1; 00319 int lowest_write = -1; 00320 int i; 00321 BOOL tex_used[MAX_TEXTURES]; 00322 00323 memset(tex_used, 0, sizeof(tex_used)); 00324 for (i = 0; i < MAX_TEXTURES; ++i) 00325 { 00326 if (op[i].cop == WINED3D_TOP_DISABLE) 00327 break; 00328 00329 if(lowest_read == -1 && 00330 (op[i].carg1 == WINED3DTA_TEMP || op[i].carg2 == WINED3DTA_TEMP || op[i].carg0 == WINED3DTA_TEMP || 00331 op[i].aarg1 == WINED3DTA_TEMP || op[i].aarg2 == WINED3DTA_TEMP || op[i].aarg0 == WINED3DTA_TEMP)) { 00332 lowest_read = i; 00333 } 00334 00335 if(lowest_write == -1 && op[i].dst == tempreg) { 00336 lowest_write = i; 00337 } 00338 00339 if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE || 00340 op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) { 00341 tex_used[i] = TRUE; 00342 } 00343 } 00344 00345 /* Temp reg not read? We don't need it, return GL_NONE */ 00346 if(lowest_read == -1) return GL_NONE; 00347 00348 if(lowest_write >= lowest_read) { 00349 FIXME("Temp register read before being written\n"); 00350 } 00351 00352 if(lowest_write == -1) { 00353 /* This needs a test. Maybe we are supposed to return 0.0/0.0/0.0/0.0, or fail drawprim, or whatever */ 00354 FIXME("Temp register read without being written\n"); 00355 return GL_REG_1_ATI; 00356 } else if(lowest_write >= 1) { 00357 /* If we're writing to the temp reg at earliest in stage 1, we can use register 1 for the temp result. 00358 * there may be texture data stored in reg 1, but we do not need it any longer since stage 1 already 00359 * read it 00360 */ 00361 return GL_REG_1_ATI; 00362 } else { 00363 /* Search for a free texture register. We have 6 registers available. GL_REG_0_ATI is already used 00364 * for the regular result 00365 */ 00366 for(i = 1; i < 6; i++) { 00367 if(!tex_used[i]) { 00368 return GL_REG_0_ATI + i; 00369 } 00370 } 00371 /* What to do here? Report it in ValidateDevice? */ 00372 FIXME("Could not find a register for the temporary register\n"); 00373 return 0; 00374 } 00375 } 00376 00377 static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info) 00378 { 00379 GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1)); 00380 unsigned int stage; 00381 GLuint arg0, arg1, arg2, extrarg; 00382 GLuint dstmod, argmod0, argmod1, argmod2, argmodextra; 00383 GLuint rep0, rep1, rep2; 00384 GLuint swizzle; 00385 GLuint tmparg = find_tmpreg(op); 00386 GLuint dstreg; 00387 00388 if(!ret) { 00389 ERR("Failed to generate a GL_ATI_fragment_shader shader id\n"); 00390 return 0; 00391 } 00392 GL_EXTCALL(glBindFragmentShaderATI(ret)); 00393 checkGLcall("GL_EXTCALL(glBindFragmentShaderATI(ret))"); 00394 00395 TRACE("glBeginFragmentShaderATI()\n"); 00396 GL_EXTCALL(glBeginFragmentShaderATI()); 00397 checkGLcall("GL_EXTCALL(glBeginFragmentShaderATI())"); 00398 00399 /* Pass 1: Generate sampling instructions for perturbation maps */ 00400 for (stage = 0; stage < gl_info->limits.textures; ++stage) 00401 { 00402 if (op[stage].cop == WINED3D_TOP_DISABLE) 00403 break; 00404 if (op[stage].cop != WINED3D_TOP_BUMPENVMAP 00405 && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) 00406 continue; 00407 00408 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, GL_SWIZZLE_STR_ATI)\n", 00409 stage, stage); 00410 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, 00411 GL_TEXTURE0_ARB + stage, 00412 GL_SWIZZLE_STR_ATI)); 00413 if(op[stage + 1].projected == proj_none) { 00414 swizzle = GL_SWIZZLE_STR_ATI; 00415 } else if(op[stage + 1].projected == proj_count4) { 00416 swizzle = GL_SWIZZLE_STQ_DQ_ATI; 00417 } else { 00418 swizzle = GL_SWIZZLE_STR_DR_ATI; 00419 } 00420 TRACE("glPassTexCoordATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n", 00421 stage + 1, stage + 1, debug_swizzle(swizzle)); 00422 GL_EXTCALL(glPassTexCoordATI(GL_REG_0_ATI + stage + 1, 00423 GL_TEXTURE0_ARB + stage + 1, 00424 swizzle)); 00425 } 00426 00427 /* Pass 2: Generate perturbation calculations */ 00428 for (stage = 0; stage < gl_info->limits.textures; ++stage) 00429 { 00430 GLuint argmodextra_x, argmodextra_y; 00431 struct color_fixup_desc fixup; 00432 00433 if (op[stage].cop == WINED3D_TOP_DISABLE) 00434 break; 00435 if (op[stage].cop != WINED3D_TOP_BUMPENVMAP 00436 && op[stage].cop != WINED3D_TOP_BUMPENVMAP_LUMINANCE) 00437 continue; 00438 00439 fixup = op[stage].color_fixup; 00440 if (fixup.x_source != CHANNEL_SOURCE_X || fixup.y_source != CHANNEL_SOURCE_Y) 00441 { 00442 FIXME("Swizzles not implemented\n"); 00443 argmodextra_x = GL_NONE; 00444 argmodextra_y = GL_NONE; 00445 } 00446 else 00447 { 00448 /* Nice thing, we get the color correction for free :-) */ 00449 argmodextra_x = fixup.x_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE; 00450 argmodextra_y = fixup.y_sign_fixup ? GL_2X_BIT_ATI | GL_BIAS_BIT_ATI : GL_NONE; 00451 } 00452 00453 wrap_op3(gl_info, GL_DOT2_ADD_ATI, GL_REG_0_ATI + stage + 1, GL_RED_BIT_ATI, GL_NONE, 00454 GL_REG_0_ATI + stage, GL_NONE, argmodextra_x, 00455 ATI_FFP_CONST_BUMPMAT(stage), GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI, 00456 GL_REG_0_ATI + stage + 1, GL_RED, GL_NONE); 00457 00458 /* Don't use GL_DOT2_ADD_ATI here because we cannot configure it to read the blue and alpha 00459 * component of the bump matrix. Instead do this with two MADs: 00460 * 00461 * coord.a = tex.r * bump.b + coord.g 00462 * coord.g = tex.g * bump.a + coord.a 00463 * 00464 * The first instruction writes to alpha so it can be coissued with the above DOT2_ADD. 00465 * coord.a is unused. If the perturbed texture is projected, this was already handled 00466 * in the glPassTexCoordATI above. 00467 */ 00468 wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE, 00469 GL_REG_0_ATI + stage, GL_RED, argmodextra_y, 00470 ATI_FFP_CONST_BUMPMAT(stage), GL_BLUE, GL_NONE, 00471 GL_REG_0_ATI + stage + 1, GL_GREEN, GL_NONE); 00472 wrap_op3(gl_info, GL_MAD_ATI, GL_REG_0_ATI + stage + 1, GL_GREEN_BIT_ATI, GL_NONE, 00473 GL_REG_0_ATI + stage, GL_GREEN, argmodextra_y, 00474 ATI_FFP_CONST_BUMPMAT(stage), GL_ALPHA, GL_NONE, 00475 GL_REG_0_ATI + stage + 1, GL_ALPHA, GL_NONE); 00476 } 00477 00478 /* Pass 3: Generate sampling instructions for regular textures */ 00479 for (stage = 0; stage < gl_info->limits.textures; ++stage) 00480 { 00481 if (op[stage].cop == WINED3D_TOP_DISABLE) 00482 break; 00483 00484 if(op[stage].projected == proj_none) { 00485 swizzle = GL_SWIZZLE_STR_ATI; 00486 } else if(op[stage].projected == proj_count3) { 00487 swizzle = GL_SWIZZLE_STR_DR_ATI; 00488 } else { 00489 swizzle = GL_SWIZZLE_STQ_DQ_ATI; 00490 } 00491 00492 if ((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00493 || (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00494 || (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00495 || (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00496 || (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00497 || (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE 00498 || op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA) 00499 { 00500 if (stage > 0 00501 && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP 00502 || op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE)) 00503 { 00504 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_REG_%d_ATI, GL_SWIZZLE_STR_ATI)\n", 00505 stage, stage); 00506 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, 00507 GL_REG_0_ATI + stage, 00508 GL_SWIZZLE_STR_ATI)); 00509 } else { 00510 TRACE("glSampleMapATI(GL_REG_%d_ATI, GL_TEXTURE_%d_ARB, %s)\n", 00511 stage, stage, debug_swizzle(swizzle)); 00512 GL_EXTCALL(glSampleMapATI(GL_REG_0_ATI + stage, 00513 GL_TEXTURE0_ARB + stage, 00514 swizzle)); 00515 } 00516 } 00517 } 00518 00519 /* Pass 4: Generate the arithmetic instructions */ 00520 for (stage = 0; stage < MAX_TEXTURES; ++stage) 00521 { 00522 if (op[stage].cop == WINED3D_TOP_DISABLE) 00523 { 00524 if (!stage) 00525 { 00526 /* Handle complete texture disabling gracefully */ 00527 wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, 00528 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 00529 wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE, 00530 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 00531 } 00532 break; 00533 } 00534 00535 if(op[stage].dst == tempreg) { 00536 /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place. 00537 * skip the entire stage, this saves some GPU time 00538 */ 00539 if(tmparg == GL_NONE) continue; 00540 00541 dstreg = tmparg; 00542 } else { 00543 dstreg = GL_REG_0_ATI; 00544 } 00545 00546 arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg); 00547 arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg); 00548 arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg); 00549 dstmod = GL_NONE; 00550 argmodextra = GL_NONE; 00551 extrarg = GL_NONE; 00552 00553 switch (op[stage].cop) 00554 { 00555 case WINED3D_TOP_SELECT_ARG2: 00556 arg1 = arg2; 00557 argmod1 = argmod2; 00558 rep1 = rep2; 00559 /* fall through */ 00560 case WINED3D_TOP_SELECT_ARG1: 00561 wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_NONE, GL_NONE, 00562 arg1, rep1, argmod1); 00563 break; 00564 00565 case WINED3D_TOP_MODULATE_4X: 00566 if(dstmod == GL_NONE) dstmod = GL_4X_BIT_ATI; 00567 /* fall through */ 00568 case WINED3D_TOP_MODULATE_2X: 00569 if(dstmod == GL_NONE) dstmod = GL_2X_BIT_ATI; 00570 dstmod |= GL_SATURATE_BIT_ATI; 00571 /* fall through */ 00572 case WINED3D_TOP_MODULATE: 00573 wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_NONE, dstmod, 00574 arg1, rep1, argmod1, 00575 arg2, rep2, argmod2); 00576 break; 00577 00578 case WINED3D_TOP_ADD_SIGNED_2X: 00579 dstmod = GL_2X_BIT_ATI; 00580 /* fall through */ 00581 case WINED3D_TOP_ADD_SIGNED: 00582 argmodextra = GL_BIAS_BIT_ATI; 00583 /* fall through */ 00584 case WINED3D_TOP_ADD: 00585 dstmod |= GL_SATURATE_BIT_ATI; 00586 wrap_op2(gl_info, GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, dstmod, 00587 arg1, rep1, argmod1, 00588 arg2, rep2, argmodextra | argmod2); 00589 break; 00590 00591 case WINED3D_TOP_SUBTRACT: 00592 dstmod |= GL_SATURATE_BIT_ATI; 00593 wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_NONE, dstmod, 00594 arg1, rep1, argmod1, 00595 arg2, rep2, argmod2); 00596 break; 00597 00598 case WINED3D_TOP_ADD_SMOOTH: 00599 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; 00600 /* Dst = arg1 + * arg2(1 -arg 1) 00601 * = arg2 * (1 - arg1) + arg1 00602 */ 00603 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, 00604 arg2, rep2, argmod2, 00605 arg1, rep1, argmodextra, 00606 arg1, rep1, argmod1); 00607 break; 00608 00609 case WINED3D_TOP_BLEND_CURRENT_ALPHA: 00610 if (extrarg == GL_NONE) 00611 extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1); 00612 /* fall through */ 00613 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 00614 if (extrarg == GL_NONE) 00615 extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1); 00616 /* fall through */ 00617 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 00618 if (extrarg == GL_NONE) 00619 extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); 00620 /* fall through */ 00621 case WINED3D_TOP_BLEND_DIFFUSE_ALPHA: 00622 if (extrarg == GL_NONE) 00623 extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1); 00624 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE, 00625 extrarg, GL_ALPHA, GL_NONE, 00626 arg1, rep1, argmod1, 00627 arg2, rep2, argmod2); 00628 break; 00629 00630 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 00631 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); 00632 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_NONE, 00633 arg2, rep2, argmod2, 00634 arg0, GL_ALPHA, GL_COMP_BIT_ATI, 00635 arg1, rep1, argmod1); 00636 break; 00637 00638 /* D3DTOP_PREMODULATE ???? */ 00639 00640 case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR: 00641 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; 00642 /* fall through */ 00643 case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR: 00644 if (!argmodextra) 00645 argmodextra = argmod1; 00646 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, 00647 arg2, rep2, argmod2, 00648 arg1, GL_ALPHA, argmodextra, 00649 arg1, rep1, argmod1); 00650 break; 00651 00652 case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA: 00653 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; 00654 /* fall through */ 00655 case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA: 00656 if (!argmodextra) 00657 argmodextra = argmod1; 00658 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, 00659 arg2, rep2, argmod2, 00660 arg1, rep1, argmodextra, 00661 arg1, GL_ALPHA, argmod1); 00662 break; 00663 00664 case WINED3D_TOP_DOTPRODUCT3: 00665 wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_NONE, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, 00666 arg1, rep1, argmod1 | GL_BIAS_BIT_ATI, 00667 arg2, rep2, argmod2 | GL_BIAS_BIT_ATI); 00668 break; 00669 00670 case WINED3D_TOP_MULTIPLY_ADD: 00671 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_NONE, GL_SATURATE_BIT_ATI, 00672 arg1, rep1, argmod1, 00673 arg2, rep2, argmod2, 00674 arg0, rep0, argmod0); 00675 break; 00676 00677 case WINED3D_TOP_LERP: 00678 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_NONE, GL_NONE, 00679 arg0, rep0, argmod0, 00680 arg1, rep1, argmod1, 00681 arg2, rep2, argmod2); 00682 break; 00683 00684 case WINED3D_TOP_BUMPENVMAP: 00685 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 00686 /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */ 00687 break; 00688 00689 default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage); 00690 } 00691 00692 arg0 = register_for_arg(op[stage].aarg0, gl_info, stage, &argmod0, NULL, tmparg); 00693 arg1 = register_for_arg(op[stage].aarg1, gl_info, stage, &argmod1, NULL, tmparg); 00694 arg2 = register_for_arg(op[stage].aarg2, gl_info, stage, &argmod2, NULL, tmparg); 00695 dstmod = GL_NONE; 00696 argmodextra = GL_NONE; 00697 extrarg = GL_NONE; 00698 00699 switch (op[stage].aop) 00700 { 00701 case WINED3D_TOP_DISABLE: 00702 /* Get the primary color to the output if on stage 0, otherwise leave register 0 untouched */ 00703 if (!stage) 00704 { 00705 wrap_op1(gl_info, GL_MOV_ATI, GL_REG_0_ATI, GL_ALPHA, GL_NONE, 00706 GL_PRIMARY_COLOR, GL_NONE, GL_NONE); 00707 } 00708 break; 00709 00710 case WINED3D_TOP_SELECT_ARG2: 00711 arg1 = arg2; 00712 argmod1 = argmod2; 00713 /* fall through */ 00714 case WINED3D_TOP_SELECT_ARG1: 00715 wrap_op1(gl_info, GL_MOV_ATI, dstreg, GL_ALPHA, GL_NONE, 00716 arg1, GL_NONE, argmod1); 00717 break; 00718 00719 case WINED3D_TOP_MODULATE_4X: 00720 if (dstmod == GL_NONE) 00721 dstmod = GL_4X_BIT_ATI; 00722 /* fall through */ 00723 case WINED3D_TOP_MODULATE_2X: 00724 if (dstmod == GL_NONE) 00725 dstmod = GL_2X_BIT_ATI; 00726 dstmod |= GL_SATURATE_BIT_ATI; 00727 /* fall through */ 00728 case WINED3D_TOP_MODULATE: 00729 wrap_op2(gl_info, GL_MUL_ATI, dstreg, GL_ALPHA, dstmod, 00730 arg1, GL_NONE, argmod1, 00731 arg2, GL_NONE, argmod2); 00732 break; 00733 00734 case WINED3D_TOP_ADD_SIGNED_2X: 00735 dstmod = GL_2X_BIT_ATI; 00736 /* fall through */ 00737 case WINED3D_TOP_ADD_SIGNED: 00738 argmodextra = GL_BIAS_BIT_ATI; 00739 /* fall through */ 00740 case WINED3D_TOP_ADD: 00741 dstmod |= GL_SATURATE_BIT_ATI; 00742 wrap_op2(gl_info, GL_ADD_ATI, dstreg, GL_ALPHA, dstmod, 00743 arg1, GL_NONE, argmod1, 00744 arg2, GL_NONE, argmodextra | argmod2); 00745 break; 00746 00747 case WINED3D_TOP_SUBTRACT: 00748 dstmod |= GL_SATURATE_BIT_ATI; 00749 wrap_op2(gl_info, GL_SUB_ATI, dstreg, GL_ALPHA, dstmod, 00750 arg1, GL_NONE, argmod1, 00751 arg2, GL_NONE, argmod2); 00752 break; 00753 00754 case WINED3D_TOP_ADD_SMOOTH: 00755 argmodextra = argmod1 & GL_COMP_BIT_ATI ? argmod1 & ~GL_COMP_BIT_ATI : argmod1 | GL_COMP_BIT_ATI; 00756 /* Dst = arg1 + * arg2(1 -arg 1) 00757 * = arg2 * (1 - arg1) + arg1 00758 */ 00759 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI, 00760 arg2, GL_NONE, argmod2, 00761 arg1, GL_NONE, argmodextra, 00762 arg1, GL_NONE, argmod1); 00763 break; 00764 00765 case WINED3D_TOP_BLEND_CURRENT_ALPHA: 00766 if (extrarg == GL_NONE) 00767 extrarg = register_for_arg(WINED3DTA_CURRENT, gl_info, stage, NULL, NULL, -1); 00768 /* fall through */ 00769 case WINED3D_TOP_BLEND_FACTOR_ALPHA: 00770 if (extrarg == GL_NONE) 00771 extrarg = register_for_arg(WINED3DTA_TFACTOR, gl_info, stage, NULL, NULL, -1); 00772 /* fall through */ 00773 case WINED3D_TOP_BLEND_TEXTURE_ALPHA: 00774 if (extrarg == GL_NONE) 00775 extrarg = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); 00776 /* fall through */ 00777 case WINED3D_TOP_BLEND_DIFFUSE_ALPHA: 00778 if (extrarg == GL_NONE) 00779 extrarg = register_for_arg(WINED3DTA_DIFFUSE, gl_info, stage, NULL, NULL, -1); 00780 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_NONE, 00781 extrarg, GL_ALPHA, GL_NONE, 00782 arg1, GL_NONE, argmod1, 00783 arg2, GL_NONE, argmod2); 00784 break; 00785 00786 case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM: 00787 arg0 = register_for_arg(WINED3DTA_TEXTURE, gl_info, stage, NULL, NULL, -1); 00788 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_NONE, 00789 arg2, GL_NONE, argmod2, 00790 arg0, GL_ALPHA, GL_COMP_BIT_ATI, 00791 arg1, GL_NONE, argmod1); 00792 break; 00793 00794 /* D3DTOP_PREMODULATE ???? */ 00795 00796 case WINED3D_TOP_DOTPRODUCT3: 00797 wrap_op2(gl_info, GL_DOT3_ATI, dstreg, GL_ALPHA, GL_4X_BIT_ATI | GL_SATURATE_BIT_ATI, 00798 arg1, GL_NONE, argmod1 | GL_BIAS_BIT_ATI, 00799 arg2, GL_NONE, argmod2 | GL_BIAS_BIT_ATI); 00800 break; 00801 00802 case WINED3D_TOP_MULTIPLY_ADD: 00803 wrap_op3(gl_info, GL_MAD_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI, 00804 arg1, GL_NONE, argmod1, 00805 arg2, GL_NONE, argmod2, 00806 arg0, GL_NONE, argmod0); 00807 break; 00808 00809 case WINED3D_TOP_LERP: 00810 wrap_op3(gl_info, GL_LERP_ATI, dstreg, GL_ALPHA, GL_SATURATE_BIT_ATI, 00811 arg1, GL_NONE, argmod1, 00812 arg2, GL_NONE, argmod2, 00813 arg0, GL_NONE, argmod0); 00814 break; 00815 00816 case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR: 00817 case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR: 00818 case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA: 00819 case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA: 00820 case WINED3D_TOP_BUMPENVMAP: 00821 case WINED3D_TOP_BUMPENVMAP_LUMINANCE: 00822 ERR("Application uses an invalid alpha operation\n"); 00823 break; 00824 00825 default: FIXME("Unhandled alpha operation %d on stage %d\n", op[stage].aop, stage); 00826 } 00827 } 00828 00829 TRACE("glEndFragmentShaderATI()\n"); 00830 GL_EXTCALL(glEndFragmentShaderATI()); 00831 checkGLcall("GL_EXTCALL(glEndFragmentShaderATI())"); 00832 return ret; 00833 } 00834 00835 static void set_tex_op_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00836 { 00837 const struct wined3d_device *device = context->swapchain->device; 00838 const struct wined3d_gl_info *gl_info = context->gl_info; 00839 const struct atifs_ffp_desc *desc; 00840 struct ffp_frag_settings settings; 00841 struct atifs_private_data *priv = device->fragment_priv; 00842 DWORD mapped_stage; 00843 unsigned int i; 00844 00845 gen_ffp_frag_op(device, state, &settings, TRUE); 00846 desc = (const struct atifs_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings); 00847 if(!desc) { 00848 struct atifs_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc)); 00849 if (!new_desc) 00850 { 00851 ERR("Out of memory\n"); 00852 return; 00853 } 00854 new_desc->num_textures_used = 0; 00855 for (i = 0; i < gl_info->limits.texture_stages; ++i) 00856 { 00857 if (settings.op[i].cop == WINED3D_TOP_DISABLE) 00858 break; 00859 new_desc->num_textures_used = i; 00860 } 00861 00862 memcpy(&new_desc->parent.settings, &settings, sizeof(settings)); 00863 new_desc->shader = gen_ati_shader(settings.op, gl_info); 00864 add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent); 00865 TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc); 00866 desc = new_desc; 00867 } 00868 00869 /* GL_ATI_fragment_shader depends on the GL_TEXTURE_xD enable settings. Update the texture stages 00870 * used by this shader 00871 */ 00872 for (i = 0; i < desc->num_textures_used; ++i) 00873 { 00874 mapped_stage = device->texUnitMap[i]; 00875 if (mapped_stage != WINED3D_UNMAPPED_STAGE) 00876 { 00877 context_active_texture(context, gl_info, mapped_stage); 00878 texture_activate_dimensions(state->textures[i], gl_info); 00879 } 00880 } 00881 00882 GL_EXTCALL(glBindFragmentShaderATI(desc->shader)); 00883 } 00884 00885 static void state_texfactor_atifs(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00886 { 00887 const struct wined3d_gl_info *gl_info = context->gl_info; 00888 float col[4]; 00889 00890 D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col); 00891 GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)); 00892 checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_TFACTOR, col)"); 00893 } 00894 00895 static void set_bumpmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00896 { 00897 DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); 00898 const struct wined3d_gl_info *gl_info = context->gl_info; 00899 float mat[2][2]; 00900 00901 mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]); 00902 mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]); 00903 mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]); 00904 mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]); 00905 /* GL_ATI_fragment_shader allows only constants from 0.0 to 1.0, but the bumpmat 00906 * constants can be in any range. While they should stay between [-1.0 and 1.0] because 00907 * Shader Model 1.x pixel shaders are clamped to that range negative values are used occasionally, 00908 * for example by our d3d9 test. So to get negative values scale -1;1 to 0;1 and undo that in the 00909 * shader(it is free). This might potentially reduce precision. However, if the hardware does 00910 * support proper floats it shouldn't, and if it doesn't we can't get anything better anyway 00911 */ 00912 mat[0][0] = (mat[0][0] + 1.0f) * 0.5f; 00913 mat[1][0] = (mat[1][0] + 1.0f) * 0.5f; 00914 mat[0][1] = (mat[0][1] + 1.0f) * 0.5f; 00915 mat[1][1] = (mat[1][1] + 1.0f) * 0.5f; 00916 GL_EXTCALL(glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), (float *) mat)); 00917 checkGLcall("glSetFragmentShaderConstantATI(ATI_FFP_CONST_BUMPMAT(stage), mat)"); 00918 } 00919 00920 static void textransform(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00921 { 00922 if (!isStateDirty(context, STATE_PIXELSHADER)) 00923 set_tex_op_atifs(context, state, state_id); 00924 } 00925 00926 static void atifs_apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00927 { 00928 const struct wined3d_device *device = context->swapchain->device; 00929 BOOL use_vshader = use_vs(state); 00930 00931 context->last_was_pshader = use_ps(state); 00932 /* The ATIFS code does not support pixel shaders currently, but we have to 00933 * provide a state handler to call shader_select to select a vertex shader 00934 * if one is applied because the vertex shader state may defer calling the 00935 * shader backend if the pshader state is dirty. 00936 * 00937 * In theory the application should not be able to mark the pixel shader 00938 * dirty because it cannot create a shader, and thus has no way to set the 00939 * state to something != NULL. However, a different pipeline part may link 00940 * a different state to its pixelshader handler, thus a pshader state 00941 * exists and can be dirtified. Also the pshader is always dirtified at 00942 * startup, and blitting disables all shaders and dirtifies all shader 00943 * states. If atifs can deal with this it keeps the rest of the code 00944 * simpler. */ 00945 if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative)) 00946 { 00947 device->shader_backend->shader_select(context, FALSE, use_vshader); 00948 00949 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) 00950 context_apply_state(context, state, STATE_VERTEXSHADERCONSTANT); 00951 } 00952 } 00953 00954 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) 00955 { 00956 if (state->render_states[WINED3D_RS_SRGBWRITEENABLE]) 00957 WARN("sRGB writes are not supported by this fragment pipe.\n"); 00958 } 00959 00960 static const struct StateEntryTemplate atifs_fragmentstate_template[] = { 00961 {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), state_texfactor_atifs }, WINED3D_GL_EXT_NONE }, 00962 {STATE_RENDER(WINED3D_RS_FOGCOLOR), { STATE_RENDER(WINED3D_RS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, 00963 {STATE_RENDER(WINED3D_RS_FOGDENSITY), { STATE_RENDER(WINED3D_RS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, 00964 {STATE_RENDER(WINED3D_RS_FOGENABLE), { STATE_RENDER(WINED3D_RS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, 00965 {STATE_RENDER(WINED3D_RS_FOGTABLEMODE), { STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 00966 {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), { STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, 00967 {STATE_RENDER(WINED3D_RS_FOGSTART), { STATE_RENDER(WINED3D_RS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, 00968 {STATE_RENDER(WINED3D_RS_FOGEND), { STATE_RENDER(WINED3D_RS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, 00969 {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), atifs_srgbwriteenable }, WINED3D_GL_EXT_NONE }, 00970 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), set_tex_op_atifs }, WINED3D_GL_EXT_NONE }, 00971 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00972 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00973 {STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00974 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00975 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00976 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00977 {STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00978 {STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00979 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 00980 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00981 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00982 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00983 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00984 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00985 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00986 {STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00987 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00988 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00989 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00990 {STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00991 {STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00992 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 00993 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00994 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00995 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 00996 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00997 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00998 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 00999 {STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01000 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01001 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01002 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01003 {STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01004 {STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01005 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01006 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01007 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01008 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01009 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01010 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01011 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01012 {STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01013 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01014 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01015 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01016 {STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01017 {STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01018 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01019 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01020 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01021 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01022 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01023 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01024 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01025 {STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01026 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01027 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01028 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01029 {STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01030 {STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01031 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01032 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01033 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01034 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01035 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01036 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01037 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01038 {STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01039 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01040 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01041 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01042 {STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01043 {STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01044 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01045 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01046 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01047 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01048 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01049 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01050 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01051 {STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01052 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01053 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01054 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01055 {STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01056 {STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01057 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01058 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01059 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01060 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01061 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01062 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01063 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01064 {STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01065 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01066 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01067 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01068 {STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01069 {STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG), { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP), NULL }, WINED3D_GL_EXT_NONE }, 01070 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), set_bumpmat }, WINED3D_GL_EXT_NONE }, 01071 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01072 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01073 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00), NULL }, WINED3D_GL_EXT_NONE }, 01074 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01075 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01076 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01077 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01078 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01079 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01080 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01081 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, 01082 {STATE_TEXTURESTAGE(0,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01083 {STATE_TEXTURESTAGE(1,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01084 {STATE_TEXTURESTAGE(2,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01085 {STATE_TEXTURESTAGE(3,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01086 {STATE_TEXTURESTAGE(4,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01087 {STATE_TEXTURESTAGE(5,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01088 {STATE_TEXTURESTAGE(6,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01089 {STATE_TEXTURESTAGE(7,WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), textransform }, WINED3D_GL_EXT_NONE }, 01090 {STATE_PIXELSHADER, { STATE_PIXELSHADER, atifs_apply_pixelshader }, WINED3D_GL_EXT_NONE }, 01091 {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, 01092 }; 01093 01094 /* Context activation and GL locking are done by the caller. */ 01095 static void atifs_enable(BOOL enable) 01096 { 01097 if(enable) { 01098 glEnable(GL_FRAGMENT_SHADER_ATI); 01099 checkGLcall("glEnable(GL_FRAGMENT_SHADER_ATI)"); 01100 } else { 01101 glDisable(GL_FRAGMENT_SHADER_ATI); 01102 checkGLcall("glDisable(GL_FRAGMENT_SHADER_ATI)"); 01103 } 01104 } 01105 01106 static void atifs_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) 01107 { 01108 caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP; 01109 caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | 01110 WINED3DTEXOPCAPS_SELECTARG1 | 01111 WINED3DTEXOPCAPS_SELECTARG2 | 01112 WINED3DTEXOPCAPS_MODULATE4X | 01113 WINED3DTEXOPCAPS_MODULATE2X | 01114 WINED3DTEXOPCAPS_MODULATE | 01115 WINED3DTEXOPCAPS_ADDSIGNED2X | 01116 WINED3DTEXOPCAPS_ADDSIGNED | 01117 WINED3DTEXOPCAPS_ADD | 01118 WINED3DTEXOPCAPS_SUBTRACT | 01119 WINED3DTEXOPCAPS_ADDSMOOTH | 01120 WINED3DTEXOPCAPS_BLENDCURRENTALPHA | 01121 WINED3DTEXOPCAPS_BLENDFACTORALPHA | 01122 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | 01123 WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | 01124 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM | 01125 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | 01126 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | 01127 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | 01128 WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | 01129 WINED3DTEXOPCAPS_DOTPRODUCT3 | 01130 WINED3DTEXOPCAPS_MULTIPLYADD | 01131 WINED3DTEXOPCAPS_LERP | 01132 WINED3DTEXOPCAPS_BUMPENVMAP; 01133 01134 /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE 01135 and WINED3DTEXOPCAPS_PREMODULATE */ 01136 01137 /* GL_ATI_fragment_shader always supports 6 textures, which was the limit on r200 cards 01138 * which this extension is exclusively focused on(later cards have GL_ARB_fragment_program). 01139 * If the current card has more than 8 fixed function textures in OpenGL's regular fixed 01140 * function pipeline then the ATI_fragment_shader backend imposes a stricter limit. This 01141 * shouldn't be too hard since Nvidia cards have a limit of 4 textures with the default ffp 01142 * pipeline, and almost all games are happy with that. We can however support up to 8 01143 * texture stages because we have a 2nd pass limit of 8 instructions, and per stage we use 01144 * only 1 instruction. 01145 * 01146 * The proper fix for this is not to use GL_ATI_fragment_shader on cards newer than the 01147 * r200 series and use an ARB or GLSL shader instead 01148 */ 01149 caps->MaxTextureBlendStages = 8; 01150 caps->MaxSimultaneousTextures = 6; 01151 } 01152 01153 static HRESULT atifs_alloc(struct wined3d_device *device) 01154 { 01155 struct atifs_private_data *priv; 01156 01157 device->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct atifs_private_data)); 01158 if (!device->fragment_priv) 01159 { 01160 ERR("Out of memory\n"); 01161 return E_OUTOFMEMORY; 01162 } 01163 priv = device->fragment_priv; 01164 if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1) 01165 { 01166 ERR("Failed to initialize rbtree.\n"); 01167 HeapFree(GetProcessHeap(), 0, device->fragment_priv); 01168 return E_OUTOFMEMORY; 01169 } 01170 return WINED3D_OK; 01171 } 01172 01173 /* Context activation is done by the caller. */ 01174 static void atifs_free_ffpshader(struct wine_rb_entry *entry, void *context) 01175 { 01176 struct wined3d_device *device = context; 01177 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; 01178 struct atifs_ffp_desc *entry_ati = WINE_RB_ENTRY_VALUE(entry, struct atifs_ffp_desc, parent.entry); 01179 01180 ENTER_GL(); 01181 GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader)); 01182 checkGLcall("glDeleteFragmentShaderATI(entry->shader)"); 01183 HeapFree(GetProcessHeap(), 0, entry_ati); 01184 LEAVE_GL(); 01185 } 01186 01187 /* Context activation is done by the caller. */ 01188 static void atifs_free(struct wined3d_device *device) 01189 { 01190 struct atifs_private_data *priv = device->fragment_priv; 01191 01192 wine_rb_destroy(&priv->fragment_shaders, atifs_free_ffpshader, device); 01193 01194 HeapFree(GetProcessHeap(), 0, priv); 01195 device->fragment_priv = NULL; 01196 } 01197 01198 static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup) 01199 { 01200 if (TRACE_ON(d3d_shader) && TRACE_ON(d3d)) 01201 { 01202 TRACE("Checking support for fixup:\n"); 01203 dump_color_fixup_desc(fixup); 01204 } 01205 01206 /* We only support sign fixup of the first two channels. */ 01207 if (fixup.x_source == CHANNEL_SOURCE_X && fixup.y_source == CHANNEL_SOURCE_Y 01208 && fixup.z_source == CHANNEL_SOURCE_Z && fixup.w_source == CHANNEL_SOURCE_W 01209 && !fixup.z_sign_fixup && !fixup.w_sign_fixup) 01210 { 01211 TRACE("[OK]\n"); 01212 return TRUE; 01213 } 01214 01215 TRACE("[FAILED]\n"); 01216 return FALSE; 01217 } 01218 01219 const struct fragment_pipeline atifs_fragment_pipeline = { 01220 atifs_enable, 01221 atifs_get_caps, 01222 atifs_alloc, 01223 atifs_free, 01224 atifs_color_fixup_supported, 01225 atifs_fragmentstate_template, 01226 TRUE /* We can disable projected textures */ 01227 }; Generated on Fri May 25 2012 04:20:12 for ReactOS by
1.7.6.1
|