From ede03a848693ebe3d3f46e75cfcac11f7dcfe482 Mon Sep 17 00:00:00 2001
From: Juan RP <xtraeme@gmail.com>
Date: Fri, 20 Apr 2012 16:10:51 +0200
Subject: [PATCH] xf86-video-ati: add patches from upstream to fix EXA
 corruption with cairo-1.12.

---
 ...000-force-1d-tiling-for-r6xx-to-r9xx.patch |  32 +
 ...port-acceleration-pictures-evergreen.patch | 286 +++++++++
 ...a-support-acceleration-pictures-r1xx.patch | 178 ++++++
 ...a-support-acceleration-pictures-r2xx.patch | 175 ++++++
 ...t-acceleration-pictures-r3xx-to-r7xx.patch | 562 ++++++++++++++++++
 srcpkgs/xf86-video-ati/template               |   2 +
 6 files changed, 1235 insertions(+)
 create mode 100644 srcpkgs/xf86-video-ati/patches/0000-force-1d-tiling-for-r6xx-to-r9xx.patch
 create mode 100644 srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-evergreen.patch
 create mode 100644 srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r1xx.patch
 create mode 100644 srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r2xx.patch
 create mode 100644 srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r3xx-to-r7xx.patch

diff --git a/srcpkgs/xf86-video-ati/patches/0000-force-1d-tiling-for-r6xx-to-r9xx.patch b/srcpkgs/xf86-video-ati/patches/0000-force-1d-tiling-for-r6xx-to-r9xx.patch
new file mode 100644
index 0000000000..e162c7e86b
--- /dev/null
+++ b/srcpkgs/xf86-video-ati/patches/0000-force-1d-tiling-for-r6xx-to-r9xx.patch
@@ -0,0 +1,32 @@
+commit d282719a9c2fb0ee32830aa75b8dfbb9392954ed
+Author: Jerome Glisse <jglisse@redhat.com>
+Date:   Wed Apr 4 17:08:30 2012 -0400
+
+    r6xx-r9xx: force 1D tiling for buffer with height < 64
+    
+    Due to some old kernel issue, height is 8 aligned insided the ddx
+    For buffer with height btw 57 & 63 this lead ddx to believe it can
+    allocate a 2D tiled surface while mesa will not align height and
+    will assume 1D tiled leading to disagreement and rendering issue.
+    This patch force buffer with height < 64 to be 1D tiled.
+    
+    Signed-off-by: Jerome Glisse <jglisse@redhat.com>
+
+diff --git a/src/radeon_exa.c b/src/radeon_exa.c
+index 99a5806..270dad4 100644
+--- a/src/radeon_exa.c
++++ b/src/radeon_exa.c
+@@ -511,6 +511,13 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
+ 			surface.last_level = 0;
+ 			surface.bpe = cpp;
+ 			surface.nsamples = 1;
++			if (height < 64) {
++				/* disable 2d tiling for small surface to work around
++				 * the fact that ddx align height to 8 pixel for old
++				 * obscure reason i can't remember
++				 */
++				tiling &= ~RADEON_TILING_MACRO;
++			}
+ 			surface.flags = RADEON_SURF_SCANOUT;
+ 			surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+ 			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
diff --git a/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-evergreen.patch b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-evergreen.patch
new file mode 100644
index 0000000000..36022bfd15
--- /dev/null
+++ b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-evergreen.patch
@@ -0,0 +1,286 @@
+commit cac2d7ed54918579418fc762558497d3ec547fad
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date:   Sat Apr 14 08:53:39 2012 -0400
+
+    EXA: Support acceleration of solid pictures on Evergreen/NI.
+    
+    Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+    Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
+index cee3ec2..61b47a4 100644
+--- a/src/evergreen_exa.c
++++ b/src/evergreen_exa.c
+@@ -748,17 +748,8 @@ static Bool EVERGREENCheckCompositeTexture(PicturePtr pPict,
+ 					   int op,
+ 					   int unit)
+ {
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+     unsigned int i;
+-    int max_tex_w, max_tex_h;
+-
+-    max_tex_w = 16384;
+-    max_tex_h = 16384;
+-
+-    if ((w > max_tex_w) || (h > max_tex_h))
+-	RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
+ 
+     for (i = 0; i < sizeof(EVERGREENTexFormats) / sizeof(EVERGREENTexFormats[0]); i++) {
+ 	if (EVERGREENTexFormats[i].fmt == pPict->format)
+@@ -798,9 +789,16 @@ static void EVERGREENXFormSetup(PicturePtr pPict, PixmapPtr pPix,
+     ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+     struct radeon_accel_state *accel_state = info->accel_state;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     int const_offset = unit * 8;
++    int w, h;
++
++    if (pPict->pDrawable) {
++	w = pPict->pDrawable->width;
++	h = pPict->pDrawable->height;
++    } else {
++	w = 1;
++	h = 1;
++    }
+ 
+     if (pPict->transform != 0) {
+ 	accel_state->is_transform[unit] = TRUE;
+@@ -837,9 +835,7 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix,
+     ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+     struct radeon_accel_state *accel_state = info->accel_state;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+-    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    unsigned int repeatType;
+     unsigned int i;
+     tex_resource_t  tex_res;
+     tex_sampler_t   tex_samp;
+@@ -854,9 +850,17 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix,
+     }
+ 
+     /* Texture */
++    if (pPict->pDrawable) {
++	tex_res.w               = pPict->pDrawable->width;
++	tex_res.h               = pPict->pDrawable->height;
++	repeatType              = pPict->repeat ? pPict->repeatType : RepeatNone;
++    } else {
++	tex_res.w               = 1;
++	tex_res.h               = 1;
++	repeatType              = RepeatNormal;
++    }
++
+     tex_res.id                  = unit;
+-    tex_res.w                   = w;
+-    tex_res.h                   = h;
+     tex_res.pitch               = accel_state->src_obj[unit].pitch;
+     tex_res.depth               = 0;
+     tex_res.dim                 = SQ_TEX_DIM_2D;
+@@ -1054,33 +1058,30 @@ static Bool EVERGREENCheckComposite(int op, PicturePtr pSrcPicture,
+ {
+     uint32_t tmp1;
+     PixmapPtr pSrcPixmap, pDstPixmap;
+-    int max_tex_w, max_tex_h, max_dst_w, max_dst_h;
+ 
+     /* Check for unsupported compositing operations. */
+     if (op >= (int) (sizeof(EVERGREENBlendOp) / sizeof(EVERGREENBlendOp[0])))
+ 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+ 
+-    if (!pSrcPicture->pDrawable)
+-	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
++    if (pSrcPicture->pDrawable) {
++	pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+ 
+-    pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+-
+-    max_tex_w = 8192;
+-    max_tex_h = 8192;
+-    max_dst_w = 8192;
+-    max_dst_h = 8192;
++	if (pSrcPixmap->drawable.width >= 16384 ||
++	    pSrcPixmap->drawable.height >= 16384) {
++	    RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
++			     pSrcPixmap->drawable.width,
++			     pSrcPixmap->drawable.height));
++	}
+ 
+-    if (pSrcPixmap->drawable.width >= max_tex_w ||
+-	pSrcPixmap->drawable.height >= max_tex_h) {
+-	RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
+-			 pSrcPixmap->drawable.width,
+-			 pSrcPixmap->drawable.height));
+-    }
++	if (!EVERGREENCheckCompositeTexture(pSrcPicture, pDstPicture, op, 0))
++	    return FALSE;
++    } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+ 
+     pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable);
+ 
+-    if (pDstPixmap->drawable.width >= max_dst_w ||
+-	pDstPixmap->drawable.height >= max_dst_h) {
++    if (pDstPixmap->drawable.width >= 16384 ||
++	pDstPixmap->drawable.height >= 16384) {
+ 	RADEON_FALLBACK(("Dest w/h too large (%d,%d).\n",
+ 			 pDstPixmap->drawable.width,
+ 			 pDstPixmap->drawable.height));
+@@ -1089,38 +1090,35 @@ static Bool EVERGREENCheckComposite(int op, PicturePtr pSrcPicture,
+     if (pMaskPicture) {
+ 	PixmapPtr pMaskPixmap;
+ 
+-	if (!pMaskPicture->pDrawable)
+-	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
++	if (pMaskPicture->pDrawable) {
++	    pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+ 
+-	if (pMaskPixmap->drawable.width >= max_tex_w ||
+-	    pMaskPixmap->drawable.height >= max_tex_h) {
+-	    RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
+-			     pMaskPixmap->drawable.width,
+-			     pMaskPixmap->drawable.height));
+-	}
++	    if (pMaskPixmap->drawable.width >= 16384 ||
++		pMaskPixmap->drawable.height >= 16384) {
++	      RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
++			       pMaskPixmap->drawable.width,
++			       pMaskPixmap->drawable.height));
++	    }
+ 
+-	if (pMaskPicture->componentAlpha) {
+-	    /* Check if it's component alpha that relies on a source alpha and
+-	     * on the source value.  We can only get one of those into the
+-	     * single source value that we get to blend with.
+-	     */
+-	    if (EVERGREENBlendOp[op].src_alpha &&
+-		(EVERGREENBlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) !=
+-		(BLEND_ZERO << COLOR_SRCBLEND_shift)) {
+-		RADEON_FALLBACK(("Component alpha not supported with source "
+-				 "alpha and source value blending.\n"));
++	    if (pMaskPicture->componentAlpha) {
++		/* Check if it's component alpha that relies on a source alpha and
++		 * on the source value.  We can only get one of those into the
++		 * single source value that we get to blend with.
++		 */
++		if (EVERGREENBlendOp[op].src_alpha &&
++		    (EVERGREENBlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) !=
++		    (BLEND_ZERO << COLOR_SRCBLEND_shift)) {
++		    RADEON_FALLBACK(("Component alpha not supported with source "
++				     "alpha and source value blending.\n"));
++		}
+ 	    }
+-	}
+ 
+-	if (!EVERGREENCheckCompositeTexture(pMaskPicture, pDstPicture, op, 1))
+-	    return FALSE;
++	    if (!EVERGREENCheckCompositeTexture(pMaskPicture, pDstPicture, op, 1))
++		return FALSE;
++	} else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	    RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+     }
+ 
+-    if (!EVERGREENCheckCompositeTexture(pSrcPicture, pDstPicture, op, 0))
+-	return FALSE;
+-
+     if (!EVERGREENGetDestFormat(pDstPicture, &tmp1))
+ 	return FALSE;
+ 
+@@ -1132,7 +1130,8 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
+ 				      PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ 				      PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+ {
+-    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+     struct radeon_accel_state *accel_state = info->accel_state;
+     uint32_t dst_format;
+@@ -1142,13 +1141,19 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
+     struct r600_accel_object src_obj, mask_obj, dst_obj;
+     float *cbuf;
+ 
+-    if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
++    if (pDst->drawable.bitsPerPixel < 8 || (pSrc && pSrc->drawable.bitsPerPixel < 8))
+ 	return FALSE;
+ 
++    if (!pSrc) {
++	pSrc = RADEONSolidPixmap(pScreen, pSrcPicture->pSourcePict->solidFill.color);
++	if (!pSrc)
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++    }
++
+     src_obj.offset = 0;
+     dst_obj.offset = 0;
+-    src_obj.bo = radeon_get_pixmap_bo(pSrc);
+     dst_obj.bo = radeon_get_pixmap_bo(pDst);
++    src_obj.bo = radeon_get_pixmap_bo(pSrc);
+     dst_obj.surface = radeon_get_pixmap_surface(pDst);
+     src_obj.surface = radeon_get_pixmap_surface(pSrc);
+     dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
+@@ -1166,7 +1171,15 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
+     dst_obj.bpp = pDst->drawable.bitsPerPixel;
+     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
+ 
+-    if (pMask) {
++    if (pMaskPicture) {
++	if (!pMask) {
++	    pMask = RADEONSolidPixmap(pScreen, pMaskPicture->pSourcePict->solidFill.color);
++	    if (!pMask) {
++		if (!pSrcPicture->pDrawable)
++		    pScreen->DestroyPixmap(pSrc);
++		RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++	    }
++	}
+ 	mask_obj.offset = 0;
+ 	mask_obj.bo = radeon_get_pixmap_bo(pMask);
+ 	mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask);
+@@ -1363,11 +1376,9 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture,
+     return TRUE;
+ }
+ 
+-static void EVERGREENDoneComposite(PixmapPtr pDst)
++static void EVERGREENFinishComposite(ScrnInfoPtr pScrn, PixmapPtr pDst,
++				     struct radeon_accel_state *accel_state)
+ {
+-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+-    RADEONInfoPtr info = RADEONPTR(pScrn);
+-    struct radeon_accel_state *accel_state = info->accel_state;
+     int vtx_size;
+ 
+     if (accel_state->vsync)
+@@ -1381,6 +1392,22 @@ static void EVERGREENDoneComposite(PixmapPtr pDst)
+     evergreen_finish_op(pScrn, vtx_size);
+ }
+ 
++static void EVERGREENDoneComposite(PixmapPtr pDst)
++{
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
++    RADEONInfoPtr info = RADEONPTR(pScrn);
++    struct radeon_accel_state *accel_state = info->accel_state;
++
++    EVERGREENFinishComposite(pScrn, pDst, accel_state);
++
++    if (!accel_state->src_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->src_pix);
++
++    if (accel_state->msk_pic && !accel_state->msk_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->msk_pix);
++}
++
+ static void EVERGREENComposite(PixmapPtr pDst,
+ 			       int srcX, int srcY,
+ 			       int maskX, int maskY,
+@@ -1393,7 +1420,7 @@ static void EVERGREENComposite(PixmapPtr pDst,
+     float *vb;
+ 
+     if (CS_FULL(info->cs)) {
+-	EVERGREENDoneComposite(info->accel_state->dst_pix);
++	EVERGREENFinishComposite(pScrn, pDst, info->accel_state);
+ 	radeon_cs_flush_indirect(pScrn);
+ 	EVERGREENPrepareComposite(info->accel_state->composite_op,
+ 				  info->accel_state->src_pic,
diff --git a/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r1xx.patch b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r1xx.patch
new file mode 100644
index 0000000000..be350553c4
--- /dev/null
+++ b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r1xx.patch
@@ -0,0 +1,178 @@
+commit a7754b076e355fef3aea082b6e2d3aefbb8e7a9b
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date:   Fri Apr 13 13:24:46 2012 -0400
+
+    EXA: Support acceleration of solid pictures on R1xx.
+    
+    Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+    Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
+index b6cc9e4..451a625 100644
+--- a/src/radeon_exa_render.c
++++ b/src/radeon_exa_render.c
+@@ -338,17 +338,8 @@ static Bool R100CheckCompositeTexture(PicturePtr pPict,
+ 				      int unit)
+ {
+     unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     int i;
+ 
+-    /* r100 limit should be 2048, there are issues with 2048
+-     * see 197a62704742a4a19736c2637ac92d1dc5ab34ed
+-     */
+-
+-    if ((w > 2047) || (h > 2047))
+-	RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
+-
+     for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++) {
+ 	if (R100TexFormats[i].fmt == pPict->format)
+ 	    break;
+@@ -357,7 +348,7 @@ static Bool R100CheckCompositeTexture(PicturePtr pPict,
+ 	RADEON_FALLBACK(("Unsupported picture format 0x%x\n",
+ 			(int)pPict->format));
+ 
+-    if (!RADEONCheckTexturePOT(pPict, unit == 0))
++    if (pPict->pDrawable && !RADEONCheckTexturePOT(pPict, unit == 0))
+ 	return FALSE;
+ 
+     if (pPict->filter != PictFilterNearest &&
+@@ -392,15 +383,24 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
+ {
+     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+     uint32_t txfilter, txformat, txoffset, txpitch;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+-    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+-    Bool repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
+-	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
+-    int i;
++    unsigned int repeatType;
++    Bool repeat;
++    int i, w, h;
+     struct radeon_exa_pixmap_priv *driver_priv;
+     ACCEL_PREAMBLE();
+ 
++    if (pPict->pDrawable) {
++	w = pPict->pDrawable->width;
++	h = pPict->pDrawable->height;
++	repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    } else {
++	w = h = 1;
++	repeatType = RepeatNormal;
++    }
++
++    repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
++	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
++
+     txpitch = exaGetPixmapPitch(pPix);
+     txoffset = 0;
+ 
+@@ -510,22 +510,6 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
+     if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
+ 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+ 
+-    if (!pSrcPicture->pDrawable)
+-	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-    /* r100 limit should be 2048, there are issues with 2048
+-     * see 197a62704742a4a19736c2637ac92d1dc5ab34ed
+-     */
+-
+-    pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+-
+-    if (pSrcPixmap->drawable.width > 2047 ||
+-	pSrcPixmap->drawable.height > 2047) {
+-	RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
+-			 pSrcPixmap->drawable.width,
+-			 pSrcPixmap->drawable.height));
+-    }
+-
+     pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable);
+ 
+     if (pDstPixmap->drawable.width > 2047 ||
+@@ -535,20 +519,35 @@ static Bool R100CheckComposite(int op, PicturePtr pSrcPicture,
+ 			 pDstPixmap->drawable.height));
+     }
+ 
++    if (pSrcPicture->pDrawable) {
++	/* r100 limit should be 2048, there are issues with 2048
++	 * see 197a62704742a4a19736c2637ac92d1dc5ab34ed
++	 */
++	pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
++
++	if (pSrcPixmap->drawable.width > 2047 ||
++	    pSrcPixmap->drawable.height > 2047) {
++	    RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
++			     pSrcPixmap->drawable.width,
++			     pSrcPixmap->drawable.height));
++	}
++    } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
++
+     if (pMaskPicture) {
+ 	PixmapPtr pMaskPixmap;
+ 
+-	if (!pMaskPicture->pDrawable)
+-	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
++	if (pMaskPicture->pDrawable) {
++	    pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+ 
+-	if (pMaskPixmap->drawable.width > 2047 ||
+-	    pMaskPixmap->drawable.height > 2047) {
+-	    RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
+-			     pMaskPixmap->drawable.width,
+-			     pMaskPixmap->drawable.height));
+-	}
++	    if (pMaskPixmap->drawable.width > 2047 ||
++		pMaskPixmap->drawable.height > 2047) {
++		RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
++				 pMaskPixmap->drawable.width,
++				 pMaskPixmap->drawable.height));
++	    }
++	} else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	    RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+ 
+ 	if (pMaskPicture->componentAlpha) {
+ 	    /* Check if it's component alpha that relies on a source alpha and
+@@ -624,7 +623,8 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
+ 					    PixmapPtr pMask,
+ 					    PixmapPtr pDst)
+ {
+-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    RINFO_FROM_SCREEN(pScreen);
+     uint32_t dst_format, dst_pitch, colorpitch;
+     uint32_t pp_cntl, blendcntl, cblend, ablend;
+     int pixel_shift;
+@@ -648,12 +648,27 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op,
+ 
+     CHECK_OFFSET(pDst, 0x0f, "destination");
+ 
++    if (!pSrc) {
++	pSrc = RADEONSolidPixmap(pScreen, cpu_to_le32(pSrcPicture->pSourcePict->solidFill.color));
++	if (!pSrc)
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++    }
++
+     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
+ 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
+ 
+     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
+ 	return FALSE;
+ 
++    if (pMaskPicture && !pMask) {
++	pMask = RADEONSolidPixmap(pScreen, cpu_to_le32(pMaskPicture->pSourcePict->solidFill.color));
++	if (!pMask) {
++	    if (!pSrcPicture->pDrawable)
++		pScreen->DestroyPixmap(pSrc);
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++	}
++    }
++
+     RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+ 			     pSrc, pMask, pDst);
+ 
diff --git a/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r2xx.patch b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r2xx.patch
new file mode 100644
index 0000000000..9b64565ba6
--- /dev/null
+++ b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r2xx.patch
@@ -0,0 +1,175 @@
+commit 0bda305f7ab2a4720b3fea3f318ab2a73be151e5
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date:   Fri Apr 13 13:28:10 2012 -0400
+
+    EXA: Support acceleration of solid pictures on R2xx.
+    
+    Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+    Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
+
+diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
+index 451a625..7f1a3ff 100644
+--- a/src/radeon_exa_render.c
++++ b/src/radeon_exa_render.c
+@@ -756,17 +756,8 @@ static Bool R200CheckCompositeTexture(PicturePtr pPict,
+ 				      int unit)
+ {
+     unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     int i;
+ 
+-    /* r200 limit should be 2048, there are issues with 2048
+-     * see bug 19269
+-     */
+-
+-    if ((w > 2047) || (h > 2047))
+-	RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
+-
+     for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++)
+     {
+ 	if (R200TexFormats[i].fmt == pPict->format)
+@@ -776,7 +767,7 @@ static Bool R200CheckCompositeTexture(PicturePtr pPict,
+ 	RADEON_FALLBACK(("Unsupported picture format 0x%x\n",
+ 			 (int)pPict->format));
+ 
+-    if (!RADEONCheckTexturePOT(pPict, unit == 0))
++    if (pPict->pDrawable && !RADEONCheckTexturePOT(pPict, unit == 0))
+ 	return FALSE;
+ 
+     if (pPict->filter != PictFilterNearest &&
+@@ -809,15 +800,24 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
+ {
+     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+     uint32_t txfilter, txformat, txoffset, txpitch;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+-    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+-    Bool repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
+-	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
+-    int i;
++    unsigned int repeatType;
++    Bool repeat;
++    int i, w, h;
+     struct radeon_exa_pixmap_priv *driver_priv;
+     ACCEL_PREAMBLE();
+ 
++    if (pPict->pDrawable) {
++	w = pPict->pDrawable->width;
++	h = pPict->pDrawable->height;
++	repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    } else {
++	w = h = 1;
++	repeatType = RepeatNormal;
++    }
++
++    repeat = (repeatType == RepeatNormal || repeatType == RepeatReflect) &&
++	!(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y));
++
+     txpitch = exaGetPixmapPitch(pPix);
+ 
+     txoffset = 0;
+@@ -926,22 +926,6 @@ static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+     if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
+ 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+ 
+-    if (!pSrcPicture->pDrawable)
+-	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-    /* r200 limit should be 2048, there are issues with 2048
+-     * see bug 19269
+-     */
+-
+-    pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+-
+-    if (pSrcPixmap->drawable.width > 2047 ||
+-	pSrcPixmap->drawable.height > 2047) {
+-	RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
+-			 pSrcPixmap->drawable.width,
+-			 pSrcPixmap->drawable.height));
+-    }
+-
+     pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable);
+ 
+     if (pDstPixmap->drawable.width > 2047 ||
+@@ -951,20 +935,35 @@ static Bool R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+ 			 pDstPixmap->drawable.height));
+     }
+ 
++    if (pSrcPicture->pDrawable) {
++	/* r200 limit should be 2048, there are issues with 2048
++	 * see 197a62704742a4a19736c2637ac92d1dc5ab34ed
++	 */
++	pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
++
++	if (pSrcPixmap->drawable.width > 2047 ||
++	    pSrcPixmap->drawable.height > 2047) {
++	    RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
++			     pSrcPixmap->drawable.width,
++			     pSrcPixmap->drawable.height));
++	}
++    } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
++
+     if (pMaskPicture) {
+ 	PixmapPtr pMaskPixmap;
+ 
+-	if (!pMaskPicture->pDrawable)
+-	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
++	if (pMaskPicture->pDrawable) {
++	    pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+ 
+-	if (pMaskPixmap->drawable.width > 2047 ||
+-	    pMaskPixmap->drawable.height > 2047) {
+-	    RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
+-			     pMaskPixmap->drawable.width,
+-			     pMaskPixmap->drawable.height));
+-	}
++	    if (pMaskPixmap->drawable.width > 2047 ||
++		pMaskPixmap->drawable.height > 2047) {
++		RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
++				 pMaskPixmap->drawable.width,
++				 pMaskPixmap->drawable.height));
++	    }
++	} else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	    RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+ 
+ 	if (pMaskPicture->componentAlpha) {
+ 	    /* Check if it's component alpha that relies on a source alpha and
+@@ -997,7 +996,8 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
+ 				PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ 				PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+ {
+-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    RINFO_FROM_SCREEN(pScreen);
+     uint32_t dst_format, dst_pitch;
+     uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch;
+     int pixel_shift;
+@@ -1024,9 +1024,24 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture,
+     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
+ 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
+ 
++    if (!pSrc) {
++	pSrc = RADEONSolidPixmap(pScreen, cpu_to_le32(pSrcPicture->pSourcePict->solidFill.color));
++	if (!pSrc)
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++    }
++
+     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, FALSE, TRUE))
+ 	return FALSE;
+ 
++    if (pMaskPicture && !pMask) {
++	pMask = RADEONSolidPixmap(pScreen, cpu_to_le32(pMaskPicture->pSourcePict->solidFill.color));
++	if (!pMask) {
++	    if (!pSrcPicture->pDrawable)
++		pScreen->DestroyPixmap(pSrc);
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++	}
++    }
++
+     RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+ 			     pSrc, pMask, pDst);
+ 
diff --git a/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r3xx-to-r7xx.patch b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r3xx-to-r7xx.patch
new file mode 100644
index 0000000000..563dac456d
--- /dev/null
+++ b/srcpkgs/xf86-video-ati/patches/0001-exa-support-acceleration-pictures-r3xx-to-r7xx.patch
@@ -0,0 +1,562 @@
+commit d88b9700137ee407c483f263bb55c77cd6f92fef
+Author: Michel Dänzer <michel.daenzer@amd.com>
+Date:   Fri Apr 13 09:35:38 2012 +0200
+
+    EXA: Support acceleration of solid pictures on R3xx-R7xx.
+    
+    Allocate 1x1 scratch pixmaps to hold the solid picture colours.
+    
+    This works around https://bugs.freedesktop.org/show_bug.cgi?id=47266 and might
+    improve performance in other cases as well.
+    
+    Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
+
+diff --git a/src/r600_exa.c b/src/r600_exa.c
+index e1eb62f..c3ae553 100644
+--- a/src/r600_exa.c
++++ b/src/r600_exa.c
+@@ -901,17 +901,8 @@ static Bool R600CheckCompositeTexture(PicturePtr pPict,
+ 				      int op,
+ 				      int unit)
+ {
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+     unsigned int i;
+-    int max_tex_w, max_tex_h;
+-
+-    max_tex_w = 8192;
+-    max_tex_h = 8192;
+-
+-    if ((w > max_tex_w) || (h > max_tex_h))
+-	RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
+ 
+     for (i = 0; i < sizeof(R600TexFormats) / sizeof(R600TexFormats[0]); i++) {
+ 	if (R600TexFormats[i].fmt == pPict->format)
+@@ -951,9 +942,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
+     ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+     struct radeon_accel_state *accel_state = info->accel_state;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+-    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    unsigned int repeatType;
+     unsigned int i;
+     tex_resource_t  tex_res;
+     tex_sampler_t   tex_samp;
+@@ -969,9 +958,16 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
+     }
+ 
+     /* Texture */
++    if (pPict->pDrawable) {
++	tex_res.w               = pPict->pDrawable->width;
++	tex_res.h               = pPict->pDrawable->height;
++	repeatType              = pPict->repeat ? pPict->repeatType : RepeatNone;
++    } else {
++	tex_res.w               = 1;
++	tex_res.h               = 1;
++	repeatType              = RepeatNormal;
++    }
+     tex_res.id                  = unit;
+-    tex_res.w                   = w;
+-    tex_res.h                   = h;
+     tex_res.pitch               = accel_state->src_obj[unit].pitch;
+     tex_res.depth               = 0;
+     tex_res.dim                 = SQ_TEX_DIM_2D;
+@@ -1170,24 +1166,24 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix,
+ 	vs_alu_consts[0] = xFixedToFloat(pPict->transform->matrix[0][0]);
+ 	vs_alu_consts[1] = xFixedToFloat(pPict->transform->matrix[0][1]);
+ 	vs_alu_consts[2] = xFixedToFloat(pPict->transform->matrix[0][2]);
+-	vs_alu_consts[3] = 1.0 / w;
++	vs_alu_consts[3] = 1.0 / tex_res.w;
+ 
+ 	vs_alu_consts[4] = xFixedToFloat(pPict->transform->matrix[1][0]);
+ 	vs_alu_consts[5] = xFixedToFloat(pPict->transform->matrix[1][1]);
+ 	vs_alu_consts[6] = xFixedToFloat(pPict->transform->matrix[1][2]);
+-	vs_alu_consts[7] = 1.0 / h;
++	vs_alu_consts[7] = 1.0 / tex_res.h;
+     } else {
+ 	accel_state->is_transform[unit] = FALSE;
+ 
+ 	vs_alu_consts[0] = 1.0;
+ 	vs_alu_consts[1] = 0.0;
+ 	vs_alu_consts[2] = 0.0;
+-	vs_alu_consts[3] = 1.0 / w;
++	vs_alu_consts[3] = 1.0 / tex_res.w;
+ 
+ 	vs_alu_consts[4] = 0.0;
+ 	vs_alu_consts[5] = 1.0;
+ 	vs_alu_consts[6] = 0.0;
+-	vs_alu_consts[7] = 1.0 / h;
++	vs_alu_consts[7] = 1.0 / tex_res.h;
+     }
+ 
+     /* VS alu constants */
+@@ -1202,33 +1198,30 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+ {
+     uint32_t tmp1;
+     PixmapPtr pSrcPixmap, pDstPixmap;
+-    int max_tex_w, max_tex_h, max_dst_w, max_dst_h;
+ 
+     /* Check for unsupported compositing operations. */
+     if (op >= (int) (sizeof(R600BlendOp) / sizeof(R600BlendOp[0])))
+ 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+ 
+-    if (!pSrcPicture->pDrawable)
+-	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-    pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
++    if (pSrcPicture->pDrawable) {
++	pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+ 
+-    max_tex_w = 8192;
+-    max_tex_h = 8192;
+-    max_dst_w = 8192;
+-    max_dst_h = 8192;
++	if (pSrcPixmap->drawable.width >= 8192 ||
++	    pSrcPixmap->drawable.height >= 8192) {
++	    RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
++			     pSrcPixmap->drawable.width,
++			     pSrcPixmap->drawable.height));
++	}
+ 
+-    if (pSrcPixmap->drawable.width >= max_tex_w ||
+-	pSrcPixmap->drawable.height >= max_tex_h) {
+-	RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
+-			 pSrcPixmap->drawable.width,
+-			 pSrcPixmap->drawable.height));
+-    }
++	if (!R600CheckCompositeTexture(pSrcPicture, pDstPicture, op, 0))
++	    return FALSE;
++    } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+ 
+     pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable);
+ 
+-    if (pDstPixmap->drawable.width >= max_dst_w ||
+-	pDstPixmap->drawable.height >= max_dst_h) {
++    if (pDstPixmap->drawable.width >= 8192 ||
++	pDstPixmap->drawable.height >= 8192) {
+ 	RADEON_FALLBACK(("Dest w/h too large (%d,%d).\n",
+ 			 pDstPixmap->drawable.width,
+ 			 pDstPixmap->drawable.height));
+@@ -1237,38 +1230,35 @@ static Bool R600CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+     if (pMaskPicture) {
+ 	PixmapPtr pMaskPixmap;
+ 
+-	if (!pMaskPicture->pDrawable)
+-	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
++	if (pMaskPicture->pDrawable) {
++	    pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+ 
+-	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+-
+-	if (pMaskPixmap->drawable.width >= max_tex_w ||
+-	    pMaskPixmap->drawable.height >= max_tex_h) {
+-	    RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
+-			     pMaskPixmap->drawable.width,
+-			     pMaskPixmap->drawable.height));
+-	}
++	    if (pMaskPixmap->drawable.width >= 8192 ||
++		pMaskPixmap->drawable.height >= 8192) {
++	      RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
++			       pMaskPixmap->drawable.width,
++			       pMaskPixmap->drawable.height));
++	    }
+ 
+-	if (pMaskPicture->componentAlpha) {
+-	    /* Check if it's component alpha that relies on a source alpha and
+-	     * on the source value.  We can only get one of those into the
+-	     * single source value that we get to blend with.
+-	     */
+-	    if (R600BlendOp[op].src_alpha &&
+-		(R600BlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) !=
+-		(BLEND_ZERO << COLOR_SRCBLEND_shift)) {
+-		RADEON_FALLBACK(("Component alpha not supported with source "
+-				 "alpha and source value blending.\n"));
++	    if (pMaskPicture->componentAlpha) {
++		/* Check if it's component alpha that relies on a source alpha and
++		 * on the source value.  We can only get one of those into the
++		 * single source value that we get to blend with.
++		 */
++		if (R600BlendOp[op].src_alpha &&
++		    (R600BlendOp[op].blend_cntl & COLOR_SRCBLEND_mask) !=
++		    (BLEND_ZERO << COLOR_SRCBLEND_shift)) {
++		    RADEON_FALLBACK(("Component alpha not supported with source "
++				     "alpha and source value blending.\n"));
++		}
+ 	    }
+-	}
+ 
+-	if (!R600CheckCompositeTexture(pMaskPicture, pDstPicture, op, 1))
+-	    return FALSE;
++	    if (!R600CheckCompositeTexture(pMaskPicture, pDstPicture, op, 1))
++		return FALSE;
++	} else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	    RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+     }
+ 
+-    if (!R600CheckCompositeTexture(pSrcPicture, pDstPicture, op, 0))
+-	return FALSE;
+-
+     if (!R600GetDestFormat(pDstPicture, &tmp1))
+ 	return FALSE;
+ 
+@@ -1280,7 +1270,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
+ 				 PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ 				 PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+ {
+-    ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+     struct radeon_accel_state *accel_state = info->accel_state;
+     uint32_t dst_format;
+@@ -1288,15 +1279,21 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
+     shader_config_t vs_conf, ps_conf;
+     struct r600_accel_object src_obj, mask_obj, dst_obj;
+ 
+-    if (pDst->drawable.bitsPerPixel < 8 || pSrc->drawable.bitsPerPixel < 8)
++    if (pDst->drawable.bitsPerPixel < 8 || (pSrc && pSrc->drawable.bitsPerPixel < 8))
+ 	return FALSE;
+ 
++    if (!pSrc) {
++	pSrc = RADEONSolidPixmap(pScreen, pSrcPicture->pSourcePict->solidFill.color);
++	if (!pSrc)
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++    }
++
+ #if defined(XF86DRM_MODE)
+     if (info->cs) {
+ 	src_obj.offset = 0;
+ 	dst_obj.offset = 0;
+-	src_obj.bo = radeon_get_pixmap_bo(pSrc);
+ 	dst_obj.bo = radeon_get_pixmap_bo(pDst);
++	src_obj.bo = radeon_get_pixmap_bo(pSrc);
+ 	dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst);
+ 	src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc);
+ 	dst_obj.surface = radeon_get_pixmap_surface(pDst);
+@@ -1322,7 +1319,16 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
+     dst_obj.bpp = pDst->drawable.bitsPerPixel;
+     dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;
+ 
+-    if (pMask) {
++    if (pMaskPicture) {
++	if (!pMask) {
++	    pMask = RADEONSolidPixmap(pScreen, pMaskPicture->pSourcePict->solidFill.color);
++	    if (!pMask) {
++		if (!pSrcPicture->pDrawable)
++		    pScreen->DestroyPixmap(pSrc);
++		RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++	    }
++	}
++
+ #if defined(XF86DRM_MODE)
+ 	if (info->cs) {
+ 	    mask_obj.offset = 0;
+@@ -1509,11 +1515,9 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture,
+     return TRUE;
+ }
+ 
+-static void R600DoneComposite(PixmapPtr pDst)
++static void R600FinishComposite(ScrnInfoPtr pScrn, PixmapPtr pDst,
++				struct radeon_accel_state *accel_state)
+ {
+-    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+-    RADEONInfoPtr info = RADEONPTR(pScrn);
+-    struct radeon_accel_state *accel_state = info->accel_state;
+     int vtx_size;
+ 
+     if (accel_state->vsync)
+@@ -1527,6 +1531,22 @@ static void R600DoneComposite(PixmapPtr pDst)
+     r600_finish_op(pScrn, vtx_size);
+ }
+ 
++static void R600DoneComposite(PixmapPtr pDst)
++{
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
++    RADEONInfoPtr info = RADEONPTR(pScrn);
++    struct radeon_accel_state *accel_state = info->accel_state;
++
++    R600FinishComposite(pScrn, pDst, accel_state);
++
++    if (!accel_state->src_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->src_pix);
++
++    if (accel_state->msk_pic && !accel_state->msk_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->msk_pix);
++}
++
+ static void R600Composite(PixmapPtr pDst,
+ 			  int srcX, int srcY,
+ 			  int maskX, int maskY,
+@@ -1543,7 +1563,7 @@ static void R600Composite(PixmapPtr pDst,
+ 
+ #ifdef XF86DRM_MODE
+     if (info->cs && CS_FULL(info->cs)) {
+-	R600DoneComposite(info->accel_state->dst_pix);
++	R600FinishComposite(pScrn, pDst, info->accel_state);
+ 	radeon_cs_flush_indirect(pScrn);
+ 	R600PrepareComposite(info->accel_state->composite_op,
+ 			     info->accel_state->src_pic,
+diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c
+index e5c231f..b6cc9e4 100644
+--- a/src/radeon_exa_render.c
++++ b/src/radeon_exa_render.c
+@@ -299,8 +299,8 @@ static Bool RADEONSetupSourceTile(PicturePtr pPict,
+     if (repeatType == RepeatNormal || repeatType == RepeatReflect) {
+ 	Bool badPitch = needMatchingPitch && !RADEONPitchMatches(pPix);
+ 	
+-	int w = pPict->pDrawable->width;
+-	int h = pPict->pDrawable->height;
++	int w = pPict->pDrawable ? pPict->pDrawable->width : 1;
++	int h = pPict->pDrawable ? pPict->pDrawable->height : 1;
+ 	
+ 	if (pPict->transform) {
+ 	    if (badPitch)
+@@ -1112,23 +1112,8 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
+     ScreenPtr pScreen = pDstPict->pDrawable->pScreen;
+     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+-
+     unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
+     int i;
+-    int max_tex_w, max_tex_h;
+-
+-    if (is_r500) {
+-	max_tex_w = 4096;
+-	max_tex_h = 4096;
+-    } else {
+-	max_tex_w = 2048;
+-	max_tex_h = 2048;
+-    }
+-
+-    if ((w > max_tex_w) || (h > max_tex_h))
+-	RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h));
+ 
+     for (i = 0; i < sizeof(R300TexFormats) / sizeof(R300TexFormats[0]); i++)
+     {
+@@ -1139,7 +1124,7 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict,
+ 	RADEON_FALLBACK(("Unsupported picture format 0x%x\n",
+ 			 (int)pPict->format));
+ 
+-    if (!RADEONCheckTexturePOT(pPict, unit == 0)) {
++    if (pPict->pDrawable && !RADEONCheckTexturePOT(pPict, unit == 0)) {
+ 	if (info->cs) {
+     		struct radeon_exa_pixmap_priv *driver_priv;
+ 		PixmapPtr pPix;
+@@ -1181,15 +1166,23 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix,
+ {
+     RINFO_FROM_SCREEN(pPix->drawable.pScreen);
+     uint32_t txfilter, txformat0, txformat1, txoffset, txpitch, us_format = 0;
+-    int w = pPict->pDrawable->width;
+-    int h = pPict->pDrawable->height;
++    int w, h;
+     int i, pixel_shift, out_size = 6;
+-    unsigned int repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    unsigned int repeatType;
+     struct radeon_exa_pixmap_priv *driver_priv;
+     ACCEL_PREAMBLE();
+ 
+     TRACE;
+ 
++    if (pPict->pDrawable) {
++	w = pPict->pDrawable->width;
++	h = pPict->pDrawable->height;
++	repeatType = pPict->repeat ? pPict->repeatType : RepeatNone;
++    } else {
++	w = h = 1;
++	repeatType = RepeatNormal;
++    }
++
+     txpitch = exaGetPixmapPitch(pPix);
+     txoffset = 0;
+ 
+@@ -1394,11 +1387,6 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+     if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
+ 	RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op));
+ 
+-    if (!pSrcPicture->pDrawable)
+-	RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
+-
+-    pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
+-
+     if (IS_R500_3D) {
+ 	max_tex_w = 4096;
+ 	max_tex_h = 4096;
+@@ -1416,13 +1404,6 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+ 	}
+     }
+ 
+-    if (pSrcPixmap->drawable.width > max_tex_w ||
+-	pSrcPixmap->drawable.height > max_tex_h) {
+-	RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
+-			 pSrcPixmap->drawable.width,
+-			 pSrcPixmap->drawable.height));
+-    }
+-
+     pDstPixmap = RADEONGetDrawablePixmap(pDstPicture->pDrawable);
+ 
+     if (pDstPixmap->drawable.width > max_dst_w ||
+@@ -1432,20 +1413,32 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP
+ 			 pDstPixmap->drawable.height));
+     }
+ 
++    if (pSrcPicture->pDrawable) {
++	pSrcPixmap = RADEONGetDrawablePixmap(pSrcPicture->pDrawable);
++
++	if (pSrcPixmap->drawable.width > max_tex_w ||
++	    pSrcPixmap->drawable.height > max_tex_h) {
++	    RADEON_FALLBACK(("Source w/h too large (%d,%d).\n",
++			     pSrcPixmap->drawable.width,
++			     pSrcPixmap->drawable.height));
++	}
++    } else if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
++
+     if (pMaskPicture) {
+ 	PixmapPtr pMaskPixmap;
+ 
+-	if (!pMaskPicture->pDrawable)
+-	    RADEON_FALLBACK(("Solid or gradient pictures not supported yet\n"));
++	if (pMaskPicture->pDrawable) {
++	    pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+ 
+-	pMaskPixmap = RADEONGetDrawablePixmap(pMaskPicture->pDrawable);
+-
+-	if (pMaskPixmap->drawable.width > max_tex_w ||
+-	    pMaskPixmap->drawable.height > max_tex_h) {
+-	    RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
+-			     pMaskPixmap->drawable.width,
+-			     pMaskPixmap->drawable.height));
+-	}
++	    if (pMaskPixmap->drawable.width > max_tex_w ||
++		pMaskPixmap->drawable.height > max_tex_h) {
++	      RADEON_FALLBACK(("Mask w/h too large (%d,%d).\n",
++			       pMaskPixmap->drawable.width,
++			       pMaskPixmap->drawable.height));
++	    }
++	} else if (pMaskPicture->pSourcePict->type != SourcePictTypeSolidFill)
++	    RADEON_FALLBACK(("Gradient pictures not supported yet\n"));
+ 
+ 	if (pMaskPicture->componentAlpha) {
+ 	    /* Check if it's component alpha that relies on a source alpha and
+@@ -1479,7 +1472,8 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
+ 				PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ 				PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+ {
+-    RINFO_FROM_SCREEN(pDst->drawable.pScreen);
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    RINFO_FROM_SCREEN(pScreen);
+     uint32_t dst_format, dst_pitch;
+     uint32_t txenable, colorpitch;
+     uint32_t blendcntl, output_fmt;
+@@ -1508,9 +1502,24 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
+     if (((dst_pitch >> pixel_shift) & 0x7) != 0)
+ 	RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch));
+ 
++    if (!pSrc) {
++	pSrc = RADEONSolidPixmap(pScreen, cpu_to_le32(pSrcPicture->pSourcePict->solidFill.color));
++	if (!pSrc)
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++    }
++
+     if (!RADEONSetupSourceTile(pSrcPicture, pSrc, TRUE, FALSE))
+ 	return FALSE;
+ 
++    if (pMaskPicture && !pMask) {
++	pMask = RADEONSolidPixmap(pScreen, cpu_to_le32(pMaskPicture->pSourcePict->solidFill.color));
++	if (!pMask) {
++	    if (!pSrcPicture->pDrawable)
++		pScreen->DestroyPixmap(pSrc);
++	    RADEON_FALLBACK("Failed to create solid scratch pixmap\n");
++	}
++    }
++
+     RADEONPrepareCompositeCS(op, pSrcPicture, pMaskPicture, pDstPicture,
+ 			     pSrc, pMask, pDst);
+ 
+@@ -2132,7 +2141,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture,
+     return TRUE;
+ }
+ 
+-static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
++static void FUNC_NAME(RadeonFinishComposite)(PixmapPtr pDst)
+ {
+     RINFO_FROM_SCREEN(pDst->drawable.pScreen);
+     ACCEL_PREAMBLE();
+@@ -2179,6 +2188,20 @@ static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
+     LEAVE_DRAW(0);
+ }
+ 
++static void FUNC_NAME(RadeonDoneComposite)(PixmapPtr pDst)
++{
++    ScreenPtr pScreen = pDst->drawable.pScreen;
++    RINFO_FROM_SCREEN(pScreen);
++    struct radeon_accel_state *accel_state = info->accel_state;
++
++    FUNC_NAME(RadeonFinishComposite)(pDst);
++
++    if (!accel_state->src_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->src_pix);
++
++    if (accel_state->msk_pic && !accel_state->msk_pic->pDrawable)
++	pScreen->DestroyPixmap(accel_state->msk_pix);
++}
+ 
+ #ifdef ACCEL_CP
+ 
+@@ -2257,7 +2280,7 @@ static void FUNC_NAME(RadeonCompositeTile)(ScrnInfoPtr pScrn,
+     if ((info->cs && CS_FULL(info->cs)) ||
+ 	(!info->cs && (info->cp->indirectBuffer->used + 4 * 32) >
+ 	 info->cp->indirectBuffer->total)) {
+-	FUNC_NAME(RadeonDoneComposite)(info->accel_state->dst_pix);
++	FUNC_NAME(RadeonFinishComposite)(info->accel_state->dst_pix);
+ 	if (info->cs)
+ 	    radeon_cs_flush_indirect(pScrn);
+ 	else
+diff --git a/src/radeon_exa_shared.c b/src/radeon_exa_shared.c
+index be1d2fa..28dc335 100644
+--- a/src/radeon_exa_shared.c
++++ b/src/radeon_exa_shared.c
+@@ -126,6 +126,25 @@ Bool RADEONCheckBPP(int bpp)
+ 	return FALSE;
+ }
+ 
++PixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid)
++{
++    PixmapPtr pPix = pScreen->CreatePixmap(pScreen, 1, 1, 32, 0);
++    struct radeon_bo *bo;
++
++    exaMoveInPixmap(pPix);
++    bo = radeon_get_pixmap_bo(pPix);
++
++    if (radeon_bo_map(bo, 1)) {
++	pScreen->DestroyPixmap(pPix);
++	return NULL;
++    }
++
++    memcpy(bo->ptr, &solid, 4);
++    radeon_bo_unmap(bo);
++
++    return pPix;
++}
++
+ static Bool radeon_vb_get(ScrnInfoPtr pScrn)
+ {
+     RADEONInfoPtr info = RADEONPTR(pScrn);
+diff --git a/src/radeon_exa_shared.h b/src/radeon_exa_shared.h
+index 7b8b5ca..60a1045 100644
+--- a/src/radeon_exa_shared.h
++++ b/src/radeon_exa_shared.h
+@@ -40,6 +40,7 @@ extern void RADEONVlineHelperClear(ScrnInfoPtr pScrn);
+ extern void RADEONVlineHelperSet(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2);
+ extern Bool RADEONValidPM(uint32_t pm, int bpp);
+ extern Bool RADEONCheckBPP(int bpp);
++extern PixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid);
+ 
+ #define RADEON_TRACE_FALL 0
+ #define RADEON_TRACE_DRAW 0
diff --git a/srcpkgs/xf86-video-ati/template b/srcpkgs/xf86-video-ati/template
index a1b3f9940d..c2c03047bd 100644
--- a/srcpkgs/xf86-video-ati/template
+++ b/srcpkgs/xf86-video-ati/template
@@ -1,6 +1,8 @@
 # Template build file for 'xf86-video-ati'.
 pkgname=xf86-video-ati
 version=6.14.4
+revision=1
+patch_args="-Np1"
 distfiles="${XORG_SITE}/driver/$pkgname-$version.tar.bz2"
 build_style=gnu-configure
 short_desc="Xorg ATI Radeon video driver"