summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-09-23 22:56:50 +0200
committerMarek Olšák <maraeo@gmail.com>2010-09-24 02:57:36 +0200
commit9f35dcd24cb520af5e39501672a3324000cdbfce (patch)
tree936e3b8d8c79e868e6363b05dd452923acf04805
parent7d28ec8500fc08fafbdb3ae5443b32dd756eddd7 (diff)
r300g: fix the border color for every format other than PIPE_FORMAT_B8G8R8A8
TX_BORDER_COLOR should be formatted according to the texture format. Also the interaction with ARB_texture_swizzle should be fixed too. NOTE: This is a candidate for the 7.9 branch.
-rw-r--r--src/gallium/drivers/r300/r300_context.h1
-rw-r--r--src/gallium/drivers/r300/r300_state.c4
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c85
3 files changed, 84 insertions, 6 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 7f655dbfd2..8f4e2de02d 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -162,7 +162,6 @@ struct r300_sampler_state {
uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */
uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */
- uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */
/* Min/max LOD must be clamped to [0, last_level], thus
* it's dependent on a currently bound texture */
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index d6cded927a..ad3282a4e6 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -1169,7 +1169,6 @@ static void*
struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state);
boolean is_r500 = r300->screen->caps.is_r500;
int lod_bias;
- union util_color uc;
sampler->state = *state;
@@ -1226,9 +1225,6 @@ static void*
sampler->filter1 |= r500_anisotropy(state->max_anisotropy);
}
- util_pack_color(state->border_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
- sampler->border_color = uc.ui;
-
/* R500-specific fixups and optimizations */
if (r300->screen->caps.is_r500) {
sampler->filter1 |= R500_BORDER_FIX;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index f9a516825d..566a828871 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -567,6 +567,85 @@ static void r300_update_rs_block(struct r300_context *r300)
}
}
+static uint32_t r300_get_border_color(enum pipe_format format,
+ const unsigned char swizzle_view[4],
+ const float border[4])
+{
+ const struct util_format_description *desc;
+ unsigned char swizzle[4];
+ unsigned i;
+ float border_swizzled[4];
+ uint32_t r;
+
+ desc = util_format_description(format);
+
+ /* Combine the swizzles. */
+ for (i = 0; i < 4; i++) {
+ swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
+ desc->swizzle[swizzle_view[i]] : swizzle_view[i];
+ }
+
+ /* Apply swizzling. */
+ for (i = 0; i < 4; i++) {
+ switch (swizzle[i]) {
+ case UTIL_FORMAT_SWIZZLE_X:
+ border_swizzled[i] = border[0];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Y:
+ border_swizzled[i] = border[1];
+ break;
+ case UTIL_FORMAT_SWIZZLE_Z:
+ border_swizzled[i] = border[2];
+ break;
+ case UTIL_FORMAT_SWIZZLE_W:
+ border_swizzled[i] = border[3];
+ break;
+ case UTIL_FORMAT_SWIZZLE_0:
+ border_swizzled[i] = 0;
+ break;
+ default: /* 1, NONE */
+ border_swizzled[i] = 1;
+ }
+ }
+
+ /* We don't use util_pack_format because it does not handle the formats
+ * we want, e.g. R4G4B4A4 is non-existent in Gallium. */
+ switch (desc->channel[0].size) {
+ case 4:
+ r = ((float_to_ubyte(border_swizzled[0]) & 0xf0) >> 4) |
+ ((float_to_ubyte(border_swizzled[1]) & 0xf0) << 0) |
+ ((float_to_ubyte(border_swizzled[2]) & 0xf0) << 4) |
+ ((float_to_ubyte(border_swizzled[3]) & 0xf0) << 8);
+ break;
+
+ case 5:
+ if (desc->channel[1].size == 5) {
+ r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) |
+ ((float_to_ubyte(border_swizzled[1]) & 0xf8) << 2) |
+ ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 7) |
+ ((float_to_ubyte(border_swizzled[3]) & 0x80) << 8);
+ } else if (desc->channel[1].size == 6) {
+ r = ((float_to_ubyte(border_swizzled[0]) & 0xf8) >> 3) |
+ ((float_to_ubyte(border_swizzled[1]) & 0xfc) << 3) |
+ ((float_to_ubyte(border_swizzled[2]) & 0xf8) << 8);
+ } else {
+ assert(0);
+ }
+ break;
+
+ default:
+ /* I think the fat formats (16, 32) are specified
+ * as the 8-bit ones. I am not sure how compressed formats
+ * work here. */
+ r = ((float_to_ubyte(border_swizzled[0]) & 0xff) << 0) |
+ ((float_to_ubyte(border_swizzled[1]) & 0xff) << 8) |
+ ((float_to_ubyte(border_swizzled[2]) & 0xff) << 16) |
+ ((float_to_ubyte(border_swizzled[3]) & 0xff) << 24);
+ }
+
+ return r;
+}
+
static void r300_merge_textures_and_samplers(struct r300_context* r300)
{
struct r300_textures_state *state =
@@ -599,7 +678,11 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
texstate->format = view->format;
texstate->filter0 = sampler->filter0;
texstate->filter1 = sampler->filter1;
- texstate->border_color = sampler->border_color;
+
+ /* Set the border color. */
+ texstate->border_color =
+ r300_get_border_color(view->base.format, view->swizzle,
+ sampler->state.border_color);
/* determine min/max levels */
max_level = MIN3(sampler->max_lod + view->base.first_level,