sna: Exploit the alpha-fixup of the BLT for texture format conversions

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-11-25 00:24:45 +00:00
parent 6d6399f97c
commit 1367e3f9ef
9 changed files with 124 additions and 54 deletions

View File

@ -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,

View File

@ -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))

View File

@ -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",

View File

@ -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,

View File

@ -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,

View File

@ -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__,

View File

@ -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__,

View File

@ -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) {
if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
return 0;
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;
}
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);
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;
}

View File

@ -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)
{