diff options
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 37 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 45 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_code.h | 12 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c | 54 |
6 files changed, 123 insertions, 36 deletions
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 37fe6622cd7..e3a1bc4a0f4 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -22,6 +22,7 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -34,6 +35,7 @@ #include "r300_screen.h" #include "r300_fs.h" #include "r300_reg.h" +#include "r300_texture.h" #include "r300_tgsi_to_rc.h" #include "radeon_code.h" @@ -148,7 +150,6 @@ static void get_external_state( struct r300_textures_state *texstate = r300->textures_state.state; struct r300_rs_state *rs = r300->rs_state.state; unsigned i; - unsigned char *swizzle; state->frag_clamp = rs ? rs->rs.clamp_fragment_color : 0; @@ -161,27 +162,37 @@ static void get_external_state( continue; } - t = r300_resource(texstate->sampler_views[i]->base.texture); + t = r300_resource(v->base.texture); if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { state->unit[i].compare_mode_enabled = 1; - /* Pass depth texture swizzling to the compiler. */ - if (texstate->sampler_views[i]) { - swizzle = texstate->sampler_views[i]->swizzle; - - state->unit[i].depth_texture_swizzle = - RC_MAKE_SWIZZLE(swizzle[0], swizzle[1], - swizzle[2], swizzle[3]); - } else { - state->unit[i].depth_texture_swizzle = RC_SWIZZLE_XYZW; - } - /* Fortunately, no need to translate this. */ state->unit[i].texture_compare_func = s->state.compare_func; } state->unit[i].non_normalized_coords = !s->state.normalized_coords; + state->unit[i].convert_unorm_to_snorm = + v->base.format == PIPE_FORMAT_RGTC1_SNORM || + v->base.format == PIPE_FORMAT_LATC1_SNORM; + + /* Pass texture swizzling to the compiler, some lowering passes need it. */ + if (v->base.format == PIPE_FORMAT_RGTC1_SNORM || + v->base.format == PIPE_FORMAT_LATC1_SNORM) { + unsigned char swizzle[4]; + + util_format_combine_swizzles(swizzle, + util_format_description(v->base.format)->swizzle, + v->swizzle); + + state->unit[i].texture_swizzle = + RC_MAKE_SWIZZLE(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + } else if (state->unit[i].compare_mode_enabled) { + state->unit[i].texture_swizzle = + RC_MAKE_SWIZZLE(v->swizzle[0], v->swizzle[1], + v->swizzle[2], v->swizzle[3]); + } /* XXX this should probably take into account STR, not just S. */ if (t->tex.is_npot) { diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 50cde5528ef..02fc1219e95 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -650,8 +650,13 @@ static uint32_t r300_get_border_color(enum pipe_format format, if (util_format_is_compressed(format)) { switch (format) { case PIPE_FORMAT_RGTC1_SNORM: - case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_LATC1_SNORM: + border_swizzled[0] = border_swizzled[0] < 0 ? + border_swizzled[0]*0.5+1 : + border_swizzled[0]*0.5; + /* Pass through. */ + + case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_LATC1_UNORM: /* Add 1/32 to round the border color instead of truncating. */ /* The Y component is used for the border color. */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 62143808223..ea6d9824030 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -39,6 +39,18 @@ #include "pipe/p_screen.h" +void util_format_combine_swizzles(unsigned char *dst, + const unsigned char *swz1, + const unsigned char *swz2) +{ + unsigned i; + + for (i = 0; i < 4; i++) { + dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ? + swz1[swz2[i]] : swz2[i]; + } +} + unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, const unsigned char *swizzle_view, boolean dxtc_swizzle) @@ -61,10 +73,7 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, if (swizzle_view) { /* Combine two sets of swizzles. */ - for (i = 0; i < 4; i++) { - swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ? - swizzle_format[swizzle_view[i]] : swizzle_view[i]; - } + util_format_combine_swizzles(swizzle, swizzle_format, swizzle_view); } else { memcpy(swizzle, swizzle_format, 4); } @@ -171,17 +180,22 @@ uint32_t r300_translate_texformat(enum pipe_format format, } } - if (util_format_is_compressed(format) && - dxtc_swizzle && - format != PIPE_FORMAT_RGTC2_UNORM && - format != PIPE_FORMAT_RGTC2_SNORM && - format != PIPE_FORMAT_LATC2_UNORM && - format != PIPE_FORMAT_LATC2_SNORM) { - result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, - TRUE); - } else { - result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, - FALSE); + /* Add swizzling. */ + /* The RGTC1_SNORM and LATC1_SNORM swizzle is done in the shader. */ + if (format != PIPE_FORMAT_RGTC1_SNORM && + format != PIPE_FORMAT_LATC1_SNORM) { + if (util_format_is_compressed(format) && + dxtc_swizzle && + format != PIPE_FORMAT_RGTC2_UNORM && + format != PIPE_FORMAT_RGTC2_SNORM && + format != PIPE_FORMAT_LATC2_UNORM && + format != PIPE_FORMAT_LATC2_SNORM) { + result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, + TRUE); + } else { + result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, + FALSE); + } } /* S3TC formats. */ @@ -212,7 +226,6 @@ uint32_t r300_translate_texformat(enum pipe_format format, switch (format) { case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_SNORM: - result |= sign_bit[2]; case PIPE_FORMAT_LATC1_UNORM: case PIPE_FORMAT_RGTC1_UNORM: return R500_TX_FORMAT_ATI1N | result; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 158a387478f..4586bb2e4dc 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -35,6 +35,10 @@ struct r300_texture_desc; struct r300_resource; struct r300_screen; +void util_format_combine_swizzles(unsigned char *dst, + const unsigned char *swz1, + const unsigned char *swz2); + unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, const unsigned char *swizzle_view, boolean dxtc_swizzle); diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index 35360aa70f0..67e6acf8b10 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -132,10 +132,10 @@ typedef enum { struct r300_fragment_program_external_state { struct { /** - * If the sampler is used as a shadow sampler, - * this field contains swizzle depending on the depth texture mode. + * This field contains swizzle for some lowering passes + * (shadow comparison, unorm->snorm conversion) */ - unsigned depth_texture_swizzle:12; + unsigned texture_swizzle:12; /** * If the sampler is used as a shadow sampler, @@ -172,6 +172,12 @@ struct r300_fragment_program_external_state { * and right before texture fetch. The scaling factor is given by * RC_STATE_R300_TEXSCALE_FACTOR. */ unsigned clamp_and_scale_before_fetch : 1; + + /** + * Fetch RGTC1_SNORM or LATC1_SNORM as UNORM and convert UNORM -> SNORM + * in the shader. + */ + unsigned convert_unorm_to_snorm:1; } unit[16]; unsigned frag_clamp:1; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c index 97225808d4d..cef448ee4e1 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c @@ -48,7 +48,7 @@ static struct rc_src_register shadow_fail_value(struct r300_fragment_program_com } reg.Swizzle = combine_swizzles(reg.Swizzle, - compiler->state.unit[tmu].depth_texture_swizzle); + compiler->state.unit[tmu].texture_swizzle); return reg; } @@ -59,7 +59,7 @@ static struct rc_src_register shadow_pass_value(struct r300_fragment_program_com reg.File = RC_FILE_NONE; reg.Swizzle = combine_swizzles(RC_SWIZZLE_1111, - compiler->state.unit[tmu].depth_texture_swizzle); + compiler->state.unit[tmu].texture_swizzle); return reg; } @@ -256,7 +256,7 @@ int radeonTransformTEX( inst_cmp->U.I.SrcReg[0].Index = tmp_sum; inst_cmp->U.I.SrcReg[0].Swizzle = combine_swizzles(RC_SWIZZLE_WWWW, - compiler->state.unit[inst->U.I.TexSrcUnit].depth_texture_swizzle); + compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle); inst_cmp->U.I.SrcReg[pass] = shadow_pass_value(compiler, inst->U.I.TexSrcUnit); inst_cmp->U.I.SrcReg[fail] = shadow_fail_value(compiler, inst->U.I.TexSrcUnit); @@ -411,6 +411,7 @@ int radeonTransformTEX( inst->U.I.SrcReg[0].Index = temp; } + /* NPOT -> POT conversion for 3D textures. */ if (inst->U.I.Opcode != RC_OPCODE_KIL && compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch) { struct rc_instruction *inst_mov; @@ -440,6 +441,53 @@ int radeonTransformTEX( scale_texcoords(compiler, inst, RC_STATE_R300_TEXSCALE_FACTOR); } + /* Convert SNORM-encoded ATI1N sampled as UNORM to SNORM. + * Formula: dst = tex > 0.5 ? tex*2-2 : tex*2 + */ + if (inst->U.I.Opcode != RC_OPCODE_KIL && + compiler->state.unit[inst->U.I.TexSrcUnit].convert_unorm_to_snorm) { + unsigned two, two_swizzle; + struct rc_instruction *inst_mul, *inst_mad, *inst_cnd; + + two = rc_constants_add_immediate_scalar(&c->Program.Constants, 2.35, &two_swizzle); + + inst_mul = rc_insert_new_instruction(c, inst); + inst_mul->U.I.Opcode = RC_OPCODE_MUL; + inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mul->U.I.DstReg.Index = rc_find_free_temporary(c); + inst_mul->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst_mul->U.I.SrcReg[0].Index = rc_find_free_temporary(c); /* redirected TEX output */ + inst_mul->U.I.SrcReg[1].File = RC_FILE_CONSTANT; /* 2 */ + inst_mul->U.I.SrcReg[1].Index = two; + inst_mul->U.I.SrcReg[1].Swizzle = two_swizzle; + + inst_mad = rc_insert_new_instruction(c, inst_mul); + inst_mad->U.I.Opcode = RC_OPCODE_MAD; + inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mad->U.I.DstReg.Index = rc_find_free_temporary(c); + inst_mad->U.I.SrcReg[0] = inst_mul->U.I.SrcReg[0]; /* redirected TEX output */ + inst_mad->U.I.SrcReg[1] = inst_mul->U.I.SrcReg[1]; /* 2 */ + inst_mad->U.I.SrcReg[2] = inst_mul->U.I.SrcReg[1]; /* 2 */ + inst_mad->U.I.SrcReg[2].Negate = RC_MASK_XYZW; + + inst_cnd = rc_insert_new_instruction(c, inst_mad); + inst_cnd->U.I.Opcode = RC_OPCODE_CND; + inst_cnd->U.I.SaturateMode = inst->U.I.SaturateMode; + inst_cnd->U.I.DstReg = inst->U.I.DstReg; + inst_cnd->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst_cnd->U.I.SrcReg[0].Index = inst_mad->U.I.DstReg.Index; + inst_cnd->U.I.SrcReg[0].Swizzle = compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle; + inst_cnd->U.I.SrcReg[1].File = RC_FILE_TEMPORARY; + inst_cnd->U.I.SrcReg[1].Index = inst_mul->U.I.DstReg.Index; + inst_cnd->U.I.SrcReg[1].Swizzle = compiler->state.unit[inst->U.I.TexSrcUnit].texture_swizzle; + inst_cnd->U.I.SrcReg[2] = inst_mul->U.I.SrcReg[0]; /* redirected TEX output */ + + inst->U.I.SaturateMode = 0; + inst->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst->U.I.DstReg.Index = inst_mul->U.I.SrcReg[0].Index; + inst->U.I.DstReg.WriteMask = RC_MASK_XYZW; + } + /* Cannot write texture to output registers or with saturate (all chips), * or with masks (non-r500). */ if (inst->U.I.Opcode != RC_OPCODE_KIL && |