[PATCH xf86-video-ati resend 2/2] EXA/6xx/7xx: accelerate PictOpOver with component alpha

Grigori Goronzy greg at chown.ath.cx
Tue May 31 11:29:21 UTC 2016


On 2016-05-27 11:05, Tan Hu wrote:
> Subpixel text rendering is typically done with a solid src and
> a pixmap mask. Traditionally, this cannot be accelerated in a single
> pass and requires two passes [1]. However, we can cheat a little
> with a constant blend color.
> 
> We can use:
> const.A = src.A / src.A
> const.R = src.R / src.A
> const.G = src.G / src.A
> const.B = src.B / src.A
> 
> dst.A = const.A * (src.A * mask.A) + (1 - (src.A * mask.A)) * dst.A
> dst.R = const.R * (src.A * mask.R) + (1 - (src.A * mask.R)) * dst.R
> dst.G = const.G * (src.A * mask.G) + (1 - (src.A * mask.G)) * dst.G
> dst.B = const.B * (src.A * mask.B) + (1 - (src.A * mask.B)) * dst.B
> 
> This only needs a single source value. src.A is cancelled down in
> the right places.
> 

With Michel's comments addressed,

Reviewed-by: Grigori Goronzy <greg at chown.ath.cx>

> [1] http://anholt.livejournal.com/32058.html
> 
> r6xx still be used on some machine,
> Ported from commit 4375a6e75e5d41139be7031a0dee58c057ecbd07.
> 
> Signed-off-by: Tan Hu <tan.hu at zte.com.cn>
> ---
>  src/r600_exa.c   | 22 ++++++++++++++++++++--
>  src/r600_state.h |  2 ++
>  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 a95f320..849b21a 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 fa777e8..fda297d 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 a97c84b..1f5c052 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)
>  {


More information about the xorg-driver-ati mailing list