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