Initial revision

This commit is contained in:
Kaleb Keithley 2003-11-25 19:29:01 +00:00
commit 90f1536dd3
91 changed files with 27196 additions and 0 deletions

View file

@ -0,0 +1,135 @@
/*
* Rootless Acceleration Code
*/
/*
* Copyright (c) 2003 Torrey T. Lyons. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlAccel.h,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
/*
* rlBlt.c
*/
void
rlBlt (FbBits *srcLine,
FbStride srcStride,
int srcX,
ScreenPtr pDstScreen,
FbBits *dstLine,
FbStride dstStride,
int dstX,
int width,
int height,
int alu,
FbBits pm,
int bpp,
Bool reverse,
Bool upsidedown);
/*
* rlCopy.c
*/
RegionPtr
rlCopyArea (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
int xIn,
int yIn,
int widthSrc,
int heightSrc,
int xOut,
int yOut);
/*
* rlFill.c
*/
void
rlFill (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
int width,
int height);
void
rlSolidBoxClipped (DrawablePtr pDrawable,
RegionPtr pClip,
int x1,
int y1,
int x2,
int y2,
FbBits and,
FbBits xor);
/*
* rlFillRect.c
*/
void
rlPolyFillRect(DrawablePtr pDrawable,
GCPtr pGC,
int nrect,
xRectangle *prect);
/*
* rlFillSpans.c
*/
void
rlFillSpans (DrawablePtr pDrawable,
GCPtr pGC,
int n,
DDXPointPtr ppt,
int *pwidth,
int fSorted);
/*
* rlGlyph.c
*/
void
rlImageGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppciInit,
pointer pglyphBase);
/*
* rlSolid.c
*/
void
rlSolid (ScreenPtr pScreen,
FbBits *dst,
FbStride dstStride,
int dstX,
int bpp,
int width,
int height,
FbBits and,
FbBits xor);

View file

@ -0,0 +1,366 @@
/*
* Accelerated rootless blit
*/
/*
* This code is largely copied from fbBlt.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlBlt.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rootlessCommon.h"
#include "rlAccel.h"
void
rlBlt (FbBits *srcLine,
FbStride srcStride,
int srcX,
ScreenPtr pDstScreen,
FbBits *dstLine,
FbStride dstStride,
int dstX,
int width,
int height,
int alu,
FbBits pm,
int bpp,
Bool reverse,
Bool upsidedown)
{
FbBits *src, *dst;
int leftShift, rightShift;
FbBits startmask, endmask;
FbBits bits, bits1;
int n, nmiddle;
Bool destInvarient;
int startbyte, endbyte;
FbDeclareMergeRop ();
#ifdef FB_24BIT
if (bpp == 24 && !FbCheck24Pix (pm))
{
fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX,
width, height, alu, pm, reverse, upsidedown);
return;
}
#endif
FbInitializeMergeRop(alu, pm);
destInvarient = FbDestInvarientMergeRop();
if (upsidedown)
{
srcLine += (height - 1) * (srcStride);
dstLine += (height - 1) * (dstStride);
srcStride = -srcStride;
dstStride = -dstStride;
}
FbMaskBitsBytes (dstX, width, destInvarient, startmask, startbyte,
nmiddle, endmask, endbyte);
/*
* Beginning of the rootless acceleration code
*/
if (!startmask && !endmask && alu == GXcopy &&
height * nmiddle * sizeof(*dst) > rootless_CopyBytes_threshold)
{
if (pm == FB_ALLONES && SCREENREC(pDstScreen)->imp->CopyBytes)
{
SCREENREC(pDstScreen)->imp->CopyBytes(
nmiddle * sizeof(*dst), height,
(char *) srcLine + (srcX >> 3),
srcStride * sizeof (*src),
(char *) dstLine + (dstX >> 3),
dstStride * sizeof (*dst));
return;
}
/* FIXME: the pm test here isn't super-wonderful - just because
we don't care about the top eight bits doesn't necessarily
mean we want them set to 255. But doing this does give a
factor of two performance improvement when copying from a
pixmap to a window, which is pretty common.. */
else if (bpp == 32 && sizeof(FbBits) == 4 &&
pm == 0x00FFFFFFUL && !reverse &&
SCREENREC(pDstScreen)->imp->CompositePixels)
{
/* need to copy XRGB to ARGB. */
void *src[2], *dest[2];
unsigned int src_rowbytes[2], dest_rowbytes[2];
unsigned int fn;
src[0] = (char *) srcLine + (srcX >> 3);
src[1] = NULL;
src_rowbytes[0] = srcStride * sizeof(*src);
src_rowbytes[1] = 0;
dest[0] = (char *) dstLine + (dstX >> 3);
dest[1] = dest[0];
dest_rowbytes[0] = dstStride * sizeof(*dst);
dest_rowbytes[1] = dest_rowbytes[0];
fn = RL_COMPOSITE_FUNCTION(RL_COMPOSITE_SRC, RL_DEPTH_ARGB8888,
RL_DEPTH_NIL, RL_DEPTH_ARGB8888);
if (SCREENREC(pDstScreen)->imp->CompositePixels(
nmiddle, height,
fn, src, src_rowbytes,
NULL, 0, dest, dest_rowbytes) == Success)
{
return;
}
}
}
/* End of the rootless acceleration code */
if (reverse)
{
srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
srcX = (srcX + width - 1) & FB_MASK;
dstX = (dstX + width - 1) & FB_MASK;
}
else
{
srcLine += srcX >> FB_SHIFT;
dstLine += dstX >> FB_SHIFT;
srcX &= FB_MASK;
dstX &= FB_MASK;
}
if (srcX == dstX)
{
while (height--)
{
src = srcLine;
srcLine += srcStride;
dst = dstLine;
dstLine += dstStride;
if (reverse)
{
if (endmask)
{
bits = *--src;
--dst;
FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
}
n = nmiddle;
if (destInvarient)
{
while (n--)
*--dst = FbDoDestInvarientMergeRop(*--src);
}
else
{
while (n--)
{
bits = *--src;
--dst;
*dst = FbDoMergeRop (bits, *dst);
}
}
if (startmask)
{
bits = *--src;
--dst;
FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
}
}
else
{
if (startmask)
{
bits = *src++;
FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
dst++;
}
n = nmiddle;
if (destInvarient)
{
#if 0
/*
* This provides some speedup on screen->screen blts
* over the PCI bus, usually about 10%. But fb
* isn't usually used for this operation...
*/
if (_ca2 + 1 == 0 && _cx2 == 0)
{
FbBits t1, t2, t3, t4;
while (n >= 4)
{
t1 = *src++;
t2 = *src++;
t3 = *src++;
t4 = *src++;
*dst++ = t1;
*dst++ = t2;
*dst++ = t3;
*dst++ = t4;
n -= 4;
}
}
#endif
while (n--)
*dst++ = FbDoDestInvarientMergeRop(*src++);
}
else
{
while (n--)
{
bits = *src++;
*dst = FbDoMergeRop (bits, *dst);
dst++;
}
}
if (endmask)
{
bits = *src;
FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
}
}
}
}
else
{
if (srcX > dstX)
{
leftShift = srcX - dstX;
rightShift = FB_UNIT - leftShift;
}
else
{
rightShift = dstX - srcX;
leftShift = FB_UNIT - rightShift;
}
while (height--)
{
src = srcLine;
srcLine += srcStride;
dst = dstLine;
dstLine += dstStride;
bits1 = 0;
if (reverse)
{
if (srcX < dstX)
bits1 = *--src;
if (endmask)
{
bits = FbScrRight(bits1, rightShift);
if (FbScrRight(endmask, leftShift))
{
bits1 = *--src;
bits |= FbScrLeft(bits1, leftShift);
}
--dst;
FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
}
n = nmiddle;
if (destInvarient)
{
while (n--)
{
bits = FbScrRight(bits1, rightShift);
bits1 = *--src;
bits |= FbScrLeft(bits1, leftShift);
--dst;
*dst = FbDoDestInvarientMergeRop(bits);
}
}
else
{
while (n--)
{
bits = FbScrRight(bits1, rightShift);
bits1 = *--src;
bits |= FbScrLeft(bits1, leftShift);
--dst;
*dst = FbDoMergeRop(bits, *dst);
}
}
if (startmask)
{
bits = FbScrRight(bits1, rightShift);
if (FbScrRight(startmask, leftShift))
{
bits1 = *--src;
bits |= FbScrLeft(bits1, leftShift);
}
--dst;
FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
}
}
else
{
if (srcX > dstX)
bits1 = *src++;
if (startmask)
{
bits = FbScrLeft(bits1, leftShift);
bits1 = *src++;
bits |= FbScrRight(bits1, rightShift);
FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
dst++;
}
n = nmiddle;
if (destInvarient)
{
while (n--)
{
bits = FbScrLeft(bits1, leftShift);
bits1 = *src++;
bits |= FbScrRight(bits1, rightShift);
*dst = FbDoDestInvarientMergeRop(bits);
dst++;
}
}
else
{
while (n--)
{
bits = FbScrLeft(bits1, leftShift);
bits1 = *src++;
bits |= FbScrRight(bits1, rightShift);
*dst = FbDoMergeRop(bits, *dst);
dst++;
}
}
if (endmask)
{
bits = FbScrLeft(bits1, leftShift);
if (FbScrLeft(endmask, rightShift))
{
bits1 = *src;
bits |= FbScrRight(bits1, rightShift);
}
FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask);
}
}
}
}
}

View file

@ -0,0 +1,103 @@
/*
* This code is largely copied from fbcopy.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlCopy.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rlAccel.h"
void
rlCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
CARD8 alu = pGC ? pGC->alu : GXcopy;
FbBits pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES;
FbBits *src;
FbStride srcStride;
int srcBpp;
int srcXoff, srcYoff;
FbBits *dst;
FbStride dstStride;
int dstBpp;
int dstXoff, dstYoff;
fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff);
fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
while (nbox--)
{
rlBlt (src + (pbox->y1 + dy + srcYoff) * srcStride,
srcStride,
(pbox->x1 + dx + srcXoff) * srcBpp,
pDstDrawable->pScreen,
dst + (pbox->y1 + dstYoff) * dstStride,
dstStride,
(pbox->x1 + dstXoff) * dstBpp,
(pbox->x2 - pbox->x1) * dstBpp,
(pbox->y2 - pbox->y1),
alu,
pm,
dstBpp,
reverse,
upsidedown);
pbox++;
}
}
RegionPtr
rlCopyArea (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
int xIn,
int yIn,
int widthSrc,
int heightSrc,
int xOut,
int yOut)
{
fbCopyProc copy;
#ifdef FB_24_32BIT
if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
copy = fb24_32CopyMtoN;
else
#endif
copy = rlCopyNtoN;
return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
widthSrc, heightSrc, xOut, yOut, copy, 0, 0);
}

View file

@ -0,0 +1,217 @@
/*
* This code is largely copied from fbfill.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlFill.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rlAccel.h"
void
rlFill (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
int width,
int height)
{
FbBits *dst;
FbStride dstStride;
int dstBpp;
int dstXoff, dstYoff;
FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
switch (pGC->fillStyle) {
case FillSolid:
rlSolid (pDrawable->pScreen,
dst + (y + dstYoff) * dstStride,
dstStride,
(x + dstXoff) * dstBpp,
dstBpp,
width * dstBpp, height,
pPriv->and, pPriv->xor);
break;
case FillStippled:
case FillOpaqueStippled: {
PixmapPtr pStip = pGC->stipple;
int stipWidth = pStip->drawable.width;
int stipHeight = pStip->drawable.height;
if (dstBpp == 1)
{
int alu;
FbBits *stip;
FbStride stipStride;
int stipBpp;
int stipXoff, stipYoff; /* XXX assumed to be zero */
if (pGC->fillStyle == FillStippled)
alu = FbStipple1Rop(pGC->alu,pGC->fgPixel);
else
alu = FbOpaqueStipple1Rop(pGC->alu,pGC->fgPixel,pGC->bgPixel);
fbGetDrawable (&pStip->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff);
fbTile (dst + (y + dstYoff) * dstStride,
dstStride,
x + dstXoff,
width, height,
stip,
stipStride,
stipWidth,
stipHeight,
alu,
pPriv->pm,
dstBpp,
(pGC->patOrg.x + pDrawable->x + dstXoff),
pGC->patOrg.y + pDrawable->y + dstYoff - y);
}
else
{
FbStip *stip;
FbStride stipStride;
int stipBpp;
int stipXoff, stipYoff; /* XXX assumed to be zero */
FbBits fgand, fgxor, bgand, bgxor;
fgand = pPriv->and;
fgxor = pPriv->xor;
if (pGC->fillStyle == FillStippled)
{
bgand = fbAnd(GXnoop,(FbBits) 0,FB_ALLONES);
bgxor = fbXor(GXnoop,(FbBits) 0,FB_ALLONES);
}
else
{
bgand = pPriv->bgand;
bgxor = pPriv->bgxor;
}
fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff);
fbStipple (dst + (y + dstYoff) * dstStride,
dstStride,
(x + dstXoff) * dstBpp,
dstBpp,
width * dstBpp, height,
stip,
stipStride,
stipWidth,
stipHeight,
pPriv->evenStipple,
fgand, fgxor,
bgand, bgxor,
pGC->patOrg.x + pDrawable->x + dstXoff,
pGC->patOrg.y + pDrawable->y + dstYoff - y);
}
break;
}
case FillTiled: {
PixmapPtr pTile = pGC->tile.pixmap;
FbBits *tile;
FbStride tileStride;
int tileBpp;
int tileWidth;
int tileHeight;
int tileXoff, tileYoff; /* XXX assumed to be zero */
fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, tileYoff);
tileWidth = pTile->drawable.width;
tileHeight = pTile->drawable.height;
fbTile (dst + (y + dstYoff) * dstStride,
dstStride,
(x + dstXoff) * dstBpp,
width * dstBpp, height,
tile,
tileStride,
tileWidth * tileBpp,
tileHeight,
pGC->alu,
pPriv->pm,
dstBpp,
(pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp,
pGC->patOrg.y + pDrawable->y + dstYoff - y);
break;
}
}
fbValidateDrawable (pDrawable);
}
void
rlSolidBoxClipped (DrawablePtr pDrawable,
RegionPtr pClip,
int x1,
int y1,
int x2,
int y2,
FbBits and,
FbBits xor)
{
FbBits *dst;
FbStride dstStride;
int dstBpp;
int dstXoff, dstYoff;
BoxPtr pbox;
int nbox;
int partX1, partX2, partY1, partY2;
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
nbox--;
pbox++)
{
partX1 = pbox->x1;
if (partX1 < x1)
partX1 = x1;
partX2 = pbox->x2;
if (partX2 > x2)
partX2 = x2;
if (partX2 <= partX1)
continue;
partY1 = pbox->y1;
if (partY1 < y1)
partY1 = y1;
partY2 = pbox->y2;
if (partY2 > y2)
partY2 = y2;
if (partY2 <= partY1)
continue;
rlSolid (pDrawable->pScreen,
dst + (partY1 + dstYoff) * dstStride,
dstStride,
(partX1 + dstXoff) * dstBpp,
dstBpp,
(partX2 - partX1) * dstBpp,
(partY2 - partY1),
and, xor);
}
}

View file

@ -0,0 +1,114 @@
/*
* This code is largely copied from fbfillrect.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlFillRect.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rlAccel.h"
void
rlPolyFillRect(DrawablePtr pDrawable,
GCPtr pGC,
int nrect,
xRectangle *prect)
{
RegionPtr pClip = fbGetCompositeClip(pGC);
register BoxPtr pbox;
BoxPtr pextent;
int extentX1, extentX2, extentY1, extentY2;
int fullX1, fullX2, fullY1, fullY2;
int partX1, partX2, partY1, partY2;
int xorg, yorg;
int n;
xorg = pDrawable->x;
yorg = pDrawable->y;
pextent = REGION_EXTENTS(pGC->pScreen, pClip);
extentX1 = pextent->x1;
extentY1 = pextent->y1;
extentX2 = pextent->x2;
extentY2 = pextent->y2;
while (nrect--)
{
fullX1 = prect->x + xorg;
fullY1 = prect->y + yorg;
fullX2 = fullX1 + (int) prect->width;
fullY2 = fullY1 + (int) prect->height;
prect++;
if (fullX1 < extentX1)
fullX1 = extentX1;
if (fullY1 < extentY1)
fullY1 = extentY1;
if (fullX2 > extentX2)
fullX2 = extentX2;
if (fullY2 > extentY2)
fullY2 = extentY2;
if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
continue;
n = REGION_NUM_RECTS (pClip);
if (n == 1)
{
rlFill (pDrawable,
pGC,
fullX1, fullY1, fullX2-fullX1, fullY2-fullY1);
}
else
{
pbox = REGION_RECTS(pClip);
/*
* clip the rectangle to each box in the clip region
* this is logically equivalent to calling Intersect()
*/
while(n--)
{
partX1 = pbox->x1;
if (partX1 < fullX1)
partX1 = fullX1;
partY1 = pbox->y1;
if (partY1 < fullY1)
partY1 = fullY1;
partX2 = pbox->x2;
if (partX2 > fullX2)
partX2 = fullX2;
partY2 = pbox->y2;
if (partY2 > fullY2)
partY2 = fullY2;
pbox++;
if (partX1 < partX2 && partY1 < partY2)
rlFill (pDrawable, pGC,
partX1, partY1,
partX2 - partX1, partY2 - partY1);
}
}
}
}

View file

@ -0,0 +1,102 @@
/*
* This code is largely copied from fbfillsp.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlFillSpans.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rlAccel.h"
void
rlFillSpans (DrawablePtr pDrawable,
GCPtr pGC,
int n,
DDXPointPtr ppt,
int *pwidth,
int fSorted)
{
RegionPtr pClip = fbGetCompositeClip(pGC);
BoxPtr pextent, pbox;
int nbox;
int extentX1, extentX2, extentY1, extentY2;
int fullX1, fullX2, fullY1;
int partX1, partX2;
pextent = REGION_EXTENTS(pGC->pScreen, pClip);
extentX1 = pextent->x1;
extentY1 = pextent->y1;
extentX2 = pextent->x2;
extentY2 = pextent->y2;
while (n--)
{
fullX1 = ppt->x;
fullY1 = ppt->y;
fullX2 = fullX1 + (int) *pwidth;
ppt++;
pwidth++;
if (fullY1 < extentY1 || extentY2 <= fullY1)
continue;
if (fullX1 < extentX1)
fullX1 = extentX1;
if (fullX2 > extentX2)
fullX2 = extentX2;
if (fullX1 >= fullX2)
continue;
nbox = REGION_NUM_RECTS (pClip);
if (nbox == 1)
{
rlFill (pDrawable,
pGC,
fullX1, fullY1, fullX2-fullX1, 1);
}
else
{
pbox = REGION_RECTS(pClip);
while(nbox--)
{
if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
{
partX1 = pbox->x1;
if (partX1 < fullX1)
partX1 = fullX1;
partX2 = pbox->x2;
if (partX2 > fullX2)
partX2 = fullX2;
if (partX2 > partX1)
{
rlFill (pDrawable, pGC,
partX1, fullY1,
partX2 - partX1, 1);
}
}
pbox++;
}
}
}
}

View file

@ -0,0 +1,166 @@
/*
* This code is largely copied from fbglyph.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlGlyph.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "rlAccel.h"
void
rlImageGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppciInit,
pointer pglyphBase)
{
FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
CharInfoPtr *ppci;
CharInfoPtr pci;
unsigned char *pglyph; /* pointer bits in glyph */
int gWidth, gHeight; /* width and height of glyph */
FbStride gStride; /* stride of glyph */
Bool opaque;
int n;
int gx, gy;
#ifndef FBNOPIXADDR
void (*glyph) (FbBits *,
FbStride,
int,
FbStip *,
FbBits,
int,
int);
FbBits *dst = 0;
FbStride dstStride = 0;
int dstBpp = 0;
int dstXoff = 0, dstYoff = 0;
glyph = 0;
if (pPriv->and == 0)
{
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
switch (dstBpp) {
case 8: glyph = fbGlyph8; break;
case 16: glyph = fbGlyph16; break;
#ifdef FB_24BIT
case 24: glyph = fbGlyph24; break;
#endif
case 32: glyph = fbGlyph32; break;
}
}
#endif
x += pDrawable->x;
y += pDrawable->y;
if (TERMINALFONT (pGC->font)
#ifndef FBNOPIXADDR
&& !glyph
#endif
)
{
opaque = TRUE;
}
else
{
int xBack, widthBack;
int yBack, heightBack;
ppci = ppciInit;
n = nglyph;
widthBack = 0;
while (n--)
widthBack += (*ppci++)->metrics.characterWidth;
xBack = x;
if (widthBack < 0)
{
xBack += widthBack;
widthBack = -widthBack;
}
yBack = y - FONTASCENT(pGC->font);
heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
rlSolidBoxClipped (pDrawable,
fbGetCompositeClip(pGC),
xBack,
yBack,
xBack + widthBack,
yBack + heightBack,
fbAnd(GXcopy,pPriv->bg,pPriv->pm),
fbXor(GXcopy,pPriv->bg,pPriv->pm));
opaque = FALSE;
}
ppci = ppciInit;
while (nglyph--)
{
pci = *ppci++;
pglyph = FONTGLYPHBITS(pglyphBase, pci);
gWidth = GLYPHWIDTHPIXELS(pci);
gHeight = GLYPHHEIGHTPIXELS(pci);
if (gWidth && gHeight)
{
gx = x + pci->metrics.leftSideBearing;
gy = y - pci->metrics.ascent;
#ifndef FBNOPIXADDR
if (glyph && gWidth <= sizeof (FbStip) * 8 &&
fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
{
(*glyph) (dst + (gy + dstYoff) * dstStride,
dstStride,
dstBpp,
(FbStip *) pglyph,
pPriv->fg,
gx + dstXoff,
gHeight);
}
else
#endif
{
gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
fbPutXYImage (pDrawable,
fbGetCompositeClip(pGC),
pPriv->fg,
pPriv->bg,
pPriv->pm,
GXcopy,
opaque,
gx,
gy,
gWidth, gHeight,
(FbStip *) pglyph,
gStride,
0);
}
}
x += pci->metrics.characterWidth;
}
}

View file

@ -0,0 +1,108 @@
/*
* Accelerated rootless fill
*/
/*
* This code is largely copied from fbsolid.c.
*
* Copyright © 1998 Keith Packard
* Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/accel/rlSolid.c,v 1.1 2003/10/24 00:33:15 torrey Exp $ */
#include "fb.h"
#include "rootlessCommon.h"
void
rlSolid (ScreenPtr pScreen,
FbBits *dst,
FbStride dstStride,
int dstX,
int bpp,
int width,
int height,
FbBits and,
FbBits xor)
{
FbBits startmask, endmask;
int n, nmiddle;
int startbyte, endbyte;
#ifdef FB_24BIT
if (bpp == 24 && (!FbCheck24Pix(and) || !FbCheck24Pix(xor)))
{
fbSolid24 (dst, dstStride, dstX, width, height, and, xor);
return;
}
#endif
dst += dstX >> FB_SHIFT;
dstX &= FB_MASK;
FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte,
nmiddle, endmask, endbyte);
/*
* Beginning of the rootless acceleration code
*/
if (!startmask && !endmask && !and &&
height * nmiddle * sizeof (*dst) > rootless_FillBytes_threshold &&
SCREENREC(pScreen)->imp->FillBytes)
{
if (bpp <= 8)
xor |= xor << 8;
if (bpp <= 16)
xor |= xor << 16;
SCREENREC(pScreen)->imp->FillBytes(nmiddle * sizeof (*dst), height,
xor, (char *) dst + (dstX >> 3),
dstStride * sizeof (*dst));
return;
}
/* End of the rootless acceleration code */
if (startmask)
dstStride--;
dstStride -= nmiddle;
while (height--)
{
if (startmask)
{
FbDoLeftMaskByteRRop(dst,startbyte,startmask,and,xor);
dst++;
}
n = nmiddle;
if (!and)
while (n--)
*dst++ = xor;
else
while (n--)
{
*dst = FbDoRRop (*dst, and, xor);
dst++;
}
if (endmask)
FbDoRightMaskByteRRop(dst,endbyte,endmask,and,xor);
dst += dstStride;
}
}

399
miext/rootless/rootless.h Normal file
View file

@ -0,0 +1,399 @@
/*
* External interface to generic rootless mode
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* Copyright (c) 2002-2003 Torrey T. Lyons. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootless.h,v 1.6 2003/10/24 00:33:14 torrey Exp $ */
#ifndef _ROOTLESS_H
#define _ROOTLESS_H
#include "rootlessConfig.h"
#include "mi.h"
#include "gcstruct.h"
/*
Each top-level rootless window has a one-to-one correspondence to a physical
on-screen window. The physical window is refered to as a "frame".
*/
typedef void * RootlessFrameID;
/*
* RootlessWindowRec
* This structure stores the per-frame data used by the rootless code.
* Each top-level X window has one RootlessWindowRec associated with it.
*/
typedef struct _RootlessWindowRec {
// Position and size includes the window border
// Position is in per-screen coordinates
int x, y;
unsigned int width, height;
unsigned int borderWidth;
RootlessFrameID wid; // implementation specific frame id
WindowPtr win; // underlying X window
// Valid only when drawing (ie. is_drawing is set)
char *pixelData;
int bytesPerRow;
PixmapPtr pixmap;
PixmapPtr oldPixmap;
#ifdef ROOTLESS_TRACK_DAMAGE
RegionRec damage;
#endif
unsigned int is_drawing :1; // Currently drawing?
unsigned int is_reorder_pending :1;
} RootlessWindowRec, *RootlessWindowPtr;
/* Offset for screen-local to global coordinate transforms */
#ifdef ROOTLESS_GLOBAL_COORDS
extern int rootlessGlobalOffsetX;
extern int rootlessGlobalOffsetY;
#endif
/* The minimum number of bytes or pixels for which to use the
implementation's accelerated functions. */
extern unsigned int rootless_CopyBytes_threshold;
extern unsigned int rootless_FillBytes_threshold;
extern unsigned int rootless_CompositePixels_threshold;
extern unsigned int rootless_CopyWindow_threshold;
/* Operations used by CompositePixels */
enum rl_composite_op_enum {
RL_COMPOSITE_SRC = 0,
RL_COMPOSITE_OVER,
};
/* Data formats for depth field and composite functions */
enum rl_depth_enum {
RL_DEPTH_NIL = 0, /* null source when compositing */
RL_DEPTH_ARGB8888,
RL_DEPTH_RGB555,
RL_DEPTH_A8, /* for masks when compositing */
RL_DEPTH_INDEX8,
};
/* Macro to form the composite function for CompositePixels */
#define RL_COMPOSITE_FUNCTION(op, src_depth, mask_depth, dest_depth) \
(((op) << 24) | ((src_depth) << 16) \
| ((mask_depth) << 8) | ((dest_depth) << 0))
/* Gravity for window contents during resizing */
enum rl_gravity_enum {
RL_GRAVITY_NONE = 0, /* no gravity, fill everything */
RL_GRAVITY_NORTH_WEST = 1, /* anchor to top-left corner */
RL_GRAVITY_NORTH_EAST = 2, /* anchor to top-right corner */
RL_GRAVITY_SOUTH_EAST = 3, /* anchor to bottom-right corner */
RL_GRAVITY_SOUTH_WEST = 4, /* anchor to bottom-left corner */
};
/*------------------------------------------
Rootless Implementation Functions
------------------------------------------*/
/*
* Create a new frame.
* The frame is created unmapped.
*
* pFrame RootlessWindowPtr for this frame should be completely
* initialized before calling except for pFrame->wid, which
* is set by this function.
* pScreen Screen on which to place the new frame
* newX, newY Position of the frame. These will be identical to pFrame-x,
* pFrame->y unless ROOTLESS_GLOBAL_COORDS is set.
* pNewShape Shape for the frame (in frame-local coordinates). NULL for
* unshaped frames.
*/
typedef Bool (*RootlessCreateFrameProc)
(RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY,
RegionPtr pNewShape);
/*
* Destroy a frame.
* Drawing is stopped and all updates are flushed before this is called.
*
* wid Frame id
*/
typedef void (*RootlessDestroyFrameProc)
(RootlessFrameID wid);
/*
* Move a frame on screen.
* Drawing is stopped and all updates are flushed before this is called.
*
* wid Frame id
* pScreen Screen to move the new frame to
* newX, newY New position of the frame
*/
typedef void (*RootlessMoveFrameProc)
(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
/*
* Resize and move a frame.
* Drawing is stopped and all updates are flushed before this is called.
*
* wid Frame id
* pScreen Screen to move the new frame to
* newX, newY New position of the frame
* newW, newH New size of the frame
* gravity Gravity for window contents (rl_gravity_enum). This is always
* RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set.
*/
typedef void (*RootlessResizeFrameProc)
(RootlessFrameID wid, ScreenPtr pScreen,
int newX, int newY, unsigned int newW, unsigned int newH,
unsigned int gravity);
/*
* Change frame ordering (AKA stacking, layering).
* Drawing is stopped before this is called. Unmapped frames are mapped by
* setting their ordering.
*
* wid Frame id
* nextWid Frame id of frame that is now above this one or NULL if this
* frame is at the top.
*/
typedef void (*RootlessRestackFrameProc)
(RootlessFrameID wid, RootlessFrameID nextWid);
/*
* Change frame's shape.
* Drawing is stopped before this is called.
*
* wid Frame id
* pNewShape New shape for the frame (in frame-local coordinates)
* or NULL if now unshaped.
*/
typedef void (*RootlessReshapeFrameProc)
(RootlessFrameID wid, RegionPtr pNewShape);
/*
* Unmap a frame.
*
* wid Frame id
*/
typedef void (*RootlessUnmapFrameProc)
(RootlessFrameID wid);
/*
* Start drawing to a frame.
* Prepare a frame for direct access to its backing buffer.
*
* wid Frame id
* pixelData Address of the backing buffer (returned)
* bytesPerRow Width in bytes of the backing buffer (returned)
*/
typedef void (*RootlessStartDrawingProc)
(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
/*
* Stop drawing to a frame.
* No drawing to the frame's backing buffer will occur until drawing
* is started again.
*
* wid Frame id
* flush Flush drawing updates for this frame to the screen. This
* will always be FALSE if ROOTLESS_TRACK_DAMAGE is set.
*/
typedef void (*RootlessStopDrawingProc)
(RootlessFrameID wid, Bool flush);
/*
* Flush drawing updates to the screen.
* Drawing is stopped before this is called.
*
* wid Frame id
* pDamage Region containing all the changed pixels in frame-lcoal
* coordinates. This is clipped to the window's clip. This
* will be NULL if ROOTLESS_TRACK_DAMAGE is not set.
*/
typedef void (*RootlessUpdateRegionProc)
(RootlessFrameID wid, RegionPtr pDamage);
/*
* Mark damaged rectangles as requiring redisplay to screen.
* This will only be called if ROOTLESS_TRACK_DAMAGE is not set.
*
* wid Frame id
* nrects Number of damaged rectangles
* rects Array of damaged rectangles in frame-local coordinates
* shift_x, Vector to shift rectangles by
* shift_y
*/
typedef void (*RootlessDamageRectsProc)
(RootlessFrameID wid, int nrects, const BoxRec *rects,
int shift_x, int shift_y);
/*
* Switch the window associated with a frame. (Optional)
* When a framed window is reparented, the frame is resized and set to
* use the new top-level parent. If defined this function will be called
* afterwards for implementation specific bookkeeping.
*
* pFrame Frame whose window has switched
* oldWin Previous window wrapped by this frame
*/
typedef void (*RootlessSwitchWindowProc)
(RootlessWindowPtr pFrame, WindowPtr oldWin);
/*
* Copy bytes. (Optional)
* Source and destinate may overlap and the right thing should happen.
*
* width Bytes to copy per row
* height Number of rows
* src Source data
* srcRowBytes Width of source in bytes
* dst Destination data
* dstRowBytes Width of destination in bytes
*/
typedef void (*RootlessCopyBytesProc)
(unsigned int width, unsigned int height,
const void *src, unsigned int srcRowBytes,
void *dst, unsigned int dstRowBytes);
/*
* Fill memory with 32-bit pattern. (Optional)
*
* width Bytes to fill per row
* height Number of rows
* value 32-bit pattern to fill with
* dst Destination data
* dstRowBytes Width of destination in bytes
*/
typedef void (*RootlessFillBytesProc)
(unsigned int width, unsigned int height, unsigned int value,
void *dst, unsigned int dstRowBytes);
/*
* Composite pixels from source and mask to destination. (Optional)
*
* width, height Size of area to composite to in pizels
* function Composite function built with RL_COMPOSITE_FUNCTION
* src Source data
* srcRowBytes Width of source in bytes (Passing NULL means source
* is a single pixel.
* mask Mask data
* maskRowBytes Width of mask in bytes
* dst Destination data
* dstRowBytes Width of destination in bytes
*
* For src and dst, the first element of the array is the color data. If
* the second element is non-null it implies there is alpha data (which
* may be meshed or planar). Data without alpha is assumed to be opaque.
*
* An X11 error code is returned.
*/
typedef int (*RootlessCompositePixelsProc)
(unsigned int width, unsigned int height, unsigned int function,
void *src[2], unsigned int srcRowBytes[2],
void *mask, unsigned int maskRowBytes,
void *dst[2], unsigned int dstRowBytes[2]);
/*
* Copy area in frame to another part of frame. (Optional)
*
* wid Frame id
* dstNrects Number of rectangles to copy
* dstRects Array of rectangles to copy
* dx, dy Number of pixels away to copy area
*/
typedef void (*RootlessCopyWindowProc)
(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
int dx, int dy);
/*
* Rootless implementation function list
*/
typedef struct _RootlessFrameProcs {
RootlessCreateFrameProc CreateFrame;
RootlessDestroyFrameProc DestroyFrame;
RootlessMoveFrameProc MoveFrame;
RootlessResizeFrameProc ResizeFrame;
RootlessRestackFrameProc RestackFrame;
RootlessReshapeFrameProc ReshapeFrame;
RootlessUnmapFrameProc UnmapFrame;
RootlessStartDrawingProc StartDrawing;
RootlessStopDrawingProc StopDrawing;
RootlessUpdateRegionProc UpdateRegion;
#ifndef ROOTLESS_TRACK_DAMAGE
RootlessDamageRectsProc DamageRects;
#endif
/* Optional frame functions */
RootlessSwitchWindowProc SwitchWindow;
/* Optional acceleration functions */
RootlessCopyBytesProc CopyBytes;
RootlessFillBytesProc FillBytes;
RootlessCompositePixelsProc CompositePixels;
RootlessCopyWindowProc CopyWindow;
} RootlessFrameProcsRec, *RootlessFrameProcsPtr;
/*
* Initialize rootless mode on the given screen.
*/
Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs);
/*
* Return the frame ID for the physical window displaying the given window.
*
* create If true and the window has no frame, attempt to create one
*/
RootlessFrameID RootlessFrameForWindow(WindowPtr pWin, Bool create);
/*
* Return the top-level parent of a window.
* The root is the top-level parent of itself, even though the root is
* not otherwise considered to be a top-level window.
*/
WindowPtr TopLevelParent(WindowPtr pWindow);
/*
* Prepare a window for direct access to its backing buffer.
*/
void RootlessStartDrawing(WindowPtr pWindow);
/*
* Finish drawing to a window's backing buffer.
*
* flush If true and ROOTLESS_TRACK_DAMAGE is set, damaged areas
* are flushed to the screen.
*/
void RootlessStopDrawing(WindowPtr pWindow, Bool flush);
#endif /* _ROOTLESS_H */

View file

@ -0,0 +1,380 @@
/*
* Common rootless definitions and code
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.c,v 1.5 2003/11/10 18:22:50 tsi Exp $ */
#include "rootlessCommon.h"
unsigned int rootless_CopyBytes_threshold = 0;
unsigned int rootless_FillBytes_threshold = 0;
unsigned int rootless_CompositePixels_threshold = 0;
unsigned int rootless_CopyWindow_threshold = 0;
#ifdef ROOTLESS_GLOBAL_COORDS
int rootlessGlobalOffsetX = 0;
int rootlessGlobalOffsetY = 0;
#endif
RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
/* Following macro from miregion.c */
/* true iff two Boxes overlap */
#define EXTENTCHECK(r1,r2) \
(!( ((r1)->x2 <= (r2)->x1) || \
((r1)->x1 >= (r2)->x2) || \
((r1)->y2 <= (r2)->y1) || \
((r1)->y1 >= (r2)->y2) ) )
/*
* TopLevelParent
* Returns the top-level parent of pWindow.
* The root is the top-level parent of itself, even though the root is
* not otherwise considered to be a top-level window.
*/
WindowPtr
TopLevelParent(WindowPtr pWindow)
{
WindowPtr top;
if (IsRoot(pWindow))
return pWindow;
top = pWindow;
while (top && ! IsTopLevel(top))
top = top->parent;
return top;
}
/*
* IsFramedWindow
* Returns TRUE if this window is visible inside a frame
* (e.g. it is visible and has a top-level or root parent)
*/
Bool
IsFramedWindow(WindowPtr pWin)
{
WindowPtr top;
if (!pWin->realized)
return FALSE;
top = TopLevelParent(pWin);
return (top && WINREC(top));
}
/*
* RootlessStartDrawing
* Prepare a window for direct access to its backing buffer.
* Each top-level parent has a Pixmap representing its backing buffer,
* which all of its children inherit.
*/
void RootlessStartDrawing(WindowPtr pWindow)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
WindowPtr top = TopLevelParent(pWindow);
RootlessWindowRec *winRec;
if (top == NULL)
return;
winRec = WINREC(top);
if (winRec == NULL)
return;
// Make sure the window's top-level parent is prepared for drawing.
if (!winRec->is_drawing) {
int bw = wBorderWidth(top);
SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData,
&winRec->bytesPerRow);
winRec->pixmap =
GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
top->drawable.depth,
top->drawable.bitsPerPixel,
winRec->bytesPerRow,
winRec->pixelData);
SetPixmapBaseToScreen(winRec->pixmap,
top->drawable.x - bw, top->drawable.y - bw);
winRec->is_drawing = TRUE;
}
winRec->oldPixmap = pScreen->GetWindowPixmap(pWindow);
pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
}
/*
* RootlessStopDrawing
* Stop drawing to a window's backing buffer. If flush is true,
* damaged regions are flushed to the screen.
*/
void RootlessStopDrawing(WindowPtr pWindow, Bool flush)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
WindowPtr top = TopLevelParent(pWindow);
RootlessWindowRec *winRec;
if (top == NULL)
return;
winRec = WINREC(top);
if (winRec == NULL)
return;
if (winRec->is_drawing) {
SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush);
FreeScratchPixmapHeader(winRec->pixmap);
pScreen->SetWindowPixmap(pWindow, winRec->oldPixmap);
winRec->pixmap = NULL;
winRec->is_drawing = FALSE;
}
else if (flush) {
SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL);
}
if (flush && winRec->is_reorder_pending) {
winRec->is_reorder_pending = FALSE;
RootlessReorderWindow(pWindow);
}
}
/*
* RootlessDamageRegion
* Mark a damaged region as requiring redisplay to screen.
* pRegion is in GLOBAL coordinates.
*/
void
RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
RootlessWindowRec *winRec;
RegionRec clipped;
WindowPtr pTop;
BoxPtr b1, b2;
RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
pTop = TopLevelParent(pWindow);
if (pTop == NULL)
return;
winRec = WINREC(pTop);
if (winRec == NULL)
return;
/* We need to intersect the drawn region with the clip of the window
to avoid marking places we didn't actually draw (which can cause
problems when the window has an extra client-side backing store)
But this is a costly operation and since we'll normally just be
drawing inside the clip, go to some lengths to avoid the general
case intersection. */
b1 = REGION_EXTENTS(pScreen, &pWindow->borderClip);
b2 = REGION_EXTENTS(pScreen, pRegion);
if (EXTENTCHECK(b1, b2)) {
/* Regions may overlap. */
if (REGION_NUM_RECTS(pRegion) == 1) {
int in;
/* Damaged region only has a single rect, so we can
just compare that against the region */
in = RECT_IN_REGION(pScreen, &pWindow->borderClip,
REGION_RECTS (pRegion));
if (in == rgnIN) {
/* clip totally contains pRegion */
#ifdef ROOTLESS_TRACK_DAMAGE
REGION_UNION(pScreen, &winRec->damage,
&winRec->damage, (pRegion));
#else
SCREENREC(pScreen)->imp->DamageRects(winRec->wid,
REGION_NUM_RECTS(pRegion),
REGION_RECTS(pRegion),
-winRec->x, -winRec->y);
#endif
RootlessQueueRedisplay(pTop->drawable.pScreen);
goto out;
}
else if (in == rgnOUT) {
/* clip doesn't contain pRegion */
goto out;
}
}
/* clip overlaps pRegion, need to intersect */
REGION_NULL(pScreen, &clipped);
REGION_INTERSECT(pScreen, &clipped, &pWindow->borderClip, pRegion);
#ifdef ROOTLESS_TRACK_DAMAGE
REGION_UNION(pScreen, &winRec->damage,
&winRec->damage, (pRegion));
#else
SCREENREC(pScreen)->imp->DamageRects(winRec->wid,
REGION_NUM_RECTS(&clipped),
REGION_RECTS(&clipped),
-winRec->x, -winRec->y);
#endif
REGION_UNINIT(pScreen, &clipped);
RootlessQueueRedisplay(pTop->drawable.pScreen);
}
out:
#ifdef ROOTLESSDEBUG
{
BoxRec *box = REGION_RECTS(pRegion), *end;
int numBox = REGION_NUM_RECTS(pRegion);
for (end = box+numBox; box < end; box++) {
RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
box->x1, box->x2, box->y1, box->y2);
}
}
#endif
return;
}
/*
* RootlessDamageBox
* Mark a damaged box as requiring redisplay to screen.
* pRegion is in GLOBAL coordinates.
*/
void
RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
{
RegionRec region;
REGION_INIT(pWindow->drawable.pScreen, &region, pBox, 1);
RootlessDamageRegion(pWindow, &region);
REGION_UNINIT(pWindow->drawable.pScreen, &region); /* no-op */
}
/*
* RootlessDamageRect
* Mark a damaged rectangle as requiring redisplay to screen.
* (x, y, w, h) is in window-local coordinates.
*/
void
RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
{
BoxRec box;
RegionRec region;
x += pWindow->drawable.x;
y += pWindow->drawable.y;
box.x1 = x;
box.x2 = x + w;
box.y1 = y;
box.y2 = y + h;
REGION_INIT(pWindow->drawable.pScreen, &region, &box, 1);
RootlessDamageRegion(pWindow, &region);
REGION_UNINIT(pWindow->drawable.pScreen, &region); /* no-op */
}
/*
* RootlessRedisplay
* Stop drawing and redisplay the damaged region of a window.
*/
void
RootlessRedisplay(WindowPtr pWindow)
{
#ifdef ROOTLESS_TRACK_DAMAGE
RootlessWindowRec *winRec = WINREC(pWindow);
ScreenPtr pScreen = pWindow->drawable.pScreen;
RootlessStopDrawing(pWindow, FALSE);
if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n",
pWindow, winRec->width, winRec->height,
winRec->x, winRec->y);
// move region to window local coords
REGION_TRANSLATE(pScreen, &winRec->damage,
-winRec->x, -winRec->y);
SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage);
REGION_EMPTY(pScreen, &winRec->damage);
}
#else /* !ROOTLESS_TRACK_DAMAGE */
RootlessStopDrawing(pWindow, TRUE);
#endif
}
/*
* RootlessRedisplayScreen
* Walk every window on a screen and redisplay the damaged regions.
*/
void
RootlessRedisplayScreen(ScreenPtr pScreen)
{
WindowPtr root = WindowTable[pScreen->myNum];
if (root != NULL) {
WindowPtr win;
RootlessRedisplay(root);
for (win = root->firstChild; win; win = win->nextSib) {
if (WINREC(win) != NULL) {
RootlessRedisplay(win);
}
}
}
}

View file

@ -0,0 +1,254 @@
/*
* Common internal rootless definitions and code
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* Copyright (c) 2002-2003 Torrey T. Lyons. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.h,v 1.4 2003/09/16 00:36:20 torrey Exp $ */
#ifndef _ROOTLESSCOMMON_H
#define _ROOTLESSCOMMON_H
#include "rootless.h"
#include "fb.h"
#ifdef RENDER
#include "picturestr.h"
#endif
// Debug output, or not.
#ifdef ROOTLESSDEBUG
#define RL_DEBUG_MSG ErrorF
#else
#define RL_DEBUG_MSG(a, ...)
#endif
// Global variables
extern int rootlessGCPrivateIndex;
extern int rootlessScreenPrivateIndex;
extern int rootlessWindowPrivateIndex;
// RootlessGCRec: private per-gc data
typedef struct {
GCFuncs *originalFuncs;
GCOps *originalOps;
} RootlessGCRec;
// RootlessScreenRec: per-screen private data
typedef struct _RootlessScreenRec {
// Rootless implementation functions
RootlessFrameProcsPtr imp;
// Wrapped screen functions
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
CreateWindowProcPtr CreateWindow;
DestroyWindowProcPtr DestroyWindow;
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
MoveWindowProcPtr MoveWindow;
ResizeWindowProcPtr ResizeWindow;
RestackWindowProcPtr RestackWindow;
ReparentWindowProcPtr ReparentWindow;
ChangeBorderWidthProcPtr ChangeBorderWidth;
PositionWindowProcPtr PositionWindow;
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
CreateGCProcPtr CreateGC;
PaintWindowBackgroundProcPtr PaintWindowBackground;
PaintWindowBorderProcPtr PaintWindowBorder;
CopyWindowProcPtr CopyWindow;
GetImageProcPtr GetImage;
SourceValidateProcPtr SourceValidate;
MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
ValidateTreeProcPtr ValidateTree;
#ifdef SHAPE
SetShapeProcPtr SetShape;
#endif
#ifdef RENDER
CompositeProcPtr Composite;
GlyphsProcPtr Glyphs;
#endif
void *pixmap_data;
unsigned int pixmap_data_size;
void *redisplay_timer;
unsigned int redisplay_timer_set :1;
unsigned int redisplay_queued :1;
unsigned int redisplay_expired :1;
} RootlessScreenRec, *RootlessScreenPtr;
#undef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
// "Definition of the Porting Layer for the X11 Sample Server" says
// unwrap and rewrap of screen functions is unnecessary, but
// screen->CreateGC changes after a call to cfbCreateGC.
#define SCREEN_UNWRAP(screen, fn) \
screen->fn = SCREENREC(screen)->fn;
#define SCREEN_WRAP(screen, fn) \
SCREENREC(screen)->fn = screen->fn; \
screen->fn = Rootless##fn
// Accessors for screen and window privates
#define SCREENREC(pScreen) \
((RootlessScreenRec *)(pScreen)->devPrivates[rootlessScreenPrivateIndex].ptr)
#define WINREC(pWin) \
((RootlessWindowRec *)(pWin)->devPrivates[rootlessWindowPrivateIndex].ptr)
// Call a rootless implementation function.
// Many rootless implementation functions are allowed to be NULL.
#define CallFrameProc(pScreen, proc, params) \
if (SCREENREC(pScreen)->frameProcs.proc) { \
RL_DEBUG_MSG("calling frame proc " #proc " "); \
SCREENREC(pScreen)->frameProcs.proc params; \
}
// BoxRec manipulators
// Copied from shadowfb
#define TRIM_BOX(box, pGC) { \
BoxPtr extents = &pGC->pCompositeClip->extents;\
if(box.x1 < extents->x1) box.x1 = extents->x1; \
if(box.x2 > extents->x2) box.x2 = extents->x2; \
if(box.y1 < extents->y1) box.y1 = extents->y1; \
if(box.y2 > extents->y2) box.y2 = extents->y2; \
}
#define TRANSLATE_BOX(box, pDraw) { \
box.x1 += pDraw->x; \
box.x2 += pDraw->x; \
box.y1 += pDraw->y; \
box.y2 += pDraw->y; \
}
#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
TRANSLATE_BOX(box, pDraw); \
TRIM_BOX(box, pGC); \
}
#define BOX_NOT_EMPTY(box) \
(((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
// HUGE_ROOT and NORMAL_ROOT
// We don't want to clip windows to the edge of the screen.
// HUGE_ROOT temporarily makes the root window really big.
// This is needed as a wrapper around any function that calls
// SetWinSize or SetBorderSize which clip a window against its
// parents, including the root.
extern RegionRec rootlessHugeRoot;
#define HUGE_ROOT(pWin) \
do { \
WindowPtr w = pWin; \
while (w->parent) \
w = w->parent; \
saveRoot = w->winSize; \
w->winSize = rootlessHugeRoot; \
} while (0)
#define NORMAL_ROOT(pWin) \
do { \
WindowPtr w = pWin; \
while (w->parent) \
w = w->parent; \
w->winSize = saveRoot; \
} while (0)
// Returns TRUE if this window is a top-level window (i.e. child of the root)
// The root is not a top-level window.
#define IsTopLevel(pWin) \
((pWin) && (pWin)->parent && !(pWin)->parent->parent)
// Returns TRUE if this window is a root window
#define IsRoot(pWin) \
((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum])
/*
* SetPixmapBaseToScreen
* Move the given pixmap's base address to where pixel (0, 0)
* would be if the pixmap's actual data started at (x, y).
* Can't access the bits before the first word of the drawable's data in
* rootless mode, so make sure our base address is always 32-bit aligned.
*/
#define SetPixmapBaseToScreen(pix, _x, _y) { \
PixmapPtr _pPix = (PixmapPtr) (pix); \
_pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
((int)(_x) * _pPix->drawable.bitsPerPixel/8 + \
(int)(_y) * _pPix->devKind); \
if (_pPix->drawable.bitsPerPixel != FB_UNIT) { \
unsigned _diff = ((unsigned) _pPix->devPrivate.ptr) & \
(FB_UNIT / CHAR_BIT - 1); \
_pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
_diff; \
_pPix->drawable.x = _diff / \
(_pPix->drawable.bitsPerPixel / CHAR_BIT); \
} \
}
// Returns TRUE if this window is visible inside a frame
// (e.g. it is visible and has a top-level or root parent)
Bool IsFramedWindow(WindowPtr pWin);
// Routines that cause regions to get redrawn.
// DamageRegion and DamageRect are in global coordinates.
// DamageBox is in window-local coordinates.
void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion);
void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h);
void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox);
void RootlessRedisplay(WindowPtr pWindow);
void RootlessRedisplayScreen(ScreenPtr pScreen);
void RootlessQueueRedisplay (ScreenPtr pScreen);
// Move the window to it's correct place in the physical stacking order.
void RootlessReorderWindow (WindowPtr pWin);
#endif /* _ROOTLESSCOMMON_H */

View file

@ -0,0 +1,50 @@
/*
* Platform specific rootless configuration
*/
/*
* Copyright (c) 2003 Torrey T. Lyons. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessConfig.h,v 1.2 2003/10/24 00:33:14 torrey Exp $ */
#ifndef _ROOTLESSCONFIG_H
#define _ROOTLESSCONFIG_H
#ifdef __DARWIN__
# define ROOTLESS_ACCEL TRUE
# define ROOTLESS_GLOBAL_COORDS TRUE
# define ROOTLESS_PROTECT_ALPHA TRUE
# define ROOTLESS_REDISPLAY_DELAY 10
# define ROOTLESS_RESIZE_GRAVITY TRUE
# undef ROOTLESS_TRACK_DAMAGE
/* Bit mask for alpha channel with a particular number of bits per
pixel. Note that we only care for 32bpp data. Mac OS X uses planar
alpha for 16bpp. */
# define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
#endif /* __DARWIN__ */
#endif /* _ROOTLESSCONFIG_H */

1515
miext/rootless/rootlessGC.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,666 @@
/*
* Screen routines for generic rootless X server
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessScreen.c,v 1.3 2003/06/30 01:45:13 torrey Exp $ */
#include "mi.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "propertyst.h"
#include "mivalidate.h"
#include "picturestr.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "rootlessCommon.h"
#include "rootlessWindow.h"
/* In milliseconds */
#ifndef ROOTLESS_REDISPLAY_DELAY
#define ROOTLESS_REDISPLAY_DELAY 10
#endif
extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
VTKind kind);
extern Bool RootlessCreateGC(GCPtr pGC);
// Initialize globals
int rootlessGCPrivateIndex = -1;
int rootlessScreenPrivateIndex = -1;
int rootlessWindowPrivateIndex = -1;
/*
* RootlessUpdateScreenPixmap
* miCreateScreenResources does not like a null framebuffer pointer,
* it leaves the screen pixmap with an uninitialized data pointer.
* Thus, rootless implementations typically set the framebuffer width
* to zero so that miCreateScreenResources does not allocate a screen
* pixmap for us. We allocate our own screen pixmap here since we need
* the screen pixmap to be valid (e.g. CopyArea from the root window).
*/
void
RootlessUpdateScreenPixmap(ScreenPtr pScreen)
{
RootlessScreenRec *s = SCREENREC(pScreen);
PixmapPtr pPix;
unsigned int rowbytes;
pPix = (*pScreen->GetScreenPixmap)(pScreen);
if (pPix == NULL) {
pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth);
(*pScreen->SetScreenPixmap)(pPix);
}
rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth);
if (s->pixmap_data_size < rowbytes) {
if (s->pixmap_data != NULL)
xfree(s->pixmap_data);
s->pixmap_data_size = rowbytes;
s->pixmap_data = xalloc(s->pixmap_data_size);
if (s->pixmap_data == NULL)
return;
memset(s->pixmap_data, 0xFF, s->pixmap_data_size);
pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height,
pScreen->rootDepth,
BitsPerPixel(pScreen->rootDepth),
0, s->pixmap_data);
/* ModifyPixmapHeader ignores zero arguments, so install rowbytes
by hand. */
pPix->devKind = 0;
}
}
/*
* RootlessCreateScreenResources
* Rootless implementations typically set a null framebuffer pointer, which
* causes problems with miCreateScreenResources. We fix things up here.
*/
static Bool
RootlessCreateScreenResources(ScreenPtr pScreen)
{
Bool ret = TRUE;
SCREEN_UNWRAP(pScreen, CreateScreenResources);
if (pScreen->CreateScreenResources != NULL)
ret = (*pScreen->CreateScreenResources)(pScreen);
SCREEN_WRAP(pScreen, CreateScreenResources);
if (!ret)
return ret;
/* Make sure we have a valid screen pixmap. */
RootlessUpdateScreenPixmap(pScreen);
return ret;
}
static Bool
RootlessCloseScreen(int i, ScreenPtr pScreen)
{
RootlessScreenRec *s;
s = SCREENREC(pScreen);
// fixme unwrap everything that was wrapped?
pScreen->CloseScreen = s->CloseScreen;
if (s->pixmap_data != NULL) {
xfree (s->pixmap_data);
s->pixmap_data = NULL;
s->pixmap_data_size = 0;
}
xfree(s);
return pScreen->CloseScreen(i, pScreen);
}
static void
RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
unsigned int format, unsigned long planeMask, char *pdstLine)
{
ScreenPtr pScreen = pDrawable->pScreen;
SCREEN_UNWRAP(pScreen, GetImage);
if (pDrawable->type == DRAWABLE_WINDOW) {
int x0, y0, x1, y1;
RootlessWindowRec *winRec;
// Many apps use GetImage to sync with the visible frame buffer
// FIXME: entire screen or just window or all screens?
RootlessRedisplayScreen(pScreen);
// RedisplayScreen stops drawing, so we need to start it again
RootlessStartDrawing((WindowPtr)pDrawable);
/* Check that we have some place to read from. */
winRec = WINREC(TopLevelParent((WindowPtr) pDrawable));
if (winRec == NULL)
goto out;
/* Clip to top-level window bounds. */
/* FIXME: fbGetImage uses the width parameter to calculate the
stride of the destination pixmap. If w is clipped, the data
returned will be garbage, although we will not crash. */
x0 = pDrawable->x + sx;
y0 = pDrawable->y + sy;
x1 = x0 + w;
y1 = y0 + h;
x0 = MAX (x0, winRec->x);
y0 = MAX (y0, winRec->y);
x1 = MIN (x1, winRec->x + winRec->width);
y1 = MIN (y1, winRec->y + winRec->height);
sx = x0 - pDrawable->x;
sy = y0 - pDrawable->y;
w = x1 - x0;
h = y1 - y0;
if (w <= 0 || h <= 0)
goto out;
}
pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
out:
SCREEN_WRAP(pScreen, GetImage);
}
/*
* RootlessSourceValidate
* CopyArea and CopyPlane use a GC tied to the destination drawable.
* StartDrawing/StopDrawing wrappers won't be called if source is
* a visible window but the destination isn't. So, we call StartDrawing
* here and leave StopDrawing for the block handler.
*/
static void
RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
{
SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
if (pDrawable->type == DRAWABLE_WINDOW) {
WindowPtr pWin = (WindowPtr)pDrawable;
RootlessStartDrawing(pWin);
}
if (pDrawable->pScreen->SourceValidate) {
pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h);
}
SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
}
#ifdef RENDER
static void
RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
{
ScreenPtr pScreen = pDst->pDrawable->pScreen;
PictureScreenPtr ps = GetPictureScreen(pScreen);
WindowPtr srcWin, dstWin, maskWin = NULL;
if (pMask) { // pMask can be NULL
maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ?
(WindowPtr)pMask->pDrawable : NULL;
}
srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
(WindowPtr)pSrc->pDrawable : NULL;
dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
(WindowPtr)pDst->pDrawable : NULL;
// SCREEN_UNWRAP(ps, Composite);
ps->Composite = SCREENREC(pScreen)->Composite;
if (srcWin && IsFramedWindow(srcWin))
RootlessStartDrawing(srcWin);
if (maskWin && IsFramedWindow(maskWin))
RootlessStartDrawing(maskWin);
if (dstWin && IsFramedWindow(dstWin))
RootlessStartDrawing(dstWin);
ps->Composite(op, pSrc, pMask, pDst,
xSrc, ySrc, xMask, yMask,
xDst, yDst, width, height);
if (dstWin && IsFramedWindow(dstWin)) {
RootlessDamageRect(dstWin, xDst, yDst, width, height);
}
ps->Composite = RootlessComposite;
// SCREEN_WRAP(ps, Composite);
}
static void
RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
int nlist, GlyphListPtr list, GlyphPtr *glyphs)
{
ScreenPtr pScreen = pDst->pDrawable->pScreen;
PictureScreenPtr ps = GetPictureScreen(pScreen);
int x, y;
int n;
GlyphPtr glyph;
WindowPtr srcWin, dstWin;
srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
(WindowPtr)pSrc->pDrawable : NULL;
dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
(WindowPtr)pDst->pDrawable : NULL;
if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
//SCREEN_UNWRAP(ps, Glyphs);
ps->Glyphs = SCREENREC(pScreen)->Glyphs;
ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
ps->Glyphs = RootlessGlyphs;
//SCREEN_WRAP(ps, Glyphs);
if (dstWin && IsFramedWindow(dstWin)) {
x = xSrc;
y = ySrc;
while (nlist--) {
x += list->xOff;
y += list->yOff;
n = list->len;
/* Calling DamageRect for the bounding box of each glyph is
inefficient. So compute the union of all glyphs in a list
and damage that. */
if (n > 0) {
BoxRec box;
glyph = *glyphs++;
box.x1 = x - glyph->info.x;
box.y1 = y - glyph->info.y;
box.x2 = box.x1 + glyph->info.width;
box.y2 = box.y2 + glyph->info.height;
x += glyph->info.xOff;
y += glyph->info.yOff;
while (--n > 0) {
short x1, y1, x2, y2;
glyph = *glyphs++;
x1 = x - glyph->info.x;
y1 = y - glyph->info.y;
x2 = x1 + glyph->info.width;
y2 = y1 + glyph->info.height;
box.x1 = MAX (box.x1, x1);
box.y1 = MAX (box.y1, y1);
box.x2 = MAX (box.x2, x2);
box.y2 = MAX (box.y2, y2);
x += glyph->info.xOff;
y += glyph->info.yOff;
}
RootlessDamageBox(dstWin, &box);
}
list++;
}
}
}
#endif // RENDER
/*
* RootlessValidateTree
* ValidateTree is modified in two ways:
* - top-level windows don't clip each other
* - windows aren't clipped against root.
* These only matter when validating from the root.
*/
static int
RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
{
int result;
RegionRec saveRoot;
ScreenPtr pScreen = pParent->drawable.pScreen;
SCREEN_UNWRAP(pScreen, ValidateTree);
RL_DEBUG_MSG("VALIDATETREE start ");
// Use our custom version to validate from root
if (IsRoot(pParent)) {
RL_DEBUG_MSG("custom ");
result = RootlessMiValidateTree(pParent, pChild, kind);
} else {
HUGE_ROOT(pParent);
result = pScreen->ValidateTree(pParent, pChild, kind);
NORMAL_ROOT(pParent);
}
SCREEN_WRAP(pScreen, ValidateTree);
RL_DEBUG_MSG("VALIDATETREE end\n");
return result;
}
/*
* RootlessMarkOverlappedWindows
* MarkOverlappedWindows is modified to ignore overlapping
* top-level windows.
*/
static Bool
RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
WindowPtr *ppLayerWin)
{
RegionRec saveRoot;
Bool result;
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
HUGE_ROOT(pWin);
if (IsRoot(pWin)) {
// root - mark nothing
RL_DEBUG_MSG("is root not marking ");
result = FALSE;
}
else if (! IsTopLevel(pWin)) {
// not top-level window - mark normally
result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
}
else {
//top-level window - mark children ONLY - NO overlaps with sibs (?)
// This code copied from miMarkOverlappedWindows()
register WindowPtr pChild;
Bool anyMarked = FALSE;
void (* MarkWindow)() = pScreen->MarkWindow;
RL_DEBUG_MSG("is top level! ");
/* single layered systems are easy */
if (ppLayerWin) *ppLayerWin = pWin;
if (pWin == pFirst) {
/* Blindly mark pWin and all of its inferiors. This is a slight
* overkill if there are mapped windows that outside pWin's border,
* but it's better than wasting time on RectIn checks.
*/
pChild = pWin;
while (1) {
if (pChild->viewable) {
if (REGION_BROKEN (pScreen, &pChild->winSize))
SetWinSize (pChild);
if (REGION_BROKEN (pScreen, &pChild->borderSize))
SetBorderSize (pChild);
(* MarkWindow)(pChild);
if (pChild->firstChild) {
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pWin))
pChild = pChild->parent;
if (pChild == pWin)
break;
pChild = pChild->nextSib;
}
anyMarked = TRUE;
pFirst = pFirst->nextSib;
}
if (anyMarked)
(* MarkWindow)(pWin->parent);
result = anyMarked;
}
NORMAL_ROOT(pWin);
SCREEN_WRAP(pScreen, MarkOverlappedWindows);
RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
return result;
}
static CARD32
RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg)
{
RootlessScreenRec *screenRec = arg;
if (!screenRec->redisplay_queued) {
/* No update needed. Stop the timer. */
screenRec->redisplay_timer_set = FALSE;
return 0;
}
screenRec->redisplay_queued = FALSE;
/* Mark that we should redisplay before waiting for I/O next time */
screenRec->redisplay_expired = TRUE;
/* Reinstall the timer immediately, so we get as close to our
redisplay interval as possible. */
return ROOTLESS_REDISPLAY_DELAY;
}
/*
* RootlessQueueRedisplay
* Queue a redisplay after a timer delay to ensure we do not redisplay
* too frequently.
*/
void
RootlessQueueRedisplay(ScreenPtr pScreen)
{
RootlessScreenRec *screenRec = SCREENREC(pScreen);
screenRec->redisplay_queued = TRUE;
if (screenRec->redisplay_timer_set)
return;
screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer,
0, ROOTLESS_REDISPLAY_DELAY,
RootlessRedisplayCallback,
screenRec);
screenRec->redisplay_timer_set = TRUE;
}
/*
* RootlessBlockHandler
* If the redisplay timer has expired, flush drawing before blocking
* on select().
*/
static void
RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
{
ScreenPtr pScreen = pbdata;
RootlessScreenRec *screenRec = SCREENREC(pScreen);
if (screenRec->redisplay_expired) {
screenRec->redisplay_expired = FALSE;
RootlessRedisplayScreen(pScreen);
}
}
static void
RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
{
// nothing here
}
static Bool
RootlessAllocatePrivates(ScreenPtr pScreen)
{
RootlessScreenRec *s;
static unsigned long rootlessGeneration = 0;
if (rootlessGeneration != serverGeneration) {
rootlessScreenPrivateIndex = AllocateScreenPrivateIndex();
if (rootlessScreenPrivateIndex == -1) return FALSE;
rootlessGCPrivateIndex = AllocateGCPrivateIndex();
if (rootlessGCPrivateIndex == -1) return FALSE;
rootlessWindowPrivateIndex = AllocateWindowPrivateIndex();
if (rootlessWindowPrivateIndex == -1) return FALSE;
rootlessGeneration = serverGeneration;
}
// no allocation needed for screen privates
if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex,
sizeof(RootlessGCRec)))
return FALSE;
if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0))
return FALSE;
s = xalloc(sizeof(RootlessScreenRec));
if (! s) return FALSE;
SCREENREC(pScreen) = s;
s->pixmap_data = NULL;
s->pixmap_data_size = 0;
s->redisplay_timer = NULL;
s->redisplay_timer_set = FALSE;
return TRUE;
}
static void
RootlessWrap(ScreenPtr pScreen)
{
RootlessScreenRec *s = (RootlessScreenRec*)
pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
#define WRAP(a) \
if (pScreen->a) { \
s->a = pScreen->a; \
} else { \
RL_DEBUG_MSG("null screen fn " #a "\n"); \
s->a = NULL; \
} \
pScreen->a = Rootless##a
WRAP(CreateScreenResources);
WRAP(CloseScreen);
WRAP(CreateGC);
WRAP(PaintWindowBackground);
WRAP(PaintWindowBorder);
WRAP(CopyWindow);
WRAP(GetImage);
WRAP(SourceValidate);
WRAP(CreateWindow);
WRAP(DestroyWindow);
WRAP(RealizeWindow);
WRAP(UnrealizeWindow);
WRAP(MoveWindow);
WRAP(PositionWindow);
WRAP(ResizeWindow);
WRAP(RestackWindow);
WRAP(ReparentWindow);
WRAP(ChangeBorderWidth);
WRAP(MarkOverlappedWindows);
WRAP(ValidateTree);
WRAP(ChangeWindowAttributes);
#ifdef SHAPE
WRAP(SetShape);
#endif
#ifdef RENDER
{
// Composite and Glyphs don't use normal screen wrapping
PictureScreenPtr ps = GetPictureScreen(pScreen);
s->Composite = ps->Composite;
ps->Composite = RootlessComposite;
s->Glyphs = ps->Glyphs;
ps->Glyphs = RootlessGlyphs;
}
#endif
// WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
// WRAP(RestoreAreas); fixme put this back?
#undef WRAP
}
/*
* RootlessInit
* Called by the rootless implementation to initialize the rootless layer.
* Rootless wraps lots of stuff and needs a bunch of devPrivates.
*/
Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs)
{
RootlessScreenRec *s;
if (!RootlessAllocatePrivates(pScreen))
return FALSE;
s = (RootlessScreenRec*)
pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
s->imp = procs;
RootlessWrap(pScreen);
if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler,
RootlessWakeupHandler,
(pointer) pScreen))
{
return FALSE;
}
return TRUE;
}

View file

@ -0,0 +1,638 @@
/*
* Calculate window clip lists for rootless mode
*
* This file is very closely based on mivaltree.c.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessValTree.c,v 1.2 2003/11/10 18:22:50 tsi Exp $ */
/*
* mivaltree.c --
* Functions for recalculating window clip lists. Main function
* is miValidateTree.
*
Copyright 1987, 1988, 1989, 1998 The Open Group
All Rights Reserved.
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
OPEN GROUP 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 of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*
* Copyright 1987, 1988, 1989 by
* Digital Equipment Corporation, Maynard, Massachusetts,
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Digital not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
* DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
******************************************************************/
/* The panoramix components contained the following notice */
/****************************************************************
* *
* Copyright (c) Digital Equipment Corporation, 1991, 1997 *
* *
* All Rights Reserved. Unpublished rights reserved under *
* the copyright laws of the United States. *
* *
* The software contained on this media is proprietary to *
* and embodies the confidential technology of Digital *
* Equipment Corporation. Possession, use, duplication or *
* dissemination of the software and media is authorized only *
* pursuant to a valid written license from Digital Equipment *
* Corporation. *
* *
* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
* by the U.S. Government is subject to restrictions as set *
* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
* or in FAR 52.227-19, as applicable. *
* *
*****************************************************************/
/*
* Aug '86: Susan Angebranndt -- original code
* July '87: Adam de Boor -- substantially modified and commented
* Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
* In particular, much improved code for window mapping and
* circulating.
* Bob Scheifler -- avoid miComputeClips for unmapped windows,
* valdata changes
*/
#include "X.h"
#include "scrnintstr.h"
#include "validate.h"
#include "windowstr.h"
#include "mi.h"
#include "regionstr.h"
#include "mivalidate.h"
#include "globals.h"
#ifdef SHAPE
/*
* Compute the visibility of a shaped window
*/
int
RootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y)
ScreenPtr pScreen;
RegionPtr universe, bounding;
BoxPtr rect;
register int x, y;
{
BoxRec box;
register BoxPtr boundBox;
int nbox;
Bool someIn, someOut;
register int t, x1, y1, x2, y2;
nbox = REGION_NUM_RECTS (bounding);
boundBox = REGION_RECTS (bounding);
someIn = someOut = FALSE;
x1 = rect->x1;
y1 = rect->y1;
x2 = rect->x2;
y2 = rect->y2;
while (nbox--)
{
if ((t = boundBox->x1 + x) < x1)
t = x1;
box.x1 = t;
if ((t = boundBox->y1 + y) < y1)
t = y1;
box.y1 = t;
if ((t = boundBox->x2 + x) > x2)
t = x2;
box.x2 = t;
if ((t = boundBox->y2 + y) > y2)
t = y2;
box.y2 = t;
if (box.x1 > box.x2)
box.x2 = box.x1;
if (box.y1 > box.y2)
box.y2 = box.y1;
switch (RECT_IN_REGION(pScreen, universe, &box))
{
case rgnIN:
if (someOut)
return rgnPART;
someIn = TRUE;
break;
case rgnOUT:
if (someIn)
return rgnPART;
someOut = TRUE;
break;
default:
return rgnPART;
}
boundBox++;
}
if (someIn)
return rgnIN;
return rgnOUT;
}
#endif
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
HasBorder(w) && \
(w)->backgroundState == ParentRelative)
/*
*-----------------------------------------------------------------------
* RootlessComputeClips --
* Recompute the clipList, borderClip, exposed and borderExposed
* regions for pParent and its children. Only viewable windows are
* taken into account.
*
* Results:
* None.
*
* Side Effects:
* clipList, borderClip, exposed and borderExposed are altered.
* A VisibilityNotify event may be generated on the parent window.
*
*-----------------------------------------------------------------------
*/
static void
RootlessComputeClips (pParent, pScreen, universe, kind, exposed)
register WindowPtr pParent;
register ScreenPtr pScreen;
register RegionPtr universe;
VTKind kind;
RegionPtr exposed; /* for intermediate calculations */
{
int dx,
dy;
RegionRec childUniverse;
register WindowPtr pChild;
int oldVis, newVis;
BoxRec borderSize;
RegionRec childUnion;
Bool overlap;
RegionPtr borderVisible;
Bool resized;
/*
* Figure out the new visibility of this window.
* The extent of the universe should be the same as the extent of
* the borderSize region. If the window is unobscured, this rectangle
* will be completely inside the universe (the universe will cover it
* completely). If the window is completely obscured, none of the
* universe will cover the rectangle.
*/
borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
if (dx > 32767)
dx = 32767;
borderSize.x2 = dx;
dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
if (dy > 32767)
dy = 32767;
borderSize.y2 = dy;
oldVis = pParent->visibility;
switch (RECT_IN_REGION( pScreen, universe, &borderSize))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnPART:
newVis = VisibilityPartiallyObscured;
#ifdef SHAPE
{
RegionPtr pBounding;
if ((pBounding = wBoundingShape (pParent)))
{
switch (RootlessShapedWindowIn (pScreen, universe,
pBounding, &borderSize,
pParent->drawable.x,
pParent->drawable.y))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnOUT:
newVis = VisibilityFullyObscured;
break;
}
}
}
#endif
break;
default:
newVis = VisibilityFullyObscured;
break;
}
pParent->visibility = newVis;
if (oldVis != newVis &&
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
SendVisibilityNotify(pParent);
dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
/*
* avoid computations when dealing with simple operations
*/
switch (kind) {
case VTMap:
case VTStack:
case VTUnmap:
break;
case VTMove:
if ((oldVis == newVis) &&
((oldVis == VisibilityFullyObscured) ||
(oldVis == VisibilityUnobscured)))
{
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
if (pChild->visibility != VisibilityFullyObscured)
{
REGION_TRANSLATE( pScreen, &pChild->borderClip,
dx, dy);
REGION_TRANSLATE( pScreen, &pChild->clipList,
dx, dy);
pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pChild, dx, dy);
}
if (pChild->valdata)
{
REGION_NULL(pScreen,
&pChild->valdata->after.borderExposed);
if (HasParentRelativeBorder(pChild))
{
REGION_SUBTRACT(pScreen,
&pChild->valdata->after.borderExposed,
&pChild->borderClip,
&pChild->winSize);
}
REGION_NULL(pScreen, &pChild->valdata->after.exposed);
}
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
return;
}
/* fall through */
default:
/*
* To calculate exposures correctly, we have to translate the old
* borderClip and clipList regions to the window's new location so there
* is a correspondence between pieces of the new and old clipping regions.
*/
if (dx || dy)
{
/*
* We translate the old clipList because that will be exposed or copied
* if gravity is right.
*/
REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
}
break;
case VTBroken:
REGION_EMPTY (pScreen, &pParent->borderClip);
REGION_EMPTY (pScreen, &pParent->clipList);
break;
}
borderVisible = pParent->valdata->before.borderVisible;
resized = pParent->valdata->before.resized;
REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
REGION_NULL(pScreen, &pParent->valdata->after.exposed);
/*
* Since the borderClip must not be clipped by the children, we do
* the border exposure first...
*
* 'universe' is the window's borderClip. To figure the exposures, remove
* the area that used to be exposed from the new.
* This leaves a region of pieces that weren't exposed before.
*/
if (HasBorder (pParent))
{
if (borderVisible)
{
/*
* when the border changes shape, the old visible portions
* of the border will be saved by DIX in borderVisible --
* use that region and destroy it
*/
REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
REGION_DESTROY( pScreen, borderVisible);
}
else
{
REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
}
if (HasParentRelativeBorder(pParent) && (dx || dy)) {
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
universe,
&pParent->winSize);
} else {
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
exposed, &pParent->winSize);
}
REGION_COPY( pScreen, &pParent->borderClip, universe);
/*
* To get the right clipList for the parent, and to make doubly sure
* that no child overlaps the parent's border, we remove the parent's
* border from the universe before proceeding.
*/
REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
}
else
REGION_COPY( pScreen, &pParent->borderClip, universe);
if ((pChild = pParent->firstChild) && pParent->mapped)
{
REGION_NULL(pScreen, &childUniverse);
REGION_NULL(pScreen, &childUnion);
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
(pChild->drawable.x < pParent->lastChild->drawable.x)))
{
for (; pChild; pChild = pChild->nextSib)
{
if (pChild->viewable)
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
}
}
else
{
for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
{
if (pChild->viewable)
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
}
}
REGION_VALIDATE( pScreen, &childUnion, &overlap);
for (pChild = pParent->firstChild;
pChild;
pChild = pChild->nextSib)
{
if (pChild->viewable) {
/*
* If the child is viewable, we want to remove its extents
* from the current universe, but we only re-clip it if
* it's been marked.
*/
if (pChild->valdata) {
/*
* Figure out the new universe from the child's
* perspective and recurse.
*/
REGION_INTERSECT( pScreen, &childUniverse,
universe,
&pChild->borderSize);
RootlessComputeClips (pChild, pScreen, &childUniverse,
kind, exposed);
}
/*
* Once the child has been processed, we remove its extents
* from the current universe, thus denying its space to any
* other sibling.
*/
if (overlap)
REGION_SUBTRACT( pScreen, universe, universe,
&pChild->borderSize);
}
}
if (!overlap)
REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
REGION_UNINIT( pScreen, &childUnion);
REGION_UNINIT( pScreen, &childUniverse);
} /* if any children */
/*
* 'universe' now contains the new clipList for the parent window.
*
* To figure the exposure of the window we subtract the old clip from the
* new, just as for the border.
*/
if (oldVis == VisibilityFullyObscured ||
oldVis == VisibilityNotViewable)
{
REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
}
else if (newVis != VisibilityFullyObscured &&
newVis != VisibilityNotViewable)
{
REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
universe, &pParent->clipList);
}
/*
* One last thing: backing storage. We have to try to save what parts of
* the window are about to be obscured. We can just subtract the universe
* from the old clipList and get the areas that were in the old but aren't
* in the new and, hence, are about to be obscured.
*/
if (pParent->backStorage && !resized)
{
REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
(* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
}
/* HACK ALERT - copying contents of regions, instead of regions */
{
RegionRec tmp;
tmp = pParent->clipList;
pParent->clipList = *universe;
*universe = tmp;
}
#ifdef NOTDEF
REGION_COPY( pScreen, &pParent->clipList, universe);
#endif
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pParent, dx, dy);
}
static void
RootlessTreeObscured(pParent)
register WindowPtr pParent;
{
register WindowPtr pChild;
register int oldVis;
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
oldVis = pChild->visibility;
if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
SendVisibilityNotify(pChild);
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
}
/*
*-----------------------------------------------------------------------
* RootlessMiValidateTree --
* Recomputes the clip list for pParent and all its inferiors.
*
* Results:
* Always returns 1.
*
* Side Effects:
* The clipList, borderClip, exposed, and borderExposed regions for
* each marked window are altered.
*
* Notes:
* This routine assumes that all affected windows have been marked
* (valdata created) and their winSize and borderSize regions
* adjusted to correspond to their new positions. The borderClip and
* clipList regions should not have been touched.
*
* The top-most level is treated differently from all lower levels
* because pParent is unchanged. For the top level, we merge the
* regions taken up by the marked children back into the clipList
* for pParent, thus forming a region from which the marked children
* can claim their areas. For lower levels, where the old clipList
* and borderClip are invalid, we can't do this and have to do the
* extra operations done in miComputeClips, but this is much faster
* e.g. when only one child has moved...
*
*-----------------------------------------------------------------------
*/
/*
Quartz version: used for validate from root in rootless mode.
We need to make sure top-level windows don't clip each other,
and that top-level windows aren't clipped to the root window.
*/
/*ARGSUSED*/
// fixme this is ugly
// Xprint/ValTree.c doesn't work, but maybe that method can?
int
RootlessMiValidateTree (pRoot, pChild, kind)
WindowPtr pRoot; /* Parent to validate */
WindowPtr pChild; /* First child of pRoot that was
* affected */
VTKind kind; /* What kind of configuration caused call */
{
RegionRec childClip; /* The new borderClip for the current
* child */
RegionRec exposed; /* For intermediate calculations */
register ScreenPtr pScreen;
register WindowPtr pWin;
pScreen = pRoot->drawable.pScreen;
if (pChild == NullWindow)
pChild = pRoot->firstChild;
REGION_NULL(pScreen, &childClip);
REGION_NULL(pScreen, &exposed);
if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
!REGION_BROKEN (pScreen, &pRoot->borderClip))
{
// fixme this might not work, but hopefully doesn't happen anyway.
kind = VTBroken;
REGION_EMPTY (pScreen, &pRoot->clipList);
ErrorF("ValidateTree: BUSTED!\n");
}
/*
* Recursively compute the clips for all children of the root.
* They don't clip against each other or the root itself, so
* childClip is always reset to that child's size.
*/
for (pWin = pChild;
pWin != NullWindow;
pWin = pWin->nextSib)
{
if (pWin->viewable) {
if (pWin->valdata) {
REGION_COPY( pScreen, &childClip, &pWin->borderSize);
RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
} else if (pWin->visibility == VisibilityNotViewable) {
RootlessTreeObscured(pWin);
}
} else {
if (pWin->valdata) {
REGION_EMPTY( pScreen, &pWin->clipList);
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pWin, 0, 0);
REGION_EMPTY( pScreen, &pWin->borderClip);
pWin->valdata = (ValidatePtr)NULL;
}
}
}
REGION_UNINIT(pScreen, &childClip);
/* The root is never clipped by its children, so nothing on the root
is ever exposed by moving or mapping its children. */
REGION_NULL(pScreen, &pRoot->valdata->after.exposed);
REGION_NULL(pScreen, &pRoot->valdata->after.borderExposed);
return 1;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
/*
* Rootless window management
*/
/*
* Copyright (c) 2001 Greg Parker. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessWindow.h,v 1.2 2003/06/30 01:45:13 torrey Exp $ */
#ifndef _ROOTLESSWINDOW_H
#define _ROOTLESSWINDOW_H
#include "rootlessCommon.h"
Bool RootlessCreateWindow(WindowPtr pWin);
Bool RootlessDestroyWindow(WindowPtr pWin);
#ifdef SHAPE
void RootlessSetShape(WindowPtr pWin);
#endif // SHAPE
Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
Bool RootlessRealizeWindow(WindowPtr pWin);
Bool RootlessUnrealizeWindow(WindowPtr pWin);
void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
void RootlessResizeWindow(WindowPtr pWin, int x, int y,
unsigned int w, unsigned int h, WindowPtr pSib);
void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
void RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
int what);
void RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
int what);
void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
#endif

View file

@ -0,0 +1,46 @@
/*
* Replacement functions to protect the alpha channel
*/
/*
* Copyright (c) 2002-2003 Torrey T. Lyons. 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.
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/safeAlpha/safeAlpha.h,v 1.2 2003/10/18 00:00:34 torrey Exp $ */
#ifndef _SAFEALPHA_H
#define _SAFEALPHA_H
#include "picturestr.h"
#include "rootlessCommon.h"
void SafeAlphaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
#ifdef RENDER
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);
#endif /* RENDER */
#endif /* _SAFEALPHA_H */

View file

@ -0,0 +1,595 @@
/*
* 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"
# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
// Replacement for fbStore_x8r8g8b8 that sets the alpha channel
void
SafeAlphaStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value)
{
FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
((CARD32 *)line)[offset >> 5] = (value & ~RootlessAlphaMask(32)) |
RootlessAlphaMask(32);
}
// Defined in fbcompose.c
extern FbCombineFunc fbCombineFuncU[];
extern FbCombineFunc fbCombineFuncC[];
/* A bunch of macros from fbpict.c */
#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)))
#if IMAGE_BYTE_ORDER == MSBFirst
#define Fetch24(a) ((unsigned long) (a) & 1 ? \
((*(a) << 16) | *((CARD16 *) ((a)+1))) : \
((*((CARD16 *) (a)) << 8) | *((a)+2)))
#define Store24(a,v) ((unsigned long) (a) & 1 ? \
((*(a) = (CARD8) ((v) >> 16)), \
(*((CARD16 *) ((a)+1)) = (CARD16) (v))) : \
((*((CARD16 *) (a)) = (CARD16) ((v) >> 8)), \
(*((a)+2) = (CARD8) (v))))
#else
#define Fetch24(a) ((unsigned long) (a) & 1 ? \
((*(a)) | (*((CARD16 *) ((a)+1)) << 8)) : \
((*((CARD16 *) (a))) | (*((a)+2) << 16)))
#define Store24(a,v) ((unsigned long) (a) & 1 ? \
((*(a) = (CARD8) (v)), \
(*((CARD16 *) ((a)+1)) = (CARD16) ((v) >> 8))) : \
((*((CARD16 *) (a)) = (CARD16) (v)),\
(*((a)+2) = (CARD8) ((v) >> 16))))
#endif
#define fbComposeGetSolid(pict, bits) { \
FbBits *__bits__; \
FbStride __stride__; \
int __bpp__; \
int __xoff__,__yoff__; \
\
fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
switch (__bpp__) { \
case 32: \
(bits) = *(CARD32 *) __bits__; \
break; \
case 24: \
(bits) = Fetch24 ((CARD8 *) __bits__); \
break; \
case 16: \
(bits) = *(CARD16 *) __bits__; \
(bits) = cvt0565to8888(bits); \
break; \
default: \
return; \
} \
/* manage missing src alpha */ \
if ((pict)->pFormat->direct.alphaMask == 0) \
(bits) |= 0xff000000; \
}
#define fbComposeGetStart(pict,x,y,type,stride,line,mul) {\
FbBits *__bits__; \
FbStride __stride__; \
int __bpp__; \
int __xoff__,__yoff__; \
\
fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \
(stride) = __stride__ * sizeof (FbBits) / sizeof (type); \
(line) = ((type *) __bits__) + (stride) * ((y) - __yoff__) + (mul) * ((x) - __xoff__); \
}
/* 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);
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
SafeAlphaCompositeGeneral(
CARD8 op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
FbCompositeOperand src[4],msk[4],dst[4],*pmsk;
FbCompositeOperand *srcPict, *srcAlpha;
FbCompositeOperand *dstPict, *dstAlpha;
FbCompositeOperand *mskPict = 0, *mskAlpha = 0;
FbCombineFunc f;
int w;
if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE))
return;
if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE))
return;
// Use SafeAlpha operands for on screen picture formats
if (pDst->format == PICT_x8r8g8b8) {
dst[0].store = SafeAlphaStore_x8r8g8b8;
}
if (pSrc->alphaMap)
{
srcPict = &src[1];
srcAlpha = &src[2];
}
else
{
srcPict = &src[0];
srcAlpha = 0;
}
if (pDst->alphaMap)
{
dstPict = &dst[1];
dstAlpha = &dst[2];
}
else
{
dstPict = &dst[0];
dstAlpha = 0;
}
f = fbCombineFuncU[op];
if (pMask)
{
if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE))
return;
pmsk = msk;
if (pMask->componentAlpha)
f = fbCombineFuncC[op];
if (pMask->alphaMap)
{
mskPict = &msk[1];
mskAlpha = &msk[2];
}
else
{
mskPict = &msk[0];
mskAlpha = 0;
}
}
else
pmsk = 0;
while (height--)
{
w = width;
while (w--)
{
(*f) (src, pmsk, dst);
(*src->over) (src);
(*dst->over) (dst);
if (pmsk)
(*pmsk->over) (pmsk);
}
(*src->down) (src);
(*dst->down) (dst);
if (pmsk)
(*pmsk->down) (pmsk);
}
}
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;
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;
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;
}
if (!miComputeCompositeRegion (&region,
pSrc,
pMask,
pDst,
xSrc,
ySrc,
xMask,
yMask,
xDst,
yDst,
width,
height))
return;
// To preserve the alpha channel we have a special,
// non-optimzied compositor.
func = SafeAlphaCompositeGeneral;
/*
* 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;
}
if (!pSrc->transform && !(pMask && pMask->transform))
if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap)
switch (op) {
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:
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:
func = fbCompositeSolidMask_nx8888x8888C;
break;
case PICT_r5g6b5:
func = fbCompositeSolidMask_nx8888x0565C;
break;
}
}
break;
case PICT_a8b8g8r8:
if (pMask->componentAlpha) {
switch (pDst->format) {
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
func = fbCompositeSolidMask_nx8888x8888C;
break;
case PICT_b5g6r5:
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;
}
}
}
}
}
else
{
switch (pSrc->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
switch (pDst->format) {
case PICT_a8r8g8b8:
case PICT_x8r8g8b8:
func = fbCompositeSrc_8888x8888;
break;
case PICT_r8g8b8:
func = fbCompositeSrc_8888x0888;
break;
case PICT_r5g6b5:
func = fbCompositeSrc_8888x0565;
break;
}
break;
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
switch (pDst->format) {
case PICT_a8b8g8r8:
case PICT_x8b8g8r8:
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:
func = fbCompositeSrcAdd_8888x8888;
break;
}
break;
case PICT_a8b8g8r8:
switch (pDst->format) {
case PICT_a8b8g8r8:
func = fbCompositeSrcAdd_8888x8888;
break;
}
break;
case PICT_a8:
switch (pDst->format) {
case PICT_a8:
func = fbCompositeSrcAdd_8000x8000;
break;
}
break;
case PICT_a1:
switch (pDst->format) {
case PICT_a1:
func = fbCompositeSrcAdd_1000x1000;
break;
}
break;
}
}
break;
}
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 to its true value
pDst->pDrawable->depth = dstDepth;
}
#endif /* RENDER */

View file

@ -0,0 +1,173 @@
/*
* Specialized window functions to protect the alpha channel
*/
/*
* Copyright (c) 2002-2003 Torrey T. Lyons. 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.
*/
/* Portions of this file are based on fbwindow.c, which contains the
* following copyright:
*
* Copyright © 1998 Keith Packard
*/
/* $XFree86: xc/programs/Xserver/miext/rootless/safeAlpha/safeAlphaWindow.c,v 1.1 2003/09/16 00:36:20 torrey Exp $ */
#include "fb.h"
#include "safeAlpha.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
/*
* SafeAlphaFillRegionTiled
* Fill using a tile while leaving the alpha channel untouched.
* Based on fbfillRegionTiled.
*/
void
SafeAlphaFillRegionTiled(
DrawablePtr pDrawable,
RegionPtr pRegion,
PixmapPtr pTile)
{
FbBits *dst;
FbStride dstStride;
int dstBpp;
int dstXoff, dstYoff;
FbBits *tile;
FbStride tileStride;
int tileBpp;
int tileXoff, tileYoff; /* XXX assumed to be zero */
int tileWidth, tileHeight;
int n = REGION_NUM_RECTS(pRegion);
BoxPtr pbox = REGION_RECTS(pRegion);
int xRot = pDrawable->x;
int yRot = pDrawable->y;
FbBits planeMask;
#ifdef PANORAMIX
if(!noPanoramiXExtension)
{
int index = pDrawable->pScreen->myNum;
if(&WindowTable[index]->drawable == pDrawable)
{
xRot -= panoramiXdataPtr[index].x;
yRot -= panoramiXdataPtr[index].y;
}
}
#endif
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
tileXoff, tileYoff);
tileWidth = pTile->drawable.width;
tileHeight = pTile->drawable.height;
xRot += dstXoff;
yRot += dstYoff;
planeMask = FB_ALLONES & ~RootlessAlphaMask(dstBpp);
while (n--)
{
fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
dstStride,
(pbox->x1 + dstXoff) * dstBpp,
(pbox->x2 - pbox->x1) * dstBpp,
pbox->y2 - pbox->y1,
tile,
tileStride,
tileWidth * dstBpp,
tileHeight,
GXcopy,
planeMask,
dstBpp,
xRot * dstBpp,
yRot - pbox->y1);
pbox++;
}
}
/*
* SafeAlphaPaintWindow
* Paint the window while filling in the alpha channel with all on.
* We can't use fbPaintWindow because it zeros the alpha channel.
*/
void
SafeAlphaPaintWindow(
WindowPtr pWin,
RegionPtr pRegion,
int what)
{
switch (what) {
case PW_BACKGROUND:
switch (pWin->backgroundState) {
case None:
break;
case ParentRelative:
do {
pWin = pWin->parent;
} while (pWin->backgroundState == ParentRelative);
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
what);
break;
case BackgroundPixmap:
SafeAlphaFillRegionTiled (&pWin->drawable,
pRegion,
pWin->background.pixmap);
break;
case BackgroundPixel:
{
Pixel pixel = pWin->background.pixel |
RootlessAlphaMask(pWin->drawable.bitsPerPixel);
fbFillRegionSolid (&pWin->drawable, pRegion, 0,
fbReplicatePixel (pixel,
pWin->drawable.bitsPerPixel));
break;
}
}
break;
case PW_BORDER:
if (pWin->borderIsPixel)
{
Pixel pixel = pWin->border.pixel |
RootlessAlphaMask(pWin->drawable.bitsPerPixel);
fbFillRegionSolid (&pWin->drawable, pRegion, 0,
fbReplicatePixel (pixel,
pWin->drawable.bitsPerPixel));
}
else
{
WindowPtr pBgWin;
for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
pBgWin = pBgWin->parent);
SafeAlphaFillRegionTiled (&pBgWin->drawable,
pRegion,
pWin->border.pixmap);
}
break;
}
fbValidateDrawable (&pWin->drawable);
}