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