From: Frank Huang Subject: [LX] 1.Change the srcColor type from unsigned int to unsigned long for 32 bit color value use(for example. ARGB32) 2.Add the maskrepeat to record if the mask picture is repeatable 3.Correct the PictOpOver operation in lx_alpha_ops struct 4.Return FALSE in lx_check_composite() for every FALSE condition in lx_prepare_compo site(), forbidding the pixmap migration as soon as possible 5.For PictOpOver operation, get the source color from the source pixmap. If that is RGB565, convert is to ARGB32; If that is ARGB32, get the first pixel color 6.Correct the PictOpSrc and PictOpOver operation with mask value 7.Add a fucntion lx_do_composite_maks_opover() to handle the PictOpOver condition with source ARGB32 and maks A8 8.Fix the progressbar and scrollbar bug --- xf86-video-geode.orig/src/lx_exa.c 2010-06-03 19:40:35.000000000 +0800 +++ xf86-video-geode/src/lx_exa.c 2010-06-07 11:29:00.000000000 +0800 @@ -45,6 +45,7 @@ #include "geode_blend.h" + #define F(x) IntToxFixed(x) #define I(x) xFixedToInt(x) @@ -85,9 +86,10 @@ unsigned int srcWidth, srcHeight; PixmapPtr srcPixmap; - unsigned int srcColor; + unsigned long srcColor; int op; int repeat; + int maskrepeat; unsigned int fourBpp; unsigned int bufferOffset; struct exa_format_t *srcFormat; @@ -408,13 +410,14 @@ }, /* PictOpOver */ { - CIMGP_ALPHA_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE}, - { - }, + CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_SOURCE},{ + CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, + /* PictOpOverReverse */ { - CIMGP_ALPHA_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { - }, + CIMGP_A_PLUS_BETA_B, CIMGP_CHANNEL_A_ALPHA, CIMGP_CHANNEL_A_DEST}, { + CIMGP_ALPHA_TIMES_A, CIMGP_CONVERTED_ALPHA, CIMGP_CHANNEL_A_SOURCE}, + /* PictOpIn */ { CIMGP_ALPHA_TIMES_A, CIMGP_CHANNEL_B_ALPHA, CIMGP_CHANNEL_A_SOURCE}, { @@ -536,6 +539,7 @@ lx_check_composite(int op, PicturePtr pSrc, PicturePtr pMsk, PicturePtr pDst) { GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst); + const struct exa_format_t *srcFmt, *dstFmt; /* Check that the operation is supported */ @@ -582,12 +586,60 @@ if (pSrc->format == PICT_a8 || pDst->format == PICT_a8) return FALSE; - if (pMsk && op != PictOpClear) { - /* We can only do masks with a 8bpp or a 4bpp mask */ + + if(pMsk && op != PictOpClear){ if (pMsk->format != PICT_a8 && pMsk->format != PICT_a4) return FALSE; + if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) + return FALSE; + } + + /* This is a one pixel drawing, return to the server to handle */ + if(pMsk && (!pSrc->repeat)) + return FALSE; + + + /* Get the formats for the source and destination */ + + if ((srcFmt = lx_get_format(pSrc)) == NULL) { + ErrorF("EXA: Invalid source format %x\n", pSrc->format); + return FALSE; } + if ((dstFmt = lx_get_format(pDst)) == NULL) { + ErrorF("EXA: Invalid destination format %x\n", pDst->format); + return FALSE; + } + + + /* Make sure operations that need alpha bits have them */ + /* If a mask is enabled, the alpha will come from there */ + + if (!pMsk && (!srcFmt->alphabits && usesSrcAlpha(op))) + return FALSE; + + if (!pMsk && (!dstFmt->alphabits && usesDstAlpha(op))) + return FALSE; + + + + + /* FIXME: See a way around this! */ + + if (srcFmt->alphabits == 0 && dstFmt->alphabits != 0) + return FALSE; + + + + /* If this is a rotate operation, then make sure the src and dst + * formats are the same */ + + if (exaScratch.rotate != RR_Rotate_0 && srcFmt != dstFmt) { + ErrorF("EXA: Can't rotate and convert formats at the same time\n"); + return FALSE; + } + + return TRUE; } @@ -644,6 +696,11 @@ struct blend_ops_t *opPtr = &lx_alpha_ops[op * 2]; int direction = (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1; + /* We can only do masks with a 8bpp or a 4bpp mask */ + + if (pMsk->format != PICT_a8 && pMsk->format != PICT_a4) + return FALSE; + /* Direction 0 indicates src->dst, 1 indiates dst->src */ if (((direction == 0) && (pxSrc->drawable.bitsPerPixel < 16)) || @@ -653,13 +710,20 @@ } /* Get the source color */ - - if (direction == 0) + if(op == PictOpOver && (srcFmt->alphabits != 0)){ + exaScratch.srcColor = exaGetPixmapFirstPixel(pxSrc); + }else if(op == PictOpOver && (srcFmt->alphabits == 0)){ exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, - pDst->format); - else - exaScratch.srcColor = lx_get_source_color(pxDst, pDst->format, - pSrc->format); + PICT_a8r8g8b8); + }else{ + if (direction == 0) + exaScratch.srcColor = lx_get_source_color(pxSrc, pSrc->format, + pDst->format); + else + exaScratch.srcColor = lx_get_source_color(pxDst, pDst->format, + pSrc->format); + } + /* FIXME: What to do here? */ @@ -669,6 +733,7 @@ /* Save off the info we need (reuse the source values to save space) */ exaScratch.type = COMP_TYPE_MASK; + exaScratch.maskrepeat = pMsk->repeat; exaScratch.srcOffset = exaGetPixmapOffset(pxMsk); exaScratch.srcPitch = exaGetPixmapPitch(pxMsk); @@ -908,6 +973,45 @@ exaScratch.srcPitch, opPtr->operation, exaScratch.fourBpp); } + +static void +lx_do_composite_mask_opover(PixmapPtr pxDst, unsigned long dstOffset, + unsigned int maskOffset, int width, int height) +{ + int apply, type; + struct blend_ops_t *opPtr; + /* Wait until the GP is idle - this will ensure that the scratch buffer + * isn't occupied */ + + gp_wait_until_idle(); + + /* Copy the source to the scratch buffer, and do a src * mask raster operation */ + gp_declare_blt(0); + opPtr = &lx_alpha_ops[(exaScratch.op * 2) + 1]; + gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); + gp_set_strides(exaScratch.srcPitch * 4, exaScratch.srcPitch); + gp_set_bpp(lx_get_bpp_from_format(CIMGP_SOURCE_FMT_8_8_8_8)); + + gp_set_solid_source(exaScratch.srcColor); + gp_blend_mask_blt(exaScratch.bufferOffset, 0, width, height, maskOffset, + exaScratch.srcPitch, opPtr->operation, exaScratch.fourBpp); + + /* Do a real OVER operation(src + (1-a) * dst), and copy the operation result to destination */ + gp_declare_blt(CIMGP_BLTFLAGS_HAZARD); + opPtr = &lx_alpha_ops[exaScratch.op * 2]; + apply = (exaScratch.dstFormat->alphabits == 0) ? + CIMGP_APPLY_BLEND_TO_RGB : CIMGP_APPLY_BLEND_TO_ALL; + gp_set_source_format(CIMGP_SOURCE_FMT_8_8_8_8); + + gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch * 4); + gp_set_bpp(lx_get_bpp_from_format(exaScratch.dstFormat->fmt)); + type = CIMGP_CONVERTED_ALPHA; + gp_set_alpha_operation(opPtr->operation, type, opPtr->channel, apply, 0); + gp_screen_to_screen_convert(dstOffset, exaScratch.bufferOffset, width, height, 0); + +} + + #define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \ (exaGetPixmapPitch((px)) * (y)) + \ ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) ) @@ -938,7 +1042,7 @@ struct blend_ops_t *opPtr = &lx_alpha_ops[exaScratch.op * 2]; unsigned int dstOffset, srcOffset = 0; - + int maskflag =0; xPointFixed srcPoint; int opX = dstX; @@ -999,13 +1103,27 @@ srcPoint.y = F(0); } + /* Get the source point position*/ srcOffset = GetSrcOffset(I(srcPoint.x), I(srcPoint.y)); - if (exaScratch.srcWidth < opWidth) - opWidth = exaScratch.srcWidth; + /* When there is no mask, exaScratch.srcWidth and exaScratch.srcHeight are the source Width and Height */ + /* When there is a mask, exaScratch.srcWidth and exaScratch.srcHeight are the mask Width and Height */ + /* ExaScratch.repeat is the source repeat attribute */ + /* ExaScratch.maskrepeat is the mask repeat attribute */ + + + 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.srcHeight < opHeight) - opHeight = exaScratch.srcHeight; while (1) { @@ -1018,13 +1136,18 @@ (opPtr->channel == CIMGP_CHANNEL_A_SOURCE) ? 0 : 1; if (direction == 1) { - dstOffset = - GetPixmapOffset(exaScratch.srcPixmap, opX, opY); - lx_do_composite_mask(exaScratch.srcPixmap, dstOffset, - srcOffset, opWidth, opHeight); + maskflag = 1; + dstOffset = GetPixmapOffset(exaScratch.srcPixmap, opX, opY); + if(exaScratch.op == PictOpOver) + lx_do_composite_mask_opover(exaScratch.srcPixmap, dstOffset,srcOffset, opWidth, opHeight); + else + lx_do_composite_mask(exaScratch.srcPixmap, dstOffset, srcOffset, opWidth, opHeight); } else { - lx_do_composite_mask(pxDst, dstOffset, srcOffset, opWidth, - opHeight); + maskflag = 1; + if(exaScratch.op == PictOpOver) + lx_do_composite_mask_opover(pxDst, dstOffset, srcOffset, opWidth, opHeight); + else + lx_do_composite_mask(pxDst, dstOffset, srcOffset, opWidth, opHeight); } } break; @@ -1044,8 +1167,6 @@ break; } - if (!exaScratch.repeat) - break; opX += opWidth; @@ -1056,11 +1177,35 @@ if (opY >= dstY + height) break; } + + + + if(maskflag == 1){ + opWidth = ((dstX + width) - opX) > (exaScratch.srcWidth - maskX) ? + (exaScratch.srcWidth - maskX) : (dstX + width) - opX; + opHeight = ((dstY + height) - opY) > (exaScratch.srcHeight - maskY) ? + (exaScratch.srcHeight - maskY) : (dstY + height) - opY; + /* If the operation is PictOpSrc, clear the region out of the Src region */ + if(exaScratch.repeat && (!exaScratch.maskrepeat) && (exaScratch.op == PictOpSrc)){ + exaScratch.type = COMP_TYPE_ONEPASS; + exaScratch.op = PictOpClear; + } + if(exaScratch.repeat && (!exaScratch.maskrepeat) && (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 the operation is PictOpSrc, clear the region out of the Src region */ + if((!exaScratch.repeat) && (exaScratch.op == PictOpSrc)){ + exaScratch.type = COMP_TYPE_ONEPASS; + exaScratch.op = PictOpClear; + } + if((!exaScratch.repeat) && (exaScratch.op == PictOpOver)) + break; + } - opWidth = ((dstX + width) - opX) > exaScratch.srcWidth ? - exaScratch.srcWidth : (dstX + width) - opX; - opHeight = ((dstY + height) - opY) > exaScratch.srcHeight ? - exaScratch.srcHeight : (dstY + height) - opY; } }