summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2011-04-05 06:21:26 +0200
committerMarek Olšák <[email protected]>2011-04-05 06:36:56 +0200
commitb3011ea60cc36a888da031ebac932d67473f4521 (patch)
treee858f95c29dfae18805140a6a731f0cf139c1788 /src
parent20141d9efdf674a3c7a13a75fabe533665d02cd0 (diff)
r300g: fix RG/LATC1_SNORM by doing UNORM->SNORM conversion in the shader
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r300/r300_fs.c37
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c7
-rw-r--r--src/gallium/drivers/r300/r300_texture.c45
-rw-r--r--src/gallium/drivers/r300/r300_texture.h4
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_code.h12
-rw-r--r--src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c54
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 &&