summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2012-09-14 05:34:23 +0200
committerMarek Olšák <[email protected]>2012-09-14 05:55:00 +0200
commit1e51d368eb5360378218217ff35731896f48512f (patch)
tree974a06b71793bd41ed9df43413e7e2db1c42a92b /src/gallium/drivers/r300
parentb33d7eaa5e77b5367584fe183c46f8c3d9a06760 (diff)
r300g: fix colormask with non-BGRA formats
NOTE: This is a candidate for the stable branches.
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/r300_context.h14
-rw-r--r--src/gallium/drivers/r300/r300_emit.c8
-rw-r--r--src/gallium/drivers/r300/r300_state.c88
-rw-r--r--src/gallium/drivers/r300/r300_texture.c81
4 files changed, 160 insertions, 31 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 6a064420603..2c7b477685a 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -41,6 +41,16 @@ struct r300_fragment_shader;
struct r300_vertex_shader;
struct r300_stencilref_context;
+enum colormask_swizzle {
+ COLORMASK_BGRA,
+ COLORMASK_RGBA,
+ COLORMASK_RRRR,
+ COLORMASK_AAAA,
+ COLORMASK_GRRG,
+ COLORMASK_ARRA,
+ COLORMASK_NUM_SWIZZLES
+};
+
struct r300_atom {
/* Name, for debugging. */
const char* name;
@@ -66,7 +76,7 @@ struct r300_aa_state {
struct r300_blend_state {
struct pipe_blend_state state;
- uint32_t cb_clamp[8];
+ uint32_t cb_clamp[COLORMASK_NUM_SWIZZLES][8];
uint32_t cb_noclamp[8];
uint32_t cb_no_readwrite[8];
};
@@ -320,6 +330,8 @@ struct r300_surface {
/* Whether the CBZB clear is allowed on the surface. */
boolean cbzb_allowed;
+
+ unsigned colormask_swizzle;
};
struct r300_texture_desc {
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 4c0daa6c56d..1da6044eb87 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -45,10 +45,12 @@ void r300_emit_blend_state(struct r300_context* r300,
CS_LOCALS(r300);
if (fb->nr_cbufs) {
- if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT)
+ if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT) {
WRITE_CS_TABLE(blend->cb_noclamp, size);
- else
- WRITE_CS_TABLE(blend->cb_clamp, size);
+ } else {
+ unsigned swz = r300_surface(fb->cbufs[0])->colormask_swizzle;
+ WRITE_CS_TABLE(blend->cb_clamp[swz], size);
+ }
} else {
WRITE_CS_TABLE(blend->cb_no_readwrite, size);
}
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 46a6bf669b7..b43f330af98 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -169,15 +169,52 @@ static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA
dstA == PIPE_BLENDFACTOR_ONE);
}
+/* The hardware colormask is clunky a must be swizzled depending on the format.
+ * This was figured out by trial-and-error. */
static unsigned bgra_cmask(unsigned mask)
{
- /* Gallium uses RGBA color ordering while R300 expects BGRA. */
-
return ((mask & PIPE_MASK_R) << 2) |
((mask & PIPE_MASK_B) >> 2) |
(mask & (PIPE_MASK_G | PIPE_MASK_A));
}
+static unsigned rgba_cmask(unsigned mask)
+{
+ return mask & PIPE_MASK_RGBA;
+}
+
+static unsigned rrrr_cmask(unsigned mask)
+{
+ return (mask & PIPE_MASK_R) |
+ ((mask & PIPE_MASK_R) << 1) |
+ ((mask & PIPE_MASK_R) << 2) |
+ ((mask & PIPE_MASK_R) << 3);
+}
+
+static unsigned aaaa_cmask(unsigned mask)
+{
+ return ((mask & PIPE_MASK_A) >> 3) |
+ ((mask & PIPE_MASK_A) >> 2) |
+ ((mask & PIPE_MASK_A) >> 1) |
+ (mask & PIPE_MASK_A);
+}
+
+static unsigned grrg_cmask(unsigned mask)
+{
+ return ((mask & PIPE_MASK_R) << 1) |
+ ((mask & PIPE_MASK_R) << 2) |
+ ((mask & PIPE_MASK_G) >> 1) |
+ ((mask & PIPE_MASK_G) << 2);
+}
+
+static unsigned arra_cmask(unsigned mask)
+{
+ return ((mask & PIPE_MASK_R) << 1) |
+ ((mask & PIPE_MASK_R) << 2) |
+ ((mask & PIPE_MASK_A) >> 3) |
+ (mask & PIPE_MASK_A);
+}
+
/* Create a new blend state based on the CSO blend state.
*
* This encompasses alpha blending, logic/raster ops, and blend dithering. */
@@ -190,9 +227,9 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
uint32_t blend_control_noclamp = 0; /* R300_RB3D_CBLEND: 0x4e04 */
uint32_t alpha_blend_control = 0; /* R300_RB3D_ABLEND: 0x4e08 */
uint32_t alpha_blend_control_noclamp = 0; /* R300_RB3D_ABLEND: 0x4e08 */
- uint32_t color_channel_mask = 0; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */
uint32_t rop = 0; /* R300_RB3D_ROPCNTL: 0x4e18 */
uint32_t dither = 0; /* R300_RB3D_DITHER_CTL: 0x4e50 */
+ int i;
CB_LOCALS;
blend->state = *state;
@@ -331,20 +368,6 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
(state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT;
}
- /* Color channel masks for all MRTs. */
- color_channel_mask = bgra_cmask(state->rt[0].colormask);
- if (r300screen->caps.is_r500 && state->independent_blend_enable) {
- if (state->rt[1].blend_enable) {
- color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4;
- }
- if (state->rt[2].blend_enable) {
- color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8;
- }
- if (state->rt[3].blend_enable) {
- color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12;
- }
- }
-
/* Neither fglrx nor classic r300 ever set this, regardless of dithering
* state. Since it's an optional implementation detail, we can leave it
* out and never dither.
@@ -358,14 +381,27 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
*/
/* Build a command buffer. */
- BEGIN_CB(blend->cb_clamp, 8);
- OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
- OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
- OUT_CB(blend_control);
- OUT_CB(alpha_blend_control);
- OUT_CB(color_channel_mask);
- OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
- END_CB;
+ {
+ unsigned (*func[COLORMASK_NUM_SWIZZLES])(unsigned) = {
+ bgra_cmask,
+ rgba_cmask,
+ rrrr_cmask,
+ aaaa_cmask,
+ grrg_cmask,
+ arra_cmask
+ };
+
+ for (i = 0; i < COLORMASK_NUM_SWIZZLES; i++) {
+ BEGIN_CB(blend->cb_clamp[i], 8);
+ OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
+ OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
+ OUT_CB(blend_control);
+ OUT_CB(alpha_blend_control);
+ OUT_CB(func[i](state->rt[0].colormask));
+ OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
+ END_CB;
+ }
+ }
/* Build a command buffer. */
BEGIN_CB(blend->cb_noclamp, 8);
@@ -373,7 +409,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
OUT_CB(blend_control_noclamp);
OUT_CB(alpha_blend_control_noclamp);
- OUT_CB(color_channel_mask);
+ OUT_CB(rgba_cmask(state->rt[0].colormask));
OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
END_CB;
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 6901722f6c1..39cca78ebce 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -704,10 +704,87 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
}
}
+static uint32_t r300_translate_colormask_swizzle(enum pipe_format format)
+{
+ switch (format) {
+ case PIPE_FORMAT_A8_UNORM:
+ case PIPE_FORMAT_A8_SNORM:
+ case PIPE_FORMAT_A16_UNORM:
+ case PIPE_FORMAT_A16_SNORM:
+ case PIPE_FORMAT_A16_FLOAT:
+ case PIPE_FORMAT_A32_FLOAT:
+ return COLORMASK_AAAA;
+
+ case PIPE_FORMAT_I8_UNORM:
+ case PIPE_FORMAT_I8_SNORM:
+ case PIPE_FORMAT_L8_UNORM:
+ case PIPE_FORMAT_L8_SNORM:
+ case PIPE_FORMAT_R8_UNORM:
+ case PIPE_FORMAT_R8_SNORM:
+ case PIPE_FORMAT_R32_FLOAT:
+ case PIPE_FORMAT_L32_FLOAT:
+ case PIPE_FORMAT_I32_FLOAT:
+ return COLORMASK_RRRR;
+
+ case PIPE_FORMAT_L8A8_SNORM:
+ case PIPE_FORMAT_L8A8_UNORM:
+ case PIPE_FORMAT_L16A16_UNORM:
+ case PIPE_FORMAT_L16A16_SNORM:
+ case PIPE_FORMAT_L16A16_FLOAT:
+ case PIPE_FORMAT_L32A32_FLOAT:
+ return COLORMASK_ARRA;
+
+ case PIPE_FORMAT_R8G8_SNORM:
+ case PIPE_FORMAT_R8G8_UNORM:
+ case PIPE_FORMAT_R16G16_UNORM:
+ case PIPE_FORMAT_R16G16_SNORM:
+ case PIPE_FORMAT_R16G16_FLOAT:
+ case PIPE_FORMAT_R32G32_FLOAT:
+ return COLORMASK_GRRG;
+
+ case PIPE_FORMAT_B5G6R5_UNORM:
+ case PIPE_FORMAT_B5G5R5A1_UNORM:
+ case PIPE_FORMAT_B5G5R5X1_UNORM:
+ case PIPE_FORMAT_B4G4R4A4_UNORM:
+ case PIPE_FORMAT_B4G4R4X4_UNORM:
+ case PIPE_FORMAT_B8G8R8A8_UNORM:
+ /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/
+ case PIPE_FORMAT_B8G8R8X8_UNORM:
+ /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/
+ case PIPE_FORMAT_B10G10R10A2_UNORM:
+ return COLORMASK_BGRA;
+
+ case PIPE_FORMAT_R8G8B8X8_UNORM:
+ /*case PIPE_FORMAT_R8G8B8X8_SNORM:*/
+ case PIPE_FORMAT_R8G8B8A8_UNORM:
+ case PIPE_FORMAT_R8G8B8A8_SNORM:
+ case PIPE_FORMAT_R10G10B10A2_UNORM:
+ case PIPE_FORMAT_R10G10B10X2_SNORM:
+ case PIPE_FORMAT_R16_UNORM:
+ case PIPE_FORMAT_R16G16B16A16_UNORM:
+ case PIPE_FORMAT_R16_SNORM:
+ case PIPE_FORMAT_R16G16B16A16_SNORM:
+ case PIPE_FORMAT_R16_FLOAT:
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_L16_UNORM:
+ case PIPE_FORMAT_L16_SNORM:
+ case PIPE_FORMAT_L16_FLOAT:
+ case PIPE_FORMAT_I16_UNORM:
+ case PIPE_FORMAT_I16_SNORM:
+ case PIPE_FORMAT_I16_FLOAT:
+ return COLORMASK_RGBA;
+
+ default:
+ return ~0; /* Unsupported. */
+ }
+}
+
boolean r300_is_colorbuffer_format_supported(enum pipe_format format)
{
return r300_translate_colorformat(format) != ~0 &&
- r300_translate_out_fmt(format) != ~0;
+ r300_translate_out_fmt(format) != ~0 &&
+ r300_translate_colormask_swizzle(format) != ~0;
}
boolean r300_is_zs_format_supported(enum pipe_format format)
@@ -827,6 +904,8 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
R300_COLOR_TILE(tex->tex.macrotile[level]) |
R300_COLOR_MICROTILE(tex->tex.microtile);
surf->format = r300_translate_out_fmt(surf->base.format);
+ surf->colormask_swizzle =
+ r300_translate_colormask_swizzle(surf->base.format);
}
}