aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c')
-rw-r--r--nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c643
1 files changed, 643 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c b/nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c
new file mode 100644
index 000000000..f73a3b5c1
--- /dev/null
+++ b/nx-X11/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c
@@ -0,0 +1,643 @@
+/*
+ * Support for RENDER extension while protecting the alpha channel
+ */
+/*
+ * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
+ * Copyright (c) 2002 Apple Computer, Inc. All Rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* This file is largely based on fbcompose.c and fbpict.c, which contain
+ * the following copyright:
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ */
+ /* $XFree86: xc/programs/Xserver/miext/rootless/safeAlpha/safeAlphaPicture.c,v 1.3 2003/10/24 00:33:15 torrey Exp $ */
+
+#ifdef RENDER
+
+#include "fb.h"
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+#include "safeAlpha.h"
+#include "rootlessCommon.h"
+
+# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
+
+
+typedef void (*CompositeFunc) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+
+/* Optimized version of fbCompositeSolidMask_nx8x8888 */
+void
+SafeAlphaCompositeSolidMask_nx8x8888(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src, srca;
+ CARD32 *dstLine, *dst, d, dstMask;
+ CARD8 *maskLine, *mask, m;
+ FbStride dstStride, maskStride;
+ CARD16 w;
+
+ fbComposeGetSolid(pSrc, src, pDst->format);
+
+ dstMask = FbFullMask (pDst->pDrawable->depth);
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+ fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
+
+ if (dstMask == FB_ALLONES && pDst->pDrawable->bitsPerPixel == 32 &&
+ width * height > rootless_CompositePixels_threshold &&
+ SCREENREC(pDst->pDrawable->pScreen)->imp->CompositePixels)
+ {
+ void *srcp[2], *destp[2];
+ unsigned int dest_rowbytes[2];
+ unsigned int fn;
+
+ srcp[0] = &src; srcp[1] = &src;
+ /* null rowbytes pointer means use first value as a constant */
+ destp[0] = dstLine; destp[1] = dstLine;
+ dest_rowbytes[0] = dstStride * 4; dest_rowbytes[1] = dest_rowbytes[0];
+ fn = RL_COMPOSITE_FUNCTION(RL_COMPOSITE_OVER, RL_DEPTH_ARGB8888,
+ RL_DEPTH_A8, RL_DEPTH_ARGB8888);
+
+ if (SCREENREC(pDst->pDrawable->pScreen)->imp->CompositePixels(
+ width, height, fn, srcp, NULL,
+ maskLine, maskStride,
+ destp, dest_rowbytes) == Success)
+ {
+ return;
+ }
+ }
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ while (w--)
+ {
+ m = *mask++;
+ if (m == 0xff)
+ {
+ if (srca == 0xff)
+ *dst = src & dstMask;
+ else
+ *dst = fbOver (src, *dst) & dstMask;
+ }
+ else if (m)
+ {
+ d = fbIn (src, m);
+ *dst = fbOver (d, *dst) & dstMask;
+ }
+ dst++;
+ }
+ }
+}
+
+void
+SafeAlphaComposite (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ RegionRec region;
+ int n;
+ BoxPtr pbox;
+ CompositeFunc func = 0;
+ Bool srcRepeat = pSrc->repeat;
+ Bool maskRepeat = FALSE;
+ Bool srcAlphaMap = pSrc->alphaMap != 0;
+ Bool maskAlphaMap = FALSE;
+ Bool dstAlphaMap = pDst->alphaMap != 0;
+ int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+ int w, h, w_this, h_this;
+ int dstDepth = pDst->pDrawable->depth;
+ int oldFormat = pDst->format;
+
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ if (pMask)
+ {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ maskRepeat = pMask->repeat;
+ maskAlphaMap = pMask->alphaMap != 0;
+ }
+
+
+ /*
+ * We can use the more optimized fbpict code, but it sets bits above
+ * the depth to zero. Temporarily adjust destination depth if needed.
+ */
+ if (pDst->pDrawable->type == DRAWABLE_WINDOW
+ && pDst->pDrawable->depth == 24
+ && pDst->pDrawable->bitsPerPixel == 32)
+ {
+ pDst->pDrawable->depth = 32;
+ }
+ /* For rootless preserve the alpha in x8r8g8b8 which really is
+ * a8r8g8b8
+ */
+ if (oldFormat == PICT_x8r8g8b8)
+ {
+ pDst->format = PICT_a8r8g8b8;
+ }
+
+
+
+ if (!pSrc->transform && !(pMask && pMask->transform))
+ if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap)
+ switch (op) {
+ case PictOpSrc:
+#ifdef USE_MMX
+ if (!pMask && pSrc->format == pDst->format &&
+ pSrc->pDrawable != pDst->pDrawable)
+ {
+ func = fbCompositeCopyAreammx;
+ }
+#endif
+ break;
+ case PictOpOver:
+ if (pMask)
+ {
+ if (srcRepeat &&
+ pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1)
+ {
+ srcRepeat = FALSE;
+ if (PICT_FORMAT_COLOR(pSrc->format)) {
+ switch (pMask->format) {
+ case PICT_a8:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ case PICT_b5g6r5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSolidMask_nx8x0565mmx;
+ else
+#endif
+ func = fbCompositeSolidMask_nx8x0565;
+ break;
+ case PICT_r8g8b8:
+ case PICT_b8g8r8:
+ func = fbCompositeSolidMask_nx8x0888;
+ break;
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = SafeAlphaCompositeSolidMask_nx8x8888;
+ break;
+ }
+ break;
+ case PICT_a8r8g8b8:
+ if (pMask->componentAlpha) {
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSolidMask_nx8888x8888Cmmx;
+ else
+#endif
+ func = fbCompositeSolidMask_nx8888x8888C;
+ break;
+ case PICT_r5g6b5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSolidMask_nx8888x0565Cmmx;
+ else
+#endif
+ func = fbCompositeSolidMask_nx8888x0565C;
+ break;
+ }
+ }
+ break;
+ case PICT_a8b8g8r8:
+ if (pMask->componentAlpha) {
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSolidMask_nx8888x8888Cmmx;
+ else
+#endif
+ func = fbCompositeSolidMask_nx8888x8888C;
+ break;
+ case PICT_b5g6r5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSolidMask_nx8888x0565Cmmx;
+ else
+#endif
+ func = fbCompositeSolidMask_nx8888x0565C;
+ break;
+ }
+ }
+ break;
+ case PICT_a1:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ case PICT_b5g6r5:
+ case PICT_r8g8b8:
+ case PICT_b8g8r8:
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+ func = fbCompositeSolidMask_nx1xn;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ else /* has mask and non-repeating source */
+ {
+ if (pSrc->pDrawable == pMask->pDrawable &&
+ xSrc == xMask && ySrc == yMask &&
+ !pMask->componentAlpha)
+ {
+ /* source == mask: non-premultiplied data */
+ switch (pSrc->format) {
+ case PICT_x8b8g8r8:
+ switch (pMask->format) {
+ case PICT_a8r8g8b8:
+ case PICT_a8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888RevNPx8888mmx;
+#endif
+ break;
+ case PICT_r5g6b5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888RevNPx0565mmx;
+#endif
+ break;
+ }
+ break;
+ }
+ break;
+ case PICT_x8r8g8b8:
+ switch (pMask->format) {
+ case PICT_a8r8g8b8:
+ case PICT_a8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888RevNPx8888mmx;
+#endif
+ break;
+ case PICT_r5g6b5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888RevNPx0565mmx;
+#endif
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ else
+ {
+ /* non-repeating source, repeating mask => translucent window */
+ if (maskRepeat &&
+ pMask->pDrawable->width == 1 &&
+ pMask->pDrawable->height == 1)
+ {
+ if (pSrc->format == PICT_x8r8g8b8 &&
+ pDst->format == PICT_x8r8g8b8 &&
+ pMask->format == PICT_a8)
+ {
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888x8x8888mmx;
+#endif
+ }
+ }
+ }
+ }
+ }
+ else /* no mask */
+ {
+ if (srcRepeat &&
+ pSrc->pDrawable->width == 1 &&
+ pSrc->pDrawable->height == 1)
+ {
+ /* no mask and repeating source */
+ switch (pSrc->format) {
+ case PICT_a8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ {
+ srcRepeat = FALSE;
+ func = fbCompositeSolid_nx8888mmx;
+ }
+#endif
+ break;
+ case PICT_r5g6b5:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ {
+ srcRepeat = FALSE;
+ func = fbCompositeSolid_nx0565mmx;
+ }
+#endif
+ break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (pSrc->format) {
+ case PICT_a8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888x8888mmx;
+ else
+#endif
+ func = fbCompositeSrc_8888x8888;
+ break;
+ case PICT_r8g8b8:
+ func = fbCompositeSrc_8888x0888;
+ break;
+ case PICT_r5g6b5:
+ func = fbCompositeSrc_8888x0565;
+ break;
+ }
+ break;
+ case PICT_x8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeCopyAreammx;
+#endif
+ break;
+ }
+ case PICT_x8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeCopyAreammx;
+#endif
+ break;
+ }
+ break;
+ case PICT_a8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+ case PICT_x8b8g8r8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrc_8888x8888mmx;
+ else
+#endif
+ func = fbCompositeSrc_8888x8888;
+ break;
+ case PICT_b8g8r8:
+ func = fbCompositeSrc_8888x0888;
+ break;
+ case PICT_b5g6r5:
+ func = fbCompositeSrc_8888x0565;
+ break;
+ }
+ break;
+ case PICT_r5g6b5:
+ switch (pDst->format) {
+ case PICT_r5g6b5:
+ func = fbCompositeSrc_0565x0565;
+ break;
+ }
+ break;
+ case PICT_b5g6r5:
+ switch (pDst->format) {
+ case PICT_b5g6r5:
+ func = fbCompositeSrc_0565x0565;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case PictOpAdd:
+ if (pMask == 0)
+ {
+ switch (pSrc->format) {
+ case PICT_a8r8g8b8:
+ switch (pDst->format) {
+ case PICT_a8r8g8b8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrcAdd_8888x8888mmx;
+ else
+#endif
+ func = fbCompositeSrcAdd_8888x8888;
+ break;
+ }
+ break;
+ case PICT_a8b8g8r8:
+ switch (pDst->format) {
+ case PICT_a8b8g8r8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrcAdd_8888x8888mmx;
+ else
+#endif
+ func = fbCompositeSrcAdd_8888x8888;
+ break;
+ }
+ break;
+ case PICT_a8:
+ switch (pDst->format) {
+ case PICT_a8:
+#ifdef USE_MMX
+ if (fbHaveMMX())
+ func = fbCompositeSrcAdd_8000x8000mmx;
+ else
+#endif
+ func = fbCompositeSrcAdd_8000x8000;
+ break;
+ }
+ break;
+ case PICT_a1:
+ switch (pDst->format) {
+ case PICT_a1:
+ func = fbCompositeSrcAdd_1000x1000;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ if (!func) {
+ /* no fast path, use the general code */
+ fbCompositeGeneral(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
+ // Reset destination depth and format to their true value
+ pDst->pDrawable->depth = dstDepth;
+ pDst->format = oldFormat;
+ return;
+ }
+
+ if (!miComputeCompositeRegion (&region,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height))
+ return;
+
+ n = REGION_NUM_RECTS (&region);
+ pbox = REGION_RECTS (&region);
+ while (n--)
+ {
+ h = pbox->y2 - pbox->y1;
+ y_src = pbox->y1 - yDst + ySrc;
+ y_msk = pbox->y1 - yDst + yMask;
+ y_dst = pbox->y1;
+ while (h)
+ {
+ h_this = h;
+ w = pbox->x2 - pbox->x1;
+ x_src = pbox->x1 - xDst + xSrc;
+ x_msk = pbox->x1 - xDst + xMask;
+ x_dst = pbox->x1;
+ if (maskRepeat)
+ {
+ y_msk = mod (y_msk, pMask->pDrawable->height);
+ if (h_this > pMask->pDrawable->height - y_msk)
+ h_this = pMask->pDrawable->height - y_msk;
+ }
+ if (srcRepeat)
+ {
+ y_src = mod (y_src, pSrc->pDrawable->height);
+ if (h_this > pSrc->pDrawable->height - y_src)
+ h_this = pSrc->pDrawable->height - y_src;
+ }
+ while (w)
+ {
+ w_this = w;
+ if (maskRepeat)
+ {
+ x_msk = mod (x_msk, pMask->pDrawable->width);
+ if (w_this > pMask->pDrawable->width - x_msk)
+ w_this = pMask->pDrawable->width - x_msk;
+ }
+ if (srcRepeat)
+ {
+ x_src = mod (x_src, pSrc->pDrawable->width);
+ if (w_this > pSrc->pDrawable->width - x_src)
+ w_this = pSrc->pDrawable->width - x_src;
+ }
+ (*func) (op, pSrc, pMask, pDst,
+ x_src, y_src, x_msk, y_msk, x_dst, y_dst,
+ w_this, h_this);
+ w -= w_this;
+ x_src += w_this;
+ x_msk += w_this;
+ x_dst += w_this;
+ }
+ h -= h_this;
+ y_src += h_this;
+ y_msk += h_this;
+ y_dst += h_this;
+ }
+ pbox++;
+ }
+ REGION_UNINIT (pDst->pDrawable->pScreen, &region);
+
+ // Reset destination depth/format to its true value
+ pDst->pDrawable->depth = dstDepth;
+ pDst->format = oldFormat;
+}
+
+#endif /* RENDER */