diff options
-rw-r--r-- | src/mesa/program/prog_statevars.c | 22 | ||||
-rw-r--r-- | src/mesa/program/prog_statevars.h | 1 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_mesa_to_tgsi.c | 43 |
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); } |