brw_wm_fp.c revision 9f344b3e7d6e23674dd4747faec253f103563b36
1/* 2 Copyright (C) Intel Corp. 2006. All Rights Reserved. 3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to 4 develop this 3D driver. 5 6 Permission is hereby granted, free of charge, to any person obtaining 7 a copy of this software and associated documentation files (the 8 "Software"), to deal in the Software without restriction, including 9 without limitation the rights to use, copy, modify, merge, publish, 10 distribute, sublicense, and/or sell copies of the Software, and to 11 permit persons to whom the Software is furnished to do so, subject to 12 the following conditions: 13 14 The above copyright notice and this permission notice (including the 15 next paragraph) shall be included in all copies or substantial 16 portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26 **********************************************************************/ 27 /* 28 * Authors: 29 * Keith Whitwell <keith@tungstengraphics.com> 30 */ 31 32 33#include "glheader.h" 34#include "macros.h" 35#include "enums.h" 36#include "brw_context.h" 37#include "brw_wm.h" 38#include "brw_util.h" 39 40#include "shader/program.h" 41#include "shader/program_instruction.h" 42#include "shader/arbprogparse.h" 43 44#define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS 45 46#define X 0 47#define Y 1 48#define Z 2 49#define W 3 50 51 52static const char *wm_opcode_strings[] = { 53 "PIXELXY", 54 "DELTAXY", 55 "PIXELW", 56 "LINTERP", 57 "PINTERP", 58 "CINTERP", 59 "WPOSXY", 60 "FB_WRITE" 61}; 62 63static const char *wm_file_strings[] = { 64 "PAYLOAD" 65}; 66 67 68/*********************************************************************** 69 * Source regs 70 */ 71 72static struct prog_src_register src_reg(GLuint file, GLuint idx) 73{ 74 struct prog_src_register reg; 75 reg.File = file; 76 reg.Index = idx; 77 reg.Swizzle = SWIZZLE_NOOP; 78 reg.RelAddr = 0; 79 reg.NegateBase = 0; 80 reg.Abs = 0; 81 reg.NegateAbs = 0; 82 return reg; 83} 84 85static struct prog_src_register src_reg_from_dst(struct prog_dst_register dst) 86{ 87 return src_reg(dst.File, dst.Index); 88} 89 90static struct prog_src_register src_undef( void ) 91{ 92 return src_reg(PROGRAM_UNDEFINED, 0); 93} 94 95static GLboolean src_is_undef(struct prog_src_register src) 96{ 97 return src.File == PROGRAM_UNDEFINED; 98} 99 100static struct prog_src_register src_swizzle( struct prog_src_register reg, int x, int y, int z, int w ) 101{ 102 reg.Swizzle = MAKE_SWIZZLE4(x,y,z,w); 103 return reg; 104} 105 106static struct prog_src_register src_swizzle1( struct prog_src_register reg, int x ) 107{ 108 return src_swizzle(reg, x, x, x, x); 109} 110 111 112/*********************************************************************** 113 * Dest regs 114 */ 115 116static struct prog_dst_register dst_reg(GLuint file, GLuint idx) 117{ 118 struct prog_dst_register reg; 119 reg.File = file; 120 reg.Index = idx; 121 reg.WriteMask = WRITEMASK_XYZW; 122 reg.CondMask = 0; 123 reg.CondSwizzle = 0; 124 reg.pad = 0; 125 reg.CondSrc = 0; 126 return reg; 127} 128 129static struct prog_dst_register dst_mask( struct prog_dst_register reg, int mask ) 130{ 131 reg.WriteMask &= mask; 132 return reg; 133} 134 135static struct prog_dst_register dst_undef( void ) 136{ 137 return dst_reg(PROGRAM_UNDEFINED, 0); 138} 139 140 141 142static struct prog_dst_register get_temp( struct brw_wm_compile *c ) 143{ 144 int bit = ffs( ~c->fp_temp ); 145 146 if (!bit) { 147 _mesa_printf("%s: out of temporaries\n", __FILE__); 148 exit(1); 149 } 150 151 c->fp_temp |= 1<<(bit-1); 152 return dst_reg(PROGRAM_TEMPORARY, FIRST_INTERNAL_TEMP+(bit-1)); 153} 154 155 156static void release_temp( struct brw_wm_compile *c, struct prog_dst_register temp ) 157{ 158 c->fp_temp &= ~1<<(temp.Index + 1 - FIRST_INTERNAL_TEMP); 159} 160 161 162/*********************************************************************** 163 * Instructions 164 */ 165 166static struct prog_instruction *get_fp_inst(struct brw_wm_compile *c) 167{ 168 return &c->prog_instructions[c->nr_fp_insns++]; 169} 170 171static struct prog_instruction *emit_insn(struct brw_wm_compile *c, 172 const struct prog_instruction *inst0) 173{ 174 struct prog_instruction *inst = get_fp_inst(c); 175 *inst = *inst0; 176 return inst; 177} 178 179static struct prog_instruction * emit_op(struct brw_wm_compile *c, 180 GLuint op, 181 struct prog_dst_register dest, 182 GLuint saturate, 183 GLuint tex_src_unit, 184 GLuint tex_src_target, 185 struct prog_src_register src0, 186 struct prog_src_register src1, 187 struct prog_src_register src2 ) 188{ 189 struct prog_instruction *inst = get_fp_inst(c); 190 191 memset(inst, 0, sizeof(*inst)); 192 193 inst->Opcode = op; 194 inst->DstReg = dest; 195 inst->SaturateMode = saturate; 196 inst->TexSrcUnit = tex_src_unit; 197 inst->TexSrcTarget = tex_src_target; 198 inst->SrcReg[0] = src0; 199 inst->SrcReg[1] = src1; 200 inst->SrcReg[2] = src2; 201 202 return inst; 203} 204 205 206 207 208/*********************************************************************** 209 * Special instructions for interpolation and other tasks 210 */ 211 212static struct prog_src_register get_pixel_xy( struct brw_wm_compile *c ) 213{ 214 if (src_is_undef(c->pixel_xy)) { 215 struct prog_dst_register pixel_xy = get_temp(c); 216 struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); 217 218 219 /* Emit the out calculations, and hold onto the results. Use 220 * two instructions as a temporary is required. 221 */ 222 /* pixel_xy.xy = PIXELXY payload[0]; 223 */ 224 emit_op(c, 225 WM_PIXELXY, 226 dst_mask(pixel_xy, WRITEMASK_XY), 227 0, 0, 0, 228 payload_r0_depth, 229 src_undef(), 230 src_undef()); 231 232 c->pixel_xy = src_reg_from_dst(pixel_xy); 233 } 234 235 return c->pixel_xy; 236} 237 238static struct prog_src_register get_delta_xy( struct brw_wm_compile *c ) 239{ 240 if (src_is_undef(c->delta_xy)) { 241 struct prog_dst_register delta_xy = get_temp(c); 242 struct prog_src_register pixel_xy = get_pixel_xy(c); 243 struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); 244 245 /* deltas.xy = DELTAXY pixel_xy, payload[0] 246 */ 247 emit_op(c, 248 WM_DELTAXY, 249 dst_mask(delta_xy, WRITEMASK_XY), 250 0, 0, 0, 251 pixel_xy, 252 payload_r0_depth, 253 src_undef()); 254 255 c->delta_xy = src_reg_from_dst(delta_xy); 256 } 257 258 return c->delta_xy; 259} 260 261static struct prog_src_register get_pixel_w( struct brw_wm_compile *c ) 262{ 263 if (src_is_undef(c->pixel_w)) { 264 struct prog_dst_register pixel_w = get_temp(c); 265 struct prog_src_register deltas = get_delta_xy(c); 266 struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS); 267 268 269 /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x 270 */ 271 emit_op(c, 272 WM_PIXELW, 273 dst_mask(pixel_w, WRITEMASK_W), 274 0, 0, 0, 275 interp_wpos, 276 deltas, 277 src_undef()); 278 279 280 c->pixel_w = src_reg_from_dst(pixel_w); 281 } 282 283 return c->pixel_w; 284} 285 286static void emit_interp( struct brw_wm_compile *c, 287 GLuint idx ) 288{ 289 struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx); 290 struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx); 291 struct prog_src_register deltas = get_delta_xy(c); 292 struct prog_src_register arg2; 293 GLuint opcode; 294 295 /* Need to use PINTERP on attributes which have been 296 * multiplied by 1/W in the SF program, and LINTERP on those 297 * which have not: 298 */ 299 switch (idx) { 300 case FRAG_ATTRIB_WPOS: 301 opcode = WM_LINTERP; 302 arg2 = src_undef(); 303 304 /* Have to treat wpos.xy specially: 305 */ 306 emit_op(c, 307 WM_WPOSXY, 308 dst_mask(dst, WRITEMASK_XY), 309 0, 0, 0, 310 get_pixel_xy(c), 311 src_undef(), 312 src_undef()); 313 314 dst = dst_mask(dst, WRITEMASK_ZW); 315 316 /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw 317 */ 318 emit_op(c, 319 WM_LINTERP, 320 dst, 321 0, 0, 0, 322 interp, 323 deltas, 324 arg2); 325 break; 326 case FRAG_ATTRIB_COL0: 327 case FRAG_ATTRIB_COL1: 328 if (c->key.flat_shade) { 329 emit_op(c, 330 WM_CINTERP, 331 dst, 332 0, 0, 0, 333 interp, 334 src_undef(), 335 src_undef()); 336 } 337 else { 338 emit_op(c, 339 WM_LINTERP, 340 dst, 341 0, 0, 0, 342 interp, 343 deltas, 344 src_undef()); 345 } 346 break; 347 default: 348 emit_op(c, 349 WM_PINTERP, 350 dst, 351 0, 0, 0, 352 interp, 353 deltas, 354 get_pixel_w(c)); 355 break; 356 } 357 358 c->fp_interp_emitted |= 1<<idx; 359} 360 361 362/*********************************************************************** 363 * Hacks to extend the program parameter and constant lists. 364 */ 365 366/* Add the fog parameters to the parameter list of the original 367 * program, rather than creating a new list. Doesn't really do any 368 * harm and it's not as if the parameter handling isn't a big hack 369 * anyway. 370 */ 371static struct prog_src_register search_or_add_param6( struct brw_wm_compile *c, 372 GLint s0, 373 GLint s1, 374 GLint s2, 375 GLint s3, 376 GLint s4, 377 GLint s5) 378{ 379 struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters; 380 GLint tokens[6]; 381 GLuint idx; 382 tokens[0] = s0; 383 tokens[1] = s1; 384 tokens[2] = s2; 385 tokens[3] = s3; 386 tokens[4] = s4; 387 tokens[5] = s5; 388 389 for (idx = 0; idx < paramList->NumParameters; idx++) { 390 if (paramList->Parameters[idx].Type == PROGRAM_STATE_VAR && 391 memcmp(paramList->Parameters[idx].StateIndexes, tokens, sizeof(tokens)) == 0) 392 return src_reg(PROGRAM_STATE_VAR, idx); 393 } 394 395 idx = _mesa_add_state_reference( paramList, tokens ); 396 397 /* Recalculate state dependency: 398 */ 399 c->fp->param_state = brw_parameter_list_state_flags( paramList ); 400 401 return src_reg(PROGRAM_STATE_VAR, idx); 402} 403 404 405static struct prog_src_register search_or_add_const4f( struct brw_wm_compile *c, 406 GLfloat s0, 407 GLfloat s1, 408 GLfloat s2, 409 GLfloat s3) 410{ 411 struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters; 412 GLfloat values[4]; 413 GLuint idx; 414 415 values[0] = s0; 416 values[1] = s1; 417 values[2] = s2; 418 values[3] = s3; 419 420 /* Have to search, otherwise multiple compilations will each grow 421 * the parameter list. 422 */ 423 for (idx = 0; idx < paramList->NumParameters; idx++) { 424 if (paramList->Parameters[idx].Type == PROGRAM_CONSTANT && 425 memcmp(paramList->ParameterValues[idx], values, sizeof(values)) == 0) 426 427 /* XXX: this mimics the mesa bug which puts all constants and 428 * parameters into the "PROGRAM_STATE_VAR" category: 429 */ 430 return src_reg(PROGRAM_STATE_VAR, idx); 431 } 432 433 idx = _mesa_add_unnamed_constant( paramList, values ); 434 435 return src_reg(PROGRAM_STATE_VAR, idx); 436} 437 438 439 440/*********************************************************************** 441 * Expand various instructions here to simpler forms. 442 */ 443static void precalc_dst( struct brw_wm_compile *c, 444 const struct prog_instruction *inst ) 445{ 446 struct prog_src_register src0 = inst->SrcReg[0]; 447 struct prog_src_register src1 = inst->SrcReg[1]; 448 struct prog_dst_register dst = inst->DstReg; 449 450 if (dst.WriteMask & WRITEMASK_Y) { 451 /* dst.y = mul src0.y, src1.y 452 */ 453 emit_op(c, 454 OPCODE_MUL, 455 dst_mask(dst, WRITEMASK_Y), 456 inst->SaturateMode, 0, 0, 457 src0, 458 src1, 459 src_undef()); 460 } 461 462 463 if (dst.WriteMask & WRITEMASK_XZ) { 464 GLuint z = GET_SWZ(src0.Swizzle, Z); 465 466 /* dst.xz = swz src0.1zzz 467 */ 468 emit_op(c, 469 OPCODE_SWZ, 470 dst_mask(dst, WRITEMASK_XZ), 471 inst->SaturateMode, 0, 0, 472 src_swizzle(src0, SWIZZLE_ONE, z, z, z), 473 src_undef(), 474 src_undef()); 475 } 476 if (dst.WriteMask & WRITEMASK_W) { 477 /* dst.w = mov src1.w 478 */ 479 emit_op(c, 480 OPCODE_MOV, 481 dst_mask(dst, WRITEMASK_W), 482 inst->SaturateMode, 0, 0, 483 src1, 484 src_undef(), 485 src_undef()); 486 } 487} 488 489 490static void precalc_lit( struct brw_wm_compile *c, 491 const struct prog_instruction *inst ) 492{ 493 struct prog_src_register src0 = inst->SrcReg[0]; 494 struct prog_dst_register dst = inst->DstReg; 495 496 if (dst.WriteMask & WRITEMASK_XW) { 497 /* dst.xw = swz src0.1111 498 */ 499 emit_op(c, 500 OPCODE_SWZ, 501 dst_mask(dst, WRITEMASK_XW), 502 0, 0, 0, 503 src_swizzle1(src0, SWIZZLE_ONE), 504 src_undef(), 505 src_undef()); 506 } 507 508 509 if (dst.WriteMask & WRITEMASK_YZ) { 510 emit_op(c, 511 OPCODE_LIT, 512 dst_mask(dst, WRITEMASK_YZ), 513 inst->SaturateMode, 0, 0, 514 src0, 515 src_undef(), 516 src_undef()); 517 } 518} 519 520static void precalc_tex( struct brw_wm_compile *c, 521 const struct prog_instruction *inst ) 522{ 523 /* Need to emit YUV texture conversions by hand. Probably need to 524 * do this here - the alternative is in brw_wm_emit.c, but the 525 * conversion requires allocating a temporary variable which we 526 * don't have the facility to do that late in the compilation. 527 */ 528 if (!(c->key.yuvtex_mask & (1<<inst->TexSrcUnit))) { 529 emit_op(c, 530 OPCODE_TEX, 531 inst->DstReg, 532 inst->SaturateMode, 533 inst->TexSrcUnit, 534 inst->TexSrcTarget, 535 inst->SrcReg[0], 536 src_undef(), 537 src_undef()); 538 } 539 else { 540 /* 541 CONST C0 = { -.5, -.0625, -.5, 1.164 } 542 CONST C1 = { 1.596, -0.813, 2.018, -.391 } 543 UYV = TEX ... 544 UYV.xyz = ADD UYV, C0 545 UYV.y = MUL UYV.y, C0.w 546 RGB.xyz = MAD UYV.xxz, C1, UYV.y 547 RGB.y = MAD UYV.z, C1.w, RGB.y 548 */ 549 struct prog_dst_register dst = inst->DstReg; 550 struct prog_src_register src0 = inst->SrcReg[0]; 551 struct prog_dst_register tmp = get_temp(c); 552 struct prog_src_register tmpsrc = src_reg_from_dst(tmp); 553 struct prog_src_register C0 = search_or_add_const4f( c, -.5, -.0625, -.5, 1.164 ); 554 struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 ); 555 556 /* tmp = TEX ... 557 */ 558 emit_op(c, 559 OPCODE_TEX, 560 tmp, 561 inst->SaturateMode, 562 inst->TexSrcUnit, 563 inst->TexSrcTarget, 564 src0, 565 src_undef(), 566 src_undef()); 567 568 /* tmp.xyz = ADD TMP, C0 569 */ 570 emit_op(c, 571 OPCODE_ADD, 572 dst_mask(tmp, WRITEMASK_XYZ), 573 0, 0, 0, 574 tmpsrc, 575 C0, 576 src_undef()); 577 578 /* YUV.y = MUL YUV.y, C0.w 579 */ 580 emit_op(c, 581 OPCODE_MUL, 582 dst_mask(tmp, WRITEMASK_Y), 583 0, 0, 0, 584 tmpsrc, 585 src_swizzle1(C0, W), 586 src_undef()); 587 588 /* RGB.xyz = MAD YUV.xxz, C1, YUV.y 589 */ 590 emit_op(c, 591 OPCODE_MAD, 592 dst_mask(dst, WRITEMASK_XYZ), 593 0, 0, 0, 594 src_swizzle(tmpsrc, X,X,Z,Z), 595 C1, 596 src_swizzle1(tmpsrc, Y)); 597 598 /* RGB.y = MAD YUV.z, C1.w, RGB.y 599 */ 600 emit_op(c, 601 OPCODE_MAD, 602 dst_mask(dst, WRITEMASK_Y), 603 0, 0, 0, 604 src_swizzle1(tmpsrc, Z), 605 src_swizzle1(C1, W), 606 src_swizzle1(src_reg_from_dst(dst), Y)); 607 } 608} 609 610 611static GLboolean projtex( struct brw_wm_compile *c, 612 const struct prog_instruction *inst ) 613{ 614 struct prog_src_register src = inst->SrcReg[0]; 615 616 /* Only try to detect the simplest cases. Could detect (later) 617 * cases where we are trying to emit code like RCP {1.0}, MUL x, 618 * {1.0}, and so on. 619 * 620 * More complex cases than this typically only arise from 621 * user-provided fragment programs anyway: 622 */ 623 if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) 624 return 0; /* ut2004 gun rendering !?! */ 625 else if (src.File == PROGRAM_INPUT && 626 GET_SWZ(src.Swizzle, W) == W && 627 (c->key.projtex_mask & (1<<src.Index)) == 0) 628 return 0; 629 else 630 return 1; 631} 632 633 634static void precalc_txp( struct brw_wm_compile *c, 635 const struct prog_instruction *inst ) 636{ 637 struct prog_src_register src0 = inst->SrcReg[0]; 638 639 if (projtex(c, inst)) { 640 struct prog_dst_register tmp = get_temp(c); 641 struct prog_instruction tmp_inst; 642 643 /* tmp0.w = RCP inst.arg[0][3] 644 */ 645 emit_op(c, 646 OPCODE_RCP, 647 dst_mask(tmp, WRITEMASK_W), 648 0, 0, 0, 649 src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)), 650 src_undef(), 651 src_undef()); 652 653 /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww 654 */ 655 emit_op(c, 656 OPCODE_MUL, 657 dst_mask(tmp, WRITEMASK_XYZ), 658 0, 0, 0, 659 src0, 660 src_swizzle1(src_reg_from_dst(tmp), W), 661 src_undef()); 662 663 /* dst = precalc(TEX tmp0) 664 */ 665 tmp_inst = *inst; 666 tmp_inst.SrcReg[0] = src_reg_from_dst(tmp); 667 precalc_tex(c, &tmp_inst); 668 669 release_temp(c, tmp); 670 } 671 else 672 { 673 /* dst = precalc(TEX src0) 674 */ 675 precalc_tex(c, inst); 676 } 677} 678 679 680 681 682 683/*********************************************************************** 684 * Add instructions to perform fog blending 685 */ 686 687static void fog_blend( struct brw_wm_compile *c, 688 struct prog_src_register fog_factor ) 689{ 690 struct prog_dst_register outcolor = dst_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); 691 struct prog_src_register fogcolor = search_or_add_param6( c, STATE_FOG_COLOR, 0,0,0,0,0 ); 692 693 /* color.xyz = LRP fog_factor.xxxx, output_color, fog_color */ 694 695 emit_op(c, 696 OPCODE_LRP, 697 dst_mask(outcolor, WRITEMASK_XYZ), 698 0, 0, 0, 699 fog_factor, 700 src_reg_from_dst(outcolor), 701 fogcolor); 702} 703 704 705 706/* This one is simple - just take the interpolated fog coordinate and 707 * use it as the fog blend factor. 708 */ 709static void fog_interpolated( struct brw_wm_compile *c ) 710{ 711 struct prog_src_register fogc = src_reg(PROGRAM_INPUT, FRAG_ATTRIB_FOGC); 712 713 if (!(c->fp_interp_emitted & (1<<FRAG_ATTRIB_FOGC))) 714 emit_interp(c, FRAG_ATTRIB_FOGC); 715 716 fog_blend( c, src_swizzle1(fogc, GET_SWZ(fogc.Swizzle,X))); 717} 718 719static void emit_fog( struct brw_wm_compile *c ) 720{ 721 if (!c->fp->program.FogOption) 722 return; 723 724 if (1) 725 fog_interpolated( c ); 726 else { 727 /* TODO: per-pixel fog */ 728 assert(0); 729 } 730} 731 732static void emit_fb_write( struct brw_wm_compile *c ) 733{ 734 struct prog_src_register outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); 735 struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); 736 struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR); 737 738 emit_op(c, 739 WM_FB_WRITE, 740 dst_mask(dst_undef(),0), 741 0, 0, 0, 742 outcolor, 743 payload_r0_depth, 744 outdepth); 745} 746 747 748 749 750/*********************************************************************** 751 * Emit INTERP instructions ahead of first use of each attrib. 752 */ 753 754static void validate_src_regs( struct brw_wm_compile *c, 755 const struct prog_instruction *inst ) 756{ 757 GLuint nr_args = brw_wm_nr_args( inst->Opcode ); 758 GLuint i; 759 760 for (i = 0; i < nr_args; i++) { 761 if (inst->SrcReg[i].File == PROGRAM_INPUT) { 762 GLuint idx = inst->SrcReg[i].Index; 763 if (!(c->fp_interp_emitted & (1<<idx))) { 764 emit_interp(c, idx); 765 } 766 } 767 } 768} 769 770 771 772void brw_wm_pass_fp( struct brw_wm_compile *c ) 773{ 774 struct brw_fragment_program *fp = c->fp; 775 GLuint insn; 776 777 if (INTEL_DEBUG & DEBUG_WM) { 778 _mesa_printf("\n\n\npre-fp:\n"); 779/* _mesa_print_program(&fp->program); */ 780 _mesa_printf("\n"); 781 } 782 783 c->pixel_xy = src_undef(); 784 c->delta_xy = src_undef(); 785 c->pixel_w = src_undef(); 786 c->nr_fp_insns = 0; 787 788 /* Emit preamble instructions: 789 */ 790 791 792 for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) { 793 const struct prog_instruction *inst = &fp->program.Base.Instructions[insn]; 794 struct prog_instruction *out; 795 796 /* Check for INPUT values, emit INTERP instructions where 797 * necessary: 798 */ 799 validate_src_regs(c, inst); 800 801 802 switch (inst->Opcode) { 803 case OPCODE_SWZ: 804 out = emit_insn(c, inst); 805 out->Opcode = OPCODE_MOV; 806 break; 807 808 case OPCODE_ABS: 809 out = emit_insn(c, inst); 810 out->Opcode = OPCODE_MOV; 811 out->SrcReg[0].NegateBase = 0; 812 out->SrcReg[0].Abs = 1; 813 break; 814 815 case OPCODE_SUB: 816 out = emit_insn(c, inst); 817 out->Opcode = OPCODE_ADD; 818 out->SrcReg[1].NegateBase ^= 0xf; 819 break; 820 821 case OPCODE_SCS: 822 out = emit_insn(c, inst); 823 /* This should probably be done in the parser. 824 */ 825 out->DstReg.WriteMask &= WRITEMASK_XY; 826 break; 827 828 case OPCODE_DST: 829 precalc_dst(c, inst); 830 break; 831 832 case OPCODE_LIT: 833 precalc_lit(c, inst); 834 break; 835 836 case OPCODE_TXP: 837 precalc_txp(c, inst); 838 break; 839 840 case OPCODE_XPD: 841 out = emit_insn(c, inst); 842 /* This should probably be done in the parser. 843 */ 844 out->DstReg.WriteMask &= WRITEMASK_XYZ; 845 break; 846 847 case OPCODE_KIL: 848 out = emit_insn(c, inst); 849 /* This should probably be done in the parser. 850 */ 851 out->DstReg.WriteMask = 0; 852 break; 853 854 case OPCODE_END: 855 case OPCODE_PRINT: 856 break; 857 858 default: 859 emit_insn(c, inst); 860 break; 861 } 862 } 863 864 emit_fog(c); 865 emit_fb_write(c); 866 867 868 if (INTEL_DEBUG & DEBUG_WM) { 869 _mesa_printf("\n\n\npass_fp:\n"); 870/* _mesa_debug_fp_inst(c->nr_fp_insns, c->prog_instructions, wm_opcode_strings, wm_file_strings); */ 871 _mesa_printf("\n"); 872 } 873} 874 875