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