summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lx_exa.c195
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;
}