[Xorg-driver-geode] [PATCH 4/4] Fix the Nautilus file broswer misrendering issue

Huang, FrankR FrankR.Huang at amd.com
Thu Aug 5 20:16:02 PDT 2010


This is patch 4 final this week.
This one has fixed several bugs below:
1)google chrome hang
2)Some website using repeat for source picture with PictOpSrc. To sum up, right now this patch has gracefully solved the Nautilus bug and some special rendering under PictOpSrc and PictOpOver I will describe all special conditions I met
Websites for test before and after this patch:
	1)http://daduke.org (greater srcX and srcY)
	2)http://bjdns2.cncmax.cn (negative srcX and srcY)


From: Frank Huang <frankr.huang at amd.com>

*When the srcX or srcY is greater than source width or source height
(or negative),the driver should do the correct region to render. Add a
function lx_composite_onepass_special to handle this. The source start
point should be calculated by a modulus operation.
*If the opeartion is with a shifted position src, then adjust the
operation region based on the operations src width and height
parameters. The rotation condition should be excluded. This part still
need investigation

Signed-off-by: Frank Huang <frankr.huang at amd.com>
---
 src/lx_exa.c |  195 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 174 insertions(+), 21 deletions(-)

diff --git a/src/lx_exa.c b/src/lx_exa.c
index e8a001a..83187fb 100644
--- a/src/lx_exa.c
+++ b/src/lx_exa.c
@@ -787,6 +787,13 @@ get_op_type(struct exa_format_t *src, struct exa_format_t *dst, int type)
  * ifdefed out until such time that we are sure its not needed
  */
 
+#define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \
+  (exaGetPixmapPitch((px)) * (y)) + \
+  ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) )
+
+#define GetSrcOffset(_x, _y) (exaScratch.srcOffset + ((_y) * exaScratch.srcPitch) + \
+			      ((_x) * exaScratch.srcBpp))
+
 static void
 lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
     unsigned long srcOffset, int width, int height)
@@ -815,6 +822,82 @@ lx_composite_onepass(PixmapPtr pxDst, unsigned long dstOffset,
     gp_screen_to_screen_convert(dstOffset, srcOffset, width, height, 0);
 }
 
+static void
+lx_composite_onepass_special(PixmapPtr pxDst, int width, int height, int opX,
+    int opY, int srcX, int srcY)
+{
+    struct blend_ops_t *opPtr;
+    int apply, type;
+    int opWidth, opHeight;
+    int optempX, optempY;
+    unsigned int dstOffset, srcOffset = 0;
+
+    optempX = opX;
+    optempY = opY;
+
+    /* Make sure srcX and srcY are in source region */
+    srcX = ((srcX % (int)exaScratch.srcWidth) + (int)exaScratch.srcWidth)
+	% (int)exaScratch.srcWidth;
+    srcY = ((srcY % (int)exaScratch.srcHeight) + (int)exaScratch.srcHeight)
+	% (int)exaScratch.srcHeight;
+
+    opWidth = exaScratch.srcWidth - srcX;
+    opHeight = exaScratch.srcHeight -  srcY;
+
+    srcOffset = GetSrcOffset(srcX, srcY);
+
+    if (width < opWidth)
+	opWidth = width;
+    if (height < opHeight)
+	opHeight = height;
+
+    while (1) {
+	gp_wait_until_idle();
+	dstOffset = GetPixmapOffset(pxDst, optempX, optempY);
+	opPtr = &lx_alpha_ops[exaScratch.op * 2];
+	apply = (exaScratch.dstFormat->alphabits != 0 &&
+	    exaScratch.srcFormat->alphabits != 0) ?
+	    CIMGP_APPLY_BLEND_TO_ALL : CIMGP_APPLY_BLEND_TO_RGB;
+	gp_declare_blt(0);
+	gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt));
+	gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch);
+	lx_set_source_format(exaScratch.srcFormat->fmt,
+	    exaScratch.dstFormat->fmt);
+	type = get_op_type(exaScratch.srcFormat, exaScratch.dstFormat,
+	    opPtr->type);
+	gp_set_alpha_operation(opPtr->operation, type, opPtr->channel,
+	    apply, 0);
+	gp_screen_to_screen_convert(dstOffset, srcOffset, opWidth, opHeight, 0);
+
+	optempX += opWidth;
+	if (optempX >= opX + width) {
+	    optempX = opX;
+	    optempY += opHeight;
+	    if (optempY >= opY + height)
+		break;
+	}
+	if (optempX == opX) {
+	    srcOffset = GetSrcOffset(srcX, 0);
+	    opWidth = ((opX + width) - optempX) > (exaScratch.srcWidth - srcX)
+		? (exaScratch.srcWidth - srcX) : ((opX + width) - optempX);
+	    opHeight = ((opY + height) - optempY) > exaScratch.srcHeight
+		? exaScratch.srcHeight : ((opY + height) - optempY);
+	} else if (optempY == opY) {
+	    srcOffset = GetSrcOffset(0, srcY);
+	    opWidth = ((opX + width) - optempX) > exaScratch.srcWidth
+		? exaScratch.srcWidth : ((opX + width) - optempX);
+	    opHeight = ((opY + height) - optempY) > (exaScratch.srcHeight -
+		srcY) ? (exaScratch.srcHeight - srcY) : ((opY + height) - optempY);
+	} else {
+	    srcOffset = GetSrcOffset(0, 0);
+	    opWidth = ((opX + width) - optempX) > exaScratch.srcWidth
+		? exaScratch.srcWidth : ((opX + width) - optempX);
+	    opHeight = ((opY + height) - optempY) > exaScratch.srcHeight
+		? exaScratch.srcHeight : ((opY + height) - optempY);
+	}
+    }
+}
+
 /* This function handles the multipass blend functions */
 
 static void
@@ -933,13 +1016,6 @@ lx_do_composite_mask(PixmapPtr pxDst, unsigned long dstOffset,
 	exaScratch.srcPitch, opPtr->operation, exaScratch.fourBpp);
 }
 
-#define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \
-  (exaGetPixmapPitch((px)) * (y)) + \
-  ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) )
-
-#define GetSrcOffset(_x, _y) (exaScratch.srcOffset + ((_y) * exaScratch.srcPitch) + \
-			      ((_x) * exaScratch.srcBpp))
-
 static void
 lx_do_composite_mask_opover(PixmapPtr pxDst, unsigned long dstOffset,
     unsigned int maskOffset, int width, int height, int opX, int opY,
@@ -1122,17 +1198,68 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
      * and maskY coordinate are negative or greater than
      * exaScratch.srcWidth and exaScratch.srcHeight */
 
-
     if (exaScratch.type == COMP_TYPE_MASK) {
 	if ((exaScratch.srcWidth - maskX) < opWidth)
 	    opWidth = exaScratch.srcWidth - maskX;
 	if ((exaScratch.srcHeight - maskY) < opHeight)
 	    opHeight = exaScratch.srcHeight - maskY;
     } else {
-	if (exaScratch.srcWidth < opWidth)
-	    opWidth = exaScratch.srcWidth;
-	if (exaScratch.srcHeight < opHeight)
-	    opHeight = exaScratch.srcHeight;
+	    if (exaScratch.type == COMP_TYPE_ONEPASS) {
+		/* This is the condition srcX or/and srcY is/are out of source
+		 * region */
+		if (((srcX >= 0 && srcY >= exaScratch.srcHeight)
+		    || (srcX >= exaScratch.srcWidth  && srcY >= 0)) &&
+		    (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) {
+		    if (exaScratch.repeat == 1) {
+			opWidth = width;
+			opHeight = height;
+		    } else {
+			if (exaScratch.op == PictOpOver)
+			    return ;
+			else {
+			    exaScratch.op = PictOpClear;
+			    opWidth = width;
+			    opHeight = height;
+			}
+		    }
+		/* This is the condition srcX or/and srcY is/are in the source
+		 * region */
+		} else if (srcX >= 0 && srcY >= 0 &&
+		    (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) {
+		    if (exaScratch.repeat == 1) {
+			opWidth = width;
+			opHeight = height;
+		    } else {
+			if ((exaScratch.srcWidth - srcX) < opWidth)
+			    opWidth = exaScratch.srcWidth - srcX;
+			if ((exaScratch.srcHeight - srcY) < opHeight)
+			    opHeight = exaScratch.srcHeight - srcY;
+		    }
+		/* This is the condition srcX or/and srcY is/are negative */
+		} else if ((srcX < 0 || srcY < 0) &&
+		    (exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)) {
+		    if (exaScratch.repeat == 1) {
+			opWidth = width;
+			opHeight = height;
+		    } else {
+			/* Have not met this condition till now */
+			return ;
+		    }
+		} else {
+		    if (exaScratch.srcWidth < opWidth)
+			opWidth = exaScratch.srcWidth;
+		    if (exaScratch.srcHeight < opHeight)
+			opHeight = exaScratch.srcHeight;
+		}
+	    } else {
+		if (exaScratch.rotate == RR_Rotate_180) {
+		} else {
+		    if ((exaScratch.srcWidth - srcY) < opWidth)
+			opWidth = exaScratch.srcWidth - srcY;
+		    if ((exaScratch.srcHeight - srcX) < opHeight)
+			opHeight = exaScratch.srcHeight - srcX;
+		}
+	    }
     }
 
     while (1) {
@@ -1144,7 +1271,6 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
 	case COMP_TYPE_MASK:{
 		int direction =
 		    (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1;
-
 		maskflag = 1;
 		if (direction == 1) {
 		    dstOffset =
@@ -1168,8 +1294,14 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
 	    break;
 
 	case COMP_TYPE_ONEPASS:
-	    lx_composite_onepass(pxDst, dstOffset, srcOffset, opWidth,
-		opHeight);
+	    if ((exaScratch.op == PictOpOver || exaScratch.op == PictOpSrc)
+		&& (exaScratch.repeat == 1)) {
+		lx_composite_onepass_special(pxDst, opWidth, opHeight, opX, opY,
+		    srcX, srcY);
+		return ;
+	    } else
+		lx_composite_onepass(pxDst, dstOffset, srcOffset, opWidth,
+		    opHeight);
 	    break;
 
 	case COMP_TYPE_TWOPASS:
@@ -1204,27 +1336,48 @@ lx_do_composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
 	    /* Use the PictOpClear to make other non-blending region(out of
 	     * mask region) to be black if the op is PictOpSrc or
 	     * PictOpClear */
-	    if (!exaScratch.maskrepeat)
+	    if (!exaScratch.maskrepeat) {
 		if ((exaScratch.op == PictOpClear) ||
 		    (exaScratch.op == PictOpSrc)) {
 		    exaScratch.op = PictOpClear;
 		    exaScratch.type = COMP_TYPE_ONEPASS;
 		} else if (exaScratch.op == PictOpOver)
 		    break;
+	    }
 	} else {
-	    opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ?
-		exaScratch.srcWidth : (dstX + width) - opX;
-	    opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ?
-		exaScratch.srcHeight : (dstY + height) - opY;
+	    if (exaScratch.type == COMP_TYPE_ONEPASS) {
+		if (srcX >= 0 && srcY >= 0 && (exaScratch.op == PictOpOver ||
+		    exaScratch.op == PictOpSrc || exaScratch.op ==
+		    PictOpClear)) {
+		    opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth -
+			srcX) ? (exaScratch.srcWidth - srcX) : (dstX + width)
+			- opX;
+		    opHeight = ((dstY + height) - opY) >
+		    (exaScratch.srcHeight - srcY) ?
+		    (exaScratch.srcHeight - srcY) : (dstY + height) - opY;
+		} else {
+		opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ?
+		    exaScratch.srcWidth : (dstX + width) - opX;
+		opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ?
+		    exaScratch.srcHeight : (dstY + height) - opY;
+		}
+	    } else {
+		opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - srcY)
+		    ? (exaScratch.srcWidth - srcY) : (dstX + width) - opX;
+		opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - srcX
+		    ) ? (exaScratch.srcHeight - srcX) : (dstY + height) - opY;
+	    }
+
 	    /* Use the PictOpClear to make other non-blending region(out of
 	     * source region) to be black if the op is PictOpSrc or
 	     * PictOpClear. Special attention to rotation condition */
-	    if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS))
+	    if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ONEPASS)) {
 		if ((exaScratch.op == PictOpClear) ||
 		    (exaScratch.op == PictOpSrc))
 		    exaScratch.op = PictOpClear;
 		else
 		    break;
+	    }
 	    if (!exaScratch.repeat && (exaScratch.type == COMP_TYPE_ROTATE))
 		    break;
 	}
-- 
1.7.1




More information about the Xorg-driver-geode mailing list