diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
commit | 9508a382f8a9f241dab097d921b6d290c1c3a776 (patch) | |
tree | fa456480bae7040c3f971a70b390f2d091c680b5 /miext | |
parent | ded6147bfb5d75ff1e67c858040a628b61bc17d1 (diff) | |
download | xserver-9508a382f8a9f241dab097d921b6d290c1c3a776.tar.gz |
Initial revision
Diffstat (limited to 'miext')
26 files changed, 4766 insertions, 0 deletions
diff --git a/miext/layer/layer.h b/miext/layer/layer.h new file mode 100644 index 000000000..630438057 --- /dev/null +++ b/miext/layer/layer.h @@ -0,0 +1,145 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layer.h,v 1.5 2002/10/03 22:50:21 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#ifndef _LAYER_H_ +#define _LAYER_H_ + +#include <shadow.h> + +#define LAYER_FB 0 +#define LAYER_SHADOW 1 + +typedef struct _LayerKind *LayerKindPtr; +typedef struct _LayerWin *LayerWinPtr; +typedef struct _LayerList *LayerListPtr; +typedef struct _LayerGC *LayerGCPtr; +typedef struct _Layer *LayerPtr; +typedef struct _LayerScreen *LayerScreenPtr; + +/* + * We'll try to work without a list of windows in each layer + * for now, this will make computing bounding boxes for each + * layer rather expensive, so that may need to change at some point. + */ + +#define LAYER_SCREEN_PIXMAP ((PixmapPtr) 1) + +typedef struct _Layer { + LayerPtr pNext; /* a list of all layers for this screen */ + LayerKindPtr pKind; /* characteristics of this layer */ + int refcnt; /* reference count, layer is freed when zero */ + int windows; /* number of windows, free pixmap when zero */ + int depth; /* window depth in this layer */ + PixmapPtr pPixmap; /* pixmap for this layer (may be frame buffer) */ + Bool freePixmap; /* whether to free this pixmap when done */ + RegionRec region; /* valid set of pPixmap for drawing */ + ShadowUpdateProc update; /* for shadow layers, update/window/closure values */ + ShadowWindowProc window; + int randr; + void *closure; +} LayerRec; + +/* + * Call this before wrapping stuff for acceleration, it + * gives layer pointers to the raw frame buffer functions + */ + +Bool +LayerStartInit (ScreenPtr pScreen); + +/* + * Initialize wrappers for each acceleration type and + * call this function, it will move the needed functions + * into a new LayerKind and replace them with the generic + * functions. + */ + +int +LayerNewKind (ScreenPtr pScreen); + +/* + * Finally, call this function and layer + * will wrap the screen functions and prepare for execution + */ + +Bool +LayerFinishInit (ScreenPtr pScreen); + +/* + * At any point after LayerStartInit, a new layer can be created. + */ +LayerPtr +LayerCreate (ScreenPtr pScreen, + int kind, + int depth, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int randr, + void *closure); + +/* + * Create a layer pixmap + */ +Bool +LayerCreatePixmap (ScreenPtr pScreen, LayerPtr pLayer); + +/* + * Change a layer pixmap + */ +void +LayerSetPixmap (ScreenPtr pScreen, LayerPtr pLayer, PixmapPtr pPixmap); + +/* + * Destroy a layer pixmap + */ +void +LayerDestroyPixmap (ScreenPtr pScreen, LayerPtr pLayer); + +/* + * Change a layer kind + */ +void +LayerSetKind (ScreenPtr pScreen, LayerPtr pLayer, int kind); + +/* + * Destroy a layer. The layer must not contain any windows. + */ +void +LayerDestroy (ScreenPtr pScreen, LayerPtr layer); + +/* + * Add a window to a layer + */ +Bool +LayerWindowAdd (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin); + +/* + * Remove a window from a layer + */ + +void +LayerWindowRemove (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin); + +#endif /* _LAYER_H_ */ diff --git a/miext/layer/layergc.c b/miext/layer/layergc.c new file mode 100644 index 000000000..52490d286 --- /dev/null +++ b/miext/layer/layergc.c @@ -0,0 +1,190 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layergc.c,v 1.5 2001/10/28 03:34:15 tsi Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#include "layerstr.h" + +GCFuncs layerGCFuncs = { + layerValidateGC, layerChangeGC, layerCopyGC, layerDestroyGC, + layerChangeClip, layerDestroyClip, layerCopyClip +}; + +#if 0 +/* + * XXX dont need this until this supports + * separate clipping and multiple layers + */ +GCOps layerGCOps = { + layerFillSpans, layerSetSpans, + layerPutImage, layerCopyArea, + layerCopyPlane, layerPolyPoint, + layerPolylines, layerPolySegment, + layerPolyRectangle, layerPolyArc, + layerFillPolygon, layerPolyFillRect, + layerPolyFillArc, layerPolyText8, + layerPolyText16, layerImageText8, + layerImageText16, layerImageGlyphBlt, + layerPolyGlyphBlt, layerPushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; +#endif + +Bool +layerCreateGC (GCPtr pGC) +{ + Bool ret = TRUE; + LayerKindPtr pLayKind; + ScreenPtr pScreen = pGC->pScreen; + layerScrPriv(pScreen); + layerGCPriv(pGC); + + /* + * XXX assume the first layer can handle all GCs + */ + pLayKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pLayKind = pLayScr->pLayers->pKind; + pLayGC->pKind = pLayKind; + LayerUnwrap (pScreen,pLayGC->pKind,CreateGC); + + if (!(*pScreen->CreateGC) (pGC)) + ret = FALSE; + LayerWrap (pScreen,pLayKind,CreateGC,layerCreateGC); + + LayerWrap (pGC,pLayGC,funcs,&layerGCFuncs); + + return ret; +} + +void +layerValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw) +{ + layerGCPriv(pGC); + LayerKindPtr pKind; + + if (pDraw->type == DRAWABLE_WINDOW) + { + layerWinPriv ((WindowPtr) pDraw); + pKind = layerWinLayer (pLayWin)->pKind; + } + else + { + /* XXX assume the first layer can handle all pixmaps */ + layerScrPriv (pDraw->pScreen); + pKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pKind = pLayScr->pLayers->pKind; + } + + LayerUnwrap (pGC,pLayGC,funcs); + if (pKind != pLayGC->pKind) + { + /* + * Clean up the previous user + */ + CreateGCProcPtr CreateGC; + (*pGC->funcs->DestroyGC) (pGC); + + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + + pLayGC->pKind = pKind; + + /* + * Temporarily unwrap Create GC and let + * the new code setup the GC + */ + CreateGC = pGC->pScreen->CreateGC; + LayerUnwrap (pGC->pScreen, pLayGC->pKind, CreateGC); + (*pGC->pScreen->CreateGC) (pGC); + LayerWrap (pGC->pScreen, pLayGC->pKind, CreateGC, CreateGC); + } + + (*pGC->funcs->ValidateGC) (pGC, changes, pDraw); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerDestroyGC(GCPtr pGC) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->DestroyGC)(pGC); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerChangeGC (GCPtr pGC, + unsigned long mask) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->ChangeGC) (pGC, mask); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + layerGCPriv(pGCDst); + LayerUnwrap (pGCDst,pLayGC,funcs); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + LayerWrap(pGCDst,pLayGC,funcs,&layerGCFuncs); +} + +void +layerChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + +void +layerCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + layerGCPriv(pGCDst); + LayerUnwrap (pGCDst,pLayGC,funcs); + (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); + LayerWrap(pGCDst,pLayGC,funcs,&layerGCFuncs); +} + +void +layerDestroyClip(GCPtr pGC) +{ + layerGCPriv(pGC); + LayerUnwrap (pGC,pLayGC,funcs); + (*pGC->funcs->DestroyClip) (pGC); + LayerWrap(pGC,pLayGC,funcs,&layerGCFuncs); +} + diff --git a/miext/layer/layerinit.c b/miext/layer/layerinit.c new file mode 100644 index 000000000..dfeae6c2d --- /dev/null +++ b/miext/layer/layerinit.c @@ -0,0 +1,359 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerinit.c,v 1.6 2002/11/08 22:19:42 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#include "layerstr.h" + +int layerScrPrivateIndex; +int layerGCPrivateIndex; +int layerWinPrivateIndex; +int layerGeneration; + +/* + * Call this before wrapping stuff for acceleration, it + * gives layer pointers to the raw frame buffer functions + */ + +extern const GCFuncs fbGCFuncs; +extern GCFuncs shadowGCFuncs; + +Bool +LayerStartInit (ScreenPtr pScreen) +{ + LayerScreenPtr pScrPriv; + + if (layerGeneration != serverGeneration) + { + layerScrPrivateIndex = AllocateScreenPrivateIndex (); + if (layerScrPrivateIndex == -1) + return FALSE; + layerGCPrivateIndex = AllocateGCPrivateIndex (); + if (layerGCPrivateIndex == -1) + return FALSE; + layerWinPrivateIndex = AllocateWindowPrivateIndex (); + if (layerWinPrivateIndex == -1) + return FALSE; + layerGeneration = serverGeneration; + } + if (!AllocateGCPrivate (pScreen, layerGCPrivateIndex, sizeof (LayerGCRec))) + return FALSE; + if (!AllocateWindowPrivate (pScreen, layerWinPrivateIndex, sizeof (LayerWinRec))) + return FALSE; + pScrPriv = (LayerScreenPtr) xalloc (sizeof (LayerScreenRec)); + if (!pScrPriv) + return FALSE; + pScrPriv->nkinds = 0; + pScrPriv->kinds = 0; + pScrPriv->pLayers = 0; + pScreen->devPrivates[layerScrPrivateIndex].ptr = (pointer) pScrPriv; + /* + * Add fb kind -- always 0 + */ + if (LayerNewKind (pScreen) < 0) + { + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + xfree (pScrPriv); + return FALSE; + } + /* + * Add shadow kind -- always 1 + */ + if (!shadowSetup (pScreen)) + return FALSE; + if (LayerNewKind (pScreen) < 0) + { + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + xfree (pScrPriv->kinds); + xfree (pScrPriv); + return FALSE; + } + return TRUE; +} + +/* + * Initialize wrappers for each acceleration type and + * call this function, it will move the needed functions + * into a new LayerKind and replace them with the generic + * functions. + */ + +int +LayerNewKind (ScreenPtr pScreen) +{ + layerScrPriv(pScreen); + LayerKindPtr pLayKind, pLayKinds; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreen (pScreen); +#endif + LayerPtr pLayer; + + /* + * Allocate a new kind structure + */ + if (pLayScr->kinds) + pLayKinds = (LayerKindPtr) xrealloc ((pointer) pLayScr->kinds, + (pLayScr->nkinds + 1) * sizeof (LayerKindRec)); + else + pLayKinds = (LayerKindPtr) xalloc (sizeof (LayerKindRec)); + if (!pLayKinds) + return -1; + + /* + * Fix up existing layers to point at the new kind + */ + for (pLayer = pLayScr->pLayers; pLayer; pLayer = pLayer->pNext) + { + int kind = pLayer->pKind - pLayScr->kinds; + + pLayer->pKind = &pLayKinds[kind]; + } + + pLayScr->kinds = pLayKinds; + pLayKind = &pLayScr->kinds[pLayScr->nkinds]; + pLayKind->kind = pLayScr->nkinds; + + /* + * Extract wrapped functions from screen and stick in kind + */ + pLayKind->CloseScreen = pScreen->CloseScreen; + + pLayKind->CreateWindow = pScreen->CreateWindow; + pLayKind->DestroyWindow = pScreen->DestroyWindow; + pLayKind->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pLayKind->PaintWindowBackground = pScreen->PaintWindowBackground; + pLayKind->PaintWindowBorder = pScreen->PaintWindowBorder; + pLayKind->CopyWindow = pScreen->CopyWindow; + + pLayKind->CreatePixmap = pScreen->CreatePixmap; + pLayKind->DestroyPixmap = pScreen->DestroyPixmap; + + pLayKind->CreateGC = pScreen->CreateGC; + +#ifdef RENDER + if (ps) + { + pLayKind->Composite = ps->Composite; + pLayKind->Glyphs = ps->Glyphs; + pLayKind->CompositeRects = ps->CompositeRects; + } +#endif + /* + * If not underlying frame buffer kind, + * replace screen functions with those + */ + if (pLayKind->kind != 0) + { + pScreen->CloseScreen = pLayKinds->CloseScreen; + + pScreen->CreateWindow = pLayKinds->CreateWindow; + pScreen->DestroyWindow = pLayKinds->DestroyWindow; + pScreen->ChangeWindowAttributes = pLayKinds->ChangeWindowAttributes; + pScreen->PaintWindowBackground = pLayKinds->PaintWindowBackground; + pScreen->PaintWindowBorder = pLayKinds->PaintWindowBorder; + pScreen->CopyWindow = pLayKinds->CopyWindow; + + pScreen->CreatePixmap = pLayKinds->CreatePixmap; + pScreen->DestroyPixmap = pLayKinds->DestroyPixmap; + + pScreen->CreateGC = pLayKinds->CreateGC; + +#ifdef RENDER + if (ps) + { + ps->Composite = pLayKinds->Composite; + ps->Glyphs = pLayKinds->Glyphs; + ps->CompositeRects = pLayKinds->CompositeRects; + } +#endif + } + + pLayScr->nkinds++; + return pLayKind->kind; +} + +/* + * Finally, call this function and layer + * will wrap the screen functions and prepare for execution + */ + +Bool +LayerFinishInit (ScreenPtr pScreen) +{ +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreen (pScreen); +#endif + + pScreen->CloseScreen = layerCloseScreen; + + pScreen->CreateWindow = layerCreateWindow; + pScreen->DestroyWindow = layerDestroyWindow; + pScreen->ChangeWindowAttributes = layerChangeWindowAttributes; + pScreen->PaintWindowBackground = layerPaintWindowBackground; + pScreen->PaintWindowBorder = layerPaintWindowBorder; + pScreen->CopyWindow = layerCopyWindow; + + pScreen->CreatePixmap = layerCreatePixmap; + pScreen->DestroyPixmap = layerDestroyPixmap; + + pScreen->CreateGC = layerCreateGC; + +#ifdef RENDER + if (ps) + { + ps->Composite = layerComposite; + ps->Glyphs = layerGlyphs; + ps->CompositeRects = layerCompositeRects; + } +#endif + + return TRUE; +} + +/* + * At any point after LayerStartInit, a new layer can be created. + */ +LayerPtr +LayerCreate (ScreenPtr pScreen, + int kind, + int depth, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int randr, + void *closure) +{ + layerScrPriv(pScreen); + LayerPtr pLay, *pPrev; + LayerKindPtr pLayKind; + + if (kind < 0 || pLayScr->nkinds <= kind) + return 0; + pLayKind = &pLayScr->kinds[kind]; + pLay = (LayerPtr) xalloc (sizeof (LayerRec)); + if (!pLay) + return 0; + /* + * Initialize the layer + */ + pLay->pNext = 0; + pLay->pKind = pLayKind; + pLay->refcnt = 1; + pLay->windows = 0; + pLay->depth = depth; + pLay->pPixmap = pPixmap; + pLay->update = update; + pLay->window = window; + pLay->randr = randr; + pLay->closure = closure; + if (pPixmap == LAYER_SCREEN_PIXMAP) + pLay->freePixmap = FALSE; + else + { + pLay->freePixmap = TRUE; + if (pPixmap) + pPixmap->refcnt++; + } + REGION_INIT (pScreen, &pLay->region, NullBox, 0); + /* + * Hook the layer at the end of the list + */ + for (pPrev = &pLayScr->pLayers; *pPrev; pPrev = &(*pPrev)->pNext) + ; + *pPrev = pLay; + return pLay; +} + +/* + * Change a layer pixmap + */ +void +LayerSetPixmap (ScreenPtr pScreen, LayerPtr pLayer, PixmapPtr pPixmap) +{ + LayerDestroyPixmap (pScreen, pLayer); + pLayer->pPixmap = pPixmap; + if (pPixmap == LAYER_SCREEN_PIXMAP) + pLayer->freePixmap = FALSE; + else + { + if (pPixmap) + pPixmap->refcnt++; + pLayer->freePixmap = TRUE; + } +} + +/* + * Destroy a layer. The layer must not contain any windows. + */ +void +LayerDestroy (ScreenPtr pScreen, LayerPtr pLay) +{ + layerScrPriv(pScreen); + LayerPtr *pPrev; + + --pLay->refcnt; + if (pLay->refcnt > 0) + return; + /* + * Unhook the layer from the list + */ + for (pPrev = &pLayScr->pLayers; *pPrev; pPrev = &(*pPrev)->pNext) + if (*pPrev == pLay) + { + *pPrev = pLay->pNext; + break; + } + /* + * Free associated storage + */ + LayerDestroyPixmap (pScreen, pLay); + REGION_UNINIT (pScreen, &pLay->region); + xfree (pLay); +} + +/* + * CloseScreen wrapper + */ +Bool +layerCloseScreen (int index, ScreenPtr pScreen) +{ + layerScrPriv(pScreen); + int kind; + + /* XXX this is a mess -- fbCloseScreen can only be called once, + * and yet the intervening layers need to be called as well. + */ + kind = pLayScr->nkinds - 1; + pScreen->CloseScreen = pLayScr->kinds[kind].CloseScreen; + (*pScreen->CloseScreen) (index, pScreen); + + /* + * make sure the shadow layer is cleaned up as well + */ + if (kind != LAYER_SHADOW) + xfree (shadowGetScrPriv (pScreen)); + + xfree (pLayScr->kinds); + xfree (pLayScr); + pScreen->devPrivates[layerScrPrivateIndex].ptr = 0; + return TRUE; +} diff --git a/miext/layer/layerpict.c b/miext/layer/layerpict.c new file mode 100644 index 000000000..e233d0271 --- /dev/null +++ b/miext/layer/layerpict.c @@ -0,0 +1,145 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerpict.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#include "layerstr.h" + +void +layerComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, Composite); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + LayerWrap (ps, pLayer->pKind, Composite, layerComposite); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], Composite); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], Composite, layerComposite); + } +} + +void +layerGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlist, list, glyphs); + LayerWrap (ps, pLayer->pKind, Glyphs, layerGlyphs); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlist, list, glyphs); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], Glyphs, layerGlyphs); + } +} + +void +layerCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + LayerPtr pLayer; + LayerWinLoopRec loop; + DrawablePtr pDstDrawable = pDst->pDrawable; + ScreenPtr pScreen = pDstDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen (pScreen); + + if (pDstDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWin = (WindowPtr) pDstDrawable; + for (pLayer = LayerWindowFirst (pWin, &loop); + pLayer; + pLayer = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap (ps, pLayer->pKind, CompositeRects); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); + LayerWrap (ps, pLayer->pKind, CompositeRects, layerCompositeRects); + } + LayerWindowDone (pWin, &loop); + } + else + { + layerScrPriv (pScreen); + LayerUnwrap (ps, &pLayScr->kinds[LAYER_FB], CompositeRects); + (*ps->CompositeRects) (op, pDst, color, nRect, rects); + LayerWrap (ps, &pLayScr->kinds[LAYER_FB], CompositeRects, layerCompositeRects); + } +} diff --git a/miext/layer/layerstr.h b/miext/layer/layerstr.h new file mode 100644 index 000000000..1720a536c --- /dev/null +++ b/miext/layer/layerstr.h @@ -0,0 +1,420 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerstr.h,v 1.3 2002/11/08 22:19:42 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#ifndef _LAYERSTR_H_ +#define _LAYERSTR_H_ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "layer.h" +#ifdef RENDER +#include "picturestr.h" +#endif + +extern int layerScrPrivateIndex; +extern int layerGCPrivateIndex; +extern int layerWinPrivateIndex; + +/* + * One of these for each possible set of underlying + * rendering code. The first kind always points at the + * underlying frame buffer code and is created in LayerStartInit + * so that LayerNewKind can unwrap the screen and prepare it + * for another wrapping sequence. + * + * The set of functions wrapped here must be at least the union + * of all functions wrapped by any rendering layer in use; they're + * easy to add, so don't be shy + */ + +typedef struct _LayerKind { + int kind; /* kind index */ + + CloseScreenProcPtr CloseScreen; + + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + + CreateGCProcPtr CreateGC; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + +} LayerKindRec; + +#define LayerWrap(orig,lay,member,func) \ + (((lay)->member = (orig)->member),\ + ((orig)->member = (func))) +#define LayerUnwrap(orig,lay,member) \ + ((orig)->member = (lay)->member) + +/* + * This is the window private structure allocated for + * all windows. There are two possible alternatives here, + * either the window belongs to a single layer and uses its + * internal clip/borderClip lists or the window belongs to one + * or more layers and uses a separate clip/borderclip for each + * layer. When this is integrated into the core window struct, + * the LayerWinKind can become a single bit saving 8 bytes per + * window. + */ + +typedef struct _LayerWin { + Bool isList; + union { + LayerPtr pLayer; + LayerListPtr pLayList; + } u; +} LayerWinRec; + +typedef struct _LayerList { + LayerListPtr pNext; /* list of layers for this window */ + LayerPtr pLayer; /* the layer */ + Bool inheritClip; /* use the window clipList/borderClip */ + RegionRec clipList; /* per-layer clip/border clip lists */ + RegionRec borderClip; +} LayerListRec; + +#define layerGetWinPriv(pWin) ((LayerWinPtr) (pWin)->devPrivates[layerWinPrivateIndex].ptr) +#define layerWinPriv(pWin) LayerWinPtr pLayWin = layerGetWinPriv(pWin) + +#define layerWinLayer(pLayWin) ((pLayWin)->isList ? (pLayWin)->u.pLayList->pLayer : (pLayWin)->u.pLayer) + +typedef struct _LayerWinLoop { + LayerWinPtr pLayWin; + LayerListPtr pLayList; + PixmapPtr pPixmap; /* original window pixmap */ + RegionRec clipList; /* saved original clipList contents */ + RegionRec borderClip; /* saved original borderClip contents */ +} LayerWinLoopRec, *LayerWinLoopPtr; + +#define layerWinFirstLayer(pLayWin,pLayList) ((pLayWin)->isList ? ((pLayList) = (pLayWin)->u.pLayList)->pLayer : pLayWin->u.pLayer) +#define layerWinNextLayer(pLayWin,pLayList) ((pLayWin)->isList ? ((pLayList) = (pLayList)->pNext)->pLayer : 0) + +LayerPtr +LayerWindowFirst (WindowPtr pWin, LayerWinLoopPtr pLoop); + +LayerPtr +LayerWindowNext (WindowPtr pWin, LayerWinLoopPtr pLoop); + +void +LayerWindowDone (WindowPtr pWin, LayerWinLoopPtr pLoop); + + +/* + * This is the GC private structure allocated for all GCs. + * XXX this is really messed up; I'm not sure how to fix it yet + */ + +typedef struct _LayerGC { + GCFuncs *funcs; + LayerKindPtr pKind; +} LayerGCRec; + +#define layerGetGCPriv(pGC) ((LayerGCPtr) (pGC)->devPrivates[layerGCPrivateIndex].ptr) +#define layerGCPriv(pGC) LayerGCPtr pLayGC = layerGetGCPriv(pGC) + +/* + * This is the screen private, it contains + * the layer kinds and the layers themselves + */ +typedef struct _LayerScreen { + int nkinds; /* number of elements in kinds array */ + LayerKindPtr kinds; /* created kinds; reallocated when new ones added */ + LayerPtr pLayers; /* list of layers for this screen */ +} LayerScreenRec; + +#define layerGetScrPriv(pScreen) ((LayerScreenPtr) (pScreen)->devPrivates[layerScrPrivateIndex].ptr) +#define layerScrPriv(pScreen) LayerScreenPtr pLayScr = layerGetScrPriv(pScreen) + +Bool +layerCloseScreen (int index, ScreenPtr pScreen); + +Bool +layerCreateWindow (WindowPtr pWin); + +Bool +layerDestroyWindow (WindowPtr pWin); + +Bool +layerChangeWindowAttributes (WindowPtr pWin, unsigned long mask); + +void +layerPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what); + +void +layerPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what); + +void +layerCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +PixmapPtr +layerCreatePixmap (ScreenPtr pScreen, int width, int height, int depth); + +Bool +layerDestroyPixmap (PixmapPtr pPixmap); + +Bool +layerCreateGC (GCPtr pGC); + +void +layerComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); +void +layerGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +void +layerCompositeRects (CARD8 op, + PicturePtr pDst, + xRenderColor *color, + int nRect, + xRectangle *rects); + +void layerValidateGC(GCPtr, unsigned long, DrawablePtr); +void layerChangeGC(GCPtr, unsigned long); +void layerCopyGC(GCPtr, unsigned long, GCPtr); +void layerDestroyGC(GCPtr); +void layerChangeClip(GCPtr, int, pointer, int); +void layerDestroyClip(GCPtr); +void layerCopyClip(GCPtr, GCPtr); + +void +layerFillSpans(DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted); + +void +layerSetSpans(DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr pptInit, + int *pwidthInit, + int nspans, + int fSorted); + +void +layerPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage +); + +RegionPtr +layerCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +); + +RegionPtr +layerCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +); + +void +layerPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit +); +void +layerPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +); + +void +layerPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +); + +void +layerPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRects, + xRectangle *pRects +); + +void +layerPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +); + +void +layerFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr pptInit +); + +void +layerPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +); + +void +layerPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +); + +int +layerPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +); + +int +layerPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +); + +void +layerImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +); + +void +layerImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +); + +void +layerImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +void +layerPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +void +layerPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg +); + +#endif /* _LAYERSTR_H_ */ diff --git a/miext/layer/layerwin.c b/miext/layer/layerwin.c new file mode 100644 index 000000000..8160000c8 --- /dev/null +++ b/miext/layer/layerwin.c @@ -0,0 +1,483 @@ +/* + * $XFree86: xc/programs/Xserver/miext/layer/layerwin.c,v 1.7 2002/11/08 22:19:42 keithp Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#include "layerstr.h" + +static LayerListPtr +NewLayerList (ScreenPtr pScreen, LayerPtr pLayer) +{ + LayerListPtr pLayList; + + pLayList = (LayerListPtr) xalloc (sizeof (LayerListRec)); + if (!pLayList) + return 0; + pLayList->pNext = 0; + pLayList->pLayer = pLayer; + pLayList->inheritClip = TRUE; + REGION_INIT (pScreen, &pLayList->clipList, NullBox, 0); + REGION_INIT (pScreen, &pLayList->borderClip, NullBox, 0); + return pLayList; +} + +static void +FreeLayerList (ScreenPtr pScreen, LayerListPtr pLayList) +{ + REGION_UNINIT (&pScreen, &pLayList->clipList); + REGION_UNINIT (&pScreen, &pLayList->borderClip); + xfree (pLayList); +} + +/* + * Create pixmap for a layer + */ + +Bool +LayerCreatePixmap (ScreenPtr pScreen, LayerPtr pLayer) +{ + LayerKindPtr pKind = pLayer->pKind; + + LayerUnwrap (pScreen, pKind, CreatePixmap); + /* XXX create full-screen sized layers all around */ + pLayer->pPixmap = (*pScreen->CreatePixmap) (pScreen, pScreen->width, + pScreen->height, pLayer->depth); + LayerWrap (pScreen, pKind, CreatePixmap, layerCreatePixmap); + if (!pLayer->pPixmap) + return FALSE; + if (pLayer->pKind->kind == LAYER_SHADOW) + { + if (!shadowAdd (pScreen, pLayer->pPixmap, pLayer->update, + pLayer->window, pLayer->randr, + pLayer->closure)) + return FALSE; + } + return TRUE; +} + +/* + * Destroy pixmap for a layer + */ + +void +LayerDestroyPixmap (ScreenPtr pScreen, LayerPtr pLayer) +{ + if (pLayer->pPixmap) + { + if (pLayer->pKind->kind == LAYER_SHADOW) + shadowRemove (pScreen, pLayer->pPixmap); + if (pLayer->freePixmap) + { + LayerKindPtr pKind = pLayer->pKind; + + LayerUnwrap (pScreen, pKind, DestroyPixmap); + (*pScreen->DestroyPixmap) (pLayer->pPixmap); + LayerWrap (pScreen, pKind, DestroyPixmap, layerDestroyPixmap); + } + pLayer->pPixmap = 0; + } +} + +/* + * Add a window to a layer + */ +Bool +LayerWindowAdd (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin) +{ + layerWinPriv(pWin); + + if (pLayer->pPixmap == LAYER_SCREEN_PIXMAP) + pLayer->pPixmap = (*pScreen->GetScreenPixmap) (pScreen); + else if (!pLayer->pPixmap && !LayerCreatePixmap (pScreen, pLayer)) + return FALSE; + /* + * Add a new layer list if needed + */ + if (pLayWin->isList || pLayWin->u.pLayer) + { + LayerListPtr pPrev; + LayerListPtr pLayList; + + if (!pLayWin->isList) + { + pPrev = NewLayerList (pScreen, pLayWin->u.pLayer); + if (!pPrev) + return FALSE; + } + else + { + for (pPrev = pLayWin->u.pLayList; pPrev->pNext; pPrev = pPrev->pNext) + ; + } + pLayList = NewLayerList (pScreen, pLayer); + if (!pLayList) + { + if (!pLayWin->isList) + FreeLayerList (pScreen, pPrev); + return FALSE; + } + pPrev->pNext = pLayList; + if (!pLayWin->isList) + { + pLayWin->isList = TRUE; + pLayWin->u.pLayList = pPrev; + } + } + else + pLayWin->u.pLayer = pLayer; + /* + * XXX only one layer supported for drawing, last one wins + */ + (*pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pLayer->refcnt++; + pLayer->windows++; + return TRUE; +} + +/* + * Remove a window from a layer + */ + +void +LayerWindowRemove (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin) +{ + layerWinPriv(pWin); + + if (pLayWin->isList) + { + LayerListPtr *pPrev; + LayerListPtr pLayList; + + for (pPrev = &pLayWin->u.pLayList; (pLayList = *pPrev); pPrev = &pLayList->pNext) + { + if (pLayList->pLayer == pLayer) + { + *pPrev = pLayList->pNext; + FreeLayerList (pScreen, pLayList); + --pLayer->windows; + if (pLayer->windows <= 0) + LayerDestroyPixmap (pScreen, pLayer); + LayerDestroy (pScreen, pLayer); + break; + } + } + pLayList = pLayWin->u.pLayList; + if (!pLayList) + { + /* + * List is empty, set isList back to false + */ + pLayWin->isList = FALSE; + pLayWin->u.pLayer = 0; + } + else if (!pLayList->pNext && pLayList->inheritClip) + { + /* + * List contains a single element using the + * window clip, free the list structure and + * host the layer back to the window private + */ + pLayer = pLayList->pLayer; + FreeLayerList (pScreen, pLayList); + pLayWin->isList = FALSE; + pLayWin->u.pLayer = pLayer; + } + } + else + { + if (pLayWin->u.pLayer == pLayer) + { + --pLayer->windows; + if (pLayer->windows <= 0) + LayerDestroyPixmap (pScreen, pLayer); + LayerDestroy (pScreen, pLayer); + pLayWin->u.pLayer = 0; + } + } + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; +} + +/* + * Looping primitives for window layering. Usage: + * + * for (pLayer = LayerWindowFirst (pWin, &loop); + * pLayer; + * pLayer = LayerWindowNext (&loop)) + * { + * ... + * } + * LayerWindowDone (pWin, &loop); + */ + +LayerPtr +LayerWindowFirst (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + layerWinPriv (pWin); + + pLoop->pLayWin = pLayWin; + if (!pLayWin->isList) + return pLayWin->u.pLayer; + + /* + * Preserve original state + */ + pLoop->clipList = pWin->clipList; + pLoop->borderClip = pWin->borderClip; + pLoop->pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + + /* + * Set initial list element + */ + pLoop->pLayList = pLayWin->u.pLayList; + + /* + * Return first layer + */ + return LayerWindowNext (pWin, pLoop); +} + +LayerPtr +LayerWindowNext (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + LayerPtr pLayer; + LayerWinPtr pLayWin = pLoop->pLayWin; + LayerListPtr pLayList; + + if (!pLayWin->isList) + return 0; + + pLayList = pLoop->pLayList; + pLayer = pLayList->pLayer; + /* + * Configure window for this layer + */ + (*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap); + if (!pLayList->inheritClip) + { + pWin->clipList = pLayList->clipList; + pWin->borderClip = pLayList->borderClip; + } + /* + * Step to next layer list + */ + pLoop->pLayList = pLayList->pNext; + /* + * Return layer + */ + return pLayer; +} + +void +LayerWindowDone (WindowPtr pWin, LayerWinLoopPtr pLoop) +{ + LayerWinPtr pLayWin = pLoop->pLayWin; + + if (!pLayWin->isList) + return; + /* + * clean up after the loop + */ + pWin->clipList = pLoop->clipList; + pWin->borderClip = pLoop->clipList; + (*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLoop->pPixmap); +} + +Bool +layerCreateWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + layerWinPriv(pWin); + layerScrPriv(pScreen); + LayerPtr pLayer; + Bool ret; + + pLayWin->isList = FALSE; + pLayWin->u.pLayer = 0; + + /* + * input only windows don't live in any layer + */ + if (pWin->drawable.type == UNDRAWABLE_WINDOW) + return TRUE; + /* + * Use a reasonable default layer -- the first + * layer matching the windows depth. Subsystems needing + * alternative layering semantics can override this by + * replacing this function. Perhaps a new screen function + * could be used to select the correct initial window + * layer instead. + */ + for (pLayer = pLayScr->pLayers; pLayer; pLayer = pLayer->pNext) + if (pLayer->depth == pWin->drawable.depth) + break; + ret = TRUE; + if (pLayer) + { + pScreen->CreateWindow = pLayer->pKind->CreateWindow; + ret = (*pScreen->CreateWindow) (pWin); + pLayer->pKind->CreateWindow = pScreen->CreateWindow; + pScreen->CreateWindow = layerCreateWindow; + LayerWindowAdd (pScreen, pLayer, pWin); + } + return ret; +} + +Bool +layerDestroyWindow (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + layerWinPriv(pWin); + LayerPtr pLayer; + Bool ret = TRUE; + + while ((pLayer = layerWinLayer (pLayWin))) + { + LayerUnwrap (pScreen, pLayer->pKind, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWin); + LayerWrap (pScreen, pLayer->pKind, DestroyWindow, layerDestroyWindow); + LayerWindowRemove (pWin->drawable.pScreen, pLayer, pWin); + } + return ret; +} + +Bool +layerChangeWindowAttributes (WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + Bool ret = TRUE; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,ChangeWindowAttributes); + if (!(*pScreen->ChangeWindowAttributes) (pWin, mask)) + ret = FALSE; + LayerWrap(pScreen,pLay->pKind,ChangeWindowAttributes,layerChangeWindowAttributes); + } + LayerWindowDone (pWin, &loop); + return ret; +} + +void +layerPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWin, pRegion, what); + LayerWrap(pScreen,pLay->pKind,PaintWindowBackground,layerPaintWindowBackground); + } + LayerWindowDone (pWin, &loop); +} + +void +layerPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWin, pRegion, what); + LayerWrap(pScreen,pLay->pKind,PaintWindowBorder,layerPaintWindowBorder); + } + LayerWindowDone (pWin, &loop); +} + +void +layerCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + LayerPtr pLay; + LayerWinLoopRec loop; + int dx = 0, dy = 0; + + for (pLay = LayerWindowFirst (pWin, &loop); + pLay; + pLay = LayerWindowNext (pWin, &loop)) + { + LayerUnwrap(pScreen,pLay->pKind,CopyWindow); + /* + * Undo the translation done within the last CopyWindow proc (sigh) + */ + if (dx || dy) + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy); + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + LayerWrap(pScreen,pLay->pKind,CopyWindow,layerCopyWindow); + /* + * Save offset to undo translation next time around + */ + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + } + LayerWindowDone (pWin, &loop); +} + +PixmapPtr +layerCreatePixmap (ScreenPtr pScreen, int width, int height, int depth) +{ + /* XXX assume the first layer can handle all pixmaps */ + layerScrPriv (pScreen); + LayerKindPtr pKind; + PixmapPtr pPixmap; + + pKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pKind = pLayScr->pLayers->pKind; + LayerUnwrap (pScreen, pKind, CreatePixmap); + pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth); + LayerWrap (pScreen,pKind,CreatePixmap,layerCreatePixmap); + return pPixmap; +} + +Bool +layerDestroyPixmap (PixmapPtr pPixmap) +{ + /* XXX assume the first layer can handle all pixmaps */ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + layerScrPriv (pScreen); + LayerKindPtr pKind; + Bool ret; + + pKind = &pLayScr->kinds[0]; + if (pLayScr->pLayers) + pKind = pLayScr->pLayers->pKind; + LayerUnwrap (pScreen, pKind, DestroyPixmap); + ret = (*pScreen->DestroyPixmap) (pPixmap); + LayerWrap (pScreen,pKind,DestroyPixmap,layerDestroyPixmap); + return ret; +} + diff --git a/miext/shadow/shadow.c b/miext/shadow/shadow.c new file mode 100644 index 000000000..60a1555d8 --- /dev/null +++ b/miext/shadow/shadow.c @@ -0,0 +1,1525 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shadow.c,v 1.13 2002/12/02 20:37:23 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" + +typedef struct _shadowGCPriv { + GCOps *ops; + GCFuncs *funcs; +} shadowGCPrivRec, *shadowGCPrivPtr; + +int shadowScrPrivateIndex; +int shadowGCPrivateIndex; +int shadowGeneration; + +#define shadowGetGCPriv(pGC) \ + ((shadowGCPrivPtr) (pGC)->devPrivates[shadowGCPrivateIndex].ptr) +#define shadowGCPriv(pGC) \ + shadowGCPrivPtr pGCPriv = shadowGetGCPriv(pGC) + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +static void +shadowRedisplay (ScreenPtr pScreen) +{ + shadowScrPriv(pScreen); + shadowBufPtr pBuf; + + for (pBuf = pScrPriv->pBuf; pBuf; pBuf = pBuf->pNext) + { + if (REGION_NOTEMPTY (pScreen, &pBuf->damage)) + { + REGION_INTERSECT (pScreen, &pBuf->damage, &pBuf->damage, + &WindowTable[pScreen->myNum]->borderClip); + (*pBuf->update) (pScreen, pBuf); + REGION_EMPTY (pScreen, &pBuf->damage); + } + } +} + +static void +shadowBlockHandler (pointer data, + OSTimePtr pTimeout, + pointer pRead) +{ + ScreenPtr pScreen = (ScreenPtr) data; + + shadowRedisplay (pScreen); +} + +static void +shadowWakeupHandler (pointer data, int i, pointer LastSelectMask) +{ +} + +static void +shadowDamageRegion (WindowPtr pWindow, RegionPtr pRegion) +{ + shadowBufPtr pBuf = shadowFindBuf (pWindow); + + if (!pBuf) + abort (); + + REGION_INTERSECT(pWindow->drawable.pScreen, pRegion, pRegion, + &pWindow->borderClip); + REGION_UNION(pWindow->drawable.pScreen, &pBuf->damage, &pBuf->damage, + pRegion); +#ifdef ALWAYS_DISPLAY + shadowRedisplay (pWindow->drawable.pScreen); +#endif +} + +static void +shadowDamageBox (WindowPtr pWindow, BoxPtr pBox) +{ + RegionRec region; + + REGION_INIT (pWindow->drawable.pScreen, ®ion, pBox, 1); + shadowDamageRegion (pWindow, ®ion); +} + +static void +shadowDamageRect (WindowPtr pWindow, int x, int y, int w, int h) +{ + BoxRec box; + + x += pWindow->drawable.x; + y += pWindow->drawable.y; + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + shadowDamageBox (pWindow, &box); +} + +static void shadowValidateGC(GCPtr, unsigned long, DrawablePtr); +static void shadowChangeGC(GCPtr, unsigned long); +static void shadowCopyGC(GCPtr, unsigned long, GCPtr); +static void shadowDestroyGC(GCPtr); +static void shadowChangeClip(GCPtr, int, pointer, int); +static void shadowDestroyClip(GCPtr); +static void shadowCopyClip(GCPtr, GCPtr); + +GCFuncs shadowGCFuncs = { + shadowValidateGC, shadowChangeGC, shadowCopyGC, shadowDestroyGC, + shadowChangeClip, shadowDestroyClip, shadowCopyClip +}; + +extern GCOps shadowGCOps; + +static Bool +shadowCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + shadowScrPriv(pScreen); + shadowGCPriv(pGC); + Bool ret; + + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &shadowGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC); + + return ret; +} + +void +shadowWrapGC (GCPtr pGC) +{ + shadowGCPriv(pGC); + + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &shadowGCFuncs; +} + +void +shadowUnwrapGC (GCPtr pGC) +{ + shadowGCPriv(pGC); + + pGC->funcs = pGCPriv->funcs; + if (pGCPriv->ops) + pGC->ops = pGCPriv->ops; +} + +#define SHADOW_GC_OP_PROLOGUE(pGC, pDraw) \ + shadowGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define SHADOW_GC_OP_EPILOGUE(pGC, pDraw) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &shadowGCOps) + +#define SHADOW_GC_FUNC_PROLOGUE(pGC) \ + shadowGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define SHADOW_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &shadowGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &shadowGCOps) + +static void +shadowValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + if(pDraw->type == DRAWABLE_WINDOW) + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + else + pGCPriv->ops = NULL; + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +shadowDestroyGC(GCPtr pGC) +{ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +shadowChangeGC ( + GCPtr pGC, + unsigned long mask +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +shadowCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst +){ + SHADOW_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + SHADOW_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +shadowChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +shadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + SHADOW_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + SHADOW_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +shadowDestroyClip(GCPtr pGC) +{ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +#define IS_VISIBLE(pWin) 1 + + +#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)) + +#ifdef RENDER +static void +shadowComposite (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); + shadowScrPriv(pScreen); + + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + wrap (pScrPriv, ps, Composite, shadowComposite); + if (pDst->pDrawable->type == DRAWABLE_WINDOW) + shadowDamageRect ((WindowPtr) pDst->pDrawable, xDst, yDst, + width, height); +} + +static void +shadowGlyphs (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); + shadowScrPriv(pScreen); + int x, y; + int n; + GlyphPtr glyph; + + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, shadowGlyphs); + if (pDst->pDrawable->type == DRAWABLE_WINDOW) + { + x = xSrc; + y = ySrc; + while (nlist--) + { + x += list->xOff; + y += list->yOff; + n = list->len; + while (n--) + { + glyph = *glyphs++; + shadowDamageRect ((WindowPtr) pDst->pDrawable, + x - glyph->info.x, + y - glyph->info.y, + glyph->info.width, + glyph->info.height); + x += glyph->info.xOff; + y += glyph->info.yOff; + } + list++; + } + } +} +#endif + +/**********************************************************/ + + +static void +shadowFillSpans( + DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nInit) { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nInit; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidthInit++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + + box.y2++; + + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } else + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); +} + +static void +shadowSetSpans( + DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr pptInit, + int *pwidthInit, + int nspans, + int fSorted +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nspans) { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nspans; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidth++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + + box.y2++; + + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, + pwidthInit, nspans, fSorted); + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } else + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, + pwidthInit, nspans, fSorted); + + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); +} + +static void +shadowPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw)) { + BoxRec box; + + box.x1 = x + pDraw->x; + box.x2 = box.x1 + w; + box.y1 = y + pDraw->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static RegionPtr +shadowCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +){ + RegionPtr ret; + SHADOW_GC_OP_PROLOGUE(pGC, pDst); + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + SHADOW_GC_OP_EPILOGUE(pGC, pDst); + + if(IS_VISIBLE(pDst)) { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDst, &box); + } + + return ret; +} + +static RegionPtr +shadowCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +){ + RegionPtr ret; + SHADOW_GC_OP_PROLOGUE(pGC, pDst); + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + SHADOW_GC_OP_EPILOGUE(pGC, pDst); + + if(IS_VISIBLE(pDst)) { + BoxRec box; + + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDst, &box); + } + + return ret; +} + +static void +shadowPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && npt) { + BoxRec box; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + /* this could be slow if the points were spread out */ + + while(--npt) { + pptInit++; + if(box.x1 > pptInit->x) box.x1 = pptInit->x; + else if(box.x2 < pptInit->x) box.x2 = pptInit->x; + if(box.y1 > pptInit->y) box.y1 = pptInit->y; + else if(box.y2 < pptInit->y) box.y2 = pptInit->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + + if(IS_VISIBLE(pDraw) && npt) { + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + if(npt > 1) { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) { + int x = box.x1; + int y = box.y1; + while(--npt) { + pptInit++; + x += pptInit->x; + y += pptInit->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } else { + while(--npt) { + pptInit++; + if(box.x1 > pptInit->x) box.x1 = pptInit->x; + else if(box.x2 < pptInit->x) box.x2 = pptInit->x; + if(box.y1 > pptInit->y) box.y1 = pptInit->y; + else if(box.y2 < pptInit->y) box.y2 = pptInit->y; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nseg) { + BoxRec box; + int extra = pGC->lineWidth; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSeg->x2 > pSeg->x1) { + box.x1 = pSeg->x1; + box.x2 = pSeg->x2; + } else { + box.x2 = pSeg->x1; + box.x1 = pSeg->x2; + } + + if(pSeg->y2 > pSeg->y1) { + box.y1 = pSeg->y1; + box.y2 = pSeg->y2; + } else { + box.y2 = pSeg->y1; + box.y1 = pSeg->y2; + } + + while(--nseg) { + pSeg++; + if(pSeg->x2 > pSeg->x1) { + if(pSeg->x1 < box.x1) box.x1 = pSeg->x1; + if(pSeg->x2 > box.x2) box.x2 = pSeg->x2; + } else { + if(pSeg->x2 < box.x1) box.x1 = pSeg->x2; + if(pSeg->x1 > box.x2) box.x2 = pSeg->x1; + } + if(pSeg->y2 > pSeg->y1) { + if(pSeg->y1 < box.y1) box.y1 = pSeg->y1; + if(pSeg->y2 > box.y2) box.y2 = pSeg->y2; + } else { + if(pSeg->y2 < box.y1) box.y1 = pSeg->y2; + if(pSeg->y1 > box.y2) box.y2 = pSeg->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRects, + xRectangle *pRects +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nRects) + { + BoxRec box; + int offset1, offset2, offset3; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRects--) + { + box.x1 = pRects->x - offset1; + box.y1 = pRects->y - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + + box.x1 = pRects->x + pRects->width - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + pRects->height - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + + pRects++; + } + } + } + +static void +shadowPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && narcs) { + int extra = pGC->lineWidth >> 1; + BoxRec box; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr pptInit +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && (count > 2)) { + DDXPointPtr ppt = pptInit; + int i = count; + BoxRec box; + + box.x2 = box.x1 = ppt->x; + box.y2 = box.y1 = ppt->y; + + if(mode != CoordModeOrigin) { + int x = box.x1; + int y = box.y1; + while(--i) { + ppt++; + x += ppt->x; + y += ppt->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } else { + while(--i) { + ppt++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + else if(box.x2 < ppt->x) box.x2 = ppt->x; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + } + + box.x2++; + box.y2++; + + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } else + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); + + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); +} + + +static void +shadowPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nRectsInit) { + BoxRec box; + xRectangle *pRects = pRectsInit; + int nRects = nRectsInit; + + box.x1 = pRects->x; + box.x2 = box.x1 + pRects->width; + box.y1 = pRects->y; + box.y2 = box.y1 + pRects->height; + + while(--nRects) { + pRects++; + if(box.x1 > pRects->x) box.x1 = pRects->x; + if(box.x2 < (pRects->x + pRects->width)) + box.x2 = pRects->x + pRects->width; + if(box.y1 > pRects->y) box.y1 = pRects->y; + if(box.y2 < (pRects->y + pRects->height)) + box.y2 = pRects->y + pRects->height; + } + + /* cfb messes with the pRectsInit so we have to do our + calculations first */ + + (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } else + (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); + + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); +} + + +static void +shadowPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && narcs) { + BoxRec box; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } + +} + +static int +shadowPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + int width; + + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + width -= x; + + if(IS_VISIBLE(pDraw) && (width > 0)) { + BoxRec box; + + /* ugh */ + box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if(count > 1) { + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } + + return (width + x); +} + +static int +shadowPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + int width; + + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + width -= x; + + if(IS_VISIBLE(pDraw) && (width > 0)) { + BoxRec box; + + /* ugh */ + box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if(count > 1) { + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } + + return (width + x); +} + +static void +shadowImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && count) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = pDraw->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} +static void +shadowImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && count) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = pDraw->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + + +static void +shadowImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph, + ppci, pglyphBase); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nglyph) { + int top, bot, width = 0; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + box.x1 = ppci[0]->metrics.leftSideBearing; + if(box.x1 > 0) box.x1 = 0; + box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - + ppci[nglyph - 1]->metrics.characterWidth; + if(box.x2 < 0) box.x2 = 0; + + box.x2 += pDraw->x + x; + box.x1 += pDraw->x + x; + + while(nglyph--) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) + box.x2 += width; + else + box.x1 += width; + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph, + ppci, pglyphBase); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw) && nglyph) { + BoxRec box; + + /* ugh */ + box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing; + box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; + + if(nglyph > 1) { + int width = 0; + + while(--nglyph) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + +static void +shadowPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg +){ + SHADOW_GC_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + SHADOW_GC_OP_EPILOGUE(pGC, pDraw); + + if(IS_VISIBLE(pDraw)) { + BoxRec box; + + box.x1 = xOrg + pDraw->x; + box.x2 = box.x1 + dx; + box.y1 = yOrg + pDraw->y; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + shadowDamageBox ((WindowPtr) pDraw, &box); + } +} + + +static void +shadowPaintWindow( + WindowPtr pWindow, + RegionPtr prgn, + int what +){ + ScreenPtr pScreen = pWindow->drawable.pScreen; + shadowScrPriv(pScreen); + + if(what == PW_BACKGROUND) { + unwrap (pScrPriv, pScreen, PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow); + } else { + unwrap (pScrPriv, pScreen, PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow); + } + shadowDamageRegion (pWindow, prgn); +} + + +static void +shadowCopyWindow( + WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgn +){ + ScreenPtr pScreen = pWindow->drawable.pScreen; + shadowScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgn); + wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow); + shadowDamageRegion (pWindow, prgn); +} + +GCOps shadowGCOps = { + shadowFillSpans, shadowSetSpans, + shadowPutImage, shadowCopyArea, + shadowCopyPlane, shadowPolyPoint, + shadowPolylines, shadowPolySegment, + shadowPolyRectangle, shadowPolyArc, + shadowFillPolygon, shadowPolyFillRect, + shadowPolyFillArc, shadowPolyText8, + shadowPolyText16, shadowImageText8, + shadowImageText16, shadowImageGlyphBlt, + shadowPolyGlyphBlt, shadowPushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; + +static void +shadowGetImage (DrawablePtr pDrawable, + int sx, + int sy, + int w, + int h, + unsigned int format, + unsigned long planeMask, + char * pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + shadowScrPriv(pScreen); + + /* Many apps use GetImage to sync with the visable frame buffer */ + if (pDrawable->type == DRAWABLE_WINDOW) + shadowRedisplay (pScreen); + unwrap (pScrPriv, pScreen, GetImage); + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + wrap (pScrPriv, pScreen, GetImage, shadowGetImage); +} + +static void +shadowRestoreAreas (PixmapPtr pPixmap, + RegionPtr prgn, + int xorg, + int yorg, + WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + shadowScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, + xorg, yorg, pWin); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + shadowRestoreAreas); + shadowDamageRegion (pWin, prgn); +} + +static Bool +shadowCloseScreen (int i, ScreenPtr pScreen) +{ + shadowScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, PaintWindowBackground); + unwrap (pScrPriv, pScreen, PaintWindowBorder); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + unwrap (pScrPriv, pScreen, GetImage); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + xfree (pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +shadowSetup (ScreenPtr pScreen) +{ + shadowScrPrivPtr pScrPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + if (shadowGeneration != serverGeneration) + { + shadowScrPrivateIndex = AllocateScreenPrivateIndex (); + if (shadowScrPrivateIndex == -1) + return FALSE; + shadowGCPrivateIndex = AllocateGCPrivateIndex (); + if (shadowGCPrivateIndex == -1) + return FALSE; + shadowGeneration = serverGeneration; + } + if (!AllocateGCPrivate (pScreen, shadowGCPrivateIndex, sizeof (shadowGCPrivRec))) + return FALSE; + pScrPriv = (shadowScrPrivPtr) xalloc (sizeof (shadowScrPrivRec)); + if (!pScrPriv) + return FALSE; + + if (!RegisterBlockAndWakeupHandlers (shadowBlockHandler, + shadowWakeupHandler, + (pointer) pScreen)) + return FALSE; + + wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC); + wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow); + wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow); + wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, shadowCloseScreen); + wrap (pScrPriv, pScreen, GetImage, shadowGetImage); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + shadowRestoreAreas); +#ifdef RENDER + if (ps) { + wrap (pScrPriv, ps, Glyphs, shadowGlyphs); + wrap (pScrPriv, ps, Composite, shadowComposite); + } +#endif + pScrPriv->pBuf = 0; + + pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pScrPriv; + return TRUE; +} + +Bool +shadowAdd (ScreenPtr pScreen, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int randr, + void *closure) +{ + shadowScrPriv(pScreen); + shadowBufPtr pBuf; + + pBuf = (shadowBufPtr) xalloc (sizeof (shadowBufRec)); + if (!pBuf) + return FALSE; + /* + * Map simple rotation values to bitmasks; fortunately, + * these are all unique + */ + switch (randr) { + case 0: + randr = SHADOW_ROTATE_0; + break; + case 90: + randr = SHADOW_ROTATE_90; + break; + case 180: + randr = SHADOW_ROTATE_180; + break; + case 270: + randr = SHADOW_ROTATE_270; + break; + } + pBuf->pPixmap = pPixmap; + pBuf->update = update; + pBuf->window = window; + REGION_INIT (pScreen, &pBuf->damage, NullBox, 0); + pBuf->pNext = pScrPriv->pBuf; + pBuf->randr = randr; + pBuf->closure = 0; + pScrPriv->pBuf = pBuf; + return TRUE; +} + +void +shadowRemove (ScreenPtr pScreen, PixmapPtr pPixmap) +{ + shadowScrPriv(pScreen); + shadowBufPtr pBuf, *pPrev; + + for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext) + if (pBuf->pPixmap == pPixmap) + { + REGION_UNINIT (pScreen, &pBuf->damage); + *pPrev = pBuf->pNext; + xfree (pBuf); + break; + } +} + +shadowBufPtr +shadowFindBuf (WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + shadowScrPriv(pScreen); + shadowBufPtr pBuf, *pPrev; + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWindow); + + for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext) + { + if (!pBuf->pPixmap) + pBuf->pPixmap = (*pScreen->GetScreenPixmap) (pScreen); + if (pBuf->pPixmap == pPixmap) + { + /* + * Reorder so this one is first next time + */ + if (pPrev != &pScrPriv->pBuf) + { + *pPrev = pBuf->pNext; + pBuf->pNext = pScrPriv->pBuf; + pScrPriv->pBuf = pBuf; + } + return pBuf; + } + } + return 0; +} + +Bool +shadowInit (ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) +{ + if (!shadowSetup (pScreen)) + return FALSE; + + if (!shadowAdd (pScreen, 0, update, window, SHADOW_ROTATE_0, 0)) + return FALSE; + + return TRUE; +} diff --git a/miext/shadow/shadow.h b/miext/shadow/shadow.h new file mode 100644 index 000000000..d8ade93dc --- /dev/null +++ b/miext/shadow/shadow.h @@ -0,0 +1,172 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shadow.h,v 1.7 2002/12/02 20:37:24 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#ifndef _SHADOW_H_ +#define _SHADOW_H_ + +#include "scrnintstr.h" + +#ifdef RENDER +#include "picturestr.h" +#endif + +typedef struct _shadowBuf *shadowBufPtr; + +typedef void (*ShadowUpdateProc) (ScreenPtr pScreen, + shadowBufPtr pBuf); + +#define SHADOW_WINDOW_RELOCATE 1 +#define SHADOW_WINDOW_READ 2 +#define SHADOW_WINDOW_WRITE 4 + +typedef void *(*ShadowWindowProc) (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure); + +typedef struct _shadowBuf { + shadowBufPtr pNext; + ShadowUpdateProc update; + ShadowWindowProc window; + RegionRec damage; + PixmapPtr pPixmap; + void *closure; + int randr; +} shadowBufRec; + +/* Match defines from randr extension */ +#define SHADOW_ROTATE_0 1 +#define SHADOW_ROTATE_90 2 +#define SHADOW_ROTATE_180 4 +#define SHADOW_ROTATE_270 8 +#define SHADOW_ROTATE_ALL (SHADOW_ROTATE_0|SHADOW_ROTATE_90|\ + SHADOW_ROTATE_180|SHADOW_ROTATE_270) +#define SHADOW_REFLECT_X 16 +#define SHADOW_REFLECT_Y 32 +#define SHADOW_REFLECT_ALL (SHADOW_REFLECT_X|SHADOW_REFLECT_Y) + +typedef struct _shadowScrPriv { + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + CloseScreenProcPtr CloseScreen; + CreateGCProcPtr CreateGC; + GetImageProcPtr GetImage; +#ifdef RENDER + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; +#endif + shadowBufPtr pBuf; + BSFuncRec BackingStoreFuncs; +} shadowScrPrivRec, *shadowScrPrivPtr; + +extern int shadowScrPrivateIndex; + +#define shadowGetScrPriv(pScr) ((shadowScrPrivPtr) (pScr)->devPrivates[shadowScrPrivateIndex].ptr) +#define shadowScrPriv(pScr) shadowScrPrivPtr pScrPriv = shadowGetScrPriv(pScr) + +Bool +shadowSetup (ScreenPtr pScreen); + +Bool +shadowAdd (ScreenPtr pScreen, + PixmapPtr pPixmap, + ShadowUpdateProc update, + ShadowWindowProc window, + int randr, + void *closure); + +void +shadowRemove (ScreenPtr pScreen, PixmapPtr pPixmap); + +shadowBufPtr +shadowFindBuf (WindowPtr pWindow); + +Bool +shadowInit (ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window); + +void * +shadowAlloc (int width, int height, int bpp); + +void +shadowUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdatePlanar4 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdatePlanar4x8 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate8_90 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate16_90 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate32_90 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate8_180 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate16_180 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate32_180 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate8_270 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate16_270 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowUpdateRotate32_270 (ScreenPtr pScreen, + shadowBufPtr pBuf); + +void +shadowWrapGC (GCPtr pGC); + +void +shadowUnwrapGC (GCPtr pGC); + +#endif /* _SHADOW_H_ */ diff --git a/miext/shadow/shalloc.c b/miext/shadow/shalloc.c new file mode 100644 index 000000000..028ec26a5 --- /dev/null +++ b/miext/shadow/shalloc.c @@ -0,0 +1,48 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shalloc.c,v 1.1 2000/09/07 23:12:15 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" + +void * +shadowAlloc (int width, int height, int bpp) +{ + int stride; + void *fb; + + /* Cant use PixmapBytePad -- the structure is probably not initialized yet */ + stride = BitmapBytePad (width * bpp); + fb = xalloc (stride * height); + return fb; +} diff --git a/miext/shadow/shpacked.c b/miext/shadow/shpacked.c new file mode 100644 index 000000000..818a37a8e --- /dev/null +++ b/miext/shadow/shpacked.c @@ -0,0 +1,108 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shpacked.c,v 1.5 2001/10/28 03:34:16 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +void +shadowUpdatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + FbBits *winBase = NULL, *win; + CARD32 winSize; + + fbGetDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); + while (nbox--) + { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + scrLine = (x >> FB_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + x &= FB_MASK; + w = (w + x + FB_MASK) >> FB_SHIFT; + + while (h--) + { + winSize = 0; + scrBase = 0; + width = w; + scr = scrLine; + sha = shaLine; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (FbBits *) (*pBuf->window) (pScreen, + y, + scr * sizeof (FbBits), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + scrBase = scr; + winSize /= sizeof (FbBits); + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; +#define PickBit(a,i) (((a) >> (i)) & 1) + while (i--) + *win++ = *sha++; + } + shaLine += shaStride; + y++; + } + pbox++; + } +} diff --git a/miext/shadow/shplanar.c b/miext/shadow/shplanar.c new file mode 100644 index 000000000..148782956 --- /dev/null +++ b/miext/shadow/shplanar.c @@ -0,0 +1,168 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shplanar.c,v 1.4 2001/10/28 03:34:16 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +/* + * 32 4-bit pixels per write + */ + +#define PL_SHIFT 7 +#define PL_UNIT (1 << PL_SHIFT) +#define PL_MASK (PL_UNIT - 1) + +/* + * 32->8 conversion: + * + * 7 6 5 4 3 2 1 0 + * A B C D E F G H + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * m . . . H . . . G . . . F . . . E . . . D . . . C . . . B . . . A + * m1 G . . . F . . . E . . . D . . . C . . . B . . . A . . . . . . . m << (7 - (p)) + * m2 . H . . . G . . . F . . . E . . . D . . . C . . . B . . . A . . (m >> (p)) << 2 + * m3 G E C A m1 & 0x80808080 + * m4 H F D B m2 & 0x40404040 + * m5 G H E F C D A B m3 | m4 + * m6 G H E F C D G H A B E F m5 | (m5 >> 20) + * m7 G H E F C D G H A B C D E F G H m6 | (m6 >> 10) + */ + +#if 0 +#define GetBits(p,o,d) {\ + m = sha[o]; \ + m1 = m << (7 - (p)); \ + m2 = (m >> (p)) << 2; \ + m3 = m1 & 0x80808080; \ + m4 = m2 & 0x40404040; \ + m5 = m3 | m4; \ + m6 = m5 | (m5 >> 20); \ + d = m6 | (m6 >> 10); \ +} +#else +#define GetBits(p,o,d) {\ + m = sha[o]; \ + m5 = ((m << (7 - (p))) & 0x80808080) | (((m >> (p)) << 2) & 0x40404040); \ + m6 = m5 | (m5 >> 20); \ + d = m6 | (m6 >> 10); \ +} +#endif + +void +shadowUpdatePlanar4 (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + CARD32 *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + CARD32 *winBase = NULL, *win; + CARD32 winSize; + int plane; + CARD32 m,m5,m6; + CARD8 s1, s2, s3, s4; + + fbGetStipDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); + while (nbox--) + { + x = (pbox->x1) * shaBpp; + y = (pbox->y1); + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + w = (w + (x & PL_MASK) + PL_MASK) >> PL_SHIFT; + x &= ~PL_MASK; + + scrLine = (x >> PL_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + while (h--) + { + for (plane = 0; plane < 4; plane++) + { + width = w; + scr = scrLine; + sha = shaLine; + winSize = 0; + scrBase = 0; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (CARD32 *) (*pBuf->window) (pScreen, + y, + (scr << 4) | (plane), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + winSize >>= 2; + scrBase = scr; + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + + while (i--) + { + GetBits(plane,0,s1); + GetBits(plane,1,s2); + GetBits(plane,2,s3); + GetBits(plane,3,s4); + *win++ = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + sha += 4; + } + } + } + shaLine += shaStride; + y++; + } + pbox++; + } +} + diff --git a/miext/shadow/shplanar8.c b/miext/shadow/shplanar8.c new file mode 100644 index 000000000..c82b5f931 --- /dev/null +++ b/miext/shadow/shplanar8.c @@ -0,0 +1,170 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shplanar8.c,v 1.4 2001/10/28 03:34:16 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +/* + * Expose 8bpp depth 4 + */ + +/* + * 32->8 conversion: + * + * 7 6 5 4 3 2 1 0 + * A B C D E F G H + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * m1 D x x x x x x x C x x x x x x x B x x x x x x x A x x x x x x x sha[0] << (7-(p)) + * m2 x x x x H x x x x x x x G x x x x x x x F x x x x x x x E x x x sha[1] << (3-(p)) + * m3 D C B A m1 & 0x80808080 + * m4 H G F E m2 & 0x08080808 + * m5 D H C G B F A E m3 | m4 + * m6 D H C G B F m5 >> 9 + * m7 D H C D G H B C F G A B E F m5 | m6 + * m8 D H C D G H m7 >> 18 + * m9 D H C D G H B C D F G H A B C D E F G H m7 | m8 + */ + +#define PL_SHIFT 8 +#define PL_UNIT (1 << PL_SHIFT) +#define PL_MASK (PL_UNIT - 1) + +#if 0 +#define GetBits(p,o,d) { \ + CARD32 m1,m2,m3,m4,m5,m6,m7,m8; \ + m1 = sha[o] << (7 - (p)); \ + m2 = sha[(o)+1] << (3 - (p)); \ + m3 = m1 & 0x80808080; \ + m4 = m2 & 0x08080808; \ + m5 = m3 | m4; \ + m6 = m5 >> 9; \ + m7 = m5 | m6; \ + m8 = m7 >> 18; \ + d = m7 | m8; \ +} +#else +#define GetBits(p,o,d) { \ + CARD32 m5,m7; \ + m5 = ((sha[o] << (7 - (p))) & 0x80808080) | ((sha[(o)+1] << (3 - (p))) & 0x08080808); \ + m7 = m5 | (m5 >> 9); \ + d = m7 | (m7 >> 18); \ +} +#endif + +void +shadowUpdatePlanar4x8 (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + CARD32 *shaBase, *shaLine, *sha; + CARD8 s1, s2, s3, s4; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + CARD32 *winBase = NULL, *win; + CARD32 winSize; + int plane; + + fbGetStipDrawable (&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, shaYoff); + while (nbox--) + { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + w = (w + (x & PL_MASK) + PL_MASK) >> PL_SHIFT; + x &= ~PL_MASK; + + scrLine = (x >> PL_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + while (h--) + { + for (plane = 0; plane < 4; plane++) + { + width = w; + scr = scrLine; + sha = shaLine; + winSize = 0; + scrBase = 0; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (CARD32 *) (*pBuf->window) (pScreen, + y, + (scr << 4) | (plane), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + winSize >>= 2; + scrBase = scr; + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + + while (i--) + { + GetBits(plane,0,s1); + GetBits(plane,2,s2); + GetBits(plane,4,s3); + GetBits(plane,6,s4); + *win++ = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24); + sha += 8; + } + } + } + shaLine += shaStride; + y++; + } + pbox++; + } +} + diff --git a/miext/shadow/shrot16pack.c b/miext/shadow/shrot16pack.c new file mode 100644 index 000000000..a1ff273de --- /dev/null +++ b/miext/shadow/shrot16pack.c @@ -0,0 +1,28 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack.c,v 1.1 2000/09/08 21:46:45 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate16 +#define Data CARD16 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot16pack_180.c b/miext/shadow/shrot16pack_180.c new file mode 100644 index 000000000..7ba41833e --- /dev/null +++ b/miext/shadow/shrot16pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate16_180 +#define Data CARD16 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot16pack_270.c b/miext/shadow/shrot16pack_270.c new file mode 100644 index 000000000..0b3c4e0ac --- /dev/null +++ b/miext/shadow/shrot16pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate16_270 +#define Data CARD16 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot16pack_90.c b/miext/shadow/shrot16pack_90.c new file mode 100644 index 000000000..574b3a157 --- /dev/null +++ b/miext/shadow/shrot16pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot16pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate16_90 +#define Data CARD16 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot32pack.c b/miext/shadow/shrot32pack.c new file mode 100644 index 000000000..327636efb --- /dev/null +++ b/miext/shadow/shrot32pack.c @@ -0,0 +1,28 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack.c,v 1.1 2000/09/08 21:46:45 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate32 +#define Data CARD32 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot32pack_180.c b/miext/shadow/shrot32pack_180.c new file mode 100644 index 000000000..838622267 --- /dev/null +++ b/miext/shadow/shrot32pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate32_180 +#define Data CARD32 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot32pack_270.c b/miext/shadow/shrot32pack_270.c new file mode 100644 index 000000000..b0dd28316 --- /dev/null +++ b/miext/shadow/shrot32pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate32_270 +#define Data CARD32 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot32pack_90.c b/miext/shadow/shrot32pack_90.c new file mode 100644 index 000000000..9bdb18e25 --- /dev/null +++ b/miext/shadow/shrot32pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot32pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate32_90 +#define Data CARD32 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot8pack.c b/miext/shadow/shrot8pack.c new file mode 100644 index 000000000..7af181f19 --- /dev/null +++ b/miext/shadow/shrot8pack.c @@ -0,0 +1,28 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack.c,v 1.1 2000/09/08 21:46:46 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate8 +#define Data CARD8 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot8pack_180.c b/miext/shadow/shrot8pack_180.c new file mode 100644 index 000000000..316c0c690 --- /dev/null +++ b/miext/shadow/shrot8pack_180.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_180.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate8_180 +#define Data CARD8 +#define ROTATE 180 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot8pack_270.c b/miext/shadow/shrot8pack_270.c new file mode 100644 index 000000000..bed542f6d --- /dev/null +++ b/miext/shadow/shrot8pack_270.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_270.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate8_270 +#define Data CARD8 +#define ROTATE 270 + +#include "shrotpack.h" diff --git a/miext/shadow/shrot8pack_90.c b/miext/shadow/shrot8pack_90.c new file mode 100644 index 000000000..f2618fc47 --- /dev/null +++ b/miext/shadow/shrot8pack_90.c @@ -0,0 +1,29 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrot8pack_90.c,v 1.1 2001/05/29 04:54:13 keithp Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +#define FUNC shadowUpdateRotate8_90 +#define Data CARD8 +#define ROTATE 90 + +#include "shrotpack.h" diff --git a/miext/shadow/shrotate.c b/miext/shadow/shrotate.c new file mode 100644 index 000000000..1277c2ee1 --- /dev/null +++ b/miext/shadow/shrotate.c @@ -0,0 +1,306 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrotate.c,v 1.5 2002/10/09 17:00:11 tsi Exp $ + * + * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +/* + * These indicate which way the source (shadow) is scanned when + * walking the screen in a particular direction + */ + +#define LEFT_TO_RIGHT 1 +#define RIGHT_TO_LEFT -1 +#define TOP_TO_BOTTOM 2 +#define BOTTOM_TO_TOP -2 + +void +shadowUpdateRotatePacked (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBits; + FbStride shaStride; + int shaBpp; + int shaXoff, shaYoff; + int box_x1, box_x2, box_y1, box_y2; + int sha_x1 = 0, sha_y1 = 0; + int scr_x1 = 0, scr_x2 = 0, scr_y1 = 0, scr_y2 = 0, scr_w, scr_h; + int scr_x, scr_y; + int w; + int pixelsPerBits; + int pixelsMask; + FbStride shaStepOverY = 0, shaStepDownY = 0; + FbStride shaStepOverX = 0, shaStepDownX = 0; + FbBits *shaLine, *sha; + int shaHeight = pShadow->drawable.height; + int shaWidth = pShadow->drawable.width; + FbBits shaMask; + int shaFirstShift, shaShift; + int o_x_dir; + int o_y_dir; + int x_dir; + int y_dir; + + fbGetDrawable (&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, shaYoff); + pixelsPerBits = (sizeof (FbBits) * 8) / shaBpp; + pixelsMask = ~(pixelsPerBits - 1); + shaMask = FbBitsMask (FB_UNIT-shaBpp, shaBpp); + /* + * Compute rotation related constants to walk the shadow + */ + o_x_dir = LEFT_TO_RIGHT; + o_y_dir = TOP_TO_BOTTOM; + if (pBuf->randr & SHADOW_REFLECT_X) + o_x_dir = -o_x_dir; + if (pBuf->randr & SHADOW_REFLECT_Y) + o_y_dir = -o_y_dir; + switch (pBuf->randr & (SHADOW_ROTATE_ALL)) { + case SHADOW_ROTATE_0: /* upper left shadow -> upper left screen */ + default: + x_dir = o_x_dir; + y_dir = o_y_dir; + break; + case SHADOW_ROTATE_90: /* upper right shadow -> upper left screen */ + x_dir = o_y_dir; + y_dir = -o_x_dir; + break; + case SHADOW_ROTATE_180: /* lower right shadow -> upper left screen */ + x_dir = -o_x_dir; + y_dir = -o_y_dir; + break; + case SHADOW_ROTATE_270: /* lower left shadow -> upper left screen */ + x_dir = -o_y_dir; + y_dir = o_x_dir; + break; + } + switch (x_dir) { + case LEFT_TO_RIGHT: + shaStepOverX = shaBpp; + shaStepOverY = 0; + break; + case TOP_TO_BOTTOM: + shaStepOverX = 0; + shaStepOverY = shaStride; + break; + case RIGHT_TO_LEFT: + shaStepOverX = -shaBpp; + shaStepOverY = 0; + break; + case BOTTOM_TO_TOP: + shaStepOverX = 0; + shaStepOverY = -shaStride; + break; + } + switch (y_dir) { + case TOP_TO_BOTTOM: + shaStepDownX = 0; + shaStepDownY = shaStride; + break; + case RIGHT_TO_LEFT: + shaStepDownX = -shaBpp; + shaStepDownY = 0; + break; + case BOTTOM_TO_TOP: + shaStepDownX = 0; + shaStepDownY = -shaStride; + break; + case LEFT_TO_RIGHT: + shaStepDownX = shaBpp; + shaStepDownY = 0; + break; + } + + while (nbox--) + { + box_x1 = pbox->x1; + box_y1 = pbox->y1; + box_x2 = pbox->x2; + box_y2 = pbox->y2; + pbox++; + + /* + * Compute screen and shadow locations for this box + */ + switch (x_dir) { + case LEFT_TO_RIGHT: + scr_x1 = box_x1 & pixelsMask; + scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask; + + sha_x1 = scr_x1; + break; + case TOP_TO_BOTTOM: + scr_x1 = box_y1 & pixelsMask; + scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask; + + sha_y1 = scr_x1; + break; + case RIGHT_TO_LEFT: + scr_x1 = (shaWidth - box_x2) & pixelsMask; + scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask; + + sha_x1 = (shaWidth - scr_x1 - 1); + break; + case BOTTOM_TO_TOP: + scr_x1 = (shaHeight - box_y2) & pixelsMask; + scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask; + + sha_y1 = (shaHeight - scr_x1 - 1); + break; + } + switch (y_dir) { + case TOP_TO_BOTTOM: + scr_y1 = box_y1; + scr_y2 = box_y2; + + sha_y1 = scr_y1; + break; + case RIGHT_TO_LEFT: + scr_y1 = (shaWidth - box_x2); + scr_y2 = (shaWidth - box_x1); + + sha_x1 = box_x2 - 1; + break; + case BOTTOM_TO_TOP: + scr_y1 = shaHeight - box_y2; + scr_y2 = shaHeight - box_y1; + + sha_y1 = box_y2 - 1; + break; + case LEFT_TO_RIGHT: + scr_y1 = box_x1; + scr_y2 = box_x2; + + sha_x1 = box_x1; + break; + } + scr_w = ((scr_x2 - scr_x1) * shaBpp) >> FB_SHIFT; + scr_h = scr_y2 - scr_y1; + scr_y = scr_y1; + + /* shift amount for first pixel on screen */ + shaFirstShift = FB_UNIT - ((sha_x1 * shaBpp) & FB_MASK) - shaBpp; + + /* pointer to shadow data first placed on screen */ + shaLine = (shaBits + + sha_y1 * shaStride + + ((sha_x1 * shaBpp) >> FB_SHIFT)); + + /* + * Copy the bits, always write across the physical frame buffer + * to take advantage of write combining. + */ + while (scr_h--) + { + int p; + FbBits bits; + FbBits *win; + int i; + CARD32 winSize; + + sha = shaLine; + shaShift = shaFirstShift; + w = scr_w; + scr_x = scr_x1 * shaBpp >> FB_SHIFT; + + while (w) + { + /* + * Map some of this line + */ + win = (FbBits *) (*pBuf->window) (pScreen, + scr_y, + scr_x << 2, + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + i = (winSize >> 2); + if (i > w) + i = w; + w -= i; + scr_x += i; + /* + * Copy the portion of the line mapped + */ + while (i--) + { + bits = 0; + p = pixelsPerBits; + /* + * Build one word of output from multiple inputs + * + * Note that for 90/270 rotations, this will walk + * down the shadow hitting each scanline once. + * This is probably not very efficient. + */ + while (p--) + { + bits = FbScrLeft(bits, shaBpp); + bits |= FbScrRight (*sha, shaShift) & shaMask; + + shaShift -= shaStepOverX; + if (shaShift >= FB_UNIT) + { + shaShift -= FB_UNIT; + sha--; + } + else if (shaShift < 0) + { + shaShift += FB_UNIT; + sha++; + } + sha += shaStepOverY; + } + *win++ = bits; + } + } + scr_y++; + shaFirstShift -= shaStepDownX; + if (shaFirstShift >= FB_UNIT) + { + shaFirstShift -= FB_UNIT; + shaLine--; + } + else if (shaFirstShift < 0) + { + shaFirstShift += FB_UNIT; + shaLine++; + } + shaLine += shaStepDownY; + } + } +} diff --git a/miext/shadow/shrotpack.h b/miext/shadow/shrotpack.h new file mode 100644 index 000000000..ce9b4c561 --- /dev/null +++ b/miext/shadow/shrotpack.h @@ -0,0 +1,182 @@ +/* + * $XFree86: xc/programs/Xserver/miext/shadow/shrotpack.h,v 1.4 2001/10/28 03:34:16 tsi Exp $ + * + * Copyright © 2000 Keith Packard + * + * 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. + */ + +/* + * Thanks to Daniel Chemko <dchemko@intrinsyc.com> for making the 90 and 180 + * orientations work. + */ + +#include "X.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "font.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" +#include "fb.h" + +#define DANDEBUG 0 + +#if ROTATE == 270 + +#define SCRLEFT(x,y,w,h) (pScreen->height - ((y) + (h))) +#define SCRY(x,y,w,h) (x) +#define SCRWIDTH(x,y,w,h) (h) +#define FIRSTSHA(x,y,w,h) (((y) + (h) - 1) * shaStride + (x)) +#define STEPDOWN(x,y,w,h) ((w)--) +#define NEXTY(x,y,w,h) ((x)++) +#define SHASTEPX(stride) -(stride) +#define SHASTEPY(stride) (1) + +#elif ROTATE == 90 + +#define SCRLEFT(x,y,w,h) (y) +#define SCRY(x,y,w,h) (pScreen->width - ((x) + (w)) - 1) +#define SCRWIDTH(x,y,w,h) (h) +#define FIRSTSHA(x,y,w,h) ((y) * shaStride + (x + w - 1)) +#define STEPDOWN(x,y,w,h) ((w)--) +#define NEXTY(x,y,w,h) ((void)(x)) +#define SHASTEPX(stride) (stride) +#define SHASTEPY(stride) (-1) + +#elif ROTATE == 180 + +#define SCRLEFT(x,y,w,h) (pScreen->width - ((x) + (w))) +#define SCRY(x,y,w,h) (pScreen->height - ((y) + (h)) - 1) +#define SCRWIDTH(x,y,w,h) (w) +#define FIRSTSHA(x,y,w,h) ((y + h - 1) * shaStride + (x + w - 1)) +#define STEPDOWN(x,y,w,h) ((h)--) +#define NEXTY(x,y,w,h) ((void)(y)) +#define SHASTEPX(stride) (-1) +#define SHASTEPY(stride) -(stride) + +#else + +#define SCRLEFT(x,y,w,h) (x) +#define SCRY(x,y,w,h) (y) +#define SCRWIDTH(x,y,w,h) (w) +#define FIRSTSHA(x,y,w,h) ((y) * shaStride + (x)) +#define STEPDOWN(x,y,w,h) ((h)--) +#define NEXTY(x,y,w,h) ((y)++) +#define SHASTEPX(stride) (1) +#define SHASTEPY(stride) (stride) + +#endif + +void +FUNC (ScreenPtr pScreen, + shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS (damage); + BoxPtr pbox = REGION_RECTS (damage); + FbBits *shaBits; + Data *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + Data *winBase = NULL, *win; + CARD32 winSize; + + fbGetDrawable (&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, shaYoff); + shaBase = (Data *) shaBits; + shaStride = shaStride * sizeof (FbBits) / sizeof (Data); +#if (DANDEBUG > 1) + ErrorF ("-> Entering Shadow Update:\r\n |- Origins: pShadow=%x, pScreen=%x, damage=%x\r\n |- Metrics: shaStride=%d, shaBase=%x, shaBpp=%d\r\n | \n", pShadow, pScreen, damage, shaStride, shaBase, shaBpp); +#endif + while (nbox--) + { + x = pbox->x1; + y = pbox->y1; + w = (pbox->x2 - pbox->x1); + h = pbox->y2 - pbox->y1; + +#if (DANDEBUG > 2) + ErrorF (" |-> Redrawing box - Metrics: X=%d, Y=%d, Width=%d, Height=%d\n", x, y, w, h); +#endif + scrLine = SCRLEFT(x,y,w,h); + shaLine = shaBase + FIRSTSHA(x,y,w,h); + + while (STEPDOWN(x,y,w,h)) + { + winSize = 0; + scrBase = 0; + width = SCRWIDTH(x,y,w,h); + scr = scrLine; + sha = shaLine; +#if (DANDEBUG > 3) + ErrorF (" | |-> StepDown - Metrics: width=%d, scr=%x, sha=%x\n", width, scr, sha); +#endif + while (width) + { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) + { + winBase = (Data *) (*pBuf->window) (pScreen, + SCRY(x,y,w,h), + scr * sizeof (Data), + SHADOW_WINDOW_WRITE, + &winSize, + pBuf->closure); + if(!winBase) + return; + scrBase = scr; + winSize /= sizeof (Data); + i = winSize; +#if(DANDEBUG > 4) + ErrorF (" | | |-> Starting New Line - Metrics: winBase=%x, scrBase=%x, winSize=%d\r\n | | | Xstride=%d, Ystride=%d, w=%d h=%d\n", winBase, scrBase, winSize, SHASTEPX(shaStride), SHASTEPY(shaStride), w, h); +#endif + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; +#if(DANDEBUG > 5) + ErrorF (" | | |-> Writing Line - Metrics: win=%x, sha=%x\n", win, sha); +#endif + while (i--) + { +#if(DANDEBUG > 6) + ErrorF (" | | |-> Writing Pixel - Metrics: win=%x, sha=%d, remaining=%d\n", win, sha, i); +#endif + *win++ = *sha; + sha += SHASTEPX(shaStride); + } /* i */ + } /* width */ + shaLine += SHASTEPY(shaStride); + NEXTY(x,y,w,h); + } /* STEPDOWN */ + pbox++; + } /* nbox */ +} |