brw_wm_fp.c revision 411d913ccea362dbd75411266d7abb685214ee93
19f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/*
29f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt Copyright (C) Intel Corp.  2006.  All Rights Reserved.
39f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
49f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt develop this 3D driver.
59f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
69f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt Permission is hereby granted, free of charge, to any person obtaining
79f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt a copy of this software and associated documentation files (the
89f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt "Software"), to deal in the Software without restriction, including
99f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt without limitation the rights to use, copy, modify, merge, publish,
109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt distribute, sublicense, and/or sell copies of the Software, and to
119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt permit persons to whom the Software is furnished to do so, subject to
129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt the following conditions:
139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt The above copyright notice and this permission notice (including the
159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt next paragraph) shall be included in all copies or substantial
169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt portions of the Software.
179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
229f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
239f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
249f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt **********************************************************************/
279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt /*
289f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt  * Authors:
299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt  *   Keith Whitwell <keith@tungstengraphics.com>
309f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt  */
319f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
329f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
33ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "main/glheader.h"
34ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "main/macros.h"
35ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "main/enums.h"
369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#include "brw_context.h"
379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#include "brw_wm.h"
389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#include "brw_util.h"
399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
40064ae479a770bf434958d673baf6f7530f642697Brian#include "shader/prog_parameter.h"
41064ae479a770bf434958d673baf6f7530f642697Brian#include "shader/prog_print.h"
42064ae479a770bf434958d673baf6f7530f642697Brian#include "shader/prog_statevars.h"
43064ae479a770bf434958d673baf6f7530f642697Brian
449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS
469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#define X    0
489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#define Y    1
499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#define Z    2
509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt#define W    3
519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic const char *wm_opcode_strings[] = {
549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "PIXELXY",
559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "DELTAXY",
569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "PIXELW",
579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "LINTERP",
589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "PINTERP",
599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "CINTERP",
609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "WPOSXY",
619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "FB_WRITE"
629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt};
639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
64e7b0ec9ae79d4ec4aba402b9124fde55d914da92Keith Whitwell#if 0
659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic const char *wm_file_strings[] = {
669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   "PAYLOAD"
679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt};
68e7b0ec9ae79d4ec4aba402b9124fde55d914da92Keith Whitwell#endif
699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Source regs
739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register src_reg(GLuint file, GLuint idx)
769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register reg;
789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.File = file;
799f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.Index = idx;
809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.Swizzle = SWIZZLE_NOOP;
819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.RelAddr = 0;
829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.NegateBase = 0;
839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.Abs = 0;
849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.NegateAbs = 0;
859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return reg;
869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register src_reg_from_dst(struct prog_dst_register dst)
899f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src_reg(dst.File, dst.Index);
919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register src_undef( void )
949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src_reg(PROGRAM_UNDEFINED, 0);
969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
989f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic GLboolean src_is_undef(struct prog_src_register src)
999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src.File == PROGRAM_UNDEFINED;
1019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1039f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register src_swizzle( struct prog_src_register reg, int x, int y, int z, int w )
1049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1059f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.Swizzle = MAKE_SWIZZLE4(x,y,z,w);
1069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return reg;
1079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register src_swizzle1( struct prog_src_register reg, int x )
1109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src_swizzle(reg, x, x, x, x);
1129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
114c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paulstatic struct prog_src_register src_swizzle4( struct prog_src_register reg, uint swizzle )
115c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul{
116c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul   reg.Swizzle = swizzle;
117c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul   return reg;
118c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul}
119c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul
1209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
1229f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Dest regs
1239f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
1249f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_dst_register dst_reg(GLuint file, GLuint idx)
1269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_dst_register reg;
1289f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.File = file;
1299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.Index = idx;
1309f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.WriteMask = WRITEMASK_XYZW;
13195fa98d61a857448e690a0671b2e1e1d2873f0ecBrian Paul   reg.RelAddr = 0;
13220f49252e1fe2e72bb620c26292f33d5315452a1Brian Paul   reg.CondMask = COND_TR;
1339f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.CondSwizzle = 0;
1349f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.CondSrc = 0;
13595fa98d61a857448e690a0671b2e1e1d2873f0ecBrian Paul   reg.pad = 0;
1369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return reg;
1379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_dst_register dst_mask( struct prog_dst_register reg, int mask )
1409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   reg.WriteMask &= mask;
1429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return reg;
1439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_dst_register dst_undef( void )
1469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return dst_reg(PROGRAM_UNDEFINED, 0);
1489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_dst_register get_temp( struct brw_wm_compile *c )
1539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1543105bc1d885ea8ce083d2be85cbeac46d4d873a1Andrzej Trznadel   int bit = _mesa_ffs( ~c->fp_temp );
1559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (!bit) {
1579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      _mesa_printf("%s: out of temporaries\n", __FILE__);
1589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      exit(1);
1599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
1609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->fp_temp |= 1<<(bit-1);
1629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return dst_reg(PROGRAM_TEMPORARY, FIRST_INTERNAL_TEMP+(bit-1));
1639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void release_temp( struct brw_wm_compile *c, struct prog_dst_register temp )
1679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1683105bc1d885ea8ce083d2be85cbeac46d4d873a1Andrzej Trznadel   c->fp_temp &= ~(1 << (temp.Index - FIRST_INTERNAL_TEMP));
1699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
1739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Instructions
1749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
1759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_instruction *get_fp_inst(struct brw_wm_compile *c)
1779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return &c->prog_instructions[c->nr_fp_insns++];
1799f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_instruction *emit_insn(struct brw_wm_compile *c,
1829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt					const struct prog_instruction *inst0)
1839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
1849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_instruction *inst = get_fp_inst(c);
1859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   *inst = *inst0;
1869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return inst;
1879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
1889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
189a79186e29efebed04c927d024b013435e7ff5725Brian Paulstatic struct prog_instruction * emit_tex_op(struct brw_wm_compile *c,
1909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       GLuint op,
1919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       struct prog_dst_register dest,
1929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       GLuint saturate,
1939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       GLuint tex_src_unit,
1949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       GLuint tex_src_target,
195e0d907308150b4863cc4f24543e70e14207e966aBrian Paul				       GLuint tex_shadow,
1969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       struct prog_src_register src0,
1979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       struct prog_src_register src1,
1989f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt				       struct prog_src_register src2 )
1999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
2009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_instruction *inst = get_fp_inst(c);
2019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   memset(inst, 0, sizeof(*inst));
2039f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->Opcode = op;
2059f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->DstReg = dest;
2069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->SaturateMode = saturate;
2079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->TexSrcUnit = tex_src_unit;
2089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->TexSrcTarget = tex_src_target;
209e0d907308150b4863cc4f24543e70e14207e966aBrian Paul   inst->TexShadow = tex_shadow;
2109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->SrcReg[0] = src0;
2119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->SrcReg[1] = src1;
2129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   inst->SrcReg[2] = src2;
2139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return inst;
2149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
2159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
217a79186e29efebed04c927d024b013435e7ff5725Brian Paulstatic struct prog_instruction * emit_op(struct brw_wm_compile *c,
218a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       GLuint op,
219a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       struct prog_dst_register dest,
220a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       GLuint saturate,
221a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       struct prog_src_register src0,
222a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       struct prog_src_register src1,
223a79186e29efebed04c927d024b013435e7ff5725Brian Paul				       struct prog_src_register src2 )
224a79186e29efebed04c927d024b013435e7ff5725Brian Paul{
225a79186e29efebed04c927d024b013435e7ff5725Brian Paul   return emit_tex_op(c, op, dest, saturate,
226e0d907308150b4863cc4f24543e70e14207e966aBrian Paul                      0, 0, 0,  /* tex unit, target, shadow */
227a79186e29efebed04c927d024b013435e7ff5725Brian Paul                      src0, src1, src2);
228a79186e29efebed04c927d024b013435e7ff5725Brian Paul}
229a79186e29efebed04c927d024b013435e7ff5725Brian Paul
230a79186e29efebed04c927d024b013435e7ff5725Brian Paul
2319f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2329f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2339f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
2349f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Special instructions for interpolation and other tasks
2359f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
2369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register get_pixel_xy( struct brw_wm_compile *c )
2389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
2399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (src_is_undef(c->pixel_xy)) {
2409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register pixel_xy = get_temp(c);
2419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
2429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* Emit the out calculations, and hold onto the results.  Use
2459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       * two instructions as a temporary is required.
2469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
2479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* pixel_xy.xy = PIXELXY payload[0];
2489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
2499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
2509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_PIXELXY,
2519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(pixel_xy, WRITEMASK_XY),
252a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
2539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      payload_r0_depth,
2549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef(),
2559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
2569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      c->pixel_xy = src_reg_from_dst(pixel_xy);
2589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
2599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return c->pixel_xy;
2619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
2629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register get_delta_xy( struct brw_wm_compile *c )
2649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
2659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (src_is_undef(c->delta_xy)) {
2669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register delta_xy = get_temp(c);
2679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register pixel_xy = get_pixel_xy(c);
2689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
2699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* deltas.xy = DELTAXY pixel_xy, payload[0]
2719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
2729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
2739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_DELTAXY,
2749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(delta_xy, WRITEMASK_XY),
275a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
2769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      pixel_xy,
2779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      payload_r0_depth,
2789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
2799f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      c->delta_xy = src_reg_from_dst(delta_xy);
2819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
2829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return c->delta_xy;
2849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
2859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
2869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register get_pixel_w( struct brw_wm_compile *c )
2879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
2889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (src_is_undef(c->pixel_w)) {
2899f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register pixel_w = get_temp(c);
2909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register deltas = get_delta_xy(c);
2919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS);
2929b78d9f65178648b1888f98153a2f738a281cb84Brian Paul
2939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x
2949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
2959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
2969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_PIXELW,
2979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(pixel_w, WRITEMASK_W),
298a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
2999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      interp_wpos,
3009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      deltas,
3019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
3029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3039f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      c->pixel_w = src_reg_from_dst(pixel_w);
3059f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
3069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return c->pixel_w;
3089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
3099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void emit_interp( struct brw_wm_compile *c,
3119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			 GLuint idx )
3129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
3139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx);
3149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
3159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register deltas = get_delta_xy(c);
316b013f945d8514ed827183a4cbfbc4dccc100704fEric Anholt
3179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   /* Need to use PINTERP on attributes which have been
3189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * multiplied by 1/W in the SF program, and LINTERP on those
3199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * which have not:
3209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    */
3219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   switch (idx) {
3229f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   case FRAG_ATTRIB_WPOS:
3239f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* Have to treat wpos.xy specially:
3249f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
3259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
3269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_WPOSXY,
3279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_XY),
328a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
3299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      get_pixel_xy(c),
3309f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef(),
3319f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
3329f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3339f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      dst = dst_mask(dst, WRITEMASK_ZW);
3349f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
3359f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* PROGRAM_INPUT.attr.xyzw = INTERP payload.interp[attr].x, deltas.xyw
3369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
3379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
3389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_LINTERP,
3399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst,
340a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
3419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      interp,
3429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      deltas,
343b013f945d8514ed827183a4cbfbc4dccc100704fEric Anholt	      src_undef());
3449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      break;
3459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   case FRAG_ATTRIB_COL0:
3469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   case FRAG_ATTRIB_COL1:
3479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      if (c->key.flat_shade) {
3489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 emit_op(c,
3499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 WM_CINTERP,
3509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 dst,
351a79186e29efebed04c927d024b013435e7ff5725Brian Paul		 0,
3529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 interp,
3539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 src_undef(),
3549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 src_undef());
3559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      }
3569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      else {
3579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 emit_op(c,
3589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 WM_LINTERP,
3599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 dst,
360a79186e29efebed04c927d024b013435e7ff5725Brian Paul		 0,
3619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 interp,
3629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 deltas,
3639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt		 src_undef());
3649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      }
3659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      break;
366411d913ccea362dbd75411266d7abb685214ee93Eric Anholt   case FRAG_ATTRIB_FOGC:
367411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      /* The FOGC input is really special.  When a program uses glFogFragCoord,
368411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       * the results returned are supposed to be (f,0,0,1).  But for Mesa GLSL,
369411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       * the glFrontFacing and glPointCoord values are also stashed in FOGC.
370411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       * So, write the interpolated fog value to X, then either 0, 1, or the
371411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       * stashed values to Y, Z, W.  Note that this means that
372411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       * glFogFragCoord.yzw can be wrong in those cases!
373411d913ccea362dbd75411266d7abb685214ee93Eric Anholt       */
374411d913ccea362dbd75411266d7abb685214ee93Eric Anholt
375411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      /* Interpolate the fog coordinate */
376411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      emit_op(c,
377411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      WM_PINTERP,
378411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      dst_mask(dst, WRITEMASK_X),
379411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      0,
380411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      interp,
381411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      deltas,
382411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      get_pixel_w(c));
383411d913ccea362dbd75411266d7abb685214ee93Eric Anholt
384411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      /* Move the front facing value into FOGC.y if it's needed. */
385411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      if (c->fp->program.UsesFrontFacing) {
386411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	 emit_op(c,
387411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 WM_PINTERP,
388411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 dst_mask(dst, WRITEMASK_Y),
389411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 0,
390411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 interp,
391411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 deltas,
392411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 get_pixel_w(c));
393411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      } else {
394411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	 emit_op(c,
395411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 OPCODE_MOV,
396411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 dst_mask(dst, WRITEMASK_Y),
397411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 0,
398411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 src_swizzle1(interp, SWIZZLE_ZERO),
399411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 src_undef(),
400411d913ccea362dbd75411266d7abb685214ee93Eric Anholt		 src_undef());
401411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      }
402411d913ccea362dbd75411266d7abb685214ee93Eric Anholt
403411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      /* Should do the PointCoord thing here. */
404411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      emit_op(c,
405411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      OPCODE_MOV,
406411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      dst_mask(dst, WRITEMASK_ZW),
407411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      0,
408411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      src_swizzle(interp,
409411d913ccea362dbd75411266d7abb685214ee93Eric Anholt			  SWIZZLE_ZERO,
410411d913ccea362dbd75411266d7abb685214ee93Eric Anholt			  SWIZZLE_ZERO,
411411d913ccea362dbd75411266d7abb685214ee93Eric Anholt			  SWIZZLE_ZERO,
412411d913ccea362dbd75411266d7abb685214ee93Eric Anholt			  SWIZZLE_ONE),
413411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      src_undef(),
414411d913ccea362dbd75411266d7abb685214ee93Eric Anholt	      src_undef());
415411d913ccea362dbd75411266d7abb685214ee93Eric Anholt      break;
4169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   default:
4179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
4189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      WM_PINTERP,
4199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst,
420a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
4219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      interp,
4229f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      deltas,
4239f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      get_pixel_w(c));
4249f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      break;
4259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
4269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->fp_interp_emitted |= 1<<idx;
4289f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
4299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
430c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan haistatic void emit_ddx( struct brw_wm_compile *c,
431c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai        const struct prog_instruction *inst )
432c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai{
433c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    GLuint idx = inst->SrcReg[0].Index;
434c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
435c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai
436c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    c->fp_deriv_emitted |= 1<<idx;
437c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    emit_op(c,
438c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            OPCODE_DDX,
439c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            inst->DstReg,
440a79186e29efebed04c927d024b013435e7ff5725Brian Paul            0,
441c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            interp,
442c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            get_pixel_w(c),
443c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            src_undef());
444c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai}
445c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai
446c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan haistatic void emit_ddy( struct brw_wm_compile *c,
447c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai        const struct prog_instruction *inst )
448c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai{
449c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    GLuint idx = inst->SrcReg[0].Index;
450c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
451c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai
452c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    c->fp_deriv_emitted |= 1<<idx;
453c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai    emit_op(c,
454c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            OPCODE_DDY,
455c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            inst->DstReg,
456a79186e29efebed04c927d024b013435e7ff5725Brian Paul            0,
457c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            interp,
458c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            get_pixel_w(c),
459c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai            src_undef());
460c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai}
4619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
4639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Hacks to extend the program parameter and constant lists.
4649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
4659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/* Add the fog parameters to the parameter list of the original
4679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * program, rather than creating a new list.  Doesn't really do any
4689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * harm and it's not as if the parameter handling isn't a big hack
4699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * anyway.
4709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
471064ae479a770bf434958d673baf6f7530f642697Brianstatic struct prog_src_register search_or_add_param5(struct brw_wm_compile *c,
472064ae479a770bf434958d673baf6f7530f642697Brian                                                     GLint s0,
473064ae479a770bf434958d673baf6f7530f642697Brian                                                     GLint s1,
474064ae479a770bf434958d673baf6f7530f642697Brian                                                     GLint s2,
475064ae479a770bf434958d673baf6f7530f642697Brian                                                     GLint s3,
476064ae479a770bf434958d673baf6f7530f642697Brian                                                     GLint s4)
4779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
4789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters;
479064ae479a770bf434958d673baf6f7530f642697Brian   gl_state_index tokens[STATE_LENGTH];
4809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLuint idx;
4819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   tokens[0] = s0;
4829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   tokens[1] = s1;
4839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   tokens[2] = s2;
4849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   tokens[3] = s3;
4859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   tokens[4] = s4;
4869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   for (idx = 0; idx < paramList->NumParameters; idx++) {
4889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      if (paramList->Parameters[idx].Type == PROGRAM_STATE_VAR &&
4899f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  memcmp(paramList->Parameters[idx].StateIndexes, tokens, sizeof(tokens)) == 0)
4909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 return src_reg(PROGRAM_STATE_VAR, idx);
4919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
4929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   idx = _mesa_add_state_reference( paramList, tokens );
4949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src_reg(PROGRAM_STATE_VAR, idx);
4969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
4979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4989f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
4999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic struct prog_src_register search_or_add_const4f( struct brw_wm_compile *c,
5009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt						     GLfloat s0,
5019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt						     GLfloat s1,
5029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt						     GLfloat s2,
5039f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt						     GLfloat s3)
5049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
5059f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters;
5069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLfloat values[4];
5079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLuint idx;
508064ae479a770bf434958d673baf6f7530f642697Brian   GLuint swizzle;
5099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   values[0] = s0;
5119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   values[1] = s1;
5129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   values[2] = s2;
5139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   values[3] = s3;
5149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   /* Have to search, otherwise multiple compilations will each grow
5169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * the parameter list.
5179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    */
5189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   for (idx = 0; idx < paramList->NumParameters; idx++) {
5199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      if (paramList->Parameters[idx].Type == PROGRAM_CONSTANT &&
5209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  memcmp(paramList->ParameterValues[idx], values, sizeof(values)) == 0)
5219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5229f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 /* XXX: this mimics the mesa bug which puts all constants and
5239f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  * parameters into the "PROGRAM_STATE_VAR" category:
5249f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  */
5259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 return src_reg(PROGRAM_STATE_VAR, idx);
5269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
5279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
528064ae479a770bf434958d673baf6f7530f642697Brian   idx = _mesa_add_unnamed_constant( paramList, values, 4, &swizzle );
5297eca6be25f31cbbe5b72a70bf6b1e17c0e6df34dEric Anholt   assert(swizzle == SWIZZLE_NOOP); /* Need to handle swizzle in reg setup */
5309f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   return src_reg(PROGRAM_STATE_VAR, idx);
5319f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
5329f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5339f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5349f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5359f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
5369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Expand various instructions here to simpler forms.
5379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
5389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void precalc_dst( struct brw_wm_compile *c,
5399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			       const struct prog_instruction *inst )
5409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
5419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register src0 = inst->SrcReg[0];
5429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register src1 = inst->SrcReg[1];
5439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_dst_register dst = inst->DstReg;
5449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (dst.WriteMask & WRITEMASK_Y) {
5469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst.y = mul src0.y, src1.y
5479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
5489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
5499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MUL,
5509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_Y),
551a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      inst->SaturateMode,
5529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src0,
5539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src1,
5549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
5559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
5569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (dst.WriteMask & WRITEMASK_XZ) {
558b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      struct prog_instruction *swz;
5599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      GLuint z = GET_SWZ(src0.Swizzle, Z);
5609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst.xz = swz src0.1zzz
5629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
563b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      swz = emit_op(c,
564b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    OPCODE_SWZ,
565b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    dst_mask(dst, WRITEMASK_XZ),
566a79186e29efebed04c927d024b013435e7ff5725Brian Paul		    inst->SaturateMode,
567b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_swizzle(src0, SWIZZLE_ONE, z, z, z),
568b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_undef(),
569b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_undef());
570b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      /* Avoid letting negation flag of src0 affect our 1 constant. */
571b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      swz->SrcReg[0].NegateBase &= ~NEGATE_X;
5729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
5739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (dst.WriteMask & WRITEMASK_W) {
5749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst.w = mov src1.w
5759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
5769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
5779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MOV,
5789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_W),
579a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      inst->SaturateMode,
5809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src1,
5819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef(),
5829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
5839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
5849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
5859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void precalc_lit( struct brw_wm_compile *c,
5889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			 const struct prog_instruction *inst )
5899f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
5909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register src0 = inst->SrcReg[0];
5919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_dst_register dst = inst->DstReg;
5929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
5939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (dst.WriteMask & WRITEMASK_XW) {
594b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      struct prog_instruction *swz;
595b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt
5969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst.xw = swz src0.1111
5979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
598b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      swz = emit_op(c,
599b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    OPCODE_SWZ,
600b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    dst_mask(dst, WRITEMASK_XW),
601a79186e29efebed04c927d024b013435e7ff5725Brian Paul		    0,
602b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_swizzle1(src0, SWIZZLE_ONE),
603b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_undef(),
604b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt		    src_undef());
605b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      /* Avoid letting the negation flag of src0 affect our 1 constant. */
606b4cbf6983e0e6d6502c1260f60c463841ab74590Eric Anholt      swz->SrcReg[0].NegateBase = 0;
6079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
6089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
6099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (dst.WriteMask & WRITEMASK_YZ) {
6109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
6119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_LIT,
6129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_YZ),
613a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      inst->SaturateMode,
6149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src0,
6159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef(),
6169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
6179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
6189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
6199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
6209e7903e492ad842481a166484e0474dd4f3100baBrian Paul
6219e7903e492ad842481a166484e0474dd4f3100baBrian Paul/**
6229e7903e492ad842481a166484e0474dd4f3100baBrian Paul * Some TEX instructions require extra code, cube map coordinate
6239e7903e492ad842481a166484e0474dd4f3100baBrian Paul * normalization, or coordinate scaling for RECT textures, etc.
6249e7903e492ad842481a166484e0474dd4f3100baBrian Paul * This function emits those extra instructions and the TEX
6259e7903e492ad842481a166484e0474dd4f3100baBrian Paul * instruction itself.
6269e7903e492ad842481a166484e0474dd4f3100baBrian Paul */
6279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void precalc_tex( struct brw_wm_compile *c,
6289f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			 const struct prog_instruction *inst )
6299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
630e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell   struct prog_src_register coord;
631e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell   struct prog_dst_register tmpcoord;
6329e7903e492ad842481a166484e0474dd4f3100baBrian Paul   const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
633e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
634175db68db59c6b917306adff98442d590df9af06Xiang, Haihao   if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
635175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_instruction *out;
636175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_dst_register tmp0 = get_temp(c);
637175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_src_register tmp0src = src_reg_from_dst(tmp0);
638175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_dst_register tmp1 = get_temp(c);
639175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
640175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       struct prog_src_register src0 = inst->SrcReg[0];
641175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6429e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* find longest component of coord vector and normalize it */
643175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       tmpcoord = get_temp(c);
644175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       coord = src_reg_from_dst(tmpcoord);
645175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6469e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* tmpcoord = src0 (i.e.: coord = src0) */
647175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       out = emit_op(c, OPCODE_MOV,
648175db68db59c6b917306adff98442d590df9af06Xiang, Haihao                     tmpcoord,
649a79186e29efebed04c927d024b013435e7ff5725Brian Paul                     0,
650175db68db59c6b917306adff98442d590df9af06Xiang, Haihao                     src0,
651175db68db59c6b917306adff98442d590df9af06Xiang, Haihao                     src_undef(),
652175db68db59c6b917306adff98442d590df9af06Xiang, Haihao                     src_undef());
653175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       out->SrcReg[0].NegateBase = 0;
654175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       out->SrcReg[0].Abs = 1;
655175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6569e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* tmp0 = MAX(coord.X, coord.Y) */
657175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       emit_op(c, OPCODE_MAX,
658175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp0,
659a79186e29efebed04c927d024b013435e7ff5725Brian Paul               0,
660175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_swizzle1(coord, X),
661175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_swizzle1(coord, Y),
662175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_undef());
663175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6649e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* tmp1 = MAX(tmp0, coord.Z) */
665175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       emit_op(c, OPCODE_MAX,
666175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp1,
667a79186e29efebed04c927d024b013435e7ff5725Brian Paul               0,
668175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp0src,
669175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_swizzle1(coord, Z),
670175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_undef());
671175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6729e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* tmp0 = 1 / tmp1 */
673175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       emit_op(c, OPCODE_RCP,
674175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp0,
675a79186e29efebed04c927d024b013435e7ff5725Brian Paul               0,
676175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp1src,
677175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_undef(),
678175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_undef());
679175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
6809e7903e492ad842481a166484e0474dd4f3100baBrian Paul       /* tmpCoord = src0 * tmp0 */
681175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       emit_op(c, OPCODE_MUL,
682175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmpcoord,
683a79186e29efebed04c927d024b013435e7ff5725Brian Paul               0,
684175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src0,
685175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               tmp0src,
686175db68db59c6b917306adff98442d590df9af06Xiang, Haihao               src_undef());
687175db68db59c6b917306adff98442d590df9af06Xiang, Haihao
688175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       release_temp(c, tmp0);
689175db68db59c6b917306adff98442d590df9af06Xiang, Haihao       release_temp(c, tmp1);
6909e7903e492ad842481a166484e0474dd4f3100baBrian Paul   }
6919e7903e492ad842481a166484e0474dd4f3100baBrian Paul   else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
692e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      struct prog_src_register scale =
693064ae479a770bf434958d673baf6f7530f642697Brian	 search_or_add_param5( c,
694e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell			       STATE_INTERNAL,
695e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell			       STATE_TEXRECT_SCALE,
696a3024caff1c790cf9f24476926aa62198f1e7b53Xiang, Haihao			       unit,
697064ae479a770bf434958d673baf6f7530f642697Brian			       0,0 );
698e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
699e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      tmpcoord = get_temp(c);
700e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
701e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      /* coord.xy   = MUL inst->SrcReg[0], { 1/width, 1/height }
702e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell       */
703e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      emit_op(c,
704e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell	      OPCODE_MUL,
705e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell	      tmpcoord,
706a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
707e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell	      inst->SrcReg[0],
708e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell	      scale,
709e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell	      src_undef());
710e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
711e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      coord = src_reg_from_dst(tmpcoord);
712e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell   }
713e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell   else {
714e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      coord = inst->SrcReg[0];
715e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell   }
716e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
7179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   /* Need to emit YUV texture conversions by hand.  Probably need to
7189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * do this here - the alternative is in brw_wm_emit.c, but the
7199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * conversion requires allocating a temporary variable which we
7209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * don't have the facility to do that late in the compilation.
7219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    */
7229e7903e492ad842481a166484e0474dd4f3100baBrian Paul   if (c->key.yuvtex_mask & (1 << unit)) {
7239e7903e492ad842481a166484e0474dd4f3100baBrian Paul      /* convert ycbcr to RGBA */
7249e7903e492ad842481a166484e0474dd4f3100baBrian Paul      GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
7257676980d38cff417015bca8d23549d567d74228bZou Nan hai
7269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /*
7279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 CONST C0 = { -.5, -.0625,  -.5, 1.164 }
7289f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
7299f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 UYV     = TEX ...
7309f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 UYV.xyz = ADD UYV,     C0
7319f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 UYV.y   = MUL UYV.y,   C0.w
7327676980d38cff417015bca8d23549d567d74228bZou Nan hai 	 if (UV swaped)
7337676980d38cff417015bca8d23549d567d74228bZou Nan hai	    RGB.xyz = MAD UYV.zzx, C1,   UYV.y
7347676980d38cff417015bca8d23549d567d74228bZou Nan hai	 else
7357676980d38cff417015bca8d23549d567d74228bZou Nan hai	    RGB.xyz = MAD UYV.xxz, C1,   UYV.y
7369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 RGB.y   = MAD UYV.z,   C1.w, RGB.y
7379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      */
7389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register dst = inst->DstReg;
7399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register tmp = get_temp(c);
7409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
7419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register C0 = search_or_add_const4f( c,  -.5, -.0625, -.5, 1.164 );
7429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 );
7439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
7449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* tmp     = TEX ...
7459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
746a79186e29efebed04c927d024b013435e7ff5725Brian Paul      emit_tex_op(c,
747a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  OPCODE_TEX,
748a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  tmp,
749a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  inst->SaturateMode,
750a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  unit,
751a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  inst->TexSrcTarget,
752e0d907308150b4863cc4f24543e70e14207e966aBrian Paul                  inst->TexShadow,
753a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  coord,
754a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  src_undef(),
755a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  src_undef());
7569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
7579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* tmp.xyz =  ADD TMP, C0
7589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
7599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
7609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_ADD,
7619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(tmp, WRITEMASK_XYZ),
762a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
7639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      tmpsrc,
7649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      C0,
7659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
7669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
7679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* YUV.y   = MUL YUV.y, C0.w
7689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
7697676980d38cff417015bca8d23549d567d74228bZou Nan hai
7709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
7719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MUL,
7729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(tmp, WRITEMASK_Y),
773a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
7749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      tmpsrc,
7759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(C0, W),
7769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
7779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
7787676980d38cff417015bca8d23549d567d74228bZou Nan hai      /*
7797676980d38cff417015bca8d23549d567d74228bZou Nan hai       * if (UV swaped)
7807676980d38cff417015bca8d23549d567d74228bZou Nan hai       *     RGB.xyz = MAD YUV.zzx, C1, YUV.y
7817676980d38cff417015bca8d23549d567d74228bZou Nan hai       * else
7827676980d38cff417015bca8d23549d567d74228bZou Nan hai       *     RGB.xyz = MAD YUV.xxz, C1, YUV.y
7839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
7847676980d38cff417015bca8d23549d567d74228bZou Nan hai
7859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
7869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MAD,
7879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_XYZ),
788a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
7897676980d38cff417015bca8d23549d567d74228bZou Nan hai	      swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z),
7909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      C1,
7919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(tmpsrc, Y));
7929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
7939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
7949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
7959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
7969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MAD,
7979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(dst, WRITEMASK_Y),
798a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
7999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(tmpsrc, Z),
8009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(C1, W),
8019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(src_reg_from_dst(dst), Y));
802e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
803e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      release_temp(c, tmp);
8049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
8059e7903e492ad842481a166484e0474dd4f3100baBrian Paul   else {
8069e7903e492ad842481a166484e0474dd4f3100baBrian Paul      /* ordinary RGBA tex instruction */
807a79186e29efebed04c927d024b013435e7ff5725Brian Paul      emit_tex_op(c,
808a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  OPCODE_TEX,
809a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  inst->DstReg,
810a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  inst->SaturateMode,
811a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  unit,
812a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  inst->TexSrcTarget,
813e0d907308150b4863cc4f24543e70e14207e966aBrian Paul                  inst->TexShadow,
814a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  coord,
815a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  src_undef(),
816a79186e29efebed04c927d024b013435e7ff5725Brian Paul                  src_undef());
8179e7903e492ad842481a166484e0474dd4f3100baBrian Paul   }
818e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell
819c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul   /* For GL_EXT_texture_swizzle: */
820c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul   if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
821c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul      /* swizzle the result of the TEX instruction */
822c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul      struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg);
8233dcc48e6882385f58ec9b19a3a7d5307ef9fc976Brian Paul      emit_op(c, OPCODE_SWZ,
824c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul              inst->DstReg,
825c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul              SATURATE_OFF, /* saturate already done above */
826c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul              src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
827c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul              src_undef(),
828c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul              src_undef());
829c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul   }
830c0d3b7679aa90e1a0dca2db152205efaec088b90Brian Paul
83128c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger   if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
83228c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger       (inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
833e38114a5e4492684333251eb22bc60ee1038de55Keith Whitwell      release_temp(c, tmpcoord);
8349f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
8359f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8369f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic GLboolean projtex( struct brw_wm_compile *c,
8389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			  const struct prog_instruction *inst )
8399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
8409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register src = inst->SrcReg[0];
8419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   /* Only try to detect the simplest cases.  Could detect (later)
8439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * cases where we are trying to emit code like RCP {1.0}, MUL x,
8449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * {1.0}, and so on.
8459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    *
8469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * More complex cases than this typically only arise from
8479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    * user-provided fragment programs anyway:
8489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    */
8499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX)
8509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      return 0;  /* ut2004 gun rendering !?! */
8519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   else if (src.File == PROGRAM_INPUT &&
8529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	    GET_SWZ(src.Swizzle, W) == W &&
85388451b04e9cd39db9cc9315aaf69e074614f22f9Xiang, Haihao           (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0)
8549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      return 0;
8559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   else
8569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      return 1;
8579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
8589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void precalc_txp( struct brw_wm_compile *c,
8619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			       const struct prog_instruction *inst )
8629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
8639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register src0 = inst->SrcReg[0];
8649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (projtex(c, inst)) {
8669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_dst_register tmp = get_temp(c);
8679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_instruction tmp_inst;
8689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* tmp0.w = RCP inst.arg[0][3]
8709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
8719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
8729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_RCP,
8739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(tmp, WRITEMASK_W),
874a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
8759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)),
8769f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef(),
8779f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
8789f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8799f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* tmp0.xyz =  MUL inst.arg[0], tmp0.wwww
8809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
8819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      emit_op(c,
8829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      OPCODE_MUL,
8839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      dst_mask(tmp, WRITEMASK_XYZ),
884a79186e29efebed04c927d024b013435e7ff5725Brian Paul	      0,
8859f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src0,
8869f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_swizzle1(src_reg_from_dst(tmp), W),
8879f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	      src_undef());
8889f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8899f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst = precalc(TEX tmp0)
8909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
8919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      tmp_inst = *inst;
8929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      tmp_inst.SrcReg[0] = src_reg_from_dst(tmp);
8939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      precalc_tex(c, &tmp_inst);
8949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
8959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      release_temp(c, tmp);
8969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
8979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   else
8989f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   {
8999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* dst = precalc(TEX src0)
9009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
9019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      precalc_tex(c, inst);
9029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
9039f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
9049f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9059f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void emit_fb_write( struct brw_wm_compile *c )
9089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
9099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
9108d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul   struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPTH);
911f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul   struct prog_src_register outcolor;
912fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai   GLuint i;
913fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai
9147936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai   struct prog_instruction *inst, *last_inst;
915fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai   struct brw_context *brw = c->func.brw;
916fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai
9178ae7e7749b708fc5a46180d3de2503ba7e2ab1f3Brian Paul   /* The inst->Aux field is used for FB write target and the EOT marker */
918fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai
919cdc63901df6af3b370935bd4997e3c9c4eb4b933root   if (brw->state.nr_color_regions > 1) {
920cdc63901df6af3b370935bd4997e3c9c4eb4b933root      for (i = 0 ; i < brw->state.nr_color_regions; i++) {
9219b78d9f65178648b1888f98153a2f738a281cb84Brian Paul         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
9229b78d9f65178648b1888f98153a2f738a281cb84Brian Paul         last_inst = inst = emit_op(c,
9239b78d9f65178648b1888f98153a2f738a281cb84Brian Paul                                    WM_FB_WRITE, dst_mask(dst_undef(),0), 0,
9249b78d9f65178648b1888f98153a2f738a281cb84Brian Paul                                    outcolor, payload_r0_depth, outdepth);
9258ae7e7749b708fc5a46180d3de2503ba7e2ab1f3Brian Paul         inst->Aux = (i<<1);
9269b78d9f65178648b1888f98153a2f738a281cb84Brian Paul         if (c->fp_fragcolor_emitted) {
9278d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul            outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
9289b78d9f65178648b1888f98153a2f738a281cb84Brian Paul            last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
9299b78d9f65178648b1888f98153a2f738a281cb84Brian Paul                                       0, outcolor, payload_r0_depth, outdepth);
9308ae7e7749b708fc5a46180d3de2503ba7e2ab1f3Brian Paul            inst->Aux = (i<<1);
9319b78d9f65178648b1888f98153a2f738a281cb84Brian Paul         }
9329b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      }
9338ae7e7749b708fc5a46180d3de2503ba7e2ab1f3Brian Paul      last_inst->Aux |= 1; //eot
934f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul   }
935f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul   else {
936f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul      /* if gl_FragData[0] is written, use it, else use gl_FragColor */
937f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul      if (c->fp->program.Base.OutputsWritten & (1 << FRAG_RESULT_DATA0))
938f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0);
939f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul      else
9408d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul         outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
941f68f94c2bc950405d4c91a1e5582a35ff4b15bdfBrian Paul
9429b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
9439b78d9f65178648b1888f98153a2f738a281cb84Brian Paul                     0, outcolor, payload_r0_depth, outdepth);
9448ae7e7749b708fc5a46180d3de2503ba7e2ab1f3Brian Paul      inst->Aux = 1|(0<<1);
945fcb7cb9e72ecac7c165a3a6ed7a033e2e6793a26Zou Nan hai   }
9469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
9479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt/***********************************************************************
9529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt * Emit INTERP instructions ahead of first use of each attrib.
9539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt */
9549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtstatic void validate_src_regs( struct brw_wm_compile *c,
9569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt			       const struct prog_instruction *inst )
9579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
9589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLuint nr_args = brw_wm_nr_args( inst->Opcode );
9599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLuint i;
9609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   for (i = 0; i < nr_args; i++) {
9629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      if (inst->SrcReg[i].File == PROGRAM_INPUT) {
9639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 GLuint idx = inst->SrcReg[i].Index;
9649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 if (!(c->fp_interp_emitted & (1<<idx))) {
9659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	    emit_interp(c, idx);
9669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 }
9679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      }
9689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
9699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
9709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
9717936c614abc165270852bc5e7e316747a9cacdfbZou Nan haistatic void validate_dst_regs( struct brw_wm_compile *c,
9727936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai			       const struct prog_instruction *inst )
9737936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai{
9747936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai   if (inst->DstReg.File == PROGRAM_OUTPUT) {
9759b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      GLuint idx = inst->DstReg.Index;
9768d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul      if (idx == FRAG_RESULT_COLOR)
9779b78d9f65178648b1888f98153a2f738a281cb84Brian Paul         c->fp_fragcolor_emitted = 1;
9787936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai   }
9797936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai}
9809f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
981cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwellstatic void print_insns( const struct prog_instruction *insn,
982cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell			 GLuint nr )
983cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell{
984cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell   GLuint i;
985cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell   for (i = 0; i < nr; i++, insn++) {
986cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell      _mesa_printf("%3d: ", i);
987cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell      if (insn->Opcode < MAX_OPCODE)
988cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell	 _mesa_print_instruction(insn);
989cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell      else if (insn->Opcode < MAX_WM_OPCODE) {
990cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell	 GLuint idx = insn->Opcode - MAX_OPCODE;
991cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell
992cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell	 _mesa_print_alu_instruction(insn,
993cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell				     wm_opcode_strings[idx],
994cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell				     3);
995cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell      }
996cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell      else
99720f49252e1fe2e72bb620c26292f33d5315452a1Brian Paul	 _mesa_printf("965 Opcode %d\n", insn->Opcode);
998cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell   }
999cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell}
1000cb54c056a6d46d03bfa0c4927f5ac8843feab8cdKeith Whitwell
10012f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul
10022f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul/**
10032f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul * Initial pass for fragment program code generation.
10042f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul * This function is used by both the GLSL and non-GLSL paths.
10052f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul */
10069f344b3e7d6e23674dd4747faec253f103563b36Eric Anholtvoid brw_wm_pass_fp( struct brw_wm_compile *c )
10079f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt{
10089f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   struct brw_fragment_program *fp = c->fp;
10099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   GLuint insn;
10109f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10119f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (INTEL_DEBUG & DEBUG_WM) {
1012fc3971d80051b34836716579fd060dbb122d036bEric Anholt      _mesa_printf("pre-fp:\n");
1013133f14168009393c5f396d218521625cb79b653fKeith Whitwell      _mesa_print_program(&fp->program.Base);
10149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      _mesa_printf("\n");
10159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
10169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->pixel_xy = src_undef();
10189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->delta_xy = src_undef();
10199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->pixel_w = src_undef();
10209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   c->nr_fp_insns = 0;
10219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10222f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul   /* Emit preamble instructions.  This is where special instructions such as
10232f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul    * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
10242f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul    * compute shader inputs from varying vars.
10259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt    */
10269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
10279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
10287936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai      validate_src_regs(c, inst);
10297936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai      validate_dst_regs(c, inst);
10307936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai   }
10312f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul
10322f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul   /* Loop over all instructions doing assorted simplifications and
10332f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul    * transformations.
10342f78d4a2cd009d8d6a5f470d5738586b7f89f3d9Brian Paul    */
10357936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai   for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
10367936c614abc165270852bc5e7e316747a9cacdfbZou Nan hai      const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
10379f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      struct prog_instruction *out;
10389f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10399f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      /* Check for INPUT values, emit INTERP instructions where
10409f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       * necessary:
10419f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt       */
10429f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10439f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      switch (inst->Opcode) {
10449f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_SWZ:
10459f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10469f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->Opcode = OPCODE_MOV;
10479f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10489f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10499f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_ABS:
10509f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10519f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->Opcode = OPCODE_MOV;
10529f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->SrcReg[0].NegateBase = 0;
10539f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->SrcReg[0].Abs = 1;
10549f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10559f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10569f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_SUB:
10579f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10589f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->Opcode = OPCODE_ADD;
10599f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->SrcReg[1].NegateBase ^= 0xf;
10609f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10619f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10629f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_SCS:
10639f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10649f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 /* This should probably be done in the parser.
10659f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  */
10669f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->DstReg.WriteMask &= WRITEMASK_XY;
10679f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10689f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10699f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_DST:
10709f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 precalc_dst(c, inst);
10719f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10729f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10739f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_LIT:
10749f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 precalc_lit(c, inst);
10759f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
107628c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger
107728c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger      case OPCODE_TEX:
107828c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger	 precalc_tex(c, inst);
107928c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger	 break;
108028c28f72fd9ed192467a3cf913b344951d0bc805Roland Scheidegger
10819f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_TXP:
10829f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 precalc_txp(c, inst);
10839f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10849f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1085c20a1736566d301f38cc1271284b1fde9adb2741Xiang, Haihao      case OPCODE_TXB:
1086c20a1736566d301f38cc1271284b1fde9adb2741Xiang, Haihao	 out = emit_insn(c, inst);
1087c20a1736566d301f38cc1271284b1fde9adb2741Xiang, Haihao	 out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit];
1088c20a1736566d301f38cc1271284b1fde9adb2741Xiang, Haihao	 break;
1089c20a1736566d301f38cc1271284b1fde9adb2741Xiang, Haihao
10909f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_XPD:
10919f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10929f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 /* This should probably be done in the parser.
10939f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  */
10949f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->DstReg.WriteMask &= WRITEMASK_XYZ;
10959f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
10969f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
10979f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_KIL:
10989f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out = emit_insn(c, inst);
10999f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 /* This should probably be done in the parser.
11009f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	  */
11019f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 out->DstReg.WriteMask = 0;
11029f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
1103c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai      case OPCODE_DDX:
1104c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai	 emit_ddx(c, inst);
1105c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai	 break;
1106c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai      case OPCODE_DDY:
1107c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai         emit_ddy(c, inst);
1108c702a7100e2aa83241e89850a97bcc23e1c6fedbZou Nan hai	break;
11099f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_END:
1110d19d0596daf004b56d80f78fa1a329b43c2ebf94Zou Nan hai	 emit_fb_write(c);
1111d19d0596daf004b56d80f78fa1a329b43c2ebf94Zou Nan hai	 break;
11129f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      case OPCODE_PRINT:
11139f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
11149f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
11159f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      default:
11169f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 emit_insn(c, inst);
11179f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt	 break;
11189f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt      }
11199f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
11209f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
11219f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   if (INTEL_DEBUG & DEBUG_WM) {
11229b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      _mesa_printf("pass_fp:\n");
11239b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      print_insns( c->prog_instructions, c->nr_fp_insns );
11249b78d9f65178648b1888f98153a2f738a281cb84Brian Paul      _mesa_printf("\n");
11259f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt   }
11269f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt}
11279f344b3e7d6e23674dd4747faec253f103563b36Eric Anholt
1128