--- xf86-video-geode/src/lx_exa.c 2010-06-03 19:40:35.000000000 +0800 +++ xf86-video-geode-new/src/lx_exa.c 2010-06-04 11:05:00.000000000 +0800 @@ -45,6 +45,7 @@ #include "geode_blend.h" + #define F(x) IntToxFixed(x) #define I(x) xFixedToInt(x) @@ -83,11 +84,14 @@ unsigned int srcPitch; unsigned int srcBpp; unsigned int srcWidth, srcHeight; + PixmapPtr srcPixmap; - unsigned int srcColor; + unsigned long srcColor; int op; int repeat; + /*add here , modify later*/ + int maskrepeat; unsigned int fourBpp; unsigned int bufferOffset; struct exa_format_t *srcFormat; @@ -408,13 +412,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 +541,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 +588,55 @@ 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; + return FALSE; + if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) + return FALSE; + } + + /* this is a 1x1 pixel drawing, return to 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 +693,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 +707,17 @@ } /* Get the source color */ - - 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); + if(op == PictOpOver){ + exaScratch.srcColor = exaGetPixmapFirstPixel(pxSrc); + }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 +727,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 +967,44 @@ 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(exaScratch.srcFormat->fmt); + gp_set_strides(exaScratch.srcPitch * 4, exaScratch.srcPitch); + gp_set_bpp(lx_get_bpp_from_format(exaScratch.srcFormat->fmt)); + 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 scratch buffer 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(exaScratch.srcFormat->fmt); + gp_set_strides(exaGetPixmapPitch(pxDst), exaScratch.srcPitch * 4); + gp_set_bpp(lx_get_bpp_from_format(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, exaScratch.bufferOffset, width, height, 0); + +} + + #define GetPixmapOffset(px, x, y) ( exaGetPixmapOffset((px)) + \ (exaGetPixmapPitch((px)) * (y)) + \ ((((px)->drawable.bitsPerPixel + 7) / 8) * (x)) ) @@ -938,7 +1035,8 @@ 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 +1097,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 +1130,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(exaScratch.srcPixmap, dstOffset,srcOffset, opWidth, opHeight); + else + lx_do_composite_mask_opover(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(pxDst, dstOffset, srcOffset, opWidth, opHeight); + else + lx_do_composite_mask_opover(pxDst, dstOffset, srcOffset, opWidth, opHeight); } } break; @@ -1044,8 +1161,6 @@ break; } - if (!exaScratch.repeat) - break; opX += opWidth; @@ -1056,11 +1171,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; + } + } }