summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-23 00:01:50 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-23 00:28:12 +0000
commit84d97bdba02b909369b54de21425ffc9f6ad581a (patch)
treea2f33adde3469fdc54846917ca9b545951eeb413
parent281f620573917faef52d9226b12737ce1e2dffdc (diff)
sna/gen2+: Reuse source channel for mask where possible
GTK+ has a clever trick for premultiplying its images by loading the same pixel data into both the source and mask, and then performing the composite. This causes us to upload the same pixel data twice! Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/gen2_render.c60
-rw-r--r--src/sna/gen3_render.c69
-rw-r--r--src/sna/gen4_render.c65
-rw-r--r--src/sna/gen5_render.c67
-rw-r--r--src/sna/gen6_render.c63
-rw-r--r--src/sna/gen7_render.c63
-rw-r--r--src/sna/sna.h27
7 files changed, 342 insertions, 72 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 519ba189..f1fdfd6f 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1401,6 +1401,42 @@ gen2_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen2_check_repeat(mask))
+ return FALSE;
+
+ if (!gen2_check_filter(mask))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = mask->repeat ? mask->repeatType : RepeatNone;
+ mc->filter = mask->filter;
+ mc->pict_format = mask->format;
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen2_render_composite(struct sna *sna,
uint8_t op,
@@ -1493,16 +1529,20 @@ gen2_render_composite(struct sna *sna,
}
if (mask) {
- switch (gen2_composite_picture(sna, mask, &tmp->mask,
- mask_x, mask_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- goto cleanup_src;
- case 0:
- gen2_composite_solid_init(sna, &tmp->mask, 0);
- case 1:
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, mask_x, mask_y)) {
+ switch (gen2_composite_picture(sna, mask, &tmp->mask,
+ mask_x, mask_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ goto cleanup_src;
+ case 0:
+ gen2_composite_solid_init(sna, &tmp->mask, 0);
+ case 1:
+ break;
+ }
}
if (mask->componentAlpha && PICT_FORMAT_RGB(mask->format)) {
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 12eebaab..5833c1fc 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2394,6 +2394,43 @@ gen3_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen3_check_repeat(mask))
+ return FALSE;
+
+ if (!gen3_check_filter(mask->filter))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = gen3_texture_repeat(mask->repeat ? mask->repeatType : RepeatNone);
+ mc->filter = gen3_filter(mask->filter);
+ mc->pict_format = mask->format;
+ gen3_composite_channel_set_format(mc, mask->format);
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen3_render_composite(struct sna *sna,
uint8_t op,
@@ -2499,20 +2536,24 @@ gen3_render_composite(struct sna *sna,
tmp->need_magic_ca_pass = FALSE;
tmp->has_component_alpha = FALSE;
if (mask && tmp->src.u.gen3.type != SHADER_ZERO) {
- tmp->mask.u.gen3.type = SHADER_TEXTURE;
- DBG(("%s: preparing mask\n", __FUNCTION__));
- switch (gen3_composite_picture(sna, mask, tmp, &tmp->mask,
- mask_x, mask_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- goto cleanup_src;
- case 0:
- tmp->mask.u.gen3.type = SHADER_ZERO;
- break;
- case 1:
- gen3_composite_channel_convert(&tmp->mask);
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, mask_x, mask_y)) {
+ tmp->mask.u.gen3.type = SHADER_TEXTURE;
+ DBG(("%s: preparing mask\n", __FUNCTION__));
+ switch (gen3_composite_picture(sna, mask, tmp, &tmp->mask,
+ mask_x, mask_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ goto cleanup_src;
+ case 0:
+ tmp->mask.u.gen3.type = SHADER_ZERO;
+ break;
+ case 1:
+ gen3_composite_channel_convert(&tmp->mask);
+ break;
+ }
}
DBG(("%s: mask type=%d\n", __FUNCTION__, tmp->mask.u.gen3.type));
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 6ccddd20..9f15b3c4 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2008,6 +2008,43 @@ gen4_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen4_check_repeat(mask))
+ return FALSE;
+
+ if (!gen4_check_filter(mask))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = gen4_repeat(mask->repeat ? mask->repeatType : RepeatNone);
+ mc->filter = gen4_filter(mask->filter);
+ mc->pict_format = mask->format;
+ mc->card_format = gen4_get_card_format(mask->format);
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen4_render_composite(struct sna *sna,
uint8_t op,
@@ -2109,18 +2146,22 @@ gen4_render_composite(struct sna *sna,
}
}
- switch (gen4_composite_picture(sna, mask, &tmp->mask,
- msk_x, msk_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- DBG(("%s: failed to prepare mask\n", __FUNCTION__));
- goto cleanup_src;
- case 0:
- gen4_composite_solid_init(sna, &tmp->mask, 0);
- case 1:
- gen4_composite_channel_convert(&tmp->mask);
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, msk_x, msk_y)) {
+ switch (gen4_composite_picture(sna, mask, &tmp->mask,
+ msk_x, msk_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ DBG(("%s: failed to prepare mask\n", __FUNCTION__));
+ goto cleanup_src;
+ case 0:
+ gen4_composite_solid_init(sna, &tmp->mask, 0);
+ case 1:
+ gen4_composite_channel_convert(&tmp->mask);
+ break;
+ }
}
tmp->is_affine &= tmp->mask.is_affine;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 180b561a..0b422726 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2050,6 +2050,43 @@ gen5_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen5_check_repeat(mask))
+ return FALSE;
+
+ if (!gen5_check_filter(mask))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = gen5_repeat(mask->repeat ? mask->repeatType : RepeatNone);
+ mc->filter = gen5_filter(mask->filter);
+ mc->pict_format = mask->format;
+ mc->card_format = gen5_get_card_format(mask->format);
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen5_render_composite(struct sna *sna,
uint8_t op,
@@ -2152,19 +2189,23 @@ gen5_render_composite(struct sna *sna,
}
}
- DBG(("%s: preparing mask\n", __FUNCTION__));
- switch (gen5_composite_picture(sna, mask, &tmp->mask,
- msk_x, msk_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- DBG(("%s: failed to prepare mask picture\n", __FUNCTION__));
- goto cleanup_src;
- case 0:
- gen5_composite_solid_init(sna, &tmp->mask, 0);
- case 1:
- gen5_composite_channel_convert(&tmp->mask);
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, msk_x, msk_y)) {
+ DBG(("%s: preparing mask\n", __FUNCTION__));
+ switch (gen5_composite_picture(sna, mask, &tmp->mask,
+ msk_x, msk_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ DBG(("%s: failed to prepare mask picture\n", __FUNCTION__));
+ goto cleanup_src;
+ case 0:
+ gen5_composite_solid_init(sna, &tmp->mask, 0);
+ case 1:
+ gen5_composite_channel_convert(&tmp->mask);
+ break;
+ }
}
tmp->is_affine &= tmp->mask.is_affine;
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 8e7ea156..985bb90b 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2225,6 +2225,43 @@ gen6_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen6_check_repeat(mask))
+ return FALSE;
+
+ if (!gen6_check_filter(mask))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = gen6_repeat(mask->repeat ? mask->repeatType : RepeatNone);
+ mc->filter = gen6_filter(mask->filter);
+ mc->pict_format = mask->format;
+ mc->card_format = gen6_get_card_format(mask->format);
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen6_render_composite(struct sna *sna,
uint8_t op,
@@ -2347,17 +2384,21 @@ gen6_render_composite(struct sna *sna,
}
}
- switch (gen6_composite_picture(sna, mask, &tmp->mask,
- msk_x, msk_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- goto cleanup_src;
- case 0:
- gen6_composite_solid_init(sna, &tmp->mask, 0);
- case 1:
- gen6_composite_channel_convert(&tmp->mask);
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, msk_x, msk_y)) {
+ switch (gen6_composite_picture(sna, mask, &tmp->mask,
+ msk_x, msk_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ goto cleanup_src;
+ case 0:
+ gen6_composite_solid_init(sna, &tmp->mask, 0);
+ case 1:
+ gen6_composite_channel_convert(&tmp->mask);
+ break;
+ }
}
tmp->is_affine &= tmp->mask.is_affine;
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 58647f74..5eac9bf6 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2338,6 +2338,43 @@ gen7_composite_fallback(struct sna *sna,
return FALSE;
}
+static int
+reuse_source(struct sna *sna,
+ PicturePtr src, struct sna_composite_channel *sc, int src_x, int src_y,
+ PicturePtr mask, struct sna_composite_channel *mc, int msk_x, int msk_y)
+{
+ if (src->pDrawable == NULL || mask->pDrawable != src->pDrawable)
+ return FALSE;
+
+ DBG(("%s: mask reuses source drawable\n", __FUNCTION__));
+
+ if (src_x != msk_x || src_y != msk_y)
+ return FALSE;
+
+ if (!sna_transform_equal(src->transform, mask->transform))
+ return FALSE;
+
+ if (!sna_picture_alphamap_equal(src, mask))
+ return FALSE;
+
+ if (!gen7_check_repeat(mask))
+ return FALSE;
+
+ if (!gen7_check_filter(mask))
+ return FALSE;
+
+ DBG(("%s: reusing source channel for mask with a twist\n",
+ __FUNCTION__));
+
+ *mc = *sc;
+ mc->repeat = gen7_repeat(mask->repeat ? mask->repeatType : RepeatNone);
+ mc->filter = gen7_filter(mask->filter);
+ mc->pict_format = mask->format;
+ mc->card_format = gen7_get_card_format(mask->format);
+ mc->bo = kgem_bo_reference(mc->bo);
+ return TRUE;
+}
+
static Bool
gen7_render_composite(struct sna *sna,
uint8_t op,
@@ -2460,17 +2497,21 @@ gen7_render_composite(struct sna *sna,
}
}
- switch (gen7_composite_picture(sna, mask, &tmp->mask,
- msk_x, msk_y,
- width, height,
- dst_x, dst_y)) {
- case -1:
- goto cleanup_src;
- case 0:
- gen7_composite_solid_init(sna, &tmp->mask, 0);
- case 1:
- gen7_composite_channel_convert(&tmp->mask);
- break;
+ if (!reuse_source(sna,
+ src, &tmp->src, src_x, src_y,
+ mask, &tmp->mask, msk_x, msk_y)) {
+ switch (gen7_composite_picture(sna, mask, &tmp->mask,
+ msk_x, msk_y,
+ width, height,
+ dst_x, dst_y)) {
+ case -1:
+ goto cleanup_src;
+ case 0:
+ gen7_composite_solid_init(sna, &tmp->mask, 0);
+ case 1:
+ gen7_composite_channel_convert(&tmp->mask);
+ break;
+ }
}
tmp->is_affine &= tmp->mask.is_affine;
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 1fa31222..1ee4da20 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -507,7 +507,7 @@ _sna_get_transformed_coordinates(int x, int y,
void
sna_get_transformed_coordinates(int x, int y,
- const PictTransform *transform,
+ const PictTransform *transform,
float *x_out, float *y_out);
Bool
@@ -521,6 +521,31 @@ Bool sna_transform_is_integer_translation(const PictTransform *t,
Bool sna_transform_is_translation(const PictTransform *t,
pixman_fixed_t *tx, pixman_fixed_t *ty);
+static inline bool
+sna_transform_equal(const PictTransform *a, const PictTransform *b)
+{
+ if (a == b)
+ return true;
+
+ if (a == NULL || b == NULL)
+ return false;
+
+ return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+static inline bool
+sna_picture_alphamap_equal(PicturePtr a, PicturePtr b)
+{
+ if (a->alphaMap != b->alphaMap)
+ return false;
+
+ if (a->alphaMap)
+ return false;
+
+ return (a->alphaOrigin.x == b->alphaOrigin.x &&
+ a->alphaOrigin.y == b->alphaOrigin.y);
+}
+
static inline bool wedged(struct sna *sna)
{
return unlikely(sna->kgem.wedged);