X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_state.c;h=4aebbea83d8abae5d2550ba50ecd40efe087f231;hb=27c054edf0ae92c8c498830e7c7510fa94f5dcfd;hp=4a5a5a89b8471ed1e8e38de358fb68e357591ada;hpb=2f89949b666889a61196657511b1dee4418ae865;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 4a5a5a89b84..4aebbea83d8 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -170,6 +170,59 @@ static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA dstA == PIPE_BLENDFACTOR_ONE); } +static unsigned blend_discard_conditionally(unsigned eqRGB, unsigned eqA, + unsigned dstRGB, unsigned dstA, + unsigned srcRGB, unsigned srcA) +{ + 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) @@ -216,6 +269,70 @@ static unsigned arra_cmask(unsigned mask) (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. */ @@ -226,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 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 */ @@ -251,123 +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) && - (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; - } - } - } - } + 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); } } @@ -397,22 +476,26 @@ static void* r300_create_blend_state(struct pipe_context* pipe, rrrr_cmask, aaaa_cmask, grrg_cmask, - arra_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(blend_control); - OUT_CB(alpha_blend_control); + 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. */ + /* 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); @@ -422,6 +505,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe, OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); END_CB; + /* 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_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; + /* The same as above, but with no colorbuffer reads and writes. */ BEGIN_CB(blend->cb_no_readwrite, 8); OUT_CB_REG(R300_RB3D_ROPCNTL, rop); @@ -487,6 +580,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, (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; + float tmp; CB_LOCALS; state->state = *color; /* Save it, so that we can reuse it in set_fb_state */ @@ -510,9 +604,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:; } } @@ -523,6 +625,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, switch (format) { 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]) | @@ -825,6 +928,13 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, r300->fb_state.size += 8; } + 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. */ } @@ -832,14 +942,18 @@ static unsigned r300_get_num_samples(struct r300_context *r300) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - unsigned num_samples; + unsigned i, num_samples; - if (fb->nr_cbufs) - num_samples = fb->cbufs[0]->texture->nr_samples; - else if (fb->zsbuf) - num_samples = fb->zsbuf->texture->nr_samples; - else - num_samples = 1; + if (!fb->nr_cbufs && !fb->zsbuf) + return 1; + + num_samples = 6; + + for (i = 0; i < fb->nr_cbufs; i++) + num_samples = MIN2(num_samples, fb->cbufs[i]->texture->nr_samples); + + if (fb->zsbuf) + num_samples = MIN2(num_samples, fb->zsbuf->texture->nr_samples); if (!num_samples) num_samples = 1; @@ -900,9 +1014,17 @@ r300_set_framebuffer_state(struct pipe_context* pipe, } assert(state->zsbuf || (r300->locked_zbuffer && !unlock_zbuffer) || !r300->zmask_in_use); + /* Set whether CMASK can be used. */ + r300->cmask_in_use = + state->nr_cbufs == 1 && + 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 zsbuf is set from NULL to non-NULL or vice versa.. */ if (!!old_state->zsbuf != !!state->zsbuf) { r300_mark_atom_dirty(r300, &r300->dsa_state); @@ -1080,8 +1202,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. */ @@ -1212,8 +1333,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, if (r300_screen(pipe->screen)->caps.has_tcl) { vap_clip_cntl = (state->clip_plane_enable & 63) | - R300_PS_UCP_MODE_CLIP_AS_TRIFAN | - (state->depth_clip ? 0 : R300_CLIP_DISABLE); + R300_PS_UCP_MODE_CLIP_AS_TRIFAN; } else { vap_clip_cntl = R300_CLIP_DISABLE; } @@ -1283,6 +1403,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* 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; if (r300->draw && rs) { draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state); @@ -1293,18 +1414,21 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) 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; } else { r300->polygon_offset_enabled = FALSE; r300->sprite_coord_enable = 0; r300->two_sided_color = FALSE; r300->msaa_enable = FALSE; + r300->flatshade = 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); } @@ -1399,7 +1523,8 @@ static void* } static void r300_bind_sampler_states(struct pipe_context* pipe, - unsigned count, + unsigned shader, + unsigned start, unsigned count, void** states) { struct r300_context* r300 = r300_context(pipe); @@ -1407,9 +1532,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; @@ -1417,6 +1546,7 @@ 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) @@ -1597,8 +1727,10 @@ static void r300_set_sample_mask(struct pipe_context *pipe, r300_mark_atom_dirty(r300, &r300->sample_mask); } -static void r300_set_scissor_state(struct pipe_context* pipe, - const struct pipe_scissor_state* state) +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); @@ -1608,8 +1740,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 = @@ -1618,7 +1752,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; } @@ -1696,10 +1830,10 @@ static void r300_set_vertex_buffers_swtcl(struct pipe_context* pipe, 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); + 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); + r300_resource(buffers[i].buffer)->malloced_buffer, ~0); } } } @@ -1731,7 +1865,7 @@ static void r300_set_index_buffer_swtcl(struct pipe_context* pipe, } draw_set_indexes(r300->draw, (const ubyte *) buf + ib->offset, - ib->index_size); + ib->index_size, ~0); } } @@ -1931,7 +2065,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, struct r300_constant_buffer *cbuf; uint32_t *mapped; - if (!cb) + if (!cb || (!cb->buffer && !cb->user_buffer)) return; switch (shader) { @@ -2029,17 +2163,16 @@ 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.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; if (r300->screen->caps.has_tcl) { r300->context.set_vertex_buffers = r300_set_vertex_buffers_hwtcl;