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

Tan Hu tan.hu at zte.com.cn
Wed Jun 1 09:02:48 UTC 2016


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.

[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 10df4ec..e9ac721 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)
 {
-- 
1.8.3.1

--------------------------------------------------------
ZTE Information Security Notice: The information contained in this mail (and any attachment transmitted herewith) is privileged and confidential and is intended for the exclusive use of the addressee(s).  If you are not an intended recipient, any disclosure, reproduction, distribution or other dissemination or use of the information contained is strictly prohibited.  If you have received this mail in error, please delete it and notify us immediately.


More information about the xorg-driver-ati mailing list