merge of glsl-compiler-1 branch
[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/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
53 static 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
65 static const char *wm_file_strings[] = {
66 "PAYLOAD"
67 };
68 #endif
69
70
71 /***********************************************************************
72 * Source regs
73 */
74
75 static 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
88 static struct prog_src_register src_reg_from_dst(struct prog_dst_register dst)
89 {
90 return src_reg(dst.File, dst.Index);
91 }
92
93 static struct prog_src_register src_undef( void )
94 {
95 return src_reg(PROGRAM_UNDEFINED, 0);
96 }
97
98 static GLboolean src_is_undef(struct prog_src_register src)
99 {
100 return src.File == PROGRAM_UNDEFINED;
101 }
102
103 static 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
109 static 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
119 static 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
132 static struct prog_dst_register dst_mask( struct prog_dst_register reg, int mask )
133 {
134 reg.WriteMask &= mask;
135 return reg;
136 }
137
138 static struct prog_dst_register dst_undef( void )
139 {
140 return dst_reg(PROGRAM_UNDEFINED, 0);
141 }
142
143
144
145 static 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
159 static 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
169 static struct prog_instruction *get_fp_inst(struct brw_wm_compile *c)
170 {
171 return &c->prog_instructions[c->nr_fp_insns++];
172 }
173
174 static 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
182 static 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
215 static 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
241 static 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
264 static 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
289 static 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 */
374 static 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
406 static 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 */
445 static 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
492 static 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
522 static 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
647 static 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)) == 0)
664 return 0;
665 else
666 return 1;
667 }
668
669
670 static 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
723 static 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 */
745 static 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
755 static 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
768 static 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
790 static 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
808 static 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
829 void 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