aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_wm_fp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm_fp.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_fp.c82
1 files changed, 62 insertions, 20 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c
index 6df2c95d80c..8b5ccdba931 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_fp.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c
@@ -111,6 +111,12 @@ static struct prog_src_register src_swizzle1( struct prog_src_register reg, int
return src_swizzle(reg, x, x, x, x);
}
+static struct prog_src_register src_swizzle4( struct prog_src_register reg, uint swizzle )
+{
+ reg.Swizzle = swizzle;
+ return reg;
+}
+
/***********************************************************************
* Dest regs
@@ -177,7 +183,6 @@ static struct prog_instruction *emit_insn(struct brw_wm_compile *c,
{
struct prog_instruction *inst = get_fp_inst(c);
*inst = *inst0;
- inst->Data = (void *)inst0;
return inst;
}
@@ -554,12 +559,19 @@ static void precalc_lit( struct brw_wm_compile *c,
}
}
+
+/**
+ * Some TEX instructions require extra code, cube map coordinate
+ * normalization, or coordinate scaling for RECT textures, etc.
+ * This function emits those extra instructions and the TEX
+ * instruction itself.
+ */
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];
+ const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
struct prog_instruction *out;
@@ -569,9 +581,11 @@ static void precalc_tex( struct brw_wm_compile *c,
struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
struct prog_src_register src0 = inst->SrcReg[0];
+ /* find longest component of coord vector and normalize it */
tmpcoord = get_temp(c);
coord = src_reg_from_dst(tmpcoord);
+ /* tmpcoord = src0 (i.e.: coord = src0) */
out = emit_op(c, OPCODE_MOV,
tmpcoord,
0, 0, 0,
@@ -581,6 +595,7 @@ static void precalc_tex( struct brw_wm_compile *c,
out->SrcReg[0].NegateBase = 0;
out->SrcReg[0].Abs = 1;
+ /* tmp0 = MAX(coord.X, coord.Y) */
emit_op(c, OPCODE_MAX,
tmp0,
0, 0, 0,
@@ -588,6 +603,7 @@ static void precalc_tex( struct brw_wm_compile *c,
src_swizzle1(coord, Y),
src_undef());
+ /* tmp1 = MAX(tmp0, coord.Z) */
emit_op(c, OPCODE_MAX,
tmp1,
0, 0, 0,
@@ -595,6 +611,7 @@ static void precalc_tex( struct brw_wm_compile *c,
src_swizzle1(coord, Z),
src_undef());
+ /* tmp0 = 1 / tmp1 */
emit_op(c, OPCODE_RCP,
tmp0,
0, 0, 0,
@@ -602,6 +619,7 @@ static void precalc_tex( struct brw_wm_compile *c,
src_undef(),
src_undef());
+ /* tmpCoord = src0 * tmp0 */
emit_op(c, OPCODE_MUL,
tmpcoord,
0, 0, 0,
@@ -611,7 +629,8 @@ static void precalc_tex( struct brw_wm_compile *c,
release_temp(c, tmp0);
release_temp(c, tmp1);
- } else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
+ }
+ else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
struct prog_src_register scale =
search_or_add_param5( c,
STATE_INTERNAL,
@@ -642,19 +661,9 @@ static void precalc_tex( struct brw_wm_compile *c,
* 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<<unit))) {
- emit_op(c,
- OPCODE_TEX,
- inst->DstReg,
- inst->SaturateMode,
- unit,
- inst->TexSrcTarget,
- coord,
- src_undef(),
- src_undef());
- }
- else {
- GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
+ if (c->key.yuvtex_mask & (1 << unit)) {
+ /* convert ycbcr to RGBA */
+ GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
/*
CONST C0 = { -.5, -.0625, -.5, 1.164 }
@@ -734,6 +743,31 @@ static void precalc_tex( struct brw_wm_compile *c,
release_temp(c, tmp);
}
+ else {
+ /* ordinary RGBA tex instruction */
+ emit_op(c,
+ OPCODE_TEX,
+ inst->DstReg,
+ inst->SaturateMode,
+ unit,
+ inst->TexSrcTarget,
+ coord,
+ src_undef(),
+ src_undef());
+ }
+
+ /* For GL_EXT_texture_swizzle: */
+ if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
+ /* swizzle the result of the TEX instruction */
+ struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg);
+ emit_op(c, OPCODE_SWZ,
+ inst->DstReg,
+ SATURATE_OFF, /* saturate already done above */
+ 0, 0, /* tex unit, target N/A */
+ src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
+ src_undef(),
+ src_undef());
+ }
if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
(inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
@@ -907,6 +941,11 @@ static void print_insns( const struct prog_instruction *insn,
}
}
+
+/**
+ * Initial pass for fragment program code generation.
+ * This function is used by both the GLSL and non-GLSL paths.
+ */
void brw_wm_pass_fp( struct brw_wm_compile *c )
{
struct brw_fragment_program *fp = c->fp;
@@ -923,15 +962,19 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
c->pixel_w = src_undef();
c->nr_fp_insns = 0;
- /* Emit preamble instructions:
+ /* Emit preamble instructions. This is where special instructions such as
+ * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
+ * compute shader inputs from varying vars.
*/
-
-
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);
}
+
+ /* Loop over all instructions doing assorted simplifications and
+ * transformations.
+ */
for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) {
const struct prog_instruction *inst = &fp->program.Base.Instructions[insn];
struct prog_instruction *out;
@@ -940,7 +983,6 @@ void brw_wm_pass_fp( struct brw_wm_compile *c )
* necessary:
*/
-
switch (inst->Opcode) {
case OPCODE_SWZ:
out = emit_insn(c, inst);