summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-04-26 09:07:07 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-04-26 09:14:17 +0100
commit9a5cd65b593ea82e56e0c403f7ddcc2420a64dc3 (patch)
tree006e8f7b75a0ce0b65bcfd117799dacd2117f281
parent86d349aa7b0a596fbb9530e896c19349405bf3ba (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.c47
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;