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 <[email protected]>

[1] http://anholt.livejournal.com/32058.html

r6xx still be used on some machine,
Ported from commit 4375a6e75e5d41139be7031a0dee58c057ecbd07.

Signed-off-by: Tan Hu <[email protected]>
---
 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)
 {
_______________________________________________
xorg-driver-ati mailing list
[email protected]
https://lists.x.org/mailman/listinfo/xorg-driver-ati

Reply via email to