From 1e51d368eb5360378218217ff35731896f48512f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 14 Sep 2012 05:34:23 +0200 Subject: [PATCH] r300g: fix colormask with non-BGRA formats NOTE: This is a candidate for the stable branches. --- src/gallium/drivers/r300/r300_context.h | 14 +++++- src/gallium/drivers/r300/r300_emit.c | 8 +-- src/gallium/drivers/r300/r300_state.c | 88 +++++++++++++++++++++++---------- src/gallium/drivers/r300/r300_texture.c | 81 +++++++++++++++++++++++++++++- 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 6a06442..2c7b477 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 4c0daa6..1da6044 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 46a6bf6..b43f330 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 6901722..39cca78 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); } } -- 2.7.4