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...@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)
 {
-- 
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.
_______________________________________________
xorg-driver-ati mailing list
xorg-driver-ati@lists.x.org
https://lists.x.org/mailman/listinfo/xorg-driver-ati

Reply via email to