X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_state.c;h=8c49bfdddd12bac651ce046af1079b209dd65440;hb=ad019bf5c65fbc10505c84c43050b5299192ca03;hp=ab5c18158d1530223ab2166aa88536d7f3b24427;hpb=31714ea4d5a20285f398286fe45b53d0609926dd;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index ab5c18158d1..8c49bfdddd1 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -25,6 +25,7 @@ #include "util/u_framebuffer.h" #include "util/u_half.h" +#include "util/u_helpers.h" #include "util/u_math.h" #include "util/u_mm.h" #include "util/u_memory.h" @@ -169,15 +170,169 @@ static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA dstA == PIPE_BLENDFACTOR_ONE); } -static unsigned bgra_cmask(unsigned mask) +static unsigned blend_discard_conditionally(unsigned eqRGB, unsigned eqA, + unsigned dstRGB, unsigned dstA, + unsigned srcRGB, unsigned srcA) { - /* Gallium uses RGBA color ordering while R300 expects BGRA. */ + unsigned blend_control = 0; + /* Optimization: discard pixels which don't change the colorbuffer. + * + * The code below is non-trivial and some math is involved. + * + * Discarding pixels must be disabled when FP16 AA is enabled. + * This is a hardware bug. Also, this implementation wouldn't work + * with FP blending enabled and equation clamping disabled. + * + * Equations other than ADD are rarely used and therefore won't be + * optimized. */ + if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) && + (eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) { + /* ADD: X+Y + * REVERSE_SUBTRACT: Y-X + * + * The idea is: + * If X = src*srcFactor = 0 and Y = dst*dstFactor = 1, + * then CB will not be changed. + * + * Given the srcFactor and dstFactor variables, we can derive + * what src and dst should be equal to and discard appropriate + * pixels. + */ + if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) { + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0; + } else if (blend_discard_if_src_alpha_1(srcRGB, srcA, + dstRGB, dstA)) { + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1; + } else if (blend_discard_if_src_color_0(srcRGB, srcA, + dstRGB, dstA)) { + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0; + } else if (blend_discard_if_src_color_1(srcRGB, srcA, + dstRGB, dstA)) { + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1; + } else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA, + dstRGB, dstA)) { + blend_control |= + R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0; + } else if (blend_discard_if_src_alpha_color_1(srcRGB, srcA, + dstRGB, dstA)) { + blend_control |= + R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1; + } + } + return blend_control; +} + +/* 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) +{ 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); +} + +static unsigned blend_read_enable(unsigned eqRGB, unsigned eqA, + unsigned dstRGB, unsigned dstA, + unsigned srcRGB, unsigned srcA, + boolean src_alpha_optz) +{ + unsigned blend_control = 0; + + /* Optimization: some operations do not require the destination color. + * + * When SRC_ALPHA_SATURATE is used, colorbuffer reads must be enabled, + * otherwise blending gives incorrect results. It seems to be + * a hardware bug. */ + if (eqRGB == PIPE_BLEND_MIN || eqA == PIPE_BLEND_MIN || + eqRGB == PIPE_BLEND_MAX || eqA == PIPE_BLEND_MAX || + dstRGB != PIPE_BLENDFACTOR_ZERO || + dstA != PIPE_BLENDFACTOR_ZERO || + srcRGB == PIPE_BLENDFACTOR_DST_COLOR || + srcRGB == PIPE_BLENDFACTOR_DST_ALPHA || + srcRGB == PIPE_BLENDFACTOR_INV_DST_COLOR || + srcRGB == PIPE_BLENDFACTOR_INV_DST_ALPHA || + srcA == PIPE_BLENDFACTOR_DST_COLOR || + srcA == PIPE_BLENDFACTOR_DST_ALPHA || + srcA == PIPE_BLENDFACTOR_INV_DST_COLOR || + srcA == PIPE_BLENDFACTOR_INV_DST_ALPHA || + srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) { + /* Enable reading from the colorbuffer. */ + blend_control |= R300_READ_ENABLE; + + if (src_alpha_optz) { + /* Optimization: Depending on incoming pixels, we can + * conditionally disable the reading in hardware... */ + if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN && + eqRGB != PIPE_BLEND_MAX && eqA != PIPE_BLEND_MAX) { + /* Disable reading if SRC_ALPHA == 0. */ + if ((dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ZERO) && + (dstA == PIPE_BLENDFACTOR_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ZERO) && + (srcRGB != PIPE_BLENDFACTOR_DST_COLOR && + srcRGB != PIPE_BLENDFACTOR_DST_ALPHA && + srcRGB != PIPE_BLENDFACTOR_INV_DST_COLOR && + srcRGB != PIPE_BLENDFACTOR_INV_DST_ALPHA)) { + blend_control |= R500_SRC_ALPHA_0_NO_READ; + } + + /* Disable reading if SRC_ALPHA == 1. */ + if ((dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ZERO) && + (dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ZERO) && + (srcRGB != PIPE_BLENDFACTOR_DST_COLOR && + srcRGB != PIPE_BLENDFACTOR_DST_ALPHA && + srcRGB != PIPE_BLENDFACTOR_INV_DST_COLOR && + srcRGB != PIPE_BLENDFACTOR_INV_DST_ALPHA)) { + blend_control |= R500_SRC_ALPHA_1_NO_READ; + } + } + } + } + return blend_control; +} + /* Create a new blend state based on the CSO blend state. * * This encompasses alpha blending, logic/raster ops, and blend dithering. */ @@ -188,24 +343,52 @@ static void* r300_create_blend_state(struct pipe_context* pipe, struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); uint32_t blend_control = 0; /* R300_RB3D_CBLEND: 0x4e04 */ uint32_t blend_control_noclamp = 0; /* R300_RB3D_CBLEND: 0x4e04 */ + uint32_t blend_control_noalpha = 0; /* R300_RB3D_CBLEND: 0x4e04 */ + uint32_t blend_control_noalpha_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 alpha_blend_control_noalpha = 0; /* R300_RB3D_ABLEND: 0x4e08 */ + uint32_t alpha_blend_control_noalpha_noclamp = 0; /* R300_RB3D_ABLEND: 0x4e08 */ uint32_t rop = 0; /* R300_RB3D_ROPCNTL: 0x4e18 */ uint32_t dither = 0; /* R300_RB3D_DITHER_CTL: 0x4e50 */ + int i; + + const unsigned eqRGB = state->rt[0].rgb_func; + const unsigned srcRGB = state->rt[0].rgb_src_factor; + const unsigned dstRGB = state->rt[0].rgb_dst_factor; + + const unsigned eqA = state->rt[0].alpha_func; + const unsigned srcA = state->rt[0].alpha_src_factor; + const unsigned dstA = state->rt[0].alpha_dst_factor; + + unsigned srcRGBX = srcRGB; + unsigned dstRGBX = dstRGB; CB_LOCALS; blend->state = *state; - if (state->rt[0].blend_enable) - { - unsigned eqRGB = state->rt[0].rgb_func; - unsigned srcRGB = state->rt[0].rgb_src_factor; - unsigned dstRGB = state->rt[0].rgb_dst_factor; + /* force DST_ALPHA to ONE where we can */ + switch (srcRGBX) { + case PIPE_BLENDFACTOR_DST_ALPHA: + srcRGBX = PIPE_BLENDFACTOR_ONE; + break; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + srcRGBX = PIPE_BLENDFACTOR_ZERO; + break; + } - unsigned eqA = state->rt[0].alpha_func; - unsigned srcA = state->rt[0].alpha_src_factor; - unsigned dstA = state->rt[0].alpha_dst_factor; + switch (dstRGBX) { + case PIPE_BLENDFACTOR_DST_ALPHA: + dstRGBX = PIPE_BLENDFACTOR_ONE; + break; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + dstRGBX = PIPE_BLENDFACTOR_ZERO; + break; + } + + /* Get blending register values. */ + if (state->rt[0].blend_enable) { + unsigned blend_eq, blend_eq_noclamp; /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha, * this is just the crappy D3D naming */ @@ -213,115 +396,57 @@ static void* r300_create_blend_state(struct pipe_context* pipe, R300_ALPHA_BLEND_ENABLE | ( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) | ( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT); - blend_control |= - r300_translate_blend_function(eqRGB, TRUE); - blend_control_noclamp |= - r300_translate_blend_function(eqRGB, FALSE); - /* Optimization: some operations do not require the destination color. - * - * When SRC_ALPHA_SATURATE is used, colorbuffer reads must be enabled, - * otherwise blending gives incorrect results. It seems to be - * a hardware bug. */ - if (eqRGB == PIPE_BLEND_MIN || eqA == PIPE_BLEND_MIN || - eqRGB == PIPE_BLEND_MAX || eqA == PIPE_BLEND_MAX || - dstRGB != PIPE_BLENDFACTOR_ZERO || - dstA != PIPE_BLENDFACTOR_ZERO || - srcRGB == PIPE_BLENDFACTOR_DST_COLOR || - srcRGB == PIPE_BLENDFACTOR_DST_ALPHA || - srcRGB == PIPE_BLENDFACTOR_INV_DST_COLOR || - srcRGB == PIPE_BLENDFACTOR_INV_DST_ALPHA || - srcA == PIPE_BLENDFACTOR_DST_COLOR || - srcA == PIPE_BLENDFACTOR_DST_ALPHA || - srcA == PIPE_BLENDFACTOR_INV_DST_COLOR || - srcA == PIPE_BLENDFACTOR_INV_DST_ALPHA || - srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) { - /* Enable reading from the colorbuffer. */ - blend_control |= R300_READ_ENABLE; - blend_control_noclamp |= R300_READ_ENABLE; - - if (r300screen->caps.is_r500) { - /* Optimization: Depending on incoming pixels, we can - * conditionally disable the reading in hardware... */ - if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN && - eqRGB != PIPE_BLEND_MAX && eqA != PIPE_BLEND_MAX) { - /* Disable reading if SRC_ALPHA == 0. */ - if ((dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA || - dstRGB == PIPE_BLENDFACTOR_ZERO) && - (dstA == PIPE_BLENDFACTOR_SRC_COLOR || - dstA == PIPE_BLENDFACTOR_SRC_ALPHA || - dstA == PIPE_BLENDFACTOR_ZERO)) { - blend_control |= R500_SRC_ALPHA_0_NO_READ; - } - - /* Disable reading if SRC_ALPHA == 1. */ - if ((dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || - dstRGB == PIPE_BLENDFACTOR_ZERO) && - (dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR || - dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || - dstA == PIPE_BLENDFACTOR_ZERO)) { - blend_control |= R500_SRC_ALPHA_1_NO_READ; - } - } - } - } + blend_control_noalpha = blend_control_noalpha_noclamp = + R300_ALPHA_BLEND_ENABLE | + ( r300_translate_blend_factor(srcRGBX) << R300_SRC_BLEND_SHIFT) | + ( r300_translate_blend_factor(dstRGBX) << R300_DST_BLEND_SHIFT); + + blend_eq = r300_translate_blend_function(eqRGB, TRUE); + blend_eq_noclamp = r300_translate_blend_function(eqRGB, FALSE); + + blend_control |= blend_eq; + blend_control_noalpha |= blend_eq; + blend_control_noclamp |= blend_eq_noclamp; + blend_control_noalpha_noclamp |= blend_eq_noclamp; + + /* Optimization: some operations do not require the destination color. */ + blend_control |= blend_read_enable(eqRGB, eqA, dstRGB, dstA, + srcRGB, srcA, r300screen->caps.is_r500); + blend_control_noclamp |= blend_read_enable(eqRGB, eqA, dstRGB, dstA, + srcRGB, srcA, FALSE); + blend_control_noalpha |= blend_read_enable(eqRGB, eqA, dstRGBX, dstA, + srcRGBX, srcA, r300screen->caps.is_r500); + blend_control_noalpha_noclamp |= blend_read_enable(eqRGB, eqA, dstRGBX, dstA, + srcRGBX, srcA, FALSE); /* Optimization: discard pixels which don't change the colorbuffer. - * - * The code below is non-trivial and some math is involved. - * - * Discarding pixels must be disabled when FP16 AA is enabled. - * This is a hardware bug. Also, this implementation wouldn't work - * with FP blending enabled and equation clamping disabled. - * - * Equations other than ADD are rarely used and therefore won't be - * optimized. */ - if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) && - (eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) { - /* ADD: X+Y - * REVERSE_SUBTRACT: Y-X - * - * The idea is: - * If X = src*srcFactor = 0 and Y = dst*dstFactor = 1, - * then CB will not be changed. - * - * Given the srcFactor and dstFactor variables, we can derive - * what src and dst should be equal to and discard appropriate - * pixels. - */ - if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) { - blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0; - } else if (blend_discard_if_src_alpha_1(srcRGB, srcA, - dstRGB, dstA)) { - blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1; - } else if (blend_discard_if_src_color_0(srcRGB, srcA, - dstRGB, dstA)) { - blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0; - } else if (blend_discard_if_src_color_1(srcRGB, srcA, - dstRGB, dstA)) { - blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1; - } else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA, - dstRGB, dstA)) { - blend_control |= - R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0; - } else if (blend_discard_if_src_alpha_color_1(srcRGB, srcA, - dstRGB, dstA)) { - blend_control |= - R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1; - } - } + * It cannot be used with FP16 AA. */ + blend_control |= blend_discard_conditionally(eqRGB, eqA, dstRGB, dstA, + srcRGB, srcA); + blend_control_noalpha |= blend_discard_conditionally(eqRGB, eqA, dstRGBX, dstA, + srcRGBX, srcA); /* separate alpha */ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) { blend_control |= R300_SEPARATE_ALPHA_ENABLE; blend_control_noclamp |= R300_SEPARATE_ALPHA_ENABLE; + alpha_blend_control = alpha_blend_control_noclamp = (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) | (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT); - alpha_blend_control |= - r300_translate_blend_function(eqA, TRUE); - alpha_blend_control_noclamp |= - r300_translate_blend_function(eqA, FALSE); + alpha_blend_control |= r300_translate_blend_function(eqA, TRUE); + alpha_blend_control_noclamp |= r300_translate_blend_function(eqA, FALSE); + } + if (srcA != srcRGBX || dstA != dstRGBX || eqA != eqRGB) { + blend_control_noalpha |= R300_SEPARATE_ALPHA_ENABLE; + blend_control_noalpha_noclamp |= R300_SEPARATE_ALPHA_ENABLE; + + alpha_blend_control_noalpha = alpha_blend_control_noalpha_noclamp = + (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) | + (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT); + alpha_blend_control_noalpha |= r300_translate_blend_function(eqA, TRUE); + alpha_blend_control_noalpha_noclamp |= r300_translate_blend_function(eqA, FALSE); } } @@ -331,20 +456,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,22 +469,49 @@ static void* r300_create_blend_state(struct pipe_context* pipe, */ /* Build a command buffer. */ - BEGIN_CB(blend->cb_clamp, 8); + { + unsigned (*func[COLORMASK_NUM_SWIZZLES])(unsigned) = { + bgra_cmask, + rgba_cmask, + rrrr_cmask, + aaaa_cmask, + grrg_cmask, + arra_cmask, + bgra_cmask, + rgba_cmask + }; + + for (i = 0; i < COLORMASK_NUM_SWIZZLES; i++) { + boolean has_alpha = i != COLORMASK_RGBX && i != COLORMASK_BGRX; + + BEGIN_CB(blend->cb_clamp[i], 8); + OUT_CB_REG(R300_RB3D_ROPCNTL, rop); + OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3); + OUT_CB(has_alpha ? blend_control : blend_control_noalpha); + OUT_CB(has_alpha ? alpha_blend_control : alpha_blend_control_noalpha); + OUT_CB(func[i](state->rt[0].colormask)); + OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); + END_CB; + } + } + + /* Build a command buffer (for RGBA16F). */ + BEGIN_CB(blend->cb_noclamp, 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(blend_control_noclamp); + OUT_CB(alpha_blend_control_noclamp); + OUT_CB(rgba_cmask(state->rt[0].colormask)); OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); END_CB; - /* Build a command buffer. */ - BEGIN_CB(blend->cb_noclamp, 8); + /* Build a command buffer (for RGB16F). */ + BEGIN_CB(blend->cb_noclamp_noalpha, 8); OUT_CB_REG(R300_RB3D_ROPCNTL, rop); 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(blend_control_noalpha_noclamp); + OUT_CB(alpha_blend_control_noalpha_noclamp); + OUT_CB(rgba_cmask(state->rt[0].colormask)); OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); END_CB; @@ -395,8 +533,27 @@ static void r300_bind_blend_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); + struct r300_blend_state *blend = (struct r300_blend_state*)state; + boolean last_alpha_to_one = r300->alpha_to_one; + boolean last_alpha_to_coverage = r300->alpha_to_coverage; UPDATE_STATE(state, r300->blend_state); + + if (!blend) + return; + + r300->alpha_to_one = blend->state.alpha_to_one; + r300->alpha_to_coverage = blend->state.alpha_to_coverage; + + if (r300->alpha_to_one != last_alpha_to_one && r300->msaa_enable && + r300->fs_status == FRAGMENT_SHADER_VALID) { + r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY; + } + + if (r300->alpha_to_coverage != last_alpha_to_coverage && + r300->msaa_enable) { + r300_mark_atom_dirty(r300, &r300->dsa_state); + } } /* Free blend state. */ @@ -422,15 +579,17 @@ static void r300_set_blend_color(struct pipe_context* pipe, struct r300_blend_color_state *state = (struct r300_blend_color_state*)r300->blend_color_state.state; struct pipe_blend_color c; - enum pipe_format format = fb->nr_cbufs ? fb->cbufs[0]->format : 0; + struct pipe_surface *cb; + float tmp; CB_LOCALS; state->state = *color; /* Save it, so that we can reuse it in set_fb_state */ c = *color; + cb = fb->nr_cbufs ? r300_get_nonnull_cb(fb, 0) : NULL; /* The blend color is dependent on the colorbuffer format. */ - if (fb->nr_cbufs) { - switch (format) { + if (cb) { + switch (cb->format) { case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_L8_UNORM: case PIPE_FORMAT_I8_UNORM: @@ -446,9 +605,17 @@ static void r300_set_blend_color(struct pipe_context* pipe, break; case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_R8A8_UNORM: c.color[2] = c.color[3]; break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: + tmp = c.color[0]; + c.color[0] = c.color[2]; + c.color[2] = tmp; + break; + default:; } } @@ -457,8 +624,9 @@ static void r300_set_blend_color(struct pipe_context* pipe, BEGIN_CB(state->cb, 3); OUT_CB_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); - switch (format) { + switch (cb ? cb->format : 0) { case PIPE_FORMAT_R16G16B16A16_FLOAT: + case PIPE_FORMAT_R16G16B16X16_FLOAT: OUT_CB(util_float_to_half(c.color[2]) | (util_float_to_half(c.color[3]) << 16)); OUT_CB(util_float_to_half(c.color[0]) | @@ -478,7 +646,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, util_pack_color(c.color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); BEGIN_CB(state->cb, 2); - OUT_CB_REG(R300_RB3D_BLEND_COLOR, uc.ui); + OUT_CB_REG(R300_RB3D_BLEND_COLOR, uc.ui[0]); END_CB; } @@ -508,49 +676,42 @@ static void r300_set_clip_state(struct pipe_context* pipe, } } -static void -r300_set_sample_mask(struct pipe_context *pipe, - unsigned sample_mask) -{ -} - - /* Create a new depth, stencil, and alpha state based on the CSO dsa state. * * This contains the depth buffer, stencil buffer, alpha test, and such. * On the Radeon, depth and stencil buffer setup are intertwined, which is * the reason for some of the strange-looking assignments across registers. */ -static void* - r300_create_dsa_state(struct pipe_context* pipe, - const struct pipe_depth_stencil_alpha_state* state) +static void* r300_create_dsa_state(struct pipe_context* pipe, + const struct pipe_depth_stencil_alpha_state* state) { - struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps; + boolean is_r500 = r300_screen(pipe->screen)->caps.is_r500; struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state); CB_LOCALS; + uint32_t alpha_value_fp16 = 0; + uint32_t z_buffer_control = 0; + uint32_t z_stencil_control = 0; + uint32_t stencil_ref_mask = 0; + uint32_t stencil_ref_bf = 0; dsa->dsa = *state; /* Depth test setup. - separate write mask depth for decomp flush */ if (state->depth.writemask) { - dsa->z_buffer_control |= R300_Z_WRITE_ENABLE; + z_buffer_control |= R300_Z_WRITE_ENABLE; } if (state->depth.enabled) { - dsa->z_buffer_control |= R300_Z_ENABLE; + z_buffer_control |= R300_Z_ENABLE; - dsa->z_stencil_control |= + z_stencil_control |= (r300_translate_depth_stencil_function(state->depth.func) << R300_Z_FUNC_SHIFT); - } else { - /* We must enable depth test, otherwise occlusion queries won't work. */ - dsa->z_buffer_control |= R300_Z_ENABLE; - dsa->z_stencil_control |= R300_ZS_ALWAYS; } /* Stencil buffer setup. */ if (state->stencil[0].enabled) { - dsa->z_buffer_control |= R300_STENCIL_ENABLE; - dsa->z_stencil_control |= + z_buffer_control |= R300_STENCIL_ENABLE; + z_stencil_control |= (r300_translate_depth_stencil_function(state->stencil[0].func) << R300_S_FRONT_FUNC_SHIFT) | (r300_translate_stencil_op(state->stencil[0].fail_op) << @@ -560,15 +721,15 @@ static void* (r300_translate_stencil_op(state->stencil[0].zfail_op) << R300_S_FRONT_ZFAIL_OP_SHIFT); - dsa->stencil_ref_mask = + stencil_ref_mask = (state->stencil[0].valuemask << R300_STENCILMASK_SHIFT) | (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT); if (state->stencil[1].enabled) { dsa->two_sided = TRUE; - dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK; - dsa->z_stencil_control |= + z_buffer_control |= R300_STENCIL_FRONT_BACK; + z_stencil_control |= (r300_translate_depth_stencil_function(state->stencil[1].func) << R300_S_BACK_FUNC_SHIFT) | (r300_translate_stencil_op(state->stencil[1].fail_op) << @@ -578,12 +739,12 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - dsa->stencil_ref_bf = + stencil_ref_bf = (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT); - if (caps->is_r500) { - dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; + if (is_r500) { + z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; } else { dsa->two_sided_stencil_ref = (state->stencil[0].valuemask != state->stencil[1].valuemask || @@ -599,55 +760,25 @@ static void* R300_FG_ALPHA_FUNC_ENABLE; dsa->alpha_function |= float_to_ubyte(state->alpha.ref_value); - dsa->alpha_value = util_float_to_half(state->alpha.ref_value); - - if (caps->is_r500) { - dsa->alpha_function_fp16 = dsa->alpha_function | - R500_FG_ALPHA_FUNC_FP16_ENABLE; - dsa->alpha_function |= R500_FG_ALPHA_FUNC_8BIT; - } + alpha_value_fp16 = util_float_to_half(state->alpha.ref_value); } - BEGIN_CB(&dsa->cb_begin, 10); - OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); + BEGIN_CB(&dsa->cb_begin, 8); OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); - OUT_CB(dsa->z_buffer_control); - OUT_CB(dsa->z_stencil_control); - OUT_CB(dsa->stencil_ref_mask); - OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); - OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value); + OUT_CB(z_buffer_control); + OUT_CB(z_stencil_control); + OUT_CB(stencil_ref_mask); + OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, stencil_ref_bf); + OUT_CB_REG(R500_FG_ALPHA_VALUE, alpha_value_fp16); END_CB; - BEGIN_CB(&dsa->cb_begin_fp16, 10); - OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function_fp16); + BEGIN_CB(dsa->cb_zb_no_readwrite, 8); OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); - OUT_CB(dsa->z_buffer_control); - OUT_CB(dsa->z_stencil_control); - OUT_CB(dsa->stencil_ref_mask); - OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); - OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value); - END_CB; - - /* We must enable depth test, otherwise occlusion queries won't work. - * We setup a dummy zbuffer to silent the CS checker, see emit_fb_state. */ - BEGIN_CB(dsa->cb_zb_no_readwrite, 10); - OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); - OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); - OUT_CB(R300_Z_ENABLE); - OUT_CB(R300_ZS_ALWAYS); OUT_CB(0); - OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0); - OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value); - END_CB; - - BEGIN_CB(dsa->cb_fp16_zb_no_readwrite, 10); - OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function_fp16); - OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); - OUT_CB(R300_Z_ENABLE); - OUT_CB(R300_ZS_ALWAYS); + OUT_CB(0); OUT_CB(0); OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0); - OUT_CB_REG(R500_FG_ALPHA_VALUE, dsa->alpha_value); + OUT_CB_REG(R500_FG_ALPHA_VALUE, alpha_value_fp16); END_CB; return (void*)dsa; @@ -703,41 +834,6 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, r300_mark_atom_dirty(r300, &r300->dsa_state); } -static void r300_tex_set_tiling_flags(struct r300_context *r300, - struct r300_resource *tex, - unsigned level) -{ - /* Check if the macrotile flag needs to be changed. - * Skip changing the flags otherwise. */ - if (tex->tex.macrotile[tex->surface_level] != - tex->tex.macrotile[level]) { - r300->rws->buffer_set_tiling(tex->buf, r300->cs, - tex->tex.microtile, tex->tex.macrotile[level], - tex->tex.stride_in_bytes[0]); - - tex->surface_level = level; - } -} - -/* This switcheroo is needed just because of goddamned MACRO_SWITCH. */ -static void r300_fb_set_tiling_flags(struct r300_context *r300, - const struct pipe_framebuffer_state *state) -{ - unsigned i; - - /* Set tiling flags for new surfaces. */ - for (i = 0; i < state->nr_cbufs; i++) { - r300_tex_set_tiling_flags(r300, - r300_resource(state->cbufs[i]->texture), - state->cbufs[i]->u.tex.level); - } - if (state->zsbuf) { - r300_tex_set_tiling_flags(r300, - r300_resource(state->zsbuf->texture), - state->zsbuf->u.tex.level); - } -} - static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, const char *binding) { @@ -789,14 +885,19 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, /* Now compute the fb_state atom size. */ r300->fb_state.size = 2 + (8 * state->nr_cbufs); - if (r300->cbzb_clear) { + if (r300->cbzb_clear) r300->fb_state.size += 10; - } else if (state->zsbuf) { + else if (state->zsbuf) { r300->fb_state.size += 10; if (r300->hyperz_enabled) r300->fb_state.size += 8; - } else if (state->nr_cbufs) { - r300->fb_state.size += 10; + } + + if (r300->cmask_in_use) { + r300->fb_state.size += 6; + if (r300->screen->caps.is_r500 && r300->screen->info.drm_minor >= 29) { + r300->fb_state.size += 3; + } } /* The size of the rest of atoms stays the same. */ @@ -808,7 +909,7 @@ r300_set_framebuffer_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; - struct pipe_framebuffer_state *old_state = r300->fb_state.state; + struct pipe_framebuffer_state *current_state = r300->fb_state.state; unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; boolean unlock_zbuffer = FALSE; @@ -827,17 +928,17 @@ r300_set_framebuffer_state(struct pipe_context* pipe, return; } - if (old_state->zsbuf && r300->zmask_in_use && !r300->locked_zbuffer) { + if (current_state->zsbuf && r300->zmask_in_use && !r300->locked_zbuffer) { /* There is a zmask in use, what are we gonna do? */ if (state->zsbuf) { - if (!pipe_surface_equal(old_state->zsbuf, state->zsbuf)) { + if (!pipe_surface_equal(current_state->zsbuf, state->zsbuf)) { /* Decompress the currently bound zbuffer before we bind another one. */ r300_decompress_zmask(r300); r300->hiz_in_use = FALSE; } } else { /* We don't bind another zbuffer, so lock the current one. */ - pipe_surface_reference(&r300->locked_zbuffer, old_state->zsbuf); + pipe_surface_reference(&r300->locked_zbuffer, current_state->zsbuf); } } else if (r300->locked_zbuffer) { /* We have a locked zbuffer now, what are we gonna do? */ @@ -855,23 +956,28 @@ r300_set_framebuffer_state(struct pipe_context* pipe, } assert(state->zsbuf || (r300->locked_zbuffer && !unlock_zbuffer) || !r300->zmask_in_use); - /* Need to reset clamping or colormask. */ - r300_mark_atom_dirty(r300, &r300->blend_state); - /* If zsbuf is set from NULL to non-NULL or vice versa.. */ - if (!!old_state->zsbuf != !!state->zsbuf) { + if (!!current_state->zsbuf != !!state->zsbuf) { r300_mark_atom_dirty(r300, &r300->dsa_state); } - if (r300->screen->info.drm_minor < 12) { - /* The tiling flags are dependent on the surface miplevel, unfortunately. - * This workarounds a bad design decision in old kernels which were - * rewriting tile fields in registers. */ - r300_fb_set_tiling_flags(r300, state); - } - util_copy_framebuffer_state(r300->fb_state.state, state); + /* Remove trailing NULL colorbuffers. */ + while (current_state->nr_cbufs && !current_state->cbufs[current_state->nr_cbufs-1]) + current_state->nr_cbufs--; + + /* Set whether CMASK can be used. */ + r300->cmask_in_use = + state->nr_cbufs == 1 && state->cbufs[0] && + r300->screen->cmask_resource == state->cbufs[0]->texture; + + /* Need to reset clamping or colormask. */ + r300_mark_atom_dirty(r300, &r300->blend_state); + + /* Re-swizzle the blend color. */ + r300_set_blend_color(pipe, &((struct r300_blend_color_state*)r300->blend_color_state.state)->state); + if (unlock_zbuffer) { pipe_surface_reference(&r300->locked_zbuffer, NULL); } @@ -897,22 +1003,22 @@ r300_set_framebuffer_state(struct pipe_context* pipe, } } - /* Set up AA config. */ - if (state->nr_cbufs && state->cbufs[0]->texture->nr_samples > 1) { - aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE; + r300->num_samples = util_framebuffer_get_num_samples(state); - switch (state->cbufs[0]->texture->nr_samples) { + /* Set up AA config. */ + if (r300->num_samples > 1) { + switch (r300->num_samples) { case 2: - aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2; - break; - case 3: - aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3; + aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE | + R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2; break; case 4: - aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4; + aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE | + R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4; break; case 6: - aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6; + aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE | + R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6; break; } } else { @@ -922,7 +1028,8 @@ r300_set_framebuffer_state(struct pipe_context* pipe, if (DBG_ON(r300, DBG_FB)) { fprintf(stderr, "r300: set_framebuffer_state:\n"); for (i = 0; i < state->nr_cbufs; i++) { - r300_print_fb_surf_info(state->cbufs[i], i, "CB"); + if (state->cbufs[i]) + r300_print_fb_surf_info(state->cbufs[i], i, "CB"); } if (state->zsbuf) { r300_print_fb_surf_info(state->zsbuf, 0, "ZB"); @@ -972,7 +1079,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) struct r300_context* r300 = r300_context(pipe); struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; - if (fs == NULL) { + if (!fs) { r300->fs.state = NULL; return; } @@ -1003,7 +1110,6 @@ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) static void r300_set_polygon_stipple(struct pipe_context* pipe, const struct pipe_poly_stipple* state) { - /* XXX no idea how to set this up, but not terribly important */ } /* Create a new rasterizer state based on the CSO rasterizer state. @@ -1035,8 +1141,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */ float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */ float point_texcoord_top = 0; /* R300_GA_POINT_T1: 0x420c */ - boolean vclamp = state->clamp_vertex_color || - !r300_context(pipe)->screen->caps.is_r500; + boolean vclamp = !r300_context(pipe)->screen->caps.is_r500; CB_LOCALS; /* Copy rasterizer state. */ @@ -1236,6 +1341,9 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_rs_state* rs = (struct r300_rs_state*)state; int last_sprite_coord_enable = r300->sprite_coord_enable; boolean last_two_sided_color = r300->two_sided_color; + boolean last_msaa_enable = r300->msaa_enable; + boolean last_flatshade = r300->flatshade; + boolean last_clip_halfz = r300->clip_halfz; if (r300->draw && rs) { draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state); @@ -1245,19 +1353,41 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) r300->polygon_offset_enabled = rs->polygon_offset_enable; r300->sprite_coord_enable = rs->rs.sprite_coord_enable; r300->two_sided_color = rs->rs.light_twoside; + r300->msaa_enable = rs->rs.multisample; + r300->flatshade = rs->rs.flatshade; + r300->clip_halfz = rs->rs.clip_halfz; } else { r300->polygon_offset_enabled = FALSE; r300->sprite_coord_enable = 0; r300->two_sided_color = FALSE; + r300->msaa_enable = FALSE; + r300->flatshade = FALSE; + r300->clip_halfz = FALSE; } UPDATE_STATE(state, r300->rs_state); r300->rs_state.size = RS_STATE_MAIN_SIZE + (r300->polygon_offset_enabled ? 5 : 0); if (last_sprite_coord_enable != r300->sprite_coord_enable || - last_two_sided_color != r300->two_sided_color) { + last_two_sided_color != r300->two_sided_color || + last_flatshade != r300->flatshade) { r300_mark_atom_dirty(r300, &r300->rs_block_state); } + + if (last_msaa_enable != r300->msaa_enable) { + if (r300->alpha_to_coverage) { + r300_mark_atom_dirty(r300, &r300->dsa_state); + } + + if (r300->alpha_to_one && + r300->fs_status == FRAGMENT_SHADER_VALID) { + r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY; + } + } + + if (r300->screen->caps.has_tcl && last_clip_halfz != r300->clip_halfz) { + r300_mark_atom_dirty(r300, &r300->vs_state); + } } /* Free rasterizer state. */ @@ -1339,7 +1469,8 @@ static void* } static void r300_bind_sampler_states(struct pipe_context* pipe, - unsigned count, + enum pipe_shader_type shader, + unsigned start, unsigned count, void** states) { struct r300_context* r300 = r300_context(pipe); @@ -1347,9 +1478,13 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, (struct r300_textures_state*)r300->textures_state.state; unsigned tex_units = r300->screen->caps.num_tex_units; - if (count > tex_units) { - return; - } + assert(start == 0); + + if (shader != PIPE_SHADER_FRAGMENT) + return; + + if (count > tex_units) + return; memcpy(state->sampler_states, states, sizeof(void*) * count); state->sampler_state_count = count; @@ -1357,12 +1492,6 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, r300_mark_atom_dirty(r300, &r300->textures_state); } -static void r300_lacks_vertex_textures(struct pipe_context* pipe, - unsigned count, - void** states) -{ -} - static void r300_delete_sampler_state(struct pipe_context* pipe, void* state) { FREE(state); @@ -1393,9 +1522,10 @@ static uint32_t r300_assign_texture_cache_region(unsigned index, unsigned num) return R300_TX_CACHE(num + index); } -static void r300_set_fragment_sampler_views(struct pipe_context* pipe, - unsigned count, - struct pipe_sampler_view** views) +static void r300_set_sampler_views(struct pipe_context* pipe, + enum pipe_shader_type shader, + unsigned start, unsigned count, + struct pipe_sampler_view** views) { struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = @@ -1405,6 +1535,11 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, unsigned tex_units = r300->screen->caps.num_tex_units; boolean dirty_tex = FALSE; + if (shader != PIPE_SHADER_FRAGMENT) + return; + + assert(start == 0); /* non-zero not handled yet */ + if (count > tex_units) { return; } @@ -1527,8 +1662,20 @@ r300_sampler_view_destroy(struct pipe_context *pipe, FREE(view); } -static void r300_set_scissor_state(struct pipe_context* pipe, - const struct pipe_scissor_state* state) +static void r300_set_sample_mask(struct pipe_context *pipe, + unsigned mask) +{ + struct r300_context* r300 = r300_context(pipe); + + *((unsigned*)r300->sample_mask.state) = mask; + + r300_mark_atom_dirty(r300, &r300->sample_mask); +} + +static void r300_set_scissor_states(struct pipe_context* pipe, + unsigned start_slot, + unsigned num_scissors, + const struct pipe_scissor_state* state) { struct r300_context* r300 = r300_context(pipe); @@ -1538,8 +1685,10 @@ static void r300_set_scissor_state(struct pipe_context* pipe, r300_mark_atom_dirty(r300, &r300->scissor_state); } -static void r300_set_viewport_state(struct pipe_context* pipe, - const struct pipe_viewport_state* state) +static void r300_set_viewport_states(struct pipe_context* pipe, + unsigned start_slot, + unsigned num_viewports, + const struct pipe_viewport_state* state) { struct r300_context* r300 = r300_context(pipe); struct r300_viewport_state* viewport = @@ -1548,7 +1697,7 @@ static void r300_set_viewport_state(struct pipe_context* pipe, r300->viewport = *state; if (r300->draw) { - draw_set_viewport_state(r300->draw, state); + draw_set_viewport_states(r300->draw, start_slot, num_viewports, state); viewport->vte_control = R300_VTX_XY_FMT | R300_VTX_Z_FMT; return; } @@ -1588,33 +1737,54 @@ static void r300_set_viewport_state(struct pipe_context* pipe, } } -static void r300_set_vertex_buffers(struct pipe_context* pipe, - unsigned count, +static void r300_set_vertex_buffers_hwtcl(struct pipe_context* pipe, + unsigned start_slot, unsigned count, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - struct pipe_vertex_buffer dummy_vb = {0}; + + util_set_vertex_buffers_count(r300->vertex_buffer, + &r300->nr_vertex_buffers, + buffers, start_slot, count); /* There must be at least one vertex buffer set, otherwise it locks up. */ - if (!count) { - dummy_vb.buffer = r300->dummy_vb; - buffers = &dummy_vb; - count = 1; + if (!r300->nr_vertex_buffers) { + util_set_vertex_buffers_count(r300->vertex_buffer, + &r300->nr_vertex_buffers, + &r300->dummy_vb, 0, 1); } - if (r300->screen->caps.has_tcl) { - u_vbuf_set_vertex_buffers(r300->vbuf_mgr, count, buffers); - r300->vertex_arrays_dirty = TRUE; - } else { - util_copy_vertex_buffers(r300->swtcl_vertex_buffer, - &r300->swtcl_nr_vertex_buffers, - buffers, count); - draw_set_vertex_buffers(r300->draw, count, buffers); + r300->vertex_arrays_dirty = TRUE; +} + +static void r300_set_vertex_buffers_swtcl(struct pipe_context* pipe, + unsigned start_slot, unsigned count, + const struct pipe_vertex_buffer* buffers) +{ + struct r300_context* r300 = r300_context(pipe); + unsigned i; + + util_set_vertex_buffers_count(r300->vertex_buffer, + &r300->nr_vertex_buffers, + buffers, start_slot, count); + draw_set_vertex_buffers(r300->draw, start_slot, count, buffers); + + if (!buffers) + return; + + for (i = 0; i < count; i++) { + if (buffers[i].user_buffer) { + draw_set_mapped_vertex_buffer(r300->draw, start_slot + i, + buffers[i].user_buffer, ~0); + } else if (buffers[i].buffer) { + draw_set_mapped_vertex_buffer(r300->draw, start_slot + i, + r300_resource(buffers[i].buffer)->malloced_buffer, ~0); + } } } -static void r300_set_index_buffer(struct pipe_context* pipe, - const struct pipe_index_buffer *ib) +static void r300_set_index_buffer_hwtcl(struct pipe_context* pipe, + const struct pipe_index_buffer *ib) { struct r300_context* r300 = r300_context(pipe); @@ -1624,9 +1794,23 @@ static void r300_set_index_buffer(struct pipe_context* pipe, } else { pipe_resource_reference(&r300->index_buffer.buffer, NULL); } +} + +static void r300_set_index_buffer_swtcl(struct pipe_context* pipe, + const struct pipe_index_buffer *ib) +{ + struct r300_context* r300 = r300_context(pipe); - if (!r300->screen->caps.has_tcl) { - draw_set_index_buffer(r300->draw, ib); + if (ib) { + const void *buf = NULL; + if (ib->user_buffer) { + buf = ib->user_buffer; + } else if (ib->buffer) { + buf = r300_resource(ib->buffer)->malloced_buffer; + } + draw_set_indexes(r300->draw, + (const ubyte *) buf + ib->offset, + ib->index_size, ~0); } } @@ -1678,7 +1862,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { - struct r300_context *r300 = r300_context(pipe); struct r300_vertex_element_state *velems; unsigned i; struct pipe_vertex_element dummy_attrib = {0}; @@ -1699,11 +1882,9 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, return NULL; velems->count = count; + memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); if (r300_screen(pipe->screen)->caps.has_tcl) { - velems->vmgr_elements = - u_vbuf_create_vertex_elements(r300->vbuf_mgr, count, attribs, - velems->velem); /* Setup PSC. * The unused components will be replaced by (..., 0, 1). */ r300_vertex_psc(velems); @@ -1713,8 +1894,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, align(util_format_get_blocksize(velems->velem[i].src_format), 4); velems->vertex_size_dwords += velems->format_size[i] / 4; } - } else { - memcpy(velems->velem, attribs, count * sizeof(struct pipe_vertex_element)); } return velems; @@ -1726,15 +1905,13 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, struct r300_context *r300 = r300_context(pipe); struct r300_vertex_element_state *velems = state; - if (velems == NULL) { + if (!velems) { return; } r300->velems = velems; - if (r300->screen->caps.has_tcl) { - u_vbuf_bind_vertex_elements(r300->vbuf_mgr, state, velems->vmgr_elements); - } else { + if (r300->draw) { draw_set_vertex_elements(r300->draw, velems->count, velems->velem); return; } @@ -1746,12 +1923,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) { - struct r300_context *r300 = r300_context(pipe); - struct r300_vertex_element_state *velems = state; - - if (r300->screen->caps.has_tcl) { - u_vbuf_destroy_vertex_elements(r300->vbuf_mgr, velems->vmgr_elements); - } FREE(state); } @@ -1780,7 +1951,7 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) struct r300_context* r300 = r300_context(pipe); struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - if (vs == NULL) { + if (!vs) { r300->vs_state.state = NULL; return; } @@ -1821,8 +1992,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) if (r300->screen->caps.has_tcl) { rc_constants_destroy(&vs->code.constants); - if (vs->code.constants_remap_table) - FREE(vs->code.constants_remap_table); + FREE(vs->code.constants_remap_table); } else { draw_delete_vertex_shader(r300->draw, (struct draw_vertex_shader*)vs->draw_vs); @@ -1834,13 +2004,15 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) static void r300_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_resource *buf) + const struct pipe_constant_buffer *cb) { struct r300_context* r300 = r300_context(pipe); struct r300_constant_buffer *cbuf; - struct r300_resource *rbuf = r300_resource(buf); uint32_t *mapped; + if (!cb || (!cb->buffer && !cb->user_buffer)) + return; + switch (shader) { case PIPE_SHADER_VERTEX: cbuf = (struct r300_constant_buffer*)r300->vs_constants.state; @@ -1852,15 +2024,17 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, return; } - if (buf == NULL || buf->width0 == 0) - return; - if (rbuf->b.user_ptr) - mapped = (uint32_t*)rbuf->b.user_ptr; - else if (rbuf->constant_buffer) - mapped = (uint32_t*)rbuf->constant_buffer; - else - return; + if (cb->user_buffer) + mapped = (uint32_t*)cb->user_buffer; + else { + struct r300_resource *rbuf = r300_resource(cb->buffer); + + if (rbuf && rbuf->malloced_buffer) + mapped = (uint32_t*)rbuf->malloced_buffer; + else + return; + } if (shader == PIPE_SHADER_FRAGMENT || (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) { @@ -1887,14 +2061,14 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, r300_mark_atom_dirty(r300, &r300->vs_constants); } else if (r300->draw) { draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, - 0, mapped, buf->width0); + 0, mapped, cb->buffer_size); } } else if (shader == PIPE_SHADER_FRAGMENT) { r300_mark_atom_dirty(r300, &r300->fs_constants); } } -static void r300_texture_barrier(struct pipe_context *pipe) +static void r300_texture_barrier(struct pipe_context *pipe, unsigned flags) { struct r300_context *r300 = r300_context(pipe); @@ -1902,6 +2076,10 @@ static void r300_texture_barrier(struct pipe_context *pipe) r300_mark_atom_dirty(r300, &r300->texture_cache_inval); } +static void r300_memory_barrier(struct pipe_context *pipe, unsigned flags) +{ +} + void r300_init_state_functions(struct r300_context* r300) { r300->context.create_blend_state = r300_create_blend_state; @@ -1934,21 +2112,24 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.delete_rasterizer_state = r300_delete_rs_state; r300->context.create_sampler_state = r300_create_sampler_state; - r300->context.bind_fragment_sampler_states = r300_bind_sampler_states; - r300->context.bind_vertex_sampler_states = r300_lacks_vertex_textures; + r300->context.bind_sampler_states = r300_bind_sampler_states; r300->context.delete_sampler_state = r300_delete_sampler_state; - r300->context.set_fragment_sampler_views = r300_set_fragment_sampler_views; + r300->context.set_sampler_views = r300_set_sampler_views; r300->context.create_sampler_view = r300_create_sampler_view; r300->context.sampler_view_destroy = r300_sampler_view_destroy; - r300->context.set_scissor_state = r300_set_scissor_state; + r300->context.set_scissor_states = r300_set_scissor_states; - r300->context.set_viewport_state = r300_set_viewport_state; + r300->context.set_viewport_states = r300_set_viewport_states; - r300->context.set_vertex_buffers = r300_set_vertex_buffers; - r300->context.set_index_buffer = r300_set_index_buffer; - r300->context.redefine_user_buffer = u_default_redefine_user_buffer; + if (r300->screen->caps.has_tcl) { + r300->context.set_vertex_buffers = r300_set_vertex_buffers_hwtcl; + r300->context.set_index_buffer = r300_set_index_buffer_hwtcl; + } else { + r300->context.set_vertex_buffers = r300_set_vertex_buffers_swtcl; + r300->context.set_index_buffer = r300_set_index_buffer_swtcl; + } r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; @@ -1959,4 +2140,5 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.delete_vs_state = r300_delete_vs_state; r300->context.texture_barrier = r300_texture_barrier; + r300->context.memory_barrier = r300_memory_barrier; }