xf86-video-intel: 2 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/gen4_render.c src/sna/gen5_render.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/gen8_render.c src/sna/sna_blt.c
Chris Wilson
ickle at kemper.freedesktop.org
Fri Apr 4 05:55:49 PDT 2014
src/sna/gen2_render.c | 12 ++++
src/sna/gen3_render.c | 12 ++++
src/sna/gen4_render.c | 12 ++++
src/sna/gen5_render.c | 12 ++++
src/sna/gen6_render.c | 12 ++++
src/sna/gen7_render.c | 12 ++++
src/sna/gen8_render.c | 12 ++++
src/sna/sna_blt.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++--
8 files changed, 217 insertions(+), 5 deletions(-)
New commits:
commit 6e86e84da1c8049a150eb6b5780526fea57e0f9d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Apr 4 12:41:25 2014 +0100
sna: Precompute OVER/ADD with solids to convert it into a BLT operation
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index b83e6b2..f68d951 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -815,6 +815,26 @@ sna_picture_is_solid(PicturePtr picture, uint32_t *color)
}
static bool
+pixel_is_transparent(uint32_t pixel, uint32_t format)
+{
+ unsigned int abits;
+
+ abits = PICT_FORMAT_A(format);
+ if (!abits)
+ return false;
+
+ if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A ||
+ PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
+ return (pixel & ((1 << abits) - 1)) == 0;
+ } else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB ||
+ PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
+ unsigned int ashift = PICT_FORMAT_BPP(format) - abits;
+ return (pixel >> ashift) == 0;
+ } else
+ return false;
+}
+
+static bool
pixel_is_opaque(uint32_t pixel, uint32_t format)
{
unsigned int abits;
@@ -868,6 +888,16 @@ is_white(PicturePtr picture)
return pixel_is_white(get_pixel(picture), picture->format);
}
+static bool
+is_transparent(PicturePtr picture)
+{
+ if (picture->pSourcePict) {
+ PictSolidFill *fill = (PictSolidFill *) picture->pSourcePict;
+ return fill->color == 0;
+ } else
+ return pixel_is_transparent(get_pixel(picture), picture->format);
+}
+
bool
sna_composite_mask_is_opaque(PicturePtr mask)
{
@@ -2361,6 +2391,71 @@ is_clear(PixmapPtr pixmap)
return priv && priv->clear;
}
+static inline uint32_t
+over(uint32_t src, uint32_t dst)
+{
+ uint32_t a = ~src >> 24;
+
+#define G_SHIFT 8
+#define RB_MASK 0xff00ff
+#define RB_ONE_HALF 0x800080
+#define RB_MASK_PLUS_ONE 0x10000100
+
+#define UN8_rb_MUL_UN8(x, a, t) do { \
+ t = ((x) & RB_MASK) * (a); \
+ t += RB_ONE_HALF; \
+ x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT; \
+ x &= RB_MASK; \
+} while (0)
+
+#define UN8_rb_ADD_UN8_rb(x, y, t) do { \
+ t = ((x) + (y)); \
+ t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK); \
+ x = (t & RB_MASK); \
+} while (0)
+
+#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) do { \
+ uint32_t r1__, r2__, r3__, t__; \
+ \
+ r1__ = (x); \
+ r2__ = (y) & RB_MASK; \
+ UN8_rb_MUL_UN8(r1__, (a), t__); \
+ UN8_rb_ADD_UN8_rb(r1__, r2__, t__); \
+ \
+ r2__ = (x) >> G_SHIFT; \
+ r3__ = ((y) >> G_SHIFT) & RB_MASK; \
+ UN8_rb_MUL_UN8(r2__, (a), t__); \
+ UN8_rb_ADD_UN8_rb(r2__, r3__, t__); \
+ \
+ (x) = r1__ | (r2__ << G_SHIFT); \
+} while (0)
+
+ UN8x4_MUL_UN8_ADD_UN8x4(dst, a, src);
+
+ return dst;
+}
+
+static inline uint32_t
+add(uint32_t src, uint32_t dst)
+{
+#define UN8x4_ADD_UN8x4(x, y) do { \
+ uint32_t r1__, r2__, r3__, t__; \
+ \
+ r1__ = (x) & RB_MASK; \
+ r2__ = (y) & RB_MASK; \
+ UN8_rb_ADD_UN8_rb(r1__, r2__, t__); \
+ \
+ r2__ = ((x) >> G_SHIFT) & RB_MASK; \
+ r3__ = ((y) >> G_SHIFT) & RB_MASK; \
+ UN8_rb_ADD_UN8_rb(r2__, r3__, t__); \
+ \
+ x = r1__ | (r2__ << G_SHIFT); \
+} while (0)
+
+ UN8x4_ADD_UN8x4(src, dst);
+ return src;
+}
+
bool
sna_blt_composite(struct sna *sna,
uint32_t op,
@@ -2459,12 +2554,40 @@ clear:
}
if (is_solid(src)) {
+ if ((op == PictOpOver || op == PictOpAdd) && is_transparent(src)) {
+ sna_pixmap(tmp->dst.pixmap)->clear = was_clear;
+ return prepare_blt_nop(sna, tmp);
+ }
if (op == PictOpOver && is_opaque_solid(src))
op = PictOpSrc;
if (op == PictOpAdd && is_white(src))
op = PictOpSrc;
- if (was_clear && (op == PictOpAdd || op == PictOpOver))
- op = PictOpSrc;
+ if (was_clear && (op == PictOpAdd || op == PictOpOver)) {
+ if (sna_pixmap(tmp->dst.pixmap)->clear_color == 0)
+ op = PictOpSrc;
+ if (op == PictOpOver) {
+ color = over(get_solid_color(src, PICT_a8r8g8b8),
+ color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+ dst->format, PICT_a8r8g8b8));
+ op = PictOpSrc;
+ DBG(("%s: precomputing solid OVER (%08x, %08x) -> %08x\n",
+ get_solid_color(src, PICT_a8r8g8b8),
+ color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+ dst->format, PICT_a8r8g8b8),
+ color));
+ }
+ if (op == PictOpAdd) {
+ color = add(get_solid_color(src, PICT_a8r8g8b8),
+ color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+ dst->format, PICT_a8r8g8b8));
+ op = PictOpSrc;
+ DBG(("%s: precomputing solid ADD (%08x, %08x) -> %08x\n",
+ get_solid_color(src, PICT_a8r8g8b8),
+ color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+ dst->format, PICT_a8r8g8b8),
+ color));
+ }
+ }
if (op == PictOpOutReverse && is_opaque_solid(src))
goto clear;
commit 31a4c7bc13c5f4560482b450b9ee4788a58930cd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Apr 4 10:46:48 2014 +0100
sna/gen2+: Replace composite sources with solids where possible
If the composite reads entirely from within a large pixmap which is a
clear color, just replace the source with a solid.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index e3931e3..698ed99 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1557,6 +1557,18 @@ gen2_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat &&
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen2_composite_solid_init(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index bb98beb..a30ee44 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3093,6 +3093,18 @@ gen3_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat ||
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen3_init_solid(channel, priv->clear_color);
+ }
+ }
} else {
channel->transform = picture->transform;
channel->is_affine = sna_transform_is_affine(picture->transform);
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 88db06e..9994bf5 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1584,6 +1584,18 @@ gen4_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat &&
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen4_channel_init_solid(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 5508d49..6408eec 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1523,6 +1523,18 @@ gen5_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat ||
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen4_channel_init_solid(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index f1f7946..867108b 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -1773,6 +1773,18 @@ gen6_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat &&
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen4_channel_init_solid(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 6c1fe26..c7ce70c 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2036,6 +2036,18 @@ gen7_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat ||
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen4_channel_init_solid(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 9e63483..0c851c8 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -1813,6 +1813,18 @@ gen8_composite_picture(struct sna *sna,
y += dy;
channel->transform = NULL;
channel->filter = PictFilterNearest;
+
+ if (channel->repeat ||
+ (x >= 0 &&
+ y >= 0 &&
+ x + w < pixmap->drawable.width &&
+ y + h < pixmap->drawable.height)) {
+ struct sna_pixmap *priv = sna_pixmap(pixmap);
+ if (priv->clear) {
+ DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+ return gen4_channel_init_solid(sna, channel, priv->clear_color);
+ }
+ }
} else
channel->transform = picture->transform;
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index c621977..b83e6b2 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -2564,9 +2564,14 @@ fill:
src_pixmap = get_drawable_pixmap(src->pDrawable);
if (is_clear(src_pixmap)) {
- color = color_convert(sna_pixmap(src_pixmap)->clear_color,
- src->format, tmp->dst.format);
- goto fill;
+ if (src->repeat ||
+ (x >= 0 && y >= 0 &&
+ x + width < src_pixmap->drawable.width &&
+ y + height < src_pixmap->drawable.height)) {
+ color = color_convert(sna_pixmap(src_pixmap)->clear_color,
+ src->format, tmp->dst.format);
+ goto fill;
+ }
}
alpha_fixup = 0;
More information about the xorg-commit
mailing list