xf86-video-intel: 2 commits - uxa/uxa-render.c

Chris Wilson ickle at kemper.freedesktop.org
Sat May 8 11:56:15 PDT 2010


 uxa/uxa-render.c |  232 ++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 198 insertions(+), 34 deletions(-)

New commits:
commit 848ab66384508c3ad3e5fb4884e4527f3ebd3bde
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat May 8 18:36:55 2010 +0100

    uxa: Transform composites with a simple translation into a blit
    
    We can also convert a composite with an integer translation into a
    blit, so long as the sample extents remains within the source.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index b2e88c4..3112677 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -1142,15 +1142,15 @@ compatible_formats (CARD8 op, PicturePtr dst, PicturePtr src)
 }
 
 static int
-drawable_contains (DrawablePtr drawable, int x1, int y1, int x2, int y2)
+drawable_contains (DrawablePtr drawable, int x, int y, int w, int h)
 {
-	if (x1 < 0 || y1 < 0)
+	if (x < 0 || y < 0)
 		return FALSE;
 
-	if (x2 > drawable->width)
+	if (x + w > drawable->width)
 		return FALSE;
 
-	if (y2 > drawable->height)
+	if (y + h > drawable->height)
 		return FALSE;
 
 	return TRUE;
@@ -1171,15 +1171,16 @@ uxa_composite(CARD8 op,
 	Bool saveSrcRepeat = pSrc->repeat;
 	Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
 	RegionRec region;
+	int tx, ty;
 
 	if (uxa_screen->swappedOut)
 		goto fallback;
 
 	/* Remove repeat in source if useless */
-	if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform &&
+	if (pSrc->pDrawable && pSrc->repeat &&
+	    transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
 	    (pSrc->pDrawable->width > 1 || pSrc->pDrawable->height > 1) &&
-	    xSrc >= 0 && (xSrc + width) <= pSrc->pDrawable->width &&
-	    ySrc >= 0 && (ySrc + height) <= pSrc->pDrawable->height)
+	    drawable_contains(pSrc->pDrawable, xSrc + tx, ySrc + ty, width, height))
 		pSrc->repeat = 0;
 
 	if (!pMask) {
@@ -1205,12 +1206,15 @@ uxa_composite(CARD8 op,
 								width, height);
 				if (ret == 1)
 					goto done;
-			} else if (!pSrc->repeat && !pSrc->transform &&
-				   drawable_contains(pSrc->pDrawable, xSrc, ySrc, xSrc + width, ySrc + height)) {
+			} else if (!pSrc->repeat &&
+				   transform_is_integer_translation(pSrc->transform, &tx, &ty) &&
+				   drawable_contains(pSrc->pDrawable,
+						     xSrc + tx, ySrc + ty,
+						     width, height)) {
 				xDst += pDst->pDrawable->x;
 				yDst += pDst->pDrawable->y;
-				xSrc += pSrc->pDrawable->x;
-				ySrc += pSrc->pDrawable->y;
+				xSrc += pSrc->pDrawable->x + tx;
+				ySrc += pSrc->pDrawable->y + ty;
 
 				if (!miComputeCompositeRegion
 				    (&region, pSrc, pMask, pDst, xSrc, ySrc,
commit a7b800513fcc94e063dfd68d2f63b6bab7fae47d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Apr 14 21:14:34 2010 +0100

    uxa: Extract sub-region from in-memory buffers.
    
    If the buffer is too large or not suitable for a GPU operation, we
    currently fallback and perform the composite on the CPU. An alternative
    is too extract the small region out of the source (as usually the
    sample extents are much smaller than the actual surface size) and try
    the composite with the new surface.
    
    The effect is particularly noticeable on pathological websites that use
    very large background images. For example, http://www.woodtv.com/ uses a
    1299x15000 pattern that is obscured by another opaque pattern.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c
index 30934d0..b2e88c4 100644
--- a/uxa/uxa-render.c
+++ b/uxa/uxa-render.c
@@ -577,17 +577,142 @@ uxa_acquire_pattern(ScreenPtr pScreen,
 	}
 }
 
+static Bool
+transform_is_integer_translation(PictTransformPtr t, int *tx, int *ty)
+{
+	if (t == NULL) {
+		*tx = *ty = 0;
+		return TRUE;
+	}
+
+	if (t->matrix[0][0] != IntToxFixed(1) ||
+	    t->matrix[0][1] != 0 ||
+	    t->matrix[1][0] != 0 ||
+	    t->matrix[1][1] != IntToxFixed(1) ||
+	    t->matrix[2][0] != 0 ||
+	    t->matrix[2][1] != 0)
+		return FALSE;
+
+	if (xFixedFrac(t->matrix[0][2]) != 0 ||
+	    xFixedFrac(t->matrix[1][2]) != 0)
+		return FALSE;
+
+	*tx = xFixedToInt(t->matrix[0][2]);
+	*ty = xFixedToInt(t->matrix[1][2]);
+	return TRUE;
+}
+
+static PicturePtr
+uxa_render_picture(ScreenPtr screen,
+		   PicturePtr src,
+		   INT16 x, INT16 y,
+		   CARD16 width, CARD16 height)
+{
+	PicturePtr picture;
+	pixman_format_code_t format;
+	int ret = 0;
+
+	format = src->format |
+		(BitsPerPixel(src->pDrawable->depth) << 24);
+
+	picture = uxa_picture_for_pixman_format(screen, format, width, height);
+	if (!picture)
+		return 0;
+
+	if (uxa_prepare_access(picture->pDrawable, UXA_ACCESS_RW)) {
+		if (uxa_prepare_access(src->pDrawable, UXA_ACCESS_RO)) {
+			ret = 1;
+			fbComposite(PictOpSrc, src, NULL, picture,
+				    x, y, 0, 0, 0, 0, width, height);
+			uxa_finish_access(src->pDrawable);
+		}
+		uxa_finish_access(picture->pDrawable);
+	}
+
+	if (!ret) {
+		FreePicture(picture, 0);
+		return 0;
+	}
+
+	return picture;
+}
+
+static PicturePtr
+uxa_acquire_drawable(ScreenPtr pScreen,
+		     PicturePtr pSrc,
+		     INT16 x, INT16 y,
+		     CARD16 width, CARD16 height,
+		     INT16 * out_x, INT16 * out_y,
+		     Bool force)
+{
+	PixmapPtr pPixmap;
+	PicturePtr pDst;
+	GCPtr pGC;
+	int depth, error;
+	int tx, ty;
+
+	if (!force && uxa_drawable_is_offscreen(pSrc->pDrawable)) {
+		*out_x = x + pSrc->pDrawable->x;
+		*out_y = y + pSrc->pDrawable->y;
+		return pSrc;
+	}
+
+	depth = pSrc->pDrawable->depth;
+	if (depth == 1 || !transform_is_integer_translation(pSrc->transform, &tx, &ty)) {
+		/* XXX extract the sample extents and do the transformation on the GPU */
+		pDst = uxa_render_picture(pScreen, pSrc, x, y, width, height);
+		goto done;
+	}
+
+	pPixmap = pScreen->CreatePixmap(pScreen, width, height, depth, 0);
+	if (!pPixmap)
+		return 0;
+
+	/* Skip the copy if the result remains in memory and not a bo */
+	if (!uxa_drawable_is_offscreen(&pPixmap->drawable)) {
+		pScreen->DestroyPixmap(pPixmap);
+		*out_x = x + pSrc->pDrawable->x;
+		*out_y = y + pSrc->pDrawable->y;
+		return pSrc;
+	}
+
+	pGC = GetScratchGC(depth, pScreen);
+	if (!pGC) {
+		pScreen->DestroyPixmap(pPixmap);
+		return 0;
+	}
+
+	ValidateGC(&pPixmap->drawable, pGC);
+	pGC->ops->CopyArea(pSrc->pDrawable, &pPixmap->drawable, pGC,
+			   x + tx, y + ty, width, height, 0, 0);
+	FreeScratchGC(pGC);
+
+	pDst = CreatePicture(0, &pPixmap->drawable,
+				 PictureMatchFormat(pScreen, depth, pSrc->format),
+				 0, 0, serverClient, &error);
+	pScreen->DestroyPixmap(pPixmap);
+	ValidatePicture(pDst);
+
+done:
+	pDst->componentAlpha = pSrc->componentAlpha;
+	*out_x = x;
+	*out_y = y;
+	return pDst;
+}
+
 static PicturePtr
 uxa_acquire_source(ScreenPtr pScreen,
 		   PicturePtr pPict,
 		   INT16 x, INT16 y,
-		   CARD16 width, CARD16 height, INT16 * out_x, INT16 * out_y)
+		   CARD16 width, CARD16 height,
+		   INT16 * out_x, INT16 * out_y,
+		   Bool force)
 {
-	if (pPict->pDrawable) {
-		*out_x = x + pPict->pDrawable->x;
-		*out_y = y + pPict->pDrawable->y;
-		return pPict;
-	}
+	if (pPict->pDrawable)
+		return uxa_acquire_drawable(pScreen, pPict,
+					    x, y, width, height,
+					    out_x, out_y,
+					    force);
 
 	*out_x = 0;
 	*out_y = 0;
@@ -599,13 +724,15 @@ static PicturePtr
 uxa_acquire_mask(ScreenPtr pScreen,
 		 PicturePtr pPict,
 		 INT16 x, INT16 y,
-		 INT16 width, INT16 height, INT16 * out_x, INT16 * out_y)
+		 INT16 width, INT16 height,
+		 INT16 * out_x, INT16 * out_y,
+		 Bool force)
 {
-	if (pPict->pDrawable) {
-		*out_x = x + pPict->pDrawable->x;
-		*out_y = y + pPict->pDrawable->y;
-		return pPict;
-	}
+	if (pPict->pDrawable)
+		return uxa_acquire_drawable(pScreen, pPict,
+					    x, y, width, height,
+					    out_x, out_y,
+					    force);
 
 	*out_x = 0;
 	*out_y = 0;
@@ -736,33 +863,41 @@ uxa_try_driver_composite(CARD8 op,
 			 PicturePtr pSrc,
 			 PicturePtr pMask,
 			 PicturePtr pDst,
-			 INT16 xSrc,
-			 INT16 ySrc,
-			 INT16 xMask,
-			 INT16 yMask,
-			 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+			 INT16 xSrc, INT16 ySrc,
+			 INT16 xMask, INT16 yMask,
+			 INT16 xDst, INT16 yDst,
+			 CARD16 width, CARD16 height)
 {
 	uxa_screen_t *uxa_screen = uxa_get_screen(pDst->pDrawable->pScreen);
 	RegionRec region;
 	BoxPtr pbox;
 	int nbox;
+	INT16 _xSrc = xSrc, _ySrc = ySrc;
+	INT16 _xMask = xMask, _yMask = yMask;
 	int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
 	PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
 	PicturePtr localSrc, localMask = NULL;
 
+	pDstPix =
+	    uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
+	if (!pDstPix)
+		return -1;
+
 	xDst += pDst->pDrawable->x;
 	yDst += pDst->pDrawable->y;
 
 	localSrc = uxa_acquire_source(pDst->pDrawable->pScreen,
 				      pSrc, xSrc, ySrc, width, height,
-				      &xSrc, &ySrc);
+				      &xSrc, &ySrc,
+				      FALSE);
 	if (!localSrc)
 		return 0;
 
 	if (pMask) {
 		localMask = uxa_acquire_mask(pDst->pDrawable->pScreen,
 					     pMask, xMask, yMask, width, height,
-					     &xMask, &yMask);
+					     &xMask, &yMask,
+					     FALSE);
 		if (!localMask) {
 			if (localSrc != pSrc)
 				FreePicture(localSrc, 0);
@@ -771,9 +906,37 @@ uxa_try_driver_composite(CARD8 op,
 		}
 	}
 
+recheck:
 	if (uxa_screen->info->check_composite &&
 	    !(*uxa_screen->info->check_composite) (op, localSrc, localMask,
 						   pDst)) {
+		if (localSrc == pSrc || (localMask && localMask == pMask)) {
+			if (localSrc == pSrc) {
+				localSrc = uxa_acquire_source(pDst->pDrawable->pScreen,
+							      pSrc, _xSrc, _ySrc, width, height,
+							      &xSrc, &ySrc, TRUE);
+				if (!localSrc || localSrc == pSrc) {
+					if (localMask && localMask != pMask)
+						FreePicture(localMask, 0);
+					return -(localSrc == pSrc);
+				}
+			}
+
+			if (localMask && localMask == pMask) {
+				localMask = uxa_acquire_mask(pDst->pDrawable->pScreen,
+							     pMask, _xMask, _yMask, width, height,
+							     &xMask, &yMask, TRUE);
+				if (!localMask || localMask == pMask) {
+					if (localSrc != pSrc)
+						FreePicture(localSrc, 0);
+
+					return -(localMask == pMask);
+				}
+			}
+
+			goto recheck;
+		}
+
 		if (localSrc != pSrc)
 			FreePicture(localSrc, 0);
 		if (localMask && localMask != pMask)
@@ -793,9 +956,6 @@ uxa_try_driver_composite(CARD8 op,
 		return 1;
 	}
 
-	pDstPix =
-	    uxa_get_offscreen_pixmap(pDst->pDrawable, &dst_off_x, &dst_off_y);
-
 	pSrcPix = uxa_get_offscreen_pixmap(localSrc->pDrawable,
 					   &src_off_x, &src_off_y);
 
@@ -803,7 +963,7 @@ uxa_try_driver_composite(CARD8 op,
 		pMaskPix = uxa_get_offscreen_pixmap(localMask->pDrawable,
 						    &mask_off_x, &mask_off_y);
 
-	if (!pDstPix || !pSrcPix || (localMask && !pMaskPix)) {
+	if (!pSrcPix || (localMask && !pMaskPix)) {
 		REGION_UNINIT(pDst->pDrawable->pScreen, &region);
 
 		if (localSrc != pSrc)


More information about the xorg-commit mailing list