/* * 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. */ #ifdef HAVE_DIX_CONFIG_H #include #endif #ifdef RENDER #include /* For NULL */ #include "fb.h" #include "picturestr.h" #include "mipict.h" #include "fbpict.h" #include "safeAlpha.h" #include "rootlessCommon.h" /* 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) { int oldDepth = pDst->pDrawable->depth; int oldFormat = pDst->format; /* * 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->pDrawable && pMask->pDrawable && !pSrc->transform && !pMask->transform && !pSrc->alphaMap && !pMask->alphaMap && !pMask->repeat && !pMask->componentAlpha && !pDst->alphaMap && pMask->format == PICT_a8 && pSrc->repeatType == RepeatNormal && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 && (pDst->format == PICT_a8r8g8b8 || pDst->format == PICT_x8r8g8b8 || pDst->format == PICT_a8b8g8r8 || pDst->format == PICT_x8b8g8r8)) { fbWalkCompositeRegion (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height, TRUE /* srcRepeat */, FALSE /* maskRepeat */, SafeAlphaCompositeSolidMask_nx8x8888); } else { fbComposite (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); } pDst->pDrawable->depth = oldDepth; pDst->format = oldFormat; } #endif /* RENDER */