atifragshader.c revision 70c8d29b6bb3214966892d51e6b2befa7040622d
1/** 2 * \file atifragshader.c 3 * \author David Airlie 4 * Copyright (C) 2004 David Airlie All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * DAVID AIRLIE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#include "main/glheader.h" 25#include "main/context.h" 26#include "main/hash.h" 27#include "main/imports.h" 28#include "main/macros.h" 29#include "main/enums.h" 30#include "main/mtypes.h" 31#include "main/dispatch.h" 32#include "main/atifragshader.h" 33 34#if FEATURE_ATI_fragment_shader 35 36#define MESA_DEBUG_ATI_FS 0 37 38static struct ati_fragment_shader DummyShader; 39 40 41void 42_mesa_init_ati_fragment_shader_dispatch(struct _glapi_table *disp) 43{ 44 SET_GenFragmentShadersATI(disp, _mesa_GenFragmentShadersATI); 45 SET_BindFragmentShaderATI(disp, _mesa_BindFragmentShaderATI); 46 SET_DeleteFragmentShaderATI(disp, _mesa_DeleteFragmentShaderATI); 47 SET_BeginFragmentShaderATI(disp, _mesa_BeginFragmentShaderATI); 48 SET_EndFragmentShaderATI(disp, _mesa_EndFragmentShaderATI); 49 SET_PassTexCoordATI(disp, _mesa_PassTexCoordATI); 50 SET_SampleMapATI(disp, _mesa_SampleMapATI); 51 SET_ColorFragmentOp1ATI(disp, _mesa_ColorFragmentOp1ATI); 52 SET_ColorFragmentOp2ATI(disp, _mesa_ColorFragmentOp2ATI); 53 SET_ColorFragmentOp3ATI(disp, _mesa_ColorFragmentOp3ATI); 54 SET_AlphaFragmentOp1ATI(disp, _mesa_AlphaFragmentOp1ATI); 55 SET_AlphaFragmentOp2ATI(disp, _mesa_AlphaFragmentOp2ATI); 56 SET_AlphaFragmentOp3ATI(disp, _mesa_AlphaFragmentOp3ATI); 57 SET_SetFragmentShaderConstantATI(disp, _mesa_SetFragmentShaderConstantATI); 58} 59 60 61/** 62 * Allocate and initialize a new ATI fragment shader object. 63 */ 64struct ati_fragment_shader * 65_mesa_new_ati_fragment_shader(GLcontext *ctx, GLuint id) 66{ 67 struct ati_fragment_shader *s = CALLOC_STRUCT(ati_fragment_shader); 68 (void) ctx; 69 if (s) { 70 s->Id = id; 71 s->RefCount = 1; 72 } 73 return s; 74} 75 76 77/** 78 * Delete the given ati fragment shader 79 */ 80void 81_mesa_delete_ati_fragment_shader(GLcontext *ctx, struct ati_fragment_shader *s) 82{ 83 GLuint i; 84 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { 85 if (s->Instructions[i]) 86 free(s->Instructions[i]); 87 if (s->SetupInst[i]) 88 free(s->SetupInst[i]); 89 } 90 free(s); 91} 92 93 94 95static void 96new_arith_inst(struct ati_fragment_shader *prog) 97{ 98/* set "default" instruction as not all may get defined. 99 there is no specified way to express a nop with ati fragment shaders we use 100 GL_NONE as the op enum and just set some params to 0 - so nothing to do here */ 101 prog->numArithInstr[prog->cur_pass >> 1]++; 102} 103 104static void 105new_tex_inst(struct ati_fragment_shader *prog) 106{ 107} 108 109static void match_pair_inst(struct ati_fragment_shader *curProg, GLuint optype) 110{ 111 if (optype == curProg->last_optype) { 112 curProg->last_optype = 1; 113 } 114} 115 116#if MESA_DEBUG_ATI_FS 117static char * 118create_dst_mod_str(GLuint mod) 119{ 120 static char ret_str[1024]; 121 122 memset(ret_str, 0, 1024); 123 if (mod & GL_2X_BIT_ATI) 124 strncat(ret_str, "|2X", 1024); 125 126 if (mod & GL_4X_BIT_ATI) 127 strncat(ret_str, "|4X", 1024); 128 129 if (mod & GL_8X_BIT_ATI) 130 strncat(ret_str, "|8X", 1024); 131 if (mod & GL_HALF_BIT_ATI) 132 strncat(ret_str, "|HA", 1024); 133 if (mod & GL_QUARTER_BIT_ATI) 134 strncat(ret_str, "|QU", 1024); 135 if (mod & GL_EIGHTH_BIT_ATI) 136 strncat(ret_str, "|EI", 1024); 137 138 if (mod & GL_SATURATE_BIT_ATI) 139 strncat(ret_str, "|SAT", 1024); 140 141 if (strlen(ret_str) == 0) 142 strncat(ret_str, "NONE", 1024); 143 return ret_str; 144} 145 146static char *atifs_ops[] = {"ColorFragmentOp1ATI", "ColorFragmentOp2ATI", "ColorFragmentOp3ATI", 147 "AlphaFragmentOp1ATI", "AlphaFragmentOp2ATI", "AlphaFragmentOp3ATI" }; 148 149static void debug_op(GLint optype, GLuint arg_count, GLenum op, GLuint dst, 150 GLuint dstMask, GLuint dstMod, GLuint arg1, 151 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, 152 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, 153 GLuint arg3Rep, GLuint arg3Mod) 154{ 155 char *op_name; 156 157 op_name = atifs_ops[(arg_count-1)+(optype?3:0)]; 158 159 fprintf(stderr, "%s(%s, %s", op_name, _mesa_lookup_enum_by_nr(op), 160 _mesa_lookup_enum_by_nr(dst)); 161 if (!optype) 162 fprintf(stderr, ", %d", dstMask); 163 164 fprintf(stderr, ", %s", create_dst_mod_str(dstMod)); 165 166 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg1), 167 _mesa_lookup_enum_by_nr(arg1Rep), arg1Mod); 168 if (arg_count>1) 169 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg2), 170 _mesa_lookup_enum_by_nr(arg2Rep), arg2Mod); 171 if (arg_count>2) 172 fprintf(stderr, ", %s, %s, %d", _mesa_lookup_enum_by_nr(arg3), 173 _mesa_lookup_enum_by_nr(arg3Rep), arg3Mod); 174 175 fprintf(stderr,")\n"); 176 177} 178#endif 179 180static int check_arith_arg(struct ati_fragment_shader *curProg, 181 GLuint optype, GLuint arg, GLuint argRep) 182{ 183 GET_CURRENT_CONTEXT(ctx); 184 185 if (((arg < GL_CON_0_ATI) || (arg > GL_CON_7_ATI)) && 186 ((arg < GL_REG_0_ATI) || (arg > GL_REG_5_ATI)) && 187 (arg != GL_ZERO) && (arg != GL_ONE) && 188 (arg != GL_PRIMARY_COLOR_ARB) && (arg != GL_SECONDARY_INTERPOLATOR_ATI)) { 189 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(arg)"); 190 return 0; 191 } 192 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || 193 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { 194 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); 195 return 0; 196 } 197 if ((arg == GL_SECONDARY_INTERPOLATOR_ATI) && (((optype == 0) && (argRep == GL_ALPHA)) || 198 ((optype == 1) && ((arg == GL_ALPHA) || (argRep == GL_NONE))))) { 199 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); 200 return 0; 201 } 202 if ((curProg->cur_pass == 1) && 203 ((arg == GL_PRIMARY_COLOR_ARB) || (arg == GL_SECONDARY_INTERPOLATOR_ATI))) { 204 curProg->interpinp1 = GL_TRUE; 205 } 206 return 1; 207} 208 209GLuint GLAPIENTRY 210_mesa_GenFragmentShadersATI(GLuint range) 211{ 212 GLuint first; 213 GLuint i; 214 GET_CURRENT_CONTEXT(ctx); 215 216 if (range == 0) { 217 _mesa_error(ctx, GL_INVALID_VALUE, "glGenFragmentShadersATI(range)"); 218 return 0; 219 } 220 221 if (ctx->ATIFragmentShader.Compiling) { 222 _mesa_error(ctx, GL_INVALID_OPERATION, "glGenFragmentShadersATI(insideShader)"); 223 return 0; 224 } 225 226 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->ATIShaders, range); 227 for (i = 0; i < range; i++) { 228 _mesa_HashInsert(ctx->Shared->ATIShaders, first + i, &DummyShader); 229 } 230 231 return first; 232} 233 234void GLAPIENTRY 235_mesa_BindFragmentShaderATI(GLuint id) 236{ 237 GET_CURRENT_CONTEXT(ctx); 238 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 239 struct ati_fragment_shader *newProg; 240 241 if (ctx->ATIFragmentShader.Compiling) { 242 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFragmentShaderATI(insideShader)"); 243 return; 244 } 245 246 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 247 248 if (curProg->Id == id) { 249 return; 250 } 251 252 /* unbind current */ 253 if (curProg->Id != 0) { 254 curProg->RefCount--; 255 if (curProg->RefCount <= 0) { 256 _mesa_HashRemove(ctx->Shared->ATIShaders, id); 257 } 258 } 259 260 /* find new shader */ 261 if (id == 0) { 262 newProg = ctx->Shared->DefaultFragmentShader; 263 } 264 else { 265 newProg = (struct ati_fragment_shader *) 266 _mesa_HashLookup(ctx->Shared->ATIShaders, id); 267 if (!newProg || newProg == &DummyShader) { 268 /* allocate a new program now */ 269 newProg = _mesa_new_ati_fragment_shader(ctx, id); 270 if (!newProg) { 271 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFragmentShaderATI"); 272 return; 273 } 274 _mesa_HashInsert(ctx->Shared->ATIShaders, id, newProg); 275 } 276 277 } 278 279 /* do actual bind */ 280 ctx->ATIFragmentShader.Current = newProg; 281 282 ASSERT(ctx->ATIFragmentShader.Current); 283 if (newProg) 284 newProg->RefCount++; 285 286 /*if (ctx->Driver.BindProgram) 287 ctx->Driver.BindProgram(ctx, target, prog); */ 288} 289 290void GLAPIENTRY 291_mesa_DeleteFragmentShaderATI(GLuint id) 292{ 293 GET_CURRENT_CONTEXT(ctx); 294 295 if (ctx->ATIFragmentShader.Compiling) { 296 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteFragmentShaderATI(insideShader)"); 297 return; 298 } 299 300 if (id != 0) { 301 struct ati_fragment_shader *prog = (struct ati_fragment_shader *) 302 _mesa_HashLookup(ctx->Shared->ATIShaders, id); 303 if (prog == &DummyShader) { 304 _mesa_HashRemove(ctx->Shared->ATIShaders, id); 305 } 306 else if (prog) { 307 if (ctx->ATIFragmentShader.Current && 308 ctx->ATIFragmentShader.Current->Id == id) { 309 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 310 _mesa_BindFragmentShaderATI(0); 311 } 312 } 313 314 /* The ID is immediately available for re-use now */ 315 _mesa_HashRemove(ctx->Shared->ATIShaders, id); 316 if (prog) { 317 prog->RefCount--; 318 if (prog->RefCount <= 0) { 319 free(prog); 320 } 321 } 322 } 323} 324 325 326void GLAPIENTRY 327_mesa_BeginFragmentShaderATI(void) 328{ 329 GLint i; 330 GET_CURRENT_CONTEXT(ctx); 331 332 if (ctx->ATIFragmentShader.Compiling) { 333 _mesa_error(ctx, GL_INVALID_OPERATION, "glBeginFragmentShaderATI(insideShader)"); 334 return; 335 } 336 337 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 338 339 /* if the shader was already defined free instructions and get new ones 340 (or, could use the same mem but would need to reinitialize) */ 341 /* no idea if it's allowed to redefine a shader */ 342 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { 343 if (ctx->ATIFragmentShader.Current->Instructions[i]) 344 free(ctx->ATIFragmentShader.Current->Instructions[i]); 345 if (ctx->ATIFragmentShader.Current->SetupInst[i]) 346 free(ctx->ATIFragmentShader.Current->SetupInst[i]); 347 } 348 349 /* malloc the instructions here - not sure if the best place but its 350 a start */ 351 for (i = 0; i < MAX_NUM_PASSES_ATI; i++) { 352 ctx->ATIFragmentShader.Current->Instructions[i] = 353 (struct atifs_instruction *) 354 calloc(1, sizeof(struct atifs_instruction) * 355 (MAX_NUM_INSTRUCTIONS_PER_PASS_ATI)); 356 ctx->ATIFragmentShader.Current->SetupInst[i] = 357 (struct atifs_setupinst *) 358 calloc(1, sizeof(struct atifs_setupinst) * 359 (MAX_NUM_FRAGMENT_REGISTERS_ATI)); 360 } 361 362/* can't rely on calloc for initialization as it's possible to redefine a shader (?) */ 363 ctx->ATIFragmentShader.Current->LocalConstDef = 0; 364 ctx->ATIFragmentShader.Current->numArithInstr[0] = 0; 365 ctx->ATIFragmentShader.Current->numArithInstr[1] = 0; 366 ctx->ATIFragmentShader.Current->regsAssigned[0] = 0; 367 ctx->ATIFragmentShader.Current->regsAssigned[1] = 0; 368 ctx->ATIFragmentShader.Current->NumPasses = 0; 369 ctx->ATIFragmentShader.Current->cur_pass = 0; 370 ctx->ATIFragmentShader.Current->last_optype = 0; 371 ctx->ATIFragmentShader.Current->interpinp1 = GL_FALSE; 372 ctx->ATIFragmentShader.Current->isValid = GL_FALSE; 373 ctx->ATIFragmentShader.Current->swizzlerq = 0; 374 ctx->ATIFragmentShader.Compiling = 1; 375} 376 377void GLAPIENTRY 378_mesa_EndFragmentShaderATI(void) 379{ 380 GET_CURRENT_CONTEXT(ctx); 381 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 382#if MESA_DEBUG_ATI_FS 383 GLint i, j; 384#endif 385 386 if (!ctx->ATIFragmentShader.Compiling) { 387 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(outsideShader)"); 388 return; 389 } 390 if (curProg->interpinp1 && (ctx->ATIFragmentShader.Current->cur_pass > 1)) { 391 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(interpinfirstpass)"); 392 /* according to spec, DON'T return here */ 393 } 394 395 match_pair_inst(curProg, 0); 396 ctx->ATIFragmentShader.Compiling = 0; 397 ctx->ATIFragmentShader.Current->isValid = GL_TRUE; 398 if ((ctx->ATIFragmentShader.Current->cur_pass == 0) || 399 (ctx->ATIFragmentShader.Current->cur_pass == 2)) { 400 _mesa_error(ctx, GL_INVALID_OPERATION, "glEndFragmentShaderATI(noarithinst)"); 401 } 402 if (ctx->ATIFragmentShader.Current->cur_pass > 1) 403 ctx->ATIFragmentShader.Current->NumPasses = 2; 404 else 405 ctx->ATIFragmentShader.Current->NumPasses = 1; 406 407 ctx->ATIFragmentShader.Current->cur_pass = 0; 408 409#if MESA_DEBUG_ATI_FS 410 for (j = 0; j < MAX_NUM_PASSES_ATI; j++) { 411 for (i = 0; i < MAX_NUM_FRAGMENT_REGISTERS_ATI; i++) { 412 GLuint op = curProg->SetupInst[j][i].Opcode; 413 const char *op_enum = op > 5 ? _mesa_lookup_enum_by_nr(op) : "0"; 414 GLuint src = curProg->SetupInst[j][i].src; 415 GLuint swizzle = curProg->SetupInst[j][i].swizzle; 416 fprintf(stderr, "%2d %04X %s %d %04X\n", i, op, op_enum, src, 417 swizzle); 418 } 419 for (i = 0; i < curProg->numArithInstr[j]; i++) { 420 GLuint op0 = curProg->Instructions[j][i].Opcode[0]; 421 GLuint op1 = curProg->Instructions[j][i].Opcode[1]; 422 const char *op0_enum = op0 > 5 ? _mesa_lookup_enum_by_nr(op0) : "0"; 423 const char *op1_enum = op1 > 5 ? _mesa_lookup_enum_by_nr(op1) : "0"; 424 GLuint count0 = curProg->Instructions[j][i].ArgCount[0]; 425 GLuint count1 = curProg->Instructions[j][i].ArgCount[1]; 426 fprintf(stderr, "%2d %04X %s %d %04X %s %d\n", i, op0, op0_enum, count0, 427 op1, op1_enum, count1); 428 } 429 } 430#endif 431 432 if (!ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_SHADER_ATI, NULL)) { 433 ctx->ATIFragmentShader.Current->isValid = GL_FALSE; 434 /* XXX is this the right error? */ 435 _mesa_error(ctx, GL_INVALID_OPERATION, 436 "glEndFragmentShaderATI(driver rejected shader)"); 437 } 438} 439 440void GLAPIENTRY 441_mesa_PassTexCoordATI(GLuint dst, GLuint coord, GLenum swizzle) 442{ 443 GET_CURRENT_CONTEXT(ctx); 444 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 445 struct atifs_setupinst *curI; 446 447 if (!ctx->ATIFragmentShader.Compiling) { 448 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(outsideShader)"); 449 return; 450 } 451 452 if (curProg->cur_pass == 1) { 453 match_pair_inst(curProg, 0); 454 curProg->cur_pass = 2; 455 } 456 if ((curProg->cur_pass > 2) || 457 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { 458 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoord(pass)"); 459 return; 460 } 461 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) || 462 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) { 463 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(dst)"); 464 return; 465 } 466 if (((coord < GL_REG_0_ATI) || (coord > GL_REG_5_ATI)) && 467 ((coord < GL_TEXTURE0_ARB) || (coord > GL_TEXTURE7_ARB) || 468 ((coord - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) { 469 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(coord)"); 470 return; 471 } 472 if ((curProg->cur_pass == 0) && (coord >= GL_REG_0_ATI)) { 473 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(coord)"); 474 return; 475 } 476 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) { 477 _mesa_error(ctx, GL_INVALID_ENUM, "glPassTexCoordATI(swizzle)"); 478 return; 479 } 480 if ((swizzle & 1) && (coord >= GL_REG_0_ATI)) { 481 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)"); 482 return; 483 } 484 if (coord <= GL_TEXTURE7_ARB) { 485 GLuint tmp = coord - GL_TEXTURE0_ARB; 486 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) && 487 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) { 488 _mesa_error(ctx, GL_INVALID_OPERATION, "glPassTexCoordATI(swizzle)"); 489 return; 490 } else { 491 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2)); 492 } 493 } 494 495 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); 496 new_tex_inst(curProg); 497 498 /* add the instructions */ 499 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; 500 501 curI->Opcode = ATI_FRAGMENT_SHADER_PASS_OP; 502 curI->src = coord; 503 curI->swizzle = swizzle; 504 505#if MESA_DEBUG_ATI_FS 506 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, 507 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(coord), 508 _mesa_lookup_enum_by_nr(swizzle)); 509#endif 510} 511 512void GLAPIENTRY 513_mesa_SampleMapATI(GLuint dst, GLuint interp, GLenum swizzle) 514{ 515 GET_CURRENT_CONTEXT(ctx); 516 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 517 struct atifs_setupinst *curI; 518 519 if (!ctx->ATIFragmentShader.Compiling) { 520 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(outsideShader)"); 521 return; 522 } 523 524 if (curProg->cur_pass == 1) { 525 match_pair_inst(curProg, 0); 526 curProg->cur_pass = 2; 527 } 528 if ((curProg->cur_pass > 2) || 529 ((1 << (dst - GL_REG_0_ATI)) & curProg->regsAssigned[curProg->cur_pass >> 1])) { 530 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(pass)"); 531 return; 532 } 533 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI) || 534 ((dst - GL_REG_0_ATI) >= ctx->Const.MaxTextureUnits)) { 535 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(dst)"); 536 return; 537 } 538 if (((interp < GL_REG_0_ATI) || (interp > GL_REG_5_ATI)) && 539 ((interp < GL_TEXTURE0_ARB) || (interp > GL_TEXTURE7_ARB) || 540 ((interp - GL_TEXTURE0_ARB) >= ctx->Const.MaxTextureUnits))) { 541 /* is this texture5 or texture7? spec is a bit unclear there */ 542 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(interp)"); 543 return; 544 } 545 if ((curProg->cur_pass == 0) && (interp >= GL_REG_0_ATI)) { 546 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(interp)"); 547 return; 548 } 549 if (!(swizzle >= GL_SWIZZLE_STR_ATI) && (swizzle <= GL_SWIZZLE_STQ_DQ_ATI)) { 550 _mesa_error(ctx, GL_INVALID_ENUM, "glSampleMapATI(swizzle)"); 551 return; 552 } 553 if ((swizzle & 1) && (interp >= GL_REG_0_ATI)) { 554 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)"); 555 return; 556 } 557 if (interp <= GL_TEXTURE7_ARB) { 558 GLuint tmp = interp - GL_TEXTURE0_ARB; 559 if ((((curProg->swizzlerq >> (tmp * 2)) & 3) != 0) && 560 (((swizzle & 1) + 1) != ((curProg->swizzlerq >> (tmp * 2)) & 3))) { 561 _mesa_error(ctx, GL_INVALID_OPERATION, "glSampleMapATI(swizzle)"); 562 return; 563 } else { 564 curProg->swizzlerq |= (((swizzle & 1) + 1) << (tmp * 2)); 565 } 566 } 567 568 curProg->regsAssigned[curProg->cur_pass >> 1] |= 1 << (dst - GL_REG_0_ATI); 569 new_tex_inst(curProg); 570 571 /* add the instructions */ 572 curI = &curProg->SetupInst[curProg->cur_pass >> 1][dst - GL_REG_0_ATI]; 573 574 curI->Opcode = ATI_FRAGMENT_SHADER_SAMPLE_OP; 575 curI->src = interp; 576 curI->swizzle = swizzle; 577 578#if MESA_DEBUG_ATI_FS 579 _mesa_debug(ctx, "%s(%s, %s, %s)\n", __FUNCTION__, 580 _mesa_lookup_enum_by_nr(dst), _mesa_lookup_enum_by_nr(interp), 581 _mesa_lookup_enum_by_nr(swizzle)); 582#endif 583} 584 585static void 586_mesa_FragmentOpXATI(GLint optype, GLuint arg_count, GLenum op, GLuint dst, 587 GLuint dstMask, GLuint dstMod, GLuint arg1, 588 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, 589 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, 590 GLuint arg3Rep, GLuint arg3Mod) 591{ 592 GET_CURRENT_CONTEXT(ctx); 593 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 594 GLint ci; 595 struct atifs_instruction *curI; 596 GLuint modtemp = dstMod & ~GL_SATURATE_BIT_ATI; 597 598 if (!ctx->ATIFragmentShader.Compiling) { 599 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(outsideShader)"); 600 return; 601 } 602 603 if (curProg->cur_pass==0) 604 curProg->cur_pass=1; 605 606 else if (curProg->cur_pass==2) 607 curProg->cur_pass=3; 608 609 /* decide whether this is a new instruction or not ... all color instructions are new, 610 and alpha instructions might also be new if there was no preceding color inst */ 611 if ((optype == 0) || (curProg->last_optype == optype)) { 612 if (curProg->numArithInstr[curProg->cur_pass >> 1] > 7) { 613 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(instrCount)"); 614 return; 615 } 616 /* easier to do that here slight side effect invalid instr will still be inserted as nops */ 617 match_pair_inst(curProg, optype); 618 new_arith_inst(curProg); 619 } 620 curProg->last_optype = optype; 621 ci = curProg->numArithInstr[curProg->cur_pass >> 1] - 1; 622 623 /* add the instructions */ 624 curI = &curProg->Instructions[curProg->cur_pass >> 1][ci]; 625 626 /* error checking */ 627 if ((dst < GL_REG_0_ATI) || (dst > GL_REG_5_ATI)) { 628 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dst)"); 629 return; 630 } 631 if ((modtemp != GL_NONE) && (modtemp != GL_2X_BIT_ATI) && 632 (modtemp != GL_4X_BIT_ATI) && (modtemp != GL_8X_BIT_ATI) && 633 (modtemp != GL_HALF_BIT_ATI) && !(modtemp != GL_QUARTER_BIT_ATI) && 634 (modtemp != GL_EIGHTH_BIT_ATI)) { 635 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(dstMod)%x", modtemp); 636 return; 637 } 638 /* op checking? Actually looks like that's missing in the spec but we'll do it anyway */ 639 if (((op < GL_ADD_ATI) || (op > GL_DOT2_ADD_ATI)) && !(op == GL_MOV_ATI)) { 640 _mesa_error(ctx, GL_INVALID_ENUM, "C/AFragmentOpATI(op)"); 641 return; 642 } 643 if (optype == 1) { 644 if (((op == GL_DOT2_ADD_ATI) && (curI->Opcode[0] != GL_DOT2_ADD_ATI)) || 645 ((op == GL_DOT3_ATI) && (curI->Opcode[0] != GL_DOT3_ATI)) || 646 ((op == GL_DOT4_ATI) && (curI->Opcode[0] != GL_DOT4_ATI)) || 647 ((op != GL_DOT4_ATI) && (curI->Opcode[0] == GL_DOT4_ATI))) { 648 _mesa_error(ctx, GL_INVALID_OPERATION, "AFragmentOpATI(op)"); 649 return; 650 } 651 } 652 if ((op == GL_DOT4_ATI) && 653 (((arg1 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg1Rep == GL_ALPHA) || (arg1Rep == GL_NONE))) || 654 (((arg2 == GL_SECONDARY_INTERPOLATOR_ATI) && ((arg2Rep == GL_ALPHA) || (arg2Rep == GL_NONE)))))) { 655 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(sec_interp)"); 656 } 657 658 if (!check_arith_arg(curProg, optype, arg1, arg1Rep)) { 659 return; 660 } 661 if (arg2) { 662 if (!check_arith_arg(curProg, optype, arg2, arg2Rep)) { 663 return; 664 } 665 } 666 if (arg3) { 667 if (!check_arith_arg(curProg, optype, arg3, arg3Rep)) { 668 return; 669 } 670 if ((arg1 >= GL_CON_0_ATI) && (arg1 <= GL_CON_7_ATI) && 671 (arg2 >= GL_CON_0_ATI) && (arg2 <= GL_CON_7_ATI) && 672 (arg3 >= GL_CON_0_ATI) && (arg3 <= GL_CON_7_ATI) && 673 (arg1 != arg2) && (arg1 != arg3) && (arg2 != arg3)) { 674 _mesa_error(ctx, GL_INVALID_OPERATION, "C/AFragmentOpATI(3Consts)"); 675 return; 676 } 677 } 678 679 /* all ok - not all fully validated though (e.g. argNMod - spec doesn't say anything) */ 680 681 curI->Opcode[optype] = op; 682 curI->SrcReg[optype][0].Index = arg1; 683 curI->SrcReg[optype][0].argRep = arg1Rep; 684 curI->SrcReg[optype][0].argMod = arg1Mod; 685 curI->ArgCount[optype] = arg_count; 686 687 if (arg2) { 688 curI->SrcReg[optype][1].Index = arg2; 689 curI->SrcReg[optype][1].argRep = arg2Rep; 690 curI->SrcReg[optype][1].argMod = arg2Mod; 691 } 692 693 if (arg3) { 694 curI->SrcReg[optype][2].Index = arg3; 695 curI->SrcReg[optype][2].argRep = arg3Rep; 696 curI->SrcReg[optype][2].argMod = arg3Mod; 697 } 698 699 curI->DstReg[optype].Index = dst; 700 curI->DstReg[optype].dstMod = dstMod; 701 curI->DstReg[optype].dstMask = dstMask; 702 703#if MESA_DEBUG_ATI_FS 704 debug_op(optype, arg_count, op, dst, dstMask, dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, arg3Rep, arg3Mod); 705#endif 706 707} 708 709void GLAPIENTRY 710_mesa_ColorFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMask, 711 GLuint dstMod, GLuint arg1, GLuint arg1Rep, 712 GLuint arg1Mod) 713{ 714 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 1, op, dst, dstMask, 715 dstMod, arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); 716} 717 718void GLAPIENTRY 719_mesa_ColorFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMask, 720 GLuint dstMod, GLuint arg1, GLuint arg1Rep, 721 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, 722 GLuint arg2Mod) 723{ 724 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 2, op, dst, dstMask, 725 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, 726 arg2Mod, 0, 0, 0); 727} 728 729void GLAPIENTRY 730_mesa_ColorFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMask, 731 GLuint dstMod, GLuint arg1, GLuint arg1Rep, 732 GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, 733 GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, 734 GLuint arg3Mod) 735{ 736 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_COLOR_OP, 3, op, dst, dstMask, 737 dstMod, arg1, arg1Rep, arg1Mod, arg2, arg2Rep, 738 arg2Mod, arg3, arg3Rep, arg3Mod); 739} 740 741void GLAPIENTRY 742_mesa_AlphaFragmentOp1ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, 743 GLuint arg1Rep, GLuint arg1Mod) 744{ 745 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 1, op, dst, 0, dstMod, 746 arg1, arg1Rep, arg1Mod, 0, 0, 0, 0, 0, 0); 747} 748 749void GLAPIENTRY 750_mesa_AlphaFragmentOp2ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, 751 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, 752 GLuint arg2Rep, GLuint arg2Mod) 753{ 754 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 2, op, dst, 0, dstMod, 755 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, 0, 0, 756 0); 757} 758 759void GLAPIENTRY 760_mesa_AlphaFragmentOp3ATI(GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, 761 GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, 762 GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, 763 GLuint arg3Rep, GLuint arg3Mod) 764{ 765 _mesa_FragmentOpXATI(ATI_FRAGMENT_SHADER_ALPHA_OP, 3, op, dst, 0, dstMod, 766 arg1, arg1Rep, arg1Mod, arg2, arg2Rep, arg2Mod, arg3, 767 arg3Rep, arg3Mod); 768} 769 770void GLAPIENTRY 771_mesa_SetFragmentShaderConstantATI(GLuint dst, const GLfloat * value) 772{ 773 GLuint dstindex; 774 GET_CURRENT_CONTEXT(ctx); 775 776 if ((dst < GL_CON_0_ATI) || (dst > GL_CON_7_ATI)) { 777 /* spec says nothing about what should happen here but we can't just segfault...*/ 778 _mesa_error(ctx, GL_INVALID_ENUM, "glSetFragmentShaderConstantATI(dst)"); 779 return; 780 } 781 782 dstindex = dst - GL_CON_0_ATI; 783 if (ctx->ATIFragmentShader.Compiling) { 784 struct ati_fragment_shader *curProg = ctx->ATIFragmentShader.Current; 785 COPY_4V(curProg->Constants[dstindex], value); 786 curProg->LocalConstDef |= 1 << dstindex; 787 } 788 else { 789 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 790 COPY_4V(ctx->ATIFragmentShader.GlobalConstants[dstindex], value); 791 } 792} 793 794#endif /* FEATURE_ATI_fragment_shader */ 795