summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-11-25 00:24:45 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-11-25 12:12:57 +0000
commit1367e3f9ef5f606c8927cbde441a2ea41fa6d025 (patch)
tree73ebe306e12e642f35bde66993052776617f48fc
parent6d6399f97cf7cb91dcf89e9a5cd1243f761e4314 (diff)
sna: Exploit the alpha-fixup of the BLT for texture format conversions
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/g4x_render.c3
-rw-r--r--src/sna/gen2_render.c10
-rw-r--r--src/sna/gen3_render.c3
-rw-r--r--src/sna/gen4_render.c3
-rw-r--r--src/sna/gen5_render.c3
-rw-r--r--src/sna/gen6_render.c3
-rw-r--r--src/sna/gen7_render.c3
-rw-r--r--src/sna/sna_render.c145
-rw-r--r--src/sna/sna_render.h3
9 files changed, 123 insertions, 53 deletions
diff --git a/src/sna/g4x_render.c b/src/sna/g4x_render.c
index 9de8340a..f92a33a7 100644
--- a/src/sna/g4x_render.c
+++ b/src/sna/g4x_render.c
@@ -1927,7 +1927,8 @@ g4x_composite_picture(struct sna *sna,
channel->card_format = g4x_get_card_format(picture->format);
if (channel->card_format == -1)
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height))
return sna_render_picture_extract(sna, picture, channel,
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 9663dff5..31074af0 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1304,7 +1304,8 @@ static bool
gen2_check_card_format(struct sna *sna,
PicturePtr picture,
struct sna_composite_channel *channel,
- int x, int y, int w, int h)
+ int x, int y, int w, int h,
+ bool *fixup_alpha)
{
uint32_t format = picture->format;
unsigned int i;
@@ -1324,10 +1325,12 @@ gen2_check_card_format(struct sna *sna,
return true;
}
+ *fixup_alpha = true;
return false;
}
}
+ *fixup_alpha = false;
return false;
}
@@ -1343,6 +1346,7 @@ gen2_composite_picture(struct sna *sna,
PixmapPtr pixmap;
uint32_t color;
int16_t dx, dy;
+ bool fixup_alpha;
DBG(("%s: (%d, %d)x(%d, %d), dst=(%d, %d)\n",
__FUNCTION__, x, y, w, h, dst_x, dst_y));
@@ -1417,9 +1421,9 @@ gen2_composite_picture(struct sna *sna,
} else
channel->transform = picture->transform;
- if (!gen2_check_card_format(sna, picture, channel, x, y, w ,h))
+ if (!gen2_check_card_format(sna, picture, channel, x, y, w ,h, &fixup_alpha))
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y, fixup_alpha);
channel->pict_format = picture->format;
if (too_large(pixmap->drawable.width, pixmap->drawable.height))
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index f0f0a487..9dcdfcdb 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2402,7 +2402,8 @@ gen3_composite_picture(struct sna *sna,
if (!gen3_composite_channel_set_format(channel, picture->format) &&
!gen3_composite_channel_set_xformat(picture, channel, x, y, w, h))
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
DBG(("%s: pixmap too large (%dx%d), extracting (%d, %d)x(%d,%d)\n",
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 057192d8..5134bb92 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1918,7 +1918,8 @@ gen4_composite_picture(struct sna *sna,
channel->card_format = gen4_get_card_format(picture->format);
if (channel->card_format == -1)
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height))
return sna_render_picture_extract(sna, picture, channel,
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index b49b25ea..31f6f216 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1936,7 +1936,8 @@ gen5_composite_picture(struct sna *sna,
channel->card_format = gen5_get_card_format(picture->format);
if (channel->card_format == -1)
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height))
return sna_render_picture_extract(sna, picture, channel,
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index fbe0951d..6cc1a7db 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2274,7 +2274,8 @@ gen6_composite_picture(struct sna *sna,
channel->card_format = gen6_get_card_format(picture->format);
if (channel->card_format == (unsigned)-1)
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__,
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 3bec5df8..a106a185 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2386,7 +2386,8 @@ gen7_composite_picture(struct sna *sna,
channel->card_format = gen7_get_card_format(picture->format);
if (channel->card_format == (unsigned)-1)
return sna_render_picture_convert(sna, picture, channel, pixmap,
- x, y, w, h, dst_x, dst_y);
+ x, y, w, h, dst_x, dst_y,
+ false);
if (too_large(pixmap->drawable.width, pixmap->drawable.height)) {
DBG(("%s: extracting from pixmap %dx%d\n", __FUNCTION__,
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index c534f612..0a2856e3 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1637,11 +1637,10 @@ sna_render_picture_convert(struct sna *sna,
PixmapPtr pixmap,
int16_t x, int16_t y,
int16_t w, int16_t h,
- int16_t dst_x, int16_t dst_y)
+ int16_t dst_x, int16_t dst_y,
+ bool fixup_alpha)
{
- pixman_image_t *src, *dst;
BoxRec box;
- void *ptr;
#if NO_CONVERT
return -1;
@@ -1691,52 +1690,113 @@ sna_render_picture_convert(struct sna *sna,
return 0;
}
- if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
- return 0;
+ if (fixup_alpha && is_gpu(&pixmap->drawable)) {
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ PixmapPtr tmp;
+ PicturePtr src, dst;
+ int error;
- src = pixman_image_create_bits(picture->format,
- pixmap->drawable.width,
- pixmap->drawable.height,
- pixmap->devPrivate.ptr,
- pixmap->devKind);
- if (!src)
- return 0;
+ assert(PICT_FORMAT_BPP(picture->format) == pixmap->drawable.bitsPerPixel);
+ channel->pict_format = PICT_FORMAT(PICT_FORMAT_BPP(picture->format),
+ PICT_FORMAT_TYPE(picture->format),
+ PICT_FORMAT_BPP(picture->format) - PIXMAN_FORMAT_DEPTH(picture->format),
+ PICT_FORMAT_R(picture->format),
+ PICT_FORMAT_G(picture->format),
+ PICT_FORMAT_B(picture->format));
- if (PICT_FORMAT_RGB(picture->format) == 0) {
- channel->pict_format = PIXMAN_a8;
- DBG(("%s: converting to a8 from %08x\n",
+ DBG(("%s: converting to %08x from %08x using composite alpha-fixup\n",
__FUNCTION__, picture->format));
+
+ tmp = screen->CreatePixmap(screen, w, h, pixmap->drawable.bitsPerPixel, 0);
+ if (tmp == NULL)
+ return 0;
+
+ dst = CreatePicture(0, &tmp->drawable,
+ PictureMatchFormat(screen,
+ pixmap->drawable.bitsPerPixel,
+ channel->pict_format),
+ 0, NULL, serverClient, &error);
+ if (dst == NULL) {
+ screen->DestroyPixmap(tmp);
+ return 0;
+ }
+
+ src = CreatePicture(0, &pixmap->drawable,
+ PictureMatchFormat(screen,
+ pixmap->drawable.depth,
+ picture->format),
+ 0, NULL, serverClient, &error);
+ if (dst == NULL) {
+ FreePicture(dst, 0);
+ screen->DestroyPixmap(tmp);
+ return 0;
+ }
+
+ ValidatePicture(src);
+ ValidatePicture(dst);
+
+ sna_composite(PictOpSrc, src, NULL, dst,
+ box.x1, box.y1,
+ 0, 0,
+ 0, 0,
+ w, h);
+ FreePicture(dst, 0);
+ FreePicture(src, 0);
+
+ channel->bo = sna_pixmap_get_bo(tmp);
+ kgem_bo_reference(channel->bo);
+ screen->DestroyPixmap(tmp);
} else {
- channel->pict_format = PIXMAN_a8r8g8b8;
- DBG(("%s: converting to a8r8g8b8 from %08x\n",
- __FUNCTION__, picture->format));
- }
+ pixman_image_t *src, *dst;
+ void *ptr;
- channel->bo = kgem_create_buffer_2d(&sna->kgem,
- w, h, PIXMAN_FORMAT_BPP(channel->pict_format),
- KGEM_BUFFER_WRITE_INPLACE,
- &ptr);
- if (!channel->bo) {
- pixman_image_unref(src);
- return 0;
- }
+ if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
+ return 0;
- dst = pixman_image_create_bits(channel->pict_format,
- w, h, ptr, channel->bo->pitch);
- if (!dst) {
- kgem_bo_destroy(&sna->kgem, channel->bo);
+ src = pixman_image_create_bits(picture->format,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ pixmap->devPrivate.ptr,
+ pixmap->devKind);
+ if (!src)
+ return 0;
+
+ if (PICT_FORMAT_RGB(picture->format) == 0) {
+ channel->pict_format = PIXMAN_a8;
+ DBG(("%s: converting to a8 from %08x\n",
+ __FUNCTION__, picture->format));
+ } else {
+ channel->pict_format = PIXMAN_a8r8g8b8;
+ DBG(("%s: converting to a8r8g8b8 from %08x\n",
+ __FUNCTION__, picture->format));
+ }
+
+ channel->bo = kgem_create_buffer_2d(&sna->kgem,
+ w, h, PIXMAN_FORMAT_BPP(channel->pict_format),
+ KGEM_BUFFER_WRITE_INPLACE,
+ &ptr);
+ if (!channel->bo) {
+ pixman_image_unref(src);
+ return 0;
+ }
+
+ dst = pixman_image_create_bits(channel->pict_format,
+ w, h, ptr, channel->bo->pitch);
+ if (!dst) {
+ kgem_bo_destroy(&sna->kgem, channel->bo);
+ pixman_image_unref(src);
+ return 0;
+ }
+
+ pixman_image_composite(PictOpSrc, src, NULL, dst,
+ box.x1, box.y1,
+ 0, 0,
+ 0, 0,
+ w, h);
+ pixman_image_unref(dst);
pixman_image_unref(src);
- return 0;
}
- pixman_image_composite(PictOpSrc, src, NULL, dst,
- box.x1, box.y1,
- 0, 0,
- 0, 0,
- w, h);
- pixman_image_unref(dst);
- pixman_image_unref(src);
-
channel->width = w;
channel->height = h;
@@ -1745,11 +1805,10 @@ sna_render_picture_convert(struct sna *sna,
channel->offset[0] = x - dst_x - box.x1;
channel->offset[1] = y - dst_y - box.y1;
- DBG(("%s: offset=(%d, %d), size=(%d, %d) ptr[0]=%08x\n",
+ DBG(("%s: offset=(%d, %d), size=(%d, %d)\n",
__FUNCTION__,
channel->offset[0], channel->offset[1],
- channel->width, channel->height,
- *(uint32_t*)ptr));
+ channel->width, channel->height));
return 1;
}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 97b92226..e9ec2ba0 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -691,7 +691,8 @@ sna_render_picture_convert(struct sna *sna,
PixmapPtr pixmap,
int16_t x, int16_t y,
int16_t w, int16_t h,
- int16_t dst_x, int16_t dst_y);
+ int16_t dst_x, int16_t dst_y,
+ bool fixup_alpha);
inline static void sna_render_composite_redirect_init(struct sna_composite_op *op)
{