diff options
-rw-r--r-- | src/r600_exa.c | 22 | ||||
-rw-r--r-- | src/r600_state.h | 2 | ||||
-rw-r--r-- | src/r6xx_accel.c | 14 |
3 files changed, 36 insertions, 2 deletions
diff --git a/src/r600_exa.c b/src/r600_exa.c index 10df4eca..e9ac721d 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -766,6 +766,14 @@ static uint32_t R600GetBlendCntl(int op, PicturePtr pMask, uint32_t dst_format) } else if (dblend == (BLEND_ONE_MINUS_SRC_ALPHA << COLOR_DESTBLEND_shift)) { dblend = (BLEND_ONE_MINUS_SRC_COLOR << COLOR_DESTBLEND_shift); } + + /* With some tricks, we can still accelerate PictOpOver with solid src. + * This is commonly used for text rendering, so it's worth the extra + * effort. + */ + if (sblend == (BLEND_ONE << COLOR_SRCBLEND_shift)) { + sblend = (BLEND_CONSTANT_COLOR << COLOR_SRCBLEND_shift); + } } return sblend | dblend; @@ -1143,12 +1151,17 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP /* Check if it's component alpha that relies on a source alpha and * on the source value. We can only get one of those into the * single source value that we get to blend with. + * + * We can cheat a bit if the src is solid, though. PictOpOver + * can use the constant blend color to sneak a second blend + * source in. */ if (R600BlendOp[op].src_alpha && (R600BlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) != (BLEND_ZERO << COLOR_SRCBLEND_shift)) { - RADEON_FALLBACK(("Component alpha not supported with source " - "alpha and source value blending.\n")); + if (pSrcPicture->pDrawable || op != PictOpOver) + RADEON_FALLBACK(("Component alpha not supported with source " + "alpha and source value blending.\n")); } } @@ -1244,6 +1257,11 @@ static void R600SetSolidConsts(ScrnInfoPtr pScrn, float *buf, int format, uint32 } else { if (accel_state->component_alpha) { if (accel_state->src_alpha) { + /* required for PictOpOver */ + float cblend[4] = { pix_r / pix_a, pix_g / pix_a, + pix_b / pix_a, pix_a / pix_a }; + r600_set_blend_color(pScrn, cblend); + if (PICT_FORMAT_A(format) == 0) { pix_r = 1.0; pix_g = 1.0; diff --git a/src/r600_state.h b/src/r600_state.h index fa777e8b..fda297d3 100644 --- a/src/r600_state.h +++ b/src/r600_state.h @@ -266,6 +266,8 @@ r600_wait_3d_idle(ScrnInfoPtr pScrn); void r600_start_3d(ScrnInfoPtr pScrn); void +r600_set_blend_color(ScrnInfoPtr pScrn, float *color); +void r600_set_render_target(ScrnInfoPtr pScrn, cb_config_t *cb_conf, uint32_t domain); void r600_cp_wait_vline_sync(ScrnInfoPtr pScrn, PixmapPtr pPix, xf86CrtcPtr crtc, int start, int stop); diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c index a97c84b3..1f5c0523 100644 --- a/src/r6xx_accel.c +++ b/src/r6xx_accel.c @@ -174,6 +174,20 @@ r600_sq_setup(ScrnInfoPtr pScrn, sq_config_t *sq_conf) END_BATCH(); } +void r600_set_blend_color(ScrnInfoPtr pScrn, float *color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + BEGIN_BATCH(2 + 4); + PACK0(CB_BLEND_RED, 4); + EFLOAT(color[0]); /* R */ + EFLOAT(color[1]); /* G */ + EFLOAT(color[2]); /* B */ + EFLOAT(color[3]); /* A */ + END_BATCH(); +} + + void r600_set_render_target(ScrnInfoPtr pScrn, cb_config_t *cb_conf, uint32_t domain) { |