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

tan.hu at zte.com.cn tan.hu at zte.com.cn
Tue May 17 10:17:48 UTC 2016


From: Tan Hu <tan.hu at zte.com.cn>

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 a95f320..92fe193 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)
 {
-- 
2.1.0

--------------------------------------------------------
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