From 35ffe94a340cf4e0ebe810a1d576113f96ea9dee Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Wed, 19 Oct 2011 16:45:58 +0200 Subject: [PATCH] mesa/st: Backport WPOS adjustment fixes from st_mesa_to_tgsi.c to st_glsl_to_tgsi.cpp. This is a trivial verbatim copy of the code from Christoph Bumiller's commit f986a6560f3ee9a79b89e9409e3a9ac52b53315c. Fixes fdo 39939 and 39942. --- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 134 +++++++++++++-------- 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 18e8a1db44e..35fd1ffc13a 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -4322,37 +4322,15 @@ compile_tgsi_instruction(struct st_translate *t, } /** - * Emit the TGSI instructions to adjust the WPOS pixel center convention - * Basically, add (adjX, adjY) to the fragment position. - */ -static void -emit_adjusted_wpos(struct st_translate *t, - const struct gl_program *program, - float adjX, float adjY) -{ - struct ureg_program *ureg = t->ureg; - struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg); - struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]]; - - /* Note that we bias X and Y and pass Z and W through unchanged. - * The shader might also use gl_FragCoord.w and .z. - */ - ureg_ADD(ureg, wpos_temp, wpos_input, - ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f)); - - t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp); -} - - -/** - * Emit the TGSI instructions for inverting the WPOS y coordinate. + * Emit the TGSI instructions for inverting and adjusting WPOS. * This code is unavoidable because it also depends on whether * a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM). */ static void -emit_wpos_inversion(struct st_translate *t, - const struct gl_program *program, - bool invert) +emit_wpos_adjustment( struct st_translate *t, + const struct gl_program *program, + boolean invert, + GLfloat adjX, GLfloat adjY[2]) { struct ureg_program *ureg = t->ureg; @@ -4371,35 +4349,55 @@ emit_wpos_inversion(struct st_translate *t, unsigned wposTransConst = _mesa_add_state_reference(program->Parameters, wposTransformState); - struct ureg_src wpostrans = ureg_DECL_constant(ureg, wposTransConst); - struct ureg_dst wpos_temp; + struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst ); + struct ureg_dst wpos_temp = ureg_DECL_temporary( ureg ); struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]]; - /* MOV wpos_temp, input[wpos] - */ - if (wpos_input.File == TGSI_FILE_TEMPORARY) - wpos_temp = ureg_dst(wpos_input); - else { - wpos_temp = ureg_DECL_temporary(ureg); - ureg_MOV(ureg, wpos_temp, wpos_input); + /* First, apply the coordinate shift: */ + if (adjX || adjY[0] || adjY[1]) { + if (adjY[0] != adjY[1]) { + /* Adjust the y coordinate by adjY[1] or adjY[0] respectively + * depending on whether inversion is actually going to be applied + * or not, which is determined by testing against the inversion + * state variable used below, which will be either +1 or -1. + */ + struct ureg_dst adj_temp = ureg_DECL_temporary(ureg); + + ureg_CMP(ureg, adj_temp, + ureg_scalar(wpostrans, invert ? 2 : 0), + ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f), + ureg_imm4f(ureg, adjX, adjY[1], 0.0f, 0.0f)); + ureg_ADD(ureg, wpos_temp, wpos_input, ureg_src(adj_temp)); + } else { + ureg_ADD(ureg, wpos_temp, wpos_input, + ureg_imm4f(ureg, adjX, adjY[0], 0.0f, 0.0f)); + } + wpos_input = ureg_src(wpos_temp); + } else { + /* MOV wpos_temp, input[wpos] + */ + ureg_MOV( ureg, wpos_temp, wpos_input ); } + /* Now the conditional y flip: STATE_FB_WPOS_Y_TRANSFORM.xy/zw will be + * inversion/identity, or the other way around if we're drawing to an FBO. + */ 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)); + 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)); + 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: @@ -4420,8 +4418,37 @@ emit_wpos(struct st_context *st, const struct gl_fragment_program *fp = (const struct gl_fragment_program *) program; struct pipe_screen *pscreen = st->pipe->screen; + GLfloat adjX = 0.0f; + GLfloat adjY[2] = { 0.0f, 0.0f }; boolean invert = FALSE; + /* Query the pixel center conventions supported by the pipe driver and set + * adjX, adjY to help out if it cannot handle the requested one internally. + * + * The bias of the y-coordinate depends on whether y-inversion takes place + * (adjY[1]) or not (adjY[0]), which is in turn dependent on whether we are + * drawing to an FBO (causes additional inversion), and whether the the pipe + * driver origin and the requested origin differ (the latter condition is + * stored in the 'invert' variable). + * + * For height = 100 (i = integer, h = half-integer, l = lower, u = upper): + * + * center shift only: + * i -> h: +0.5 + * h -> i: -0.5 + * + * inversion only: + * l,i -> u,i: ( 0.0 + 1.0) * -1 + 100 = 99 + * l,h -> u,h: ( 0.5 + 0.0) * -1 + 100 = 99.5 + * u,i -> l,i: (99.0 + 1.0) * -1 + 100 = 0 + * u,h -> l,h: (99.5 + 0.0) * -1 + 100 = 0.5 + * + * inversion and center shift: + * l,i -> u,h: ( 0.0 + 0.5) * -1 + 100 = 99.5 + * l,h -> u,i: ( 0.5 + 0.5) * -1 + 100 = 99 + * u,i -> l,h: (99.0 + 0.5) * -1 + 100 = 0.5 + * u,h -> l,i: (99.5 + 0.5) * -1 + 100 = 0 + */ if (fp->OriginUpperLeft) { /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { @@ -4449,12 +4476,17 @@ emit_wpos(struct st_context *st, if (fp->PixelCenterInteger) { /* Fragment shader wants pixel center integer */ - if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) + if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { /* the driver supports pixel center integer */ + adjY[1] = 1.0f; ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) + } + else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) { /* the driver supports pixel center half integer, need to bias X,Y */ - emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f); + adjX = -0.5f; + adjY[0] = -0.5f; + adjY[1] = 0.5f; + } else assert(0); } @@ -4465,8 +4497,8 @@ emit_wpos(struct st_context *st, } else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { /* the driver supports pixel center integer, need to bias X,Y */ + adjX = adjY[0] = adjY[1] = 0.5f; ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER); - emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f); } else assert(0); @@ -4474,7 +4506,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 */ - emit_wpos_inversion(t, program, invert); + emit_wpos_adjustment(t, program, invert, adjX, adjY); } /** -- 2.30.2