Minor r200 vertex program cleanups. Remove disabled leftovers from r300 vertex progra...
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_fp.c
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
52 static const char *wm_opcode_strings[] = {
53 "PIXELXY",
54 "DELTAXY",
55 "PIXELW",
56 "LINTERP",
57 "PINTERP",
58 "CINTERP",
59 "WPOSXY",
60 "FB_WRITE"
61 };
62
63 static const char *wm_file_strings[] = {
64 "PAYLOAD"
65 };
66
67
68 /***********************************************************************
69 * Source regs
70 */
71
72 static 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
85 static struct prog_src_register src_reg_from_dst(struct prog_dst_register dst)
86 {
87 return src_reg(dst.File, dst.Index);
88 }
89
90 static struct prog_src_register src_undef( void )
91 {
92 return src_reg(PROGRAM_UNDEFINED, 0);
93 }
94
95 static GLboolean src_is_undef(struct prog_src_register src)
96 {
97 return src.File == PROGRAM_UNDEFINED;
98 }
99
100 static 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
106 static 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
116 static 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
129 static struct prog_dst_register dst_mask( struct prog_dst_register reg, int mask )
130 {
131 reg.WriteMask &= mask;
132 return reg;
133 }
134
135 static struct prog_dst_register dst_undef( void )
136 {
137 return dst_reg(PROGRAM_UNDEFINED, 0);
138 }
139
140
141
142 static 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
156 static 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
166 static struct prog_instruction *get_fp_inst(struct brw_wm_compile *c)
167 {
168 return &c->prog_instructions[c->nr_fp_insns++];
169 }
170
171 static 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
179 static 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
212 static 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
238 static 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
261 static 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
286 static 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 */
371 static 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
405 static 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 */
443 static 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
490 static 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
520 static 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
611 static 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
634 static 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
687 static 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 */
709 static 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
719 static 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
732 static 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
754 static 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
772 void 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