*/
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
#include "brw_context.h"
#include "brw_wm.h"
#include "brw_util.h"
-#include "shader/program.h"
-#include "shader/program_instruction.h"
-#include "shader/arbprogparse.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
+#include "shader/prog_statevars.h"
+
#define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS
"FB_WRITE"
};
+#if 0
static const char *wm_file_strings[] = {
"PAYLOAD"
};
+#endif
/***********************************************************************
static struct prog_dst_register get_temp( struct brw_wm_compile *c )
{
- int bit = ffs( ~c->fp_temp );
+ int bit = _mesa_ffs( ~c->fp_temp );
if (!bit) {
_mesa_printf("%s: out of temporaries\n", __FILE__);
static void release_temp( struct brw_wm_compile *c, struct prog_dst_register temp )
{
- c->fp_temp &= ~1<<(temp.Index + 1 - FIRST_INTERNAL_TEMP);
+ c->fp_temp &= ~(1 << (temp.Index - FIRST_INTERNAL_TEMP));
}
{
struct prog_instruction *inst = get_fp_inst(c);
*inst = *inst0;
+ inst->Data = (void *)inst0;
return inst;
}
inst->SrcReg[0] = src0;
inst->SrcReg[1] = src1;
inst->SrcReg[2] = src2;
-
return inst;
}
c->fp_interp_emitted |= 1<<idx;
}
+static void emit_ddx( struct brw_wm_compile *c,
+ const struct prog_instruction *inst )
+{
+ GLuint idx = inst->SrcReg[0].Index;
+ struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
+
+ c->fp_deriv_emitted |= 1<<idx;
+ emit_op(c,
+ OPCODE_DDX,
+ inst->DstReg,
+ 0, 0, 0,
+ interp,
+ get_pixel_w(c),
+ src_undef());
+}
+
+static void emit_ddy( struct brw_wm_compile *c,
+ const struct prog_instruction *inst )
+{
+ GLuint idx = inst->SrcReg[0].Index;
+ struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx);
+
+ c->fp_deriv_emitted |= 1<<idx;
+ emit_op(c,
+ OPCODE_DDY,
+ inst->DstReg,
+ 0, 0, 0,
+ interp,
+ get_pixel_w(c),
+ src_undef());
+}
/***********************************************************************
* Hacks to extend the program parameter and constant lists.
* harm and it's not as if the parameter handling isn't a big hack
* anyway.
*/
-static struct prog_src_register search_or_add_param6( struct brw_wm_compile *c,
- GLint s0,
- GLint s1,
- GLint s2,
- GLint s3,
- GLint s4,
- GLint s5)
+static struct prog_src_register search_or_add_param5(struct brw_wm_compile *c,
+ GLint s0,
+ GLint s1,
+ GLint s2,
+ GLint s3,
+ GLint s4)
{
struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters;
- GLint tokens[6];
+ gl_state_index tokens[STATE_LENGTH];
GLuint idx;
tokens[0] = s0;
tokens[1] = s1;
tokens[2] = s2;
tokens[3] = s3;
tokens[4] = s4;
- tokens[5] = s5;
for (idx = 0; idx < paramList->NumParameters; idx++) {
if (paramList->Parameters[idx].Type == PROGRAM_STATE_VAR &&
idx = _mesa_add_state_reference( paramList, tokens );
- /* Recalculate state dependency:
- */
- c->fp->param_state = brw_parameter_list_state_flags( paramList );
-
return src_reg(PROGRAM_STATE_VAR, idx);
}
struct gl_program_parameter_list *paramList = c->fp->program.Base.Parameters;
GLfloat values[4];
GLuint idx;
+ GLuint swizzle;
values[0] = s0;
values[1] = s1;
return src_reg(PROGRAM_STATE_VAR, idx);
}
- idx = _mesa_add_unnamed_constant( paramList, values );
-
+ idx = _mesa_add_unnamed_constant( paramList, values, 4, &swizzle );
+ assert(swizzle == SWIZZLE_NOOP); /* Need to handle swizzle in reg setup */
return src_reg(PROGRAM_STATE_VAR, idx);
}
if (dst.WriteMask & WRITEMASK_XZ) {
+ struct prog_instruction *swz;
GLuint z = GET_SWZ(src0.Swizzle, Z);
/* dst.xz = swz src0.1zzz
*/
- emit_op(c,
- OPCODE_SWZ,
- dst_mask(dst, WRITEMASK_XZ),
- inst->SaturateMode, 0, 0,
- src_swizzle(src0, SWIZZLE_ONE, z, z, z),
- src_undef(),
- src_undef());
+ swz = emit_op(c,
+ OPCODE_SWZ,
+ dst_mask(dst, WRITEMASK_XZ),
+ inst->SaturateMode, 0, 0,
+ src_swizzle(src0, SWIZZLE_ONE, z, z, z),
+ src_undef(),
+ src_undef());
+ /* Avoid letting negation flag of src0 affect our 1 constant. */
+ swz->SrcReg[0].NegateBase &= ~NEGATE_X;
}
if (dst.WriteMask & WRITEMASK_W) {
/* dst.w = mov src1.w
struct prog_dst_register dst = inst->DstReg;
if (dst.WriteMask & WRITEMASK_XW) {
+ struct prog_instruction *swz;
+
/* dst.xw = swz src0.1111
*/
- emit_op(c,
- OPCODE_SWZ,
- dst_mask(dst, WRITEMASK_XW),
- 0, 0, 0,
- src_swizzle1(src0, SWIZZLE_ONE),
- src_undef(),
- src_undef());
+ swz = emit_op(c,
+ OPCODE_SWZ,
+ dst_mask(dst, WRITEMASK_XW),
+ 0, 0, 0,
+ src_swizzle1(src0, SWIZZLE_ONE),
+ src_undef(),
+ src_undef());
+ /* Avoid letting the negation flag of src0 affect our 1 constant. */
+ swz->SrcReg[0].NegateBase = 0;
}
static void precalc_tex( struct brw_wm_compile *c,
const struct prog_instruction *inst )
{
+ struct prog_src_register coord;
+ struct prog_dst_register tmpcoord;
+ GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
+ if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
+ struct prog_instruction *out;
+ struct prog_dst_register tmp0 = get_temp(c);
+ struct prog_src_register tmp0src = src_reg_from_dst(tmp0);
+ struct prog_dst_register tmp1 = get_temp(c);
+ struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
+ struct prog_src_register src0 = inst->SrcReg[0];
+
+ tmpcoord = get_temp(c);
+ coord = src_reg_from_dst(tmpcoord);
+
+ out = emit_op(c, OPCODE_MOV,
+ tmpcoord,
+ 0, 0, 0,
+ src0,
+ src_undef(),
+ src_undef());
+ out->SrcReg[0].NegateBase = 0;
+ out->SrcReg[0].Abs = 1;
+
+ emit_op(c, OPCODE_MAX,
+ tmp0,
+ 0, 0, 0,
+ src_swizzle1(coord, X),
+ src_swizzle1(coord, Y),
+ src_undef());
+
+ emit_op(c, OPCODE_MAX,
+ tmp1,
+ 0, 0, 0,
+ tmp0src,
+ src_swizzle1(coord, Z),
+ src_undef());
+
+ emit_op(c, OPCODE_RCP,
+ tmp0,
+ 0, 0, 0,
+ tmp1src,
+ src_undef(),
+ src_undef());
+
+ emit_op(c, OPCODE_MUL,
+ tmpcoord,
+ 0, 0, 0,
+ src0,
+ tmp0src,
+ src_undef());
+
+ release_temp(c, tmp0);
+ release_temp(c, tmp1);
+ } else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
+ struct prog_src_register scale =
+ search_or_add_param5( c,
+ STATE_INTERNAL,
+ STATE_TEXRECT_SCALE,
+ unit,
+ 0,0 );
+
+ tmpcoord = get_temp(c);
+
+ /* coord.xy = MUL inst->SrcReg[0], { 1/width, 1/height }
+ */
+ emit_op(c,
+ OPCODE_MUL,
+ tmpcoord,
+ 0, 0, 0,
+ inst->SrcReg[0],
+ scale,
+ src_undef());
+
+ coord = src_reg_from_dst(tmpcoord);
+ }
+ else {
+ coord = inst->SrcReg[0];
+ }
+
/* Need to emit YUV texture conversions by hand. Probably need to
* do this here - the alternative is in brw_wm_emit.c, but the
* conversion requires allocating a temporary variable which we
* don't have the facility to do that late in the compilation.
*/
- if (!(c->key.yuvtex_mask & (1<<inst->TexSrcUnit))) {
+ if (!(c->key.yuvtex_mask & (1<<unit))) {
emit_op(c,
OPCODE_TEX,
inst->DstReg,
inst->SaturateMode,
- inst->TexSrcUnit,
+ unit,
inst->TexSrcTarget,
- inst->SrcReg[0],
+ coord,
src_undef(),
src_undef());
}
else {
+ GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
+
/*
CONST C0 = { -.5, -.0625, -.5, 1.164 }
CONST C1 = { 1.596, -0.813, 2.018, -.391 }
UYV = TEX ...
UYV.xyz = ADD UYV, C0
UYV.y = MUL UYV.y, C0.w
- RGB.xyz = MAD UYV.xxz, C1, UYV.y
+ if (UV swaped)
+ RGB.xyz = MAD UYV.zzx, C1, UYV.y
+ else
+ RGB.xyz = MAD UYV.xxz, C1, UYV.y
RGB.y = MAD UYV.z, C1.w, RGB.y
*/
struct prog_dst_register dst = inst->DstReg;
- struct prog_src_register src0 = inst->SrcReg[0];
struct prog_dst_register tmp = get_temp(c);
struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
struct prog_src_register C0 = search_or_add_const4f( c, -.5, -.0625, -.5, 1.164 );
OPCODE_TEX,
tmp,
inst->SaturateMode,
- inst->TexSrcUnit,
+ unit,
inst->TexSrcTarget,
- src0,
+ coord,
src_undef(),
src_undef());
/* YUV.y = MUL YUV.y, C0.w
*/
+
emit_op(c,
OPCODE_MUL,
dst_mask(tmp, WRITEMASK_Y),
src_swizzle1(C0, W),
src_undef());
- /* RGB.xyz = MAD YUV.xxz, C1, YUV.y
+ /*
+ * if (UV swaped)
+ * RGB.xyz = MAD YUV.zzx, C1, YUV.y
+ * else
+ * RGB.xyz = MAD YUV.xxz, C1, YUV.y
*/
+
emit_op(c,
OPCODE_MAD,
dst_mask(dst, WRITEMASK_XYZ),
0, 0, 0,
- src_swizzle(tmpsrc, X,X,Z,Z),
+ swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z),
C1,
src_swizzle1(tmpsrc, Y));
src_swizzle1(tmpsrc, Z),
src_swizzle1(C1, W),
src_swizzle1(src_reg_from_dst(dst), Y));
+
+ release_temp(c, tmp);
}
+
+ if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
+ (inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
+ release_temp(c, tmpcoord);
}
return 0; /* ut2004 gun rendering !?! */
else if (src.File == PROGRAM_INPUT &&
GET_SWZ(src.Swizzle, W) == W &&
- (c->key.projtex_mask & (1<<src.Index)) == 0)
+ (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0)
return 0;
else
return 1;
struct prog_src_register fog_factor )
{
struct prog_dst_register outcolor = dst_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
- struct prog_src_register fogcolor = search_or_add_param6( c, STATE_FOG_COLOR, 0,0,0,0,0 );
+ struct prog_src_register fogcolor = search_or_add_param5( c, STATE_FOG_COLOR, 0,0,0,0 );
/* color.xyz = LRP fog_factor.xxxx, output_color, fog_color */
struct prog_src_register outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR);
+ GLuint i;
- emit_op(c,
- WM_FB_WRITE,
- dst_mask(dst_undef(),0),
- 0, 0, 0,
- outcolor,
- payload_r0_depth,
- outdepth);
+ struct prog_instruction *inst, *last_inst;
+ struct brw_context *brw = c->func.brw;
+
+ /* inst->Sampler is not used by backend,
+ use it for fb write target and eot */
+
+ if (brw->state.nr_draw_regions > 1) {
+ for (i = 0 ; i < brw->state.nr_draw_regions; i++) {
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
+ last_inst = inst = emit_op(c,
+ WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0,
+ outcolor, payload_r0_depth, outdepth);
+ inst->Sampler = (i<<1);
+ if (c->fp_fragcolor_emitted) {
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
+ last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+ 0, 0, 0, outcolor, payload_r0_depth, outdepth);
+ inst->Sampler = (i<<1);
+ }
+ }
+ last_inst->Sampler |= 1; //eot
+ }else {
+ inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+ 0, 0, 0, outcolor, payload_r0_depth, outdepth);
+ inst->Sampler = 1|(0<<1);
+ }
}
}
}
+static void validate_dst_regs( struct brw_wm_compile *c,
+ const struct prog_instruction *inst )
+{
+ if (inst->DstReg.File == PROGRAM_OUTPUT) {
+ GLuint idx = inst->DstReg.Index;
+ if (idx == FRAG_RESULT_COLR)
+ c->fp_fragcolor_emitted = 1;
+ }
+}
+static void print_insns( const struct prog_instruction *insn,
+ GLuint nr )
+{
+ GLuint i;
+ for (i = 0; i < nr; i++, insn++) {
+ _mesa_printf("%3d: ", i);
+ if (insn->Opcode < MAX_OPCODE)
+ _mesa_print_instruction(insn);
+ else if (insn->Opcode < MAX_WM_OPCODE) {
+ GLuint idx = insn->Opcode - MAX_OPCODE;
+
+ _mesa_print_alu_instruction(insn,
+ wm_opcode_strings[idx],
+ 3);
+ }
+ else
+ _mesa_printf("UNKNOWN\n");
+
+ }
+}
void brw_wm_pass_fp( struct brw_wm_compile *c )
{
if (INTEL_DEBUG & DEBUG_WM) {
_mesa_printf("\n\n\npre-fp:\n");
-/* _mesa_print_program(&fp->program); */
+ _mesa_print_program(&fp->program.Base);
_mesa_printf("\n");
}
*/
+ for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
+ const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
+ validate_src_regs(c, inst);
+ validate_dst_regs(c, inst);
+ }
for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
struct prog_instruction *out;
/* Check for INPUT values, emit INTERP instructions where
* necessary:
*/
- validate_src_regs(c, inst);
switch (inst->Opcode) {
case OPCODE_LIT:
precalc_lit(c, inst);
break;
-
+
+ case OPCODE_TEX:
+ precalc_tex(c, inst);
+ break;
+
case OPCODE_TXP:
precalc_txp(c, inst);
break;
+ case OPCODE_TXB:
+ out = emit_insn(c, inst);
+ out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+ break;
+
case OPCODE_XPD:
out = emit_insn(c, inst);
/* This should probably be done in the parser.
*/
out->DstReg.WriteMask = 0;
break;
-
+ case OPCODE_DDX:
+ emit_ddx(c, inst);
+ break;
+ case OPCODE_DDY:
+ emit_ddy(c, inst);
+ break;
case OPCODE_END:
+ emit_fog(c);
+ emit_fb_write(c);
+ break;
case OPCODE_PRINT:
break;
break;
}
}
-
- emit_fog(c);
- emit_fb_write(c);
-
if (INTEL_DEBUG & DEBUG_WM) {
- _mesa_printf("\n\n\npass_fp:\n");
-/* _mesa_debug_fp_inst(c->nr_fp_insns, c->prog_instructions, wm_opcode_strings, wm_file_strings); */
- _mesa_printf("\n");
+ _mesa_printf("\n\n\npass_fp:\n");
+ print_insns( c->prog_instructions, c->nr_fp_insns );
+ _mesa_printf("\n");
}
}