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