diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-04-26 09:07:07 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-04-26 09:14:17 +0100 |
commit | 9a5cd65b593ea82e56e0c403f7ddcc2420a64dc3 (patch) | |
tree | 006e8f7b75a0ce0b65bcfd117799dacd2117f281 | |
parent | 86d349aa7b0a596fbb9530e896c19349405bf3ba (diff) |
i830: if pixman_blt() fails fallback to fbCopyArea()
On older versions of pixman, pixman_blt() can return false if the images
are <= 8bpp. If we are being called from CopyArea, then we cannot return
FALSE here as that will trigger an infinite recursion. Instead we must
manually perform the fallback using fbCopyArea().
Reported-by: Peter Clifton <pcjc2@cam.ac.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/i830_uxa.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 79dfeaee..07fca490 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -825,6 +825,8 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap, (*screen->DestroyPixmap)(scratch); } else { + int dst_pitch; + /* bo is not busy so can be mapped without a stall, upload in-place. */ if (drm_intel_gem_bo_map_gtt(priv->bo)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, @@ -832,17 +834,44 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap, return FALSE; } - pixman_blt((uint32_t *)src, priv->bo->virtual, - src_pitch / sizeof(uint32_t), - pixmap->devKind / sizeof(uint32_t), - pixmap->drawable.bitsPerPixel, - pixmap->drawable.bitsPerPixel, - 0, 0, - x, y, - w, h); + ret = TRUE; + + /* Older version of pixman did not allow blt for <= 8bpp + * images, so if the blt fails fallback to using the fb. + */ + dst_pitch = i830_pixmap_pitch (pixmap); + if (! pixman_blt((uint32_t *)src, + priv->bo->virtual, + src_pitch / sizeof(uint32_t), + dst_pitch / sizeof(uint32_t), + pixmap->drawable.bitsPerPixel, + pixmap->drawable.bitsPerPixel, + 0, 0, + x, y, + w, h)) + { + ret = FALSE; + + scratch = GetScratchPixmapHeader(screen, + w, h, + pixmap->drawable.depth, + pixmap->drawable.bitsPerPixel, + src_pitch, + (pointer) src); + if (scratch) { + gc = GetScratchGC(pixmap->drawable.depth, screen); + if (gc) { + ret = !! fbCopyArea(&scratch->drawable, &pixmap->drawable, gc, + 0, 0, + w, h, + x, y); + FreeScratchGC(gc); + } + FreeScratchPixmapHeader(scratch); + } + } drm_intel_gem_bo_unmap_gtt(priv->bo); - ret = TRUE; } return ret; |