summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/program/prog_statevars.c22
-rw-r--r--src/mesa/program/prog_statevars.h1
-rw-r--r--src/mesa/state_tracker/st_mesa_to_tgsi.c43
3 files changed, 51 insertions, 15 deletions
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index baac29ff0dd..83bd3727f33 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -572,6 +572,24 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
value[3] = 0.0F;
return;
+ case STATE_FB_WPOS_Y_TRANSFORM:
+ /* A driver may negate this conditional by using ZW swizzle
+ * instead of XY (based on e.g. some other state). */
+ if (ctx->DrawBuffer->Name != 0) {
+ /* Identity (XY) followed by flipping Y upside down (ZW). */
+ value[0] = 1.0F;
+ value[1] = 0.0F;
+ value[2] = -1.0F;
+ value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ } else {
+ /* Flipping Y upside down (XY) followed by identity (ZW). */
+ value[0] = -1.0F;
+ value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ value[2] = 1.0F;
+ value[3] = 0.0F;
+ }
+ return;
+
case STATE_ROT_MATRIX_0:
{
const int unit = (int) state[2];
@@ -695,6 +713,7 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
return _NEW_PIXEL;
case STATE_FB_SIZE:
+ case STATE_FB_WPOS_Y_TRANSFORM:
return _NEW_BUFFERS;
default:
@@ -900,6 +919,9 @@ append_token(char *dst, gl_state_index k)
case STATE_FB_SIZE:
append(dst, "FbSize");
break;
+ case STATE_FB_WPOS_Y_TRANSFORM:
+ append(dst, "FbWposYTransform");
+ break;
case STATE_ROT_MATRIX_0:
append(dst, "rotMatrixRow0");
break;
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index 6e5be53630c..009ebde0012 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -117,6 +117,7 @@ typedef enum gl_state_index_ {
STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */
+ STATE_FB_WPOS_Y_TRANSFORM, /**< (1, 0, -1, height-1) if a FBO is bound, (-1, height-1, 1, 0) otherwise */
STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c
index c5c239b2c95..f848462310e 100644
--- a/src/mesa/state_tracker/st_mesa_to_tgsi.c
+++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c
@@ -760,10 +760,13 @@ emit_adjusted_wpos( struct st_translate *t,
/**
* Emit the TGSI instructions for inverting the WPOS y coordinate.
+ * This code is unavoidable because it also depends on whether
+ * a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM).
*/
static void
-emit_inverted_wpos( struct st_translate *t,
- const struct gl_program *program )
+emit_wpos_inversion( struct st_translate *t,
+ const struct gl_program *program,
+ boolean invert)
{
struct ureg_program *ureg = t->ureg;
@@ -771,17 +774,17 @@ emit_inverted_wpos( struct st_translate *t,
* Need to replace instances of INPUT[WPOS] with temp T
* where T = INPUT[WPOS] by y is inverted.
*/
- static const gl_state_index winSizeState[STATE_LENGTH]
- = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 };
+ static const gl_state_index wposTransformState[STATE_LENGTH]
+ = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, 0, 0, 0 };
/* XXX: note we are modifying the incoming shader here! Need to
* do this before emitting the constant decls below, or this
* will be missed:
*/
- unsigned winHeightConst = _mesa_add_state_reference(program->Parameters,
- winSizeState);
+ unsigned wposTransConst = _mesa_add_state_reference(program->Parameters,
+ wposTransformState);
- struct ureg_src winsize = ureg_DECL_constant( ureg, winHeightConst );
+ struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst );
struct ureg_dst wpos_temp;
struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]];
@@ -794,12 +797,23 @@ emit_inverted_wpos( struct st_translate *t,
ureg_MOV( ureg, wpos_temp, wpos_input );
}
- /* SUB wpos_temp.y, winsize_const, wpos_input
- */
- ureg_SUB( ureg,
- ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
- winsize,
- wpos_input);
+ if (invert) {
+ /* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy
+ */
+ ureg_MAD( ureg,
+ ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
+ wpos_input,
+ ureg_scalar(wpostrans, 0),
+ ureg_scalar(wpostrans, 1));
+ } else {
+ /* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww
+ */
+ ureg_MAD( ureg,
+ ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
+ wpos_input,
+ ureg_scalar(wpostrans, 2),
+ ureg_scalar(wpostrans, 3));
+ }
/* Use wpos_temp as position input from here on:
*/
@@ -861,8 +875,7 @@ emit_wpos(struct st_context *st,
/* we invert after adjustment so that we avoid the MOV to temporary,
* and reuse the adjustment ADD instead */
- if (invert)
- emit_inverted_wpos(t, program);
+ emit_wpos_inversion(t, program, invert);
}