diff options
Diffstat (limited to 'miext')
-rw-r--r-- | miext/cw/cw.c | 685 | ||||
-rw-r--r-- | miext/cw/cw.h | 164 | ||||
-rw-r--r-- | miext/cw/cw_ops.c | 466 | ||||
-rw-r--r-- | miext/cw/cw_render.c | 497 | ||||
-rwxr-xr-x | miext/damage/damage.c | 1933 | ||||
-rwxr-xr-x | miext/damage/damagestr.h | 107 | ||||
-rw-r--r-- | miext/rootless/rootless.h | 13 | ||||
-rw-r--r-- | miext/rootless/rootlessCommon.c | 87 | ||||
-rw-r--r-- | miext/rootless/rootlessCommon.h | 45 | ||||
-rw-r--r-- | miext/rootless/rootlessValTree.c | 1 | ||||
-rw-r--r-- | miext/rootless/rootlessWindow.c | 57 | ||||
-rw-r--r-- | miext/rootless/safeAlpha/safeAlphaWindow.c | 2 | ||||
-rw-r--r-- | miext/shadow/shadow.h | 7 | ||||
-rw-r--r-- | miext/shadow/shpacked.c | 2 | ||||
-rw-r--r-- | miext/shadow/shplanar.c | 9 | ||||
-rw-r--r-- | miext/shadow/shrotate.c | 4 |
16 files changed, 4005 insertions, 74 deletions
diff --git a/miext/cw/cw.c b/miext/cw/cw.c new file mode 100644 index 000000000..f834148a7 --- /dev/null +++ b/miext/cw/cw.c @@ -0,0 +1,685 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT 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. + */ +/* $Header$ */ + +#include "gcstruct.h" +#include "windowstr.h" +#include "cw.h" + +#define CW_DEBUG 1 + +#if CW_DEBUG +#define CW_ASSERT(x) do { \ + if (!(x)) { \ + ErrorF("composite wrapper: assertion failed at %s:%d\n", __FUNC__, \ + __LINE__); \ + } \ +} while (0) +#else +#define CW_ASSERT(x) do {} while (0) +#endif + +int cwGCIndex; +int cwScreenIndex; +int cwWindowIndex; +#ifdef RENDER +int cwPictureIndex; +#endif +static unsigned long cwGeneration = 0; +extern GCOps cwGCOps; + +static Bool +cwCloseScreen (int i, ScreenPtr pScreen); + +static void +cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable); +static void +cwChangeGC(GCPtr pGC, unsigned long mask); +static void +cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void +cwDestroyGC(GCPtr pGC); +static void +cwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); +static void +cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc); +static void +cwDestroyClip(GCPtr pGC); + +GCFuncs cwGCFuncs = { + cwValidateGC, + cwChangeGC, + cwCopyGC, + cwDestroyGC, + cwChangeClip, + cwDestroyClip, + cwCopyClip, +}; + +/* Find the real drawable to draw to, and provide offsets that will translate + * window coordinates to backing pixmap coordinates. + */ +DrawablePtr +cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW && + (pPixmap = getCwPixmap ((WindowPtr) pDrawable))) + { + *x_off = pDrawable->x - pPixmap->screen_x; + *y_off = pDrawable->y - pPixmap->screen_y; + return &pPixmap->drawable; + } else { + *x_off = *y_off = 0; + return pDrawable; + } +} + +#define FUNC_PROLOGUE(pGC, pPriv) do { \ + (pGC)->funcs = (pPriv)->wrapFuncs; \ + (pGC)->ops = (pPriv)->wrapOps; \ +} while (0) + +#define FUNC_EPILOGUE(pGC, pPriv) do { \ + (pPriv)->wrapFuncs = (pGC)->funcs; \ + (pPriv)->wrapOps = (pGC)->ops; \ + (pGC)->funcs = &cwGCFuncs; \ + (pGC)->ops = &cwGCOps; \ +} while (0) + + +static Bool +cwCreateBackingGC(GCPtr pGC, DrawablePtr pDrawable) +{ + cwGCRec *pPriv = getCwGC(pGC); + int status, x_off, y_off; + XID noexpose = xFalse; + DrawablePtr pBackingDrawable; + + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + pPriv->pBackingGC = CreateGC(pBackingDrawable, GCGraphicsExposures, + &noexpose, &status); + if (status != Success) + return FALSE; + + pPriv->serialNumber = 0; + pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1; + + return TRUE; +} + +static void +cwDestroyBackingGC(GCPtr pGC) +{ + cwGCPtr pPriv; + + pPriv = (cwGCPtr) getCwGC (pGC); + + if (pPriv->pBackingGC) { + FreeGC(pPriv->pBackingGC, (XID)0); + pPriv->pBackingGC = NULL; + } +} + +static void +cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable) +{ + GCPtr pBackingGC; + cwGCPtr pPriv; + DrawablePtr pBackingDrawable; + int x_off, y_off; + + pPriv = (cwGCPtr) getCwGC (pGC); + + FUNC_PROLOGUE(pGC, pPriv); + + /* + * Must call ValidateGC to ensure pGC->pCompositeClip is valid + */ + (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable); + + if (!cwDrawableIsRedirWindow(pDrawable)) { + cwDestroyBackingGC(pGC); + FUNC_EPILOGUE(pGC, pPriv); + return; + } else { + if (!pPriv->pBackingGC && !cwCreateBackingGC(pGC, pDrawable)) { + FUNC_EPILOGUE(pGC, pPriv); + return; + } + } + + pBackingGC = pPriv->pBackingGC; + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + + pPriv->stateChanges |= stateChanges; + + /* + * Copy the composite clip into the backing GC if either + * the drawable clip list has changed or the client has changed + * the client clip data + */ + if (pDrawable->serialNumber != pPriv->serialNumber || + (pPriv->stateChanges & (GCClipXOrigin|GCClipYOrigin|GCClipMask))) + { + XID vals[2]; + RegionPtr pCompositeClip; + + pCompositeClip = REGION_CREATE (pScreen, NULL, 0); + REGION_COPY (pScreen, pCompositeClip, pGC->pCompositeClip); + + /* Either the drawable has changed, or the clip list in the drawable has + * changed. Copy the new clip list over and set the new translated + * offset for it. + */ + + (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, + (pointer) pCompositeClip, 0); + + vals[0] = x_off - pDrawable->x; + vals[1] = y_off - pDrawable->y; + dixChangeGC(NullClient, pBackingGC, + (GCClipXOrigin | GCClipYOrigin), vals, NULL); + + pPriv->serialNumber = pDrawable->serialNumber; + /* + * Mask off any client clip changes to make sure + * the clip list set above remains in effect + */ + pPriv->stateChanges &= ~(GCClipXOrigin|GCClipYOrigin|GCClipMask); + } + + if (pPriv->stateChanges) { + CopyGC(pGC, pBackingGC, pPriv->stateChanges); + pPriv->stateChanges = 0; + } + + if ((pGC->patOrg.x + x_off) != pBackingGC->patOrg.x || + (pGC->patOrg.y + y_off) != pBackingGC->patOrg.y) + { + XID vals[2]; + vals[0] = pGC->patOrg.x + x_off; + vals[1] = pGC->patOrg.y + y_off; + dixChangeGC(NullClient, pBackingGC, + (GCTileStipXOrigin | GCTileStipYOrigin), vals, NULL); + } + + ValidateGC(pBackingDrawable, pBackingGC); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwChangeGC(GCPtr pGC, unsigned long mask) +{ + cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->ChangeGC) (pGC, mask); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + cwGCPtr pPriv = (cwGCPtr)(pGCDst)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pGCDst, pPriv); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + FUNC_EPILOGUE(pGCDst, pPriv); +} + +static void +cwDestroyGC(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pGC, pPriv); + + cwDestroyBackingGC(pGC); + + (*pGC->funcs->DestroyGC) (pGC); + + /* leave it unwrapped */ +} + +static void +cwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) +{ + cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + cwGCPtr pPriv = (cwGCPtr)(pgcDst)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pgcDst, pPriv); + + (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + + FUNC_EPILOGUE(pgcDst, pPriv); +} + +static void +cwDestroyClip(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr; + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->DestroyClip)(pGC); + + FUNC_EPILOGUE(pGC, pPriv); +} + +/* + * Screen wrappers. + */ + +#define SCREEN_PROLOGUE(pScreen, field) \ + ((pScreen)->field = getCwScreen(pScreen)->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper) do { \ + getCwScreen(pScreen)->field = (pScreen)->field; \ + (pScreen)->field = (wrapper); \ +} while (0) + +static Bool +cwCreateGC(GCPtr pGC) +{ + cwGCPtr pPriv = getCwGC(pGC); + ScreenPtr pScreen = pGC->pScreen; + Bool ret; + + bzero(pPriv, sizeof(cwGCRec)); + SCREEN_PROLOGUE(pScreen, CreateGC); + + if ( (ret = (*pScreen->CreateGC)(pGC)) ) + FUNC_EPILOGUE(pGC, pPriv); + + SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); + + return ret; +} + +static void +cwGetImage(DrawablePtr pSrc, int x, int y, int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine) +{ + ScreenPtr pScreen = pSrc->pScreen; + DrawablePtr pBackingDrawable; + int src_off_x, src_off_y; + + SCREEN_PROLOGUE(pScreen, GetImage); + + pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y); + + CW_OFFSET_XY_SRC(x, y); + + (*pScreen->GetImage)(pBackingDrawable, x, y, w, h, format, planemask, + pdstLine); + + SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); +} + +static void +cwGetSpans(DrawablePtr pSrc, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pSrc->pScreen; + DrawablePtr pBackingDrawable; + int i; + int src_off_x, src_off_y; + + SCREEN_PROLOGUE(pScreen, GetSpans); + + pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y); + + for (i = 0; i < nspans; i++) + CW_OFFSET_XY_SRC(ppt[i].x, ppt[i].y); + + (*pScreen->GetSpans)(pBackingDrawable, wMax, ppt, pwidth, nspans, + pdstStart); + + SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); +} + +static void +cwFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, unsigned long pixel) +{ + ScreenPtr pScreen = pDrawable->pScreen; + GCPtr pGC; + BoxPtr pBox; + int nbox, i; + ChangeGCVal v[3]; + + pGC = GetScratchGC(pDrawable->depth, pScreen); + v[0].val = GXcopy; + v[1].val = pixel; + v[2].val = FillSolid; + dixChangeGC(NullClient, pGC, (GCFunction | GCForeground | GCFillStyle), + NULL, v); + ValidateGC(pDrawable, pGC); + + pBox = REGION_RECTS(pRegion); + nbox = REGION_NUM_RECTS(pRegion); + + for (i = 0; i < nbox; i++, pBox++) { + xRectangle rect; + rect.x = pBox->x1; + rect.y = pBox->y1; + rect.width = pBox->x2 - pBox->x1; + rect.height = pBox->y2 - pBox->y1; + (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &rect); + } + + FreeScratchGC(pGC); +} + +static void +cwFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, + int x_off, int y_off) +{ + ScreenPtr pScreen = pDrawable->pScreen; + GCPtr pGC; + BoxPtr pBox; + int nbox, i; + ChangeGCVal v[5]; + + pGC = GetScratchGC(pDrawable->depth, pScreen); + v[0].val = GXcopy; + v[1].val = FillTiled; + v[2].ptr = (pointer) pTile; + v[3].val = x_off; + v[4].val = y_off; + dixChangeGC(NullClient, pGC, (GCFunction | GCFillStyle | GCTile | + GCTileStipXOrigin | GCTileStipYOrigin), NULL, v); + + ValidateGC(pDrawable, pGC); + + pBox = REGION_RECTS(pRegion); + nbox = REGION_NUM_RECTS(pRegion); + + for (i = 0; i < nbox; i++, pBox++) { + xRectangle rect; + rect.x = pBox->x1; + rect.y = pBox->y1; + rect.width = pBox->x2 - pBox->x1; + rect.height = pBox->y2 - pBox->y1; + (*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &rect); + } + + FreeScratchGC(pGC); +} + +static void +cwPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, PaintWindowBackground); + + if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) { + (*pScreen->PaintWindowBackground)(pWin, pRegion, what); + } else { + DrawablePtr pBackingDrawable; + int x_off, y_off, x_screen, y_screen; + + while (pWin && pWin->backgroundState == ParentRelative) + pWin = pWin->parent; + + pBackingDrawable = cwGetBackingDrawable((DrawablePtr)pWin, &x_off, + &y_off); + + x_screen = x_off - pWin->drawable.x; + y_screen = y_off - pWin->drawable.y; + + if (pWin && (pWin->backgroundState == BackgroundPixel || + pWin->backgroundState == BackgroundPixmap)) + { + REGION_TRANSLATE(pScreen, pRegion, x_screen, y_screen); + + if (pWin->backgroundState == BackgroundPixel) { + cwFillRegionSolid(pBackingDrawable, pRegion, + pWin->background.pixel); + } else { + cwFillRegionTiled(pBackingDrawable, pRegion, + pWin->background.pixmap, x_off, y_off); + } + + REGION_TRANSLATE(pScreen, pRegion, -x_screen, -y_screen); + } + } + + SCREEN_EPILOGUE(pScreen, PaintWindowBackground, cwPaintWindowBackground); +} + +static void +cwPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, PaintWindowBorder); + + if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) { + (*pScreen->PaintWindowBorder)(pWin, pRegion, what); + } else { + DrawablePtr pBackingDrawable; + int x_off, y_off, x_screen, y_screen; + + pBackingDrawable = cwGetBackingDrawable((DrawablePtr)pWin, &x_off, + &y_off); + + x_screen = x_off - pWin->drawable.x; + y_screen = y_off - pWin->drawable.y; + + REGION_TRANSLATE(pScreen, pRegion, x_screen, y_screen); + + if (pWin->borderIsPixel) { + cwFillRegionSolid(pBackingDrawable, pRegion, pWin->border.pixel); + } else { + cwFillRegionTiled(pBackingDrawable, pRegion, pWin->border.pixmap, + x_off, y_off); + } + + REGION_TRANSLATE(pScreen, pRegion, -x_screen, -y_screen); + } + + SCREEN_EPILOGUE(pScreen, PaintWindowBorder, cwPaintWindowBorder); +} + +static void +cwCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, CopyWindow); + + if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) { + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + } else { + GCPtr pGC; + BoxPtr pExtents; + int x_off, y_off; + int dx, dy; + PixmapPtr pBackingPixmap; + RegionPtr pClip; + int src_x, src_y, dst_x, dst_y, w, h; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + pExtents = REGION_EXTENTS(pScreen, prgnSrc); + + pBackingPixmap = (PixmapPtr) cwGetBackingDrawable((DrawablePtr)pWin, + &x_off, &y_off); + + src_x = pExtents->x1 - pBackingPixmap->screen_x; + src_y = pExtents->y1 - pBackingPixmap->screen_y; + w = pExtents->x2 - pExtents->x1; + h = pExtents->y2 - pExtents->y1; + dst_x = src_x - dx; + dst_y = src_y - dy; + + /* Translate region (as required by API) */ + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + + pGC = GetScratchGC(pBackingPixmap->drawable.depth, pScreen); + /* + * Copy region to GC as clip, aligning as dest clip + */ + pClip = REGION_CREATE (pScreen, NULL, 0); + REGION_INTERSECT(pScreen, pClip, &pWin->borderClip, prgnSrc); + REGION_TRANSLATE(pScreen, pClip, + -pBackingPixmap->screen_x, + -pBackingPixmap->screen_y); + + (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); + + ValidateGC(&pBackingPixmap->drawable, pGC); + + (*pGC->ops->CopyArea) (&pBackingPixmap->drawable, + &pBackingPixmap->drawable, pGC, + src_x, src_y, w, h, dst_x, dst_y); + + (*pGC->funcs->DestroyClip) (pGC); + + FreeScratchGC(pGC); + } + + SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); +} + +static PixmapPtr +cwGetWindowPixmap (WindowPtr pWin) +{ + PixmapPtr pPixmap = getCwPixmap (pWin); + + if (!pPixmap) + { + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_PROLOGUE(pScreen, GetWindowPixmap); + if (pScreen->GetWindowPixmap) + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); + } + return pPixmap; +} + +static void +cwSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + + if (pPixmap == (*pScreen->GetScreenPixmap) (pScreen)) + pPixmap = NULL; + setCwPixmap (pWindow, pPixmap); +} + +/* Screen initialization/teardown */ +void +miInitializeCompositeWrapper(ScreenPtr pScreen) +{ + cwScreenPtr pScreenPriv; + + if (cwGeneration != serverGeneration) + { + cwScreenIndex = AllocateScreenPrivateIndex(); + if (cwScreenIndex < 0) + return; + cwGCIndex = AllocateGCPrivateIndex(); + cwWindowIndex = AllocateWindowPrivateIndex(); +#ifdef RENDER + cwPictureIndex = AllocatePicturePrivateIndex(); +#endif + cwGeneration = serverGeneration; + } + if (!AllocateGCPrivate(pScreen, cwGCIndex, sizeof(cwGCRec))) + return; + if (!AllocateWindowPrivate(pScreen, cwWindowIndex, 0)) + return; +#ifdef RENDER + if (!AllocatePicturePrivate(pScreen, cwPictureIndex, 0)) + return; +#endif + pScreenPriv = (cwScreenPtr)xalloc(sizeof(cwScreenRec)); + if (!pScreenPriv) + return; + + pScreen->devPrivates[cwScreenIndex].ptr = (pointer)pScreenPriv; + + SCREEN_EPILOGUE(pScreen, CloseScreen, cwCloseScreen); + SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); + SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); + SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); + SCREEN_EPILOGUE(pScreen, PaintWindowBackground, cwPaintWindowBackground); + SCREEN_EPILOGUE(pScreen, PaintWindowBorder, cwPaintWindowBorder); + SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); + + SCREEN_EPILOGUE(pScreen, SetWindowPixmap, cwSetWindowPixmap); + SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); + +#ifdef RENDER + if (GetPictureScreen (pScreen)) + cwInitializeRender(pScreen); +#endif +} + +static Bool +cwCloseScreen (int i, ScreenPtr pScreen) +{ + cwScreenPtr pScreenPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + pScreenPriv = (cwScreenPtr)pScreen->devPrivates[cwScreenIndex].ptr; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground; + pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + +#ifdef RENDER + if (ps) + cwFiniRender(pScreen); +#endif + + xfree((pointer)pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} diff --git a/miext/cw/cw.h b/miext/cw/cw.h new file mode 100644 index 000000000..2e26e097e --- /dev/null +++ b/miext/cw/cw.h @@ -0,0 +1,164 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT 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. + */ +/* $Header$ */ + +#include "picturestr.h" + +/* + * One of these structures is allocated per GC that gets used with a window with + * backing pixmap. + */ + +typedef struct { + GCPtr pBackingGC; /* Copy of the GC but with graphicsExposures + * set FALSE and the clientClip set to + * clip output to the valid regions of the + * backing pixmap. */ + unsigned long serialNumber; /* clientClip computed time */ + unsigned long stateChanges; /* changes in parent gc since last copy */ + GCOps *wrapOps; /* wrapped ops */ + GCFuncs *wrapFuncs; /* wrapped funcs */ +} cwGCRec, *cwGCPtr; + +extern int cwGCIndex; + +#define getCwGC(pGC) ((cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr) +#define setCwGC(pGC,p) ((pGC)->devPrivates[cwGCIndex].ptr = (pointer) (p)) + +/* + * One of these structures is allocated per Picture that gets used with a + * window with a backing pixmap + */ + +typedef struct { + PicturePtr pBackingPicture; + unsigned long serialNumber; + unsigned long stateChanges; +} cwPictureRec, *cwPicturePtr; + +#define getCwPicture(pPicture) ((cwPicturePtr)(pPicture)->devPrivates[cwPictureIndex].ptr) +#define setCwPicture(pPicture,p) ((pPicture)->devPrivates[cwPictureIndex].ptr = (pointer) (p)) + +extern int cwPictureIndex; + +extern int cwWindowIndex; + +#define cwWindowPrivate(pWindow) ((pWindow)->devPrivates[cwWindowIndex].ptr) +#define getCwPixmap(pWindow) ((PixmapPtr) cwWindowPrivate(pWindow)) +#define setCwPixmap(pWindow,pPixmap) (cwWindowPrivate(pWindow) = (pointer) (pPixmap)) + +#define cwDrawableIsRedirWindow(pDraw) \ + ((pDraw)->type == DRAWABLE_WINDOW && \ + getCwPixmap((WindowPtr) (pDraw)) != NULL) + +typedef struct { + /* + * screen func wrappers + */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CreateGCProcPtr CreateGC; + + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + + GetWindowPixmapProcPtr GetWindowPixmap; + SetWindowPixmapProcPtr SetWindowPixmap; + +#ifdef RENDER + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + CompositeRectsProcPtr CompositeRects; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + TriStripProcPtr TriStrip; + TriFanProcPtr TriFan; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +#endif +} cwScreenRec, *cwScreenPtr; + +extern int cwScreenIndex; + +#define getCwScreen(pScreen) ((cwScreenPtr)(pScreen)->devPrivates[cwScreenIndex].ptr) +#define setCwScreen(pScreen,p) ((cwScreenPtr)(pScreen)->devPrivates[cwScreenIndex].ptr = (p)) + +#define CW_OFFSET_XYPOINTS(ppt, npt) do { \ + DDXPointPtr _ppt = (DDXPointPtr)(ppt); \ + int _i; \ + for (_i = 0; _i < npt; _i++) { \ + _ppt[_i].x += dst_off_x; \ + _ppt[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_RECTS(prect, nrect) do { \ + int _i; \ + for (_i = 0; _i < nrect; _i++) { \ + (prect)[_i].x += dst_off_x; \ + (prect)[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_ARCS(parc, narc) do { \ + int _i; \ + for (_i = 0; _i < narc; _i++) { \ + (parc)[_i].x += dst_off_x; \ + (parc)[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_XY_DST(x, y) do { \ + (x) = (x) + dst_off_x; \ + (y) = (y) + dst_off_y; \ +} while (0) + +#define CW_OFFSET_XY_SRC(x, y) do { \ + (x) = (x) + src_off_x; \ + (y) = (y) + src_off_y; \ +} while (0) + +/* cw.c */ +DrawablePtr +cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off); + +/* cw_render.c */ + +void +cwInitializeRender (ScreenPtr pScreen); + +void +cwFiniRender (ScreenPtr pScreen); + +/* cw.c */ +void +miInitializeCompositeWrapper(ScreenPtr pScreen); diff --git a/miext/cw/cw_ops.c b/miext/cw/cw_ops.c new file mode 100644 index 000000000..f4d6e3478 --- /dev/null +++ b/miext/cw/cw_ops.c @@ -0,0 +1,466 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT 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. + */ +/* $Header$ */ + +#include "gcstruct.h" +#include "cw.h" + +#define SETUP_BACKING_DST(_pDst, _pGC) \ + cwGCPtr pGCPrivate = getCwGC (_pGC); \ + int dst_off_x, dst_off_y; \ + DrawablePtr pBackingDst = cwGetBackingDrawable(pDst, &dst_off_x, \ + &dst_off_y); \ + GCPtr pBackingGC = pGCPrivate->pBackingGC ? pGCPrivate->pBackingGC : _pGC + +#define SETUP_BACKING_SRC(pSrc, pGC) \ + int src_off_x, src_off_y; \ + DrawablePtr pBackingSrc = cwGetBackingDrawable(pSrc, &src_off_x, \ + &src_off_y) + +#define PROLOGUE(pGC) do { \ + pGC->funcs = pGCPrivate->wrapFuncs;\ + pGC->ops = pGCPrivate->wrapOps;\ +} while (0) + +#define EPILOGUE(pGC) do { \ + pGCPrivate->wrapFuncs = (pGC)->funcs; \ + pGCPrivate->wrapOps = (pGC)->ops; \ + (pGC)->funcs = &cwGCFuncs; \ + (pGC)->ops = &cwGCOps; \ +} while (0) + +extern GCFuncs cwGCFuncs; + +/* + * GC ops -- wrap each GC operation with our own function + */ + +static void cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int fSorted); +static void cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); +static void cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pBits); +static RegionPtr cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty); +static RegionPtr cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long plane); +static void cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt, + xPoint *pptInit); +static void cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt, + DDXPointPtr pptInit); +static void cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg, + xSegment *pSegs); +static void cwPolyRectangle(DrawablePtr pDst, GCPtr pGC, + int nrects, xRectangle *pRects); +static void cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *parcs); +static void cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode, + int count, DDXPointPtr pPts); +static void cwPolyFillRect(DrawablePtr pDst, GCPtr pGC, + int nrectFill, xRectangle *prectInit); +static void cwPolyFillArc(DrawablePtr pDst, GCPtr pGC, + int narcs, xArc *parcs); +static int cwPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars); +static int cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, char *chars); +static void cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); +static void cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, + unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); +static void cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, + int w, int h, int x, int y); + +GCOps cwGCOps = { + cwFillSpans, + cwSetSpans, + cwPutImage, + cwCopyArea, + cwCopyPlane, + cwPolyPoint, + cwPolylines, + cwPolySegment, + cwPolyRectangle, + cwPolyArc, + cwFillPolygon, + cwPolyFillRect, + cwPolyFillArc, + cwPolyText8, + cwPolyText16, + cwImageText8, + cwImageText16, + cwImageGlyphBlt, + cwPolyGlyphBlt, + cwPushPixels +}; + +static void +cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nspans, DDXPointPtr ppt, + int *pwidth, int fSorted) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(ppt, nspans); + + (*pBackingGC->ops->FillSpans)(pBackingDst, pBackingGC, nspans, ppt, + pwidth, fSorted); + + EPILOGUE(pGC); +} + +static void +cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc, DDXPointPtr ppt, + int *pwidth, int nspans, int fSorted) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(ppt, nspans); + + (*pBackingGC->ops->SetSpans)(pBackingDst, pBackingGC, psrc, ppt, pwidth, + nspans, fSorted); + + EPILOGUE(pGC); +} + +static void +cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PutImage)(pBackingDst, pBackingGC, depth, x, y, w, h, + leftPad, format, pBits); + + EPILOGUE(pGC); +} + +static RegionPtr +cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty) +{ + int odstx, odsty; + RegionPtr exposed = NULL; + SETUP_BACKING_DST(pDst, pGC); + SETUP_BACKING_SRC(pSrc, pGC); + + PROLOGUE(pGC); + + odstx = dstx; + odsty = dsty; + CW_OFFSET_XY_DST(dstx, dsty); + CW_OFFSET_XY_SRC(srcx, srcy); + + exposed = (*pBackingGC->ops->CopyArea)(pBackingSrc, pBackingDst, + pBackingGC, srcx, srcy, w, h, + dstx, dsty); + + if (exposed != NULL) + REGION_TRANSLATE(pDst->pScreen, exposed, odstx - dstx, odsty - dsty); + + EPILOGUE(pGC); + + return exposed; +} + +static RegionPtr +cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, unsigned long plane) +{ + int odstx, odsty; + RegionPtr exposed = NULL; + SETUP_BACKING_DST(pDst, pGC); + SETUP_BACKING_SRC(pSrc, pGC); + + PROLOGUE(pGC); + + odstx = dstx; + odsty = dsty; + CW_OFFSET_XY_DST(dstx, dsty); + CW_OFFSET_XY_SRC(srcx, srcy); + + exposed = (*pBackingGC->ops->CopyPlane)(pBackingSrc, pBackingDst, + pBackingGC, srcx, srcy, w, h, + dstx, dsty, plane); + + if (exposed != NULL) + REGION_TRANSLATE(pDst->pScreen, exposed, odstx - dstx, odsty - dsty); + + EPILOGUE(pGC); + + return exposed; +} + +static void +cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt, xPoint *ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->PolyPoint)(pBackingDst, pBackingGC, mode, npt, ppt); + + EPILOGUE(pGC); +} + +static void +cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->Polylines)(pBackingDst, pBackingGC, mode, npt, ppt); + + EPILOGUE(pGC); +} + +static void +cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg, xSegment *pSegs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(pSegs, nseg * 2); + + (*pBackingGC->ops->PolySegment)(pBackingDst, pBackingGC, nseg, pSegs); + + EPILOGUE(pGC); +} + +static void +cwPolyRectangle(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pRects, nrects); + + (*pBackingGC->ops->PolyRectangle)(pBackingDst, pBackingGC, nrects, pRects); + + EPILOGUE(pGC); +} + +static void +cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *pArcs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pArcs, narcs); + + (*pBackingGC->ops->PolyArc)(pBackingDst, pBackingGC, narcs, pArcs); + + EPILOGUE(pGC); +} + +static void +cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode, int npt, + DDXPointPtr ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->FillPolygon)(pBackingDst, pBackingGC, shape, mode, npt, + ppt); + + EPILOGUE(pGC); +} + +static void +cwPolyFillRect(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pRects, nrects); + + (*pBackingGC->ops->PolyFillRect)(pBackingDst, pBackingGC, nrects, pRects); + + EPILOGUE(pGC); +} + +static void +cwPolyFillArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *parcs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(parcs, narcs); + + (*pBackingGC->ops->PolyFillArc)(pBackingDst, pBackingGC, narcs, parcs); + + EPILOGUE(pGC); +} + +static int +cwPolyText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars) +{ + int result; + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + result = (*pBackingGC->ops->PolyText8)(pBackingDst, pBackingGC, x, y, + count, chars); + + EPILOGUE(pGC); + + return result; +} + +static int +cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + int result; + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + result = (*pBackingGC->ops->PolyText16)(pBackingDst, pBackingGC, x, y, + count, chars); + + EPILOGUE(pGC); + return result; +} + +static void +cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageText8)(pBackingDst, pBackingGC, x, y, count, + chars); + + EPILOGUE(pGC); +} + +static void +cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageText16)(pBackingDst, pBackingGC, x, y, count, + chars); + + EPILOGUE(pGC); +} + +static void +cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageGlyphBlt)(pBackingDst, pBackingGC, x, y, nglyph, + ppci, pglyphBase); + + EPILOGUE(pGC); +} + +static void +cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PolyGlyphBlt)(pBackingDst, pBackingGC, x, y, nglyph, + ppci, pglyphBase); + + EPILOGUE(pGC); +} + +static void +cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h, + int x, int y) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PushPixels)(pBackingGC, pBitMap, pBackingDst, w, h, + x, y); + + EPILOGUE(pGC); +} + diff --git a/miext/cw/cw_render.c b/miext/cw/cw_render.c new file mode 100644 index 000000000..f7e361496 --- /dev/null +++ b/miext/cw/cw_render.c @@ -0,0 +1,497 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT 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. + */ +/* $Header$ */ + +#include "gcstruct.h" +#include "windowstr.h" +#include "cw.h" + +#ifdef RENDER + +#define cwPsDecl(pScreen) \ + PictureScreenPtr ps = GetPictureScreen (pScreen); \ + cwScreenPtr pCwScreen = getCwScreen (pScreen) + +#define cwPicturePrivate \ + cwPicturePtr pPicturePrivate = getCwPicture(pPicture) + +#define cwSrcPictureDecl \ + int src_picture_x_off, src_picture_y_off; \ + PicturePtr pBackingSrcPicture = cwGetBackingPicture(pSrcPicture, \ + &src_picture_x_off,\ + &src_picture_y_off) + +#define cwDstPictureDecl \ + int dst_picture_x_off, dst_picture_y_off; \ + PicturePtr pBackingDstPicture = cwGetBackingPicture(pDstPicture, \ + &dst_picture_x_off,\ + &dst_picture_y_off) + +#define cwMskPictureDecl \ + int msk_picture_x_off = 0, msk_picture_y_off = 0; \ + PicturePtr pBackingMskPicture = (!pMskPicture ? 0 : \ + cwGetBackingPicture(pMskPicture, \ + &msk_picture_x_off,\ + &msk_picture_y_off)) + +#define cwPsUnwrap(elt) { \ + ps->elt = pCwScreen->elt; \ +} + +#define cwPsWrap(elt,func) { \ + pCwScreen->elt = ps->elt; \ + ps->elt = func; \ +} + +static cwPicturePtr +cwCreatePicturePrivate (PicturePtr pPicture) +{ + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PixmapPtr pPixmap = getCwPixmap (pWindow); + int error; + cwPicturePtr pPicturePrivate; + + pPicturePrivate = xalloc (sizeof (cwPictureRec)); + if (!pPicturePrivate) + return NULL; + + pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable, + pPicture->pFormat, + 0, 0, serverClient, + &error); + if (!pPicturePrivate->pBackingPicture) + { + xfree (pPicturePrivate); + return NULL; + } + + /* + * Ensure that this serial number does not match the window's + */ + pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber; + pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1; + + setCwPicture(pPicture, pPicturePrivate); + + return pPicturePrivate; +} + +static void +cwDestroyPicturePrivate (PicturePtr pPicture) +{ + cwPicturePrivate; + + if (pPicturePrivate) + { + if (pPicturePrivate->pBackingPicture) + FreePicture (pPicturePrivate->pBackingPicture, 0); + xfree (pPicturePrivate); + setCwPicture(pPicture, NULL); + } +} + +static PicturePtr +cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off) +{ + cwPicturePrivate; + + if (pPicturePrivate) + { + DrawablePtr pDrawable = pPicture->pDrawable; + WindowPtr pWindow = (WindowPtr) pDrawable; + PixmapPtr pPixmap = getCwPixmap (pWindow); + + *x_off = pDrawable->x - pPixmap->screen_x; + *y_off = pDrawable->y - pPixmap->screen_y; + + return pPicturePrivate->pBackingPicture; + } + else + { + *x_off = *y_off = 0; + return pPicture; + } +} + +static void +cwDestroyPicture (PicturePtr pPicture) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + + cwPsUnwrap(DestroyPicture); + cwDestroyPicturePrivate (pPicture); + (*ps->DestroyPicture) (pPicture); + cwPsWrap(DestroyPicture, cwDestroyPicture); +} + +static void +cwChangePicture (PicturePtr pPicture, Mask mask) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwPicturePtr pPicturePrivate = getCwPicture(pPicture); + + cwPsUnwrap(ChangePicture); + (*ps->ChangePicture) (pPicture, mask); + if (pPicturePrivate) + pPicturePrivate->stateChanges |= mask; + cwPsWrap(ChangePicture, cwChangePicture); +} + + +static void +cwValidatePicture (PicturePtr pPicture, + Mask mask) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + ScreenPtr pScreen = pDrawable->pScreen; + cwPsDecl(pScreen); + cwPicturePrivate; + + cwPsUnwrap(ValidatePicture); + + /* + * Must call ValidatePicture to ensure pPicture->pCompositeClip is valid + */ + (*ps->ValidatePicture) (pPicture, mask); + + if (!cwDrawableIsRedirWindow (pDrawable)) + { + if (pPicturePrivate) + cwDestroyPicturePrivate (pPicture); + } + else + { + PicturePtr pBackingPicture; + DrawablePtr pBackingDrawable; + int x_off, y_off; + + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + + if (pPicturePrivate && + pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable) + { + cwDestroyPicturePrivate (pPicture); + pPicturePrivate = 0; + } + + if (!pPicturePrivate) + { + pPicturePrivate = cwCreatePicturePrivate (pPicture); + if (!pPicturePrivate) + { + cwPsWrap(ValidatePicture, cwValidatePicture); + return; + } + } + + pBackingPicture = pPicturePrivate->pBackingPicture; + + /* + * Always copy transform and filters because there's no + * indication of when they've changed + */ + SetPictureTransform(pBackingPicture, pPicture->transform); + + if (pBackingPicture->filter != pPicture->filter || + pPicture->filter_nparams > 0) + { + char *filter = PictureGetFilterName (pPicture->filter); + + SetPictureFilter(pBackingPicture, + filter, strlen (filter), + pPicture->filter_params, + pPicture->filter_nparams); + } + + pPicturePrivate->stateChanges |= mask; + + if (pPicturePrivate->serialNumber != pDrawable->serialNumber || + (pPicturePrivate->stateChanges & (CPClipXOrigin|CPClipYOrigin|CPClipMask))) + { + SetPictureClipRegion (pBackingPicture, + x_off - pDrawable->x, + y_off - pDrawable->y, + pPicture->pCompositeClip); + + pPicturePrivate->serialNumber = pDrawable->serialNumber; + pPicturePrivate->stateChanges &= ~(CPClipXOrigin | CPClipYOrigin | CPClipMask); + } + + CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture); + + ValidatePicture (pBackingPicture); + } + cwPsWrap(ValidatePicture, cwValidatePicture); +} + +static void +cwComposite (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pMskPicture, + PicturePtr pDstPicture, + INT16 xSrc, + INT16 ySrc, + INT16 xMsk, + INT16 yMsk, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwMskPictureDecl; + cwDstPictureDecl; + + cwPsUnwrap(Composite); + (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + xMsk + msk_picture_x_off, yMsk + msk_picture_y_off, + xDst + dst_picture_x_off, yDst + dst_picture_y_off, + width, height); + cwPsWrap(Composite, cwComposite); +} + +static void +cwGlyphs (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlists, + GlyphListPtr lists, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + + cwPsUnwrap(Glyphs); + if (nlists) + { + lists->xOff += dst_picture_x_off; + lists->yOff += dst_picture_y_off; + } + (*ps->Glyphs) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + nlists, lists, glyphs); + cwPsWrap(Glyphs, cwGlyphs); +} + +static void +cwCompositeRects (CARD8 op, + PicturePtr pDstPicture, + xRenderColor *color, + int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwDstPictureDecl; + int i; + + cwPsUnwrap(CompositeRects); + for (i = 0; i < nRect; i++) + { + rects[i].x += dst_picture_x_off; + rects[i].y += dst_picture_y_off; + } + (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects); + cwPsWrap(CompositeRects, cwCompositeRects); +} + +static void +cwTrapezoids (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntrap, + xTrapezoid *traps) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(Trapezoids); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < ntrap; i++) + { + traps[i].top += dst_picture_y_off << 16; + traps[i].bottom += dst_picture_y_off << 16; + traps[i].left.p1.x += dst_picture_x_off << 16; + traps[i].left.p1.y += dst_picture_y_off << 16; + traps[i].left.p2.x += dst_picture_x_off << 16; + traps[i].left.p2.y += dst_picture_y_off << 16; + traps[i].right.p1.x += dst_picture_x_off << 16; + traps[i].right.p1.y += dst_picture_y_off << 16; + traps[i].right.p2.x += dst_picture_x_off << 16; + traps[i].right.p2.y += dst_picture_y_off << 16; + } + } + (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + ntrap, traps); + cwPsWrap(Trapezoids, cwTrapezoids); +} + +static void +cwTriangles (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int ntri, + xTriangle *tris) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(Triangles); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < ntri; i++) + { + tris[i].p1.x += dst_picture_x_off << 16; + tris[i].p1.y += dst_picture_y_off << 16; + tris[i].p2.x += dst_picture_x_off << 16; + tris[i].p2.y += dst_picture_y_off << 16; + tris[i].p3.x += dst_picture_x_off << 16; + tris[i].p3.y += dst_picture_y_off << 16; + } + } + (*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + ntri, tris); + cwPsWrap(Triangles, cwTriangles); +} + +static void +cwTriStrip (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(TriStrip); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < npoint; i++) + { + points[i].x += dst_picture_x_off << 16; + points[i].y += dst_picture_y_off << 16; + } + } + (*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + npoint, points); + cwPsWrap(TriStrip, cwTriStrip); +} + +static void +cwTriFan (CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int npoint, + xPointFixed *points) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(TriFan); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < npoint; i++) + { + points[i].x += dst_picture_x_off << 16; + points[i].y += dst_picture_y_off << 16; + } + } + (*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + npoint, points); + cwPsWrap(TriFan, cwTriFan); +} + +void +cwInitializeRender (ScreenPtr pScreen) +{ + cwPsDecl (pScreen); + + cwPsWrap(DestroyPicture, cwDestroyPicture); + cwPsWrap(ChangePicture, cwChangePicture); + cwPsWrap(ValidatePicture, cwValidatePicture); + cwPsWrap(Composite, cwComposite); + cwPsWrap(Glyphs, cwGlyphs); + cwPsWrap(CompositeRects, cwCompositeRects); + cwPsWrap(Trapezoids, cwTrapezoids); + cwPsWrap(Triangles, cwTriangles); + cwPsWrap(TriStrip, cwTriStrip); + cwPsWrap(TriFan, cwTriFan); + /* There is no need to wrap AddTraps as far as we can tell. AddTraps can + * only be done on alpha-only pictures, and we won't be getting + * alpha-only window pictures, so there's no need to translate. + */ +} + +void +cwFiniRender (ScreenPtr pScreen) +{ + cwPsDecl (pScreen); + + cwPsUnwrap(DestroyPicture); + cwPsUnwrap(ChangePicture); + cwPsUnwrap(ValidatePicture); + cwPsUnwrap(Composite); + cwPsUnwrap(Glyphs); + cwPsUnwrap(CompositeRects); + cwPsUnwrap(Trapezoids); + cwPsUnwrap(Triangles); + cwPsUnwrap(TriStrip); + cwPsUnwrap(TriFan); +} + +#endif /* RENDER */ diff --git a/miext/damage/damage.c b/miext/damage/damage.c new file mode 100755 index 000000000..963780f70 --- /dev/null +++ b/miext/damage/damage.c @@ -0,0 +1,1933 @@ +/* + * $Id$ + * + * Copyright © 2003 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <X11/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 "damage.h" +#include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define wrap(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define BOX_SAME(a,b) \ + ((a)->x1 == (b)->x1 && \ + (a)->y1 == (b)->y1 && \ + (a)->x2 == (b)->x2 && \ + (a)->y2 == (b)->y2) + +#define DAMAGE_VALIDATE_ENABLE 0 +#define DAMAGE_DEBUG_ENABLE 0 +#if DAMAGE_DEBUG_ENABLE +#define DAMAGE_DEBUG(x) ErrorF x +#else +#define DAMAGE_DEBUG(x) +#endif + +#define getPixmapDamageRef(pPixmap) \ + ((DamagePtr *) &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static DamagePtr * +getDrawableDamageRef (DrawablePtr pDrawable) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW) + { + ScreenPtr pScreen = pDrawable->pScreen; + + pPixmap = 0; + if (pScreen->GetWindowPixmap +#ifdef ROOTLESS_WORKAROUND + && ((WindowPtr)pDrawable)->viewable +#endif + ) + pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr)pDrawable); + + if (!pPixmap) + { + damageScrPriv(pScreen); + + return &pScrPriv->pScreenDamage; + } + } + else + pPixmap = (PixmapPtr) pDrawable; + return getPixmapDamageRef (pPixmap); +} + +#define getDrawableDamage(pDrawable) (*getDrawableDamageRef (pDrawable)) +#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable) + +#define drawableDamage(pDrawable) \ + DamagePtr pDamage = getDrawableDamage(pDrawable) + +#define windowDamage(pWin) drawableDamage(&(pWin)->drawable) + +#define winDamageRef(pWindow) \ + DamagePtr *pPrev = (DamagePtr *) \ + &(pWindow->devPrivates[damageWinPrivateIndex].ptr) + +#if DAMAGE_DEBUG_ENABLE +static void +_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, char *where) +#define damageDamageRegion(d,r,c) _damageDamageRegion(d,r,c,__FUNCTION__) +#else +static void +damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionPtr pClip; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + Bool was_empty; + RegionRec tmpRegion; + BoxRec tmpBox; + int draw_x, draw_y; +#ifdef COMPOSITE + int screen_x = 0, screen_y = 0; +#endif + + /* short circuit for empty regions */ + if (!REGION_NOTEMPTY(pScreen, pRegion)) + return; + +#ifdef COMPOSITE + /* + * When drawing to a pixmap which is storing window contents, + * the region presented is in pixmap relative coordinates which + * need to be converted to screen relative coordinates + */ + if (pDrawable->type != DRAWABLE_WINDOW) + { + screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; + screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; + } + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); +#endif + + REGION_NULL (pScreen, &clippedRec); + for (; pDamage; pDamage = pNext) + { + pNext = pDamage->pNext; + /* + * Check for internal damage and don't send events + */ + if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) + { + DAMAGE_DEBUG (("non internal damage, skipping at %d\n", + pScrPriv->internalLevel)); + continue; + } + /* + * Check for unrealized windows + */ + if (pDamage->pDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr) (pDamage->pDrawable))->realized) + { +#if 0 + DAMAGE_DEBUG (("damage while window unrealized\n")); +#endif + continue; + } + + draw_x = pDamage->pDrawable->x; + draw_y = pDamage->pDrawable->y; +#ifdef COMPOSITE + /* + * Need to move everyone to screen coordinates + * XXX what about off-screen pixmaps with non-zero x/y? + */ + if (pDamage->pDrawable->type != DRAWABLE_WINDOW) + { + draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x; + draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y; + } +#endif + + /* + * Clip against border or pixmap bounds + */ + + pDamageRegion = pRegion; + if (clip || pDamage->pDrawable != pDrawable) + { + pDamageRegion = &clippedRec; + if (pDamage->pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr)(pDamage->pDrawable))->borderClip; + else + { + BoxRec box; + box.x1 = draw_x; + box.y1 = draw_y; + box.x2 = draw_x + pDamage->pDrawable->width; + box.y2 = draw_y + pDamage->pDrawable->height; + REGION_INIT(pScreen, &pixClip, &box, 1); + pClip = &pixClip; + } + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, pClip); + /* + * Short circuit empty results + */ + if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) + continue; + } + + DAMAGE_DEBUG (("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n", + where, + pDamageRegion->extents.x2 - pDamageRegion->extents.x1, + pDamageRegion->extents.y2 - pDamageRegion->extents.y1, + pDamageRegion->extents.x1, pDamageRegion->extents.y1, + pDrawable->id, pDamage->pDrawable->id)); + + /* + * Move region to target coordinate space + */ + if (draw_x || draw_y) + REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) + { + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) + (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); + break; + case DamageReportNone: + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } + /* + * translate original region back + */ + if (pDamageRegion == pRegion && (draw_x || draw_y)) + REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); + } +#ifdef COMPOSITE + if (screen_x || screen_y) + REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y); +#endif + + REGION_UNINIT (pScreen, &clippedRec); +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b) _damageDamageBox(d,b,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox) +#endif +{ + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageDamageRegion (pDrawable, ®ion, TRUE, where); +#else + damageDamageRegion (pDrawable, ®ion, TRUE); +#endif + REGION_UNINIT (pDrawable->pScreen, ®ion); +} + +static void damageValidateGC(GCPtr, unsigned long, DrawablePtr); +static void damageChangeGC(GCPtr, unsigned long); +static void damageCopyGC(GCPtr, unsigned long, GCPtr); +static void damageDestroyGC(GCPtr); +static void damageChangeClip(GCPtr, int, pointer, int); +static void damageDestroyClip(GCPtr); +static void damageCopyClip(GCPtr, GCPtr); + +GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +extern GCOps damageGCOps; + +static Bool +damageCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + damageScrPriv(pScreen); + damageGCPriv(pGC); + Bool ret; + + pGC->pCompositeClip = 0; + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + + return ret; +} + +#ifdef NOTUSED +static void +damageWrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &damageGCFuncs; +} + +static void +damageUnwrapGC (GCPtr pGC) +{ + damageGCPriv(pGC); + + pGC->funcs = pGCPriv->funcs; + if (pGCPriv->ops) + pGC->ops = pGCPriv->ops; +} +#endif + +#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ + damageGCPriv(pGC); \ + GCFuncs *oldFuncs = pGC->funcs; \ + unwrap(pGCPriv, pGC, funcs); \ + unwrap(pGCPriv, pGC, ops); \ + +#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \ + wrap(pGCPriv, pGC, funcs, oldFuncs); \ + wrap(pGCPriv, pGC, ops, &damageGCOps) + +#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \ + damageGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops) + +#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &damageGCFuncs); \ + if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps) + +static void +damageValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageDestroyGC(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageChangeGC (GCPtr pGC, + unsigned long mask) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + DAMAGE_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +damageChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +static void +damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + DAMAGE_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + DAMAGE_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +damageDestroyClip(GCPtr pGC) +{ + DAMAGE_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + DAMAGE_GC_FUNC_EPILOGUE (pGC); +} + +#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ + 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, pDrawable) { \ + box.x1 += pDrawable->x; \ + box.x2 += pDrawable->x; \ + box.y1 += pDrawable->y; \ + box.y2 += pDrawable->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ + TRANSLATE_BOX(box, pDrawable); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + +#define checkGCDamage(d,g) (getDrawableDamage(d) && \ + (!g->pCompositeClip ||\ + REGION_NOTEMPTY(d->pScreen, \ + g->pCompositeClip))) + +#ifdef RENDER + +#define TRIM_PICTURE_BOX(box, pDst) { \ + BoxPtr extents = &pDst->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 checkPictureDamage(p) (getDrawableDamage(p->pDrawable) && \ + REGION_NOTEMPTY(pScreen, p->pCompositeClip)) + +static void +damageComposite (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); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + BoxRec box; + + box.x1 = xDst + pDst->pDrawable->x; + box.y1 = yDst + pDst->pDrawable->y; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + TRIM_PICTURE_BOX(box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + wrap (pScrPriv, ps, Composite, damageComposite); +} + +static void +damageGlyphs (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); + damageScrPriv(pScreen); + + if (checkPictureDamage (pDst)) + { + int nlistTmp = nlist; + GlyphListPtr listTmp = list; + GlyphPtr *glyphsTmp = glyphs; + int x, y; + int n; + GlyphPtr glyph; + BoxRec box; + int x1, y1, x2, y2; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pDst->pDrawable->x; + y = pDst->pDrawable->y; + while (nlistTmp--) + { + x += listTmp->xOff; + y += listTmp->yOff; + n = listTmp->len; + while (n--) + { + glyph = *glyphsTmp++; + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + if (x1 < box.x1) + box.x1 = x1; + if (y1 < box.y1) + box.y1 = y1; + if (x2 > box.x2) + box.x2 = x2; + if (y2 > box.y2) + box.y2 = y2; + x += glyph->info.xOff; + y += glyph->info.yOff; + } + listTmp++; + } + TRIM_PICTURE_BOX (box, pDst); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pDst->pDrawable, &box); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} +#endif + +/**********************************************************/ + + +static void +damageFillSpans(DrawablePtr pDrawable, + GC *pGC, + int npt, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageSetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr ppt, + int *pwidth, + int npt, + int fSorted) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int *pwidthTmp = pwidth; + int nptTmp = npt; + BoxRec box; + + box.x1 = pptTmp->x; + box.x2 = box.x1 + *pwidthTmp; + box.y2 = box.y1 = pptTmp->y; + + while(--nptTmp) + { + pptTmp++; + pwidthTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + if(box.x2 < (pptTmp->x + *pwidthTmp)) + box.x2 = pptTmp->x + *pwidthTmp; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDrawable); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePutImage(DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = x + pDrawable->x; + box.x2 = box.x1 + w; + box.y1 = y + pDrawable->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static RegionPtr +damageCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate) + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + + if (checkGCDamage (pDst, pGC)) + { + 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)) + damageDamageBox (pDst, &box); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static RegionPtr +damageCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane) +{ + RegionPtr ret; + DAMAGE_GC_OP_PROLOGUE(pGC, pDst); + + /* The driver will only call SourceValidate() when pSrc != pDst, + * but the software sprite (misprite.c) always need to know when a + * drawable is copied so it can remove the sprite. See #1030. */ + if ((pSrc == pDst) && pSrc->pScreen->SourceValidate) + (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height); + + if (checkGCDamage (pDst, pGC)) + { + 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)) + damageDamageBox (pDst, &box); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + DAMAGE_GC_OP_EPILOGUE(pGC, pDst); + return ret; +} + +static void +damagePolyPoint(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nptTmp = npt; + xPoint *pptTmp = ppt; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + /* this could be slow if the points were spread out */ + + while(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolylines(DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt && checkGCDamage (pDrawable, pGC)) + { + int nptTmp = npt; + DDXPointPtr pptTmp = ppt; + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(nptTmp > 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(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->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(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolySegment(DrawablePtr pDrawable, + GCPtr pGC, + int nSeg, + xSegment *pSeg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nSeg && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int extra = pGC->lineWidth; + int nsegTmp = nSeg; + xSegment *pSegTmp = pSeg; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSegTmp->x2 > pSegTmp->x1) { + box.x1 = pSegTmp->x1; + box.x2 = pSegTmp->x2; + } else { + box.x2 = pSegTmp->x1; + box.x1 = pSegTmp->x2; + } + + if(pSegTmp->y2 > pSegTmp->y1) { + box.y1 = pSegTmp->y1; + box.y2 = pSegTmp->y2; + } else { + box.y2 = pSegTmp->y1; + box.y1 = pSegTmp->y2; + } + + while(--nsegTmp) + { + pSegTmp++; + if(pSegTmp->x2 > pSegTmp->x1) + { + if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; + if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; + } + else + { + if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; + if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; + } + if(pSegTmp->y2 > pSegTmp->y1) + { + if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; + if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; + } + else + { + if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; + if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyRectangle(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int offset1, offset2, offset3; + int nRectsTmp = nRects; + xRectangle *pRectsTmp = pRects; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while(nRectsTmp--) + { + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + + box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; + box.y1 = pRectsTmp->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRectsTmp->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + + box.x1 = pRectsTmp->x - offset1; + box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; + box.x2 = box.x1 + pRectsTmp->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + int extra = pGC->lineWidth >> 1; + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + if(extra) + { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageFillPolygon(DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int npt, + DDXPointPtr ppt) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (npt > 2 && checkGCDamage (pDrawable, pGC)) + { + DDXPointPtr pptTmp = ppt; + int nptTmp = npt; + BoxRec box; + + box.x2 = box.x1 = pptTmp->x; + box.y2 = box.y1 = pptTmp->y; + + if(mode != CoordModeOrigin) + { + int x = box.x1; + int y = box.y1; + while(--nptTmp) + { + pptTmp++; + x += pptTmp->x; + y += pptTmp->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(--nptTmp) + { + pptTmp++; + if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; + else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; + if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; + else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nRects, + xRectangle *pRects) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if (nRects && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + xRectangle *pRectsTmp = pRects; + int nRectsTmp = nRects; + + box.x1 = pRectsTmp->x; + box.x2 = box.x1 + pRectsTmp->width; + box.y1 = pRectsTmp->y; + box.y2 = box.y1 + pRectsTmp->height; + + while(--nRectsTmp) + { + pRectsTmp++; + if(box.x1 > pRectsTmp->x) box.x1 = pRectsTmp->x; + if(box.x2 < (pRectsTmp->x + pRectsTmp->width)) + box.x2 = pRectsTmp->x + pRectsTmp->width; + if(box.y1 > pRectsTmp->y) box.y1 = pRectsTmp->y; + if(box.y2 < (pRectsTmp->y + pRectsTmp->height)) + box.y2 = pRectsTmp->y + pRectsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damagePolyFillArc(DrawablePtr pDrawable, + GCPtr pGC, + int nArcs, + xArc *pArcs) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (nArcs && checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + int nArcsTmp = nArcs; + xArc *pArcsTmp = pArcs; + + box.x1 = pArcsTmp->x; + box.x2 = box.x1 + pArcsTmp->width; + box.y1 = pArcsTmp->y; + box.y2 = box.y1 + pArcsTmp->height; + + while(--nArcsTmp) + { + pArcsTmp++; + if(box.x1 > pArcsTmp->x) + box.x1 = pArcsTmp->x; + if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) + box.x2 = pArcsTmp->x + pArcsTmp->width; + if(box.y1 > pArcsTmp->y) + box.y1 = pArcsTmp->y; + if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) + box.y2 = pArcsTmp->y + pArcsTmp->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +/* + * general Poly/Image text function. Extract glyph information, + * compute bounding box and remove cursor if it is overlapped. + */ + +static void +damageDamageChars (DrawablePtr pDrawable, + FontPtr font, + int x, + int y, + unsigned int n, + CharInfoPtr *charinfo, + Bool imageblt) +{ + ExtentInfoRec extents; + BoxRec box; + + QueryGlyphExtents(font, charinfo, n, &extents); + if (imageblt) + { + if (extents.overallWidth > extents.overallRight) + extents.overallRight = extents.overallWidth; + if (extents.overallWidth < extents.overallLeft) + extents.overallLeft = extents.overallWidth; + if (extents.overallLeft > 0) + extents.overallLeft = 0; + if (extents.fontAscent > extents.overallAscent) + extents.overallAscent = extents.fontAscent; + if (extents.fontDescent > extents.overallDescent) + extents.overallDescent = extents.fontDescent; + } + box.x1 = x + extents.overallLeft; + box.y1 = y - extents.overallAscent; + box.x2 = x + extents.overallRight; + box.y2 = y + extents.overallDescent; + damageDamageBox (pDrawable, &box); +} + +/* + * values for textType: + */ +#define TT_POLY8 0 +#define TT_IMAGE8 1 +#define TT_POLY16 2 +#define TT_IMAGE16 3 + +static int +damageText (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned long count, + char *chars, + FontEncoding fontEncoding, + Bool textType) +{ + CharInfoPtr *charinfo; + CharInfoPtr *info; + unsigned long i; + unsigned int n; + int w; + Bool imageblt; + + imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); + + charinfo = (CharInfoPtr *) ALLOCATE_LOCAL(count * sizeof(CharInfoPtr)); + if (!charinfo) + return x; + + GetGlyphs(pGC->font, count, (unsigned char *)chars, + fontEncoding, &i, charinfo); + n = (unsigned int)i; + w = 0; + if (!imageblt) + for (info = charinfo; i--; info++) + w += (*info)->metrics.characterWidth; + + if (n != 0) { + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, + charinfo, imageblt); + if (imageblt) + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + else + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo, + FONTGLYPHS(pGC->font)); + } + DEALLOCATE_LOCAL(charinfo); + return x + w; +} + +static int +damagePolyText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static int +damagePolyText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_POLY16); + else + x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); + return x; +} + +static void +damageImageText8(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + char *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_IMAGE8); + else + (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageImageText16(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + + if (checkGCDamage (pDrawable, pGC)) + damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, + FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, + TT_IMAGE16); + else + (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + + +static void +damageImageGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, TRUE); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePolyGlyphBlt(DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, + nglyph, ppci, FALSE); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damagePushPixels(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable); + if(checkGCDamage (pDrawable, pGC)) + { + BoxRec box; + + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDrawable->x; + box.y1 += pDrawable->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) + damageDamageBox (pDrawable, &box); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable); +} + +static void +damageRemoveDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNext; + return; + } + pPrev = &(*pPrev)->pNext; + } +#if DAMAGE_VALIDATE_ENABLE + ErrorF ("Damage not on list\n"); + abort (); +#endif +} + +static void +damageInsertDamage (DamagePtr *pPrev, DamagePtr pDamage) +{ +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNext) + if (pOld == pDamage) { + ErrorF ("Damage already on list\n"); + abort (); + } +#endif + pDamage->pNext = *pPrev; + *pPrev = pDamage; +} + +static Bool +damageDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + damageScrPriv(pScreen); + + if (pPixmap->refcnt == 1) + { + DamagePtr *pPrev = getPixmapDamageRef (pPixmap); + DamagePtr pDamage; + + while ((pDamage = *pPrev)) + { + damageRemoveDamage (pPrev, pDamage); + if (!pDamage->isWindow) + DamageDestroy (pDamage); + } + } + unwrap (pScrPriv, pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + return TRUE; +} + +static void +damagePaintWindow(WindowPtr pWindow, + RegionPtr prgn, + int what) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + /* + * Painting background none doesn't actually *do* anything, so + * no damage is recorded + */ + if ((what != PW_BACKGROUND || pWindow->backgroundState != None) && + getWindowDamage (pWindow)) + damageDamageRegion (&pWindow->drawable, prgn, FALSE); + if(what == PW_BACKGROUND) { + unwrap (pScrPriv, pScreen, PaintWindowBackground); + (*pScreen->PaintWindowBackground) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + } else { + unwrap (pScrPriv, pScreen, PaintWindowBorder); + (*pScreen->PaintWindowBorder) (pWindow, prgn, what); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + } +} + + +static void +damageCopyWindow(WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if (getWindowDamage (pWindow)) + { + int dx = pWindow->drawable.x - ptOldOrg.x; + int dy = pWindow->drawable.y - ptOldOrg.y; + + /* + * The region comes in source relative, but the damage occurs + * at the destination location. Translate back and forth. + */ + REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); + damageDamageRegion (&pWindow->drawable, prgnSrc, FALSE); + REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, +#ifdef NEED_LINEHELPER + NULL, +#endif + {NULL} /* devPrivate */ +}; + +static void +damageRestoreAreas (PixmapPtr pPixmap, + RegionPtr prgn, + int xorg, + int yorg, + WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + damageDamageRegion (&pWindow->drawable, prgn, FALSE); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + (*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn, + xorg, yorg, pWindow); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +} + +static void +damageSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + damageScrPriv(pScreen); + + if ((pDamage = damageGetWinPriv(pWindow))) + { + PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow); + DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap); + + while (pDamage) + { + damageRemoveDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } + unwrap (pScrPriv, pScreen, SetWindowPixmap); + (*pScreen->SetWindowPixmap) (pWindow, pPixmap); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + if ((pDamage = damageGetWinPriv(pWindow))) + { + DamagePtr *pPrev = getPixmapDamageRef(pPixmap); + + while (pDamage) + { + damageInsertDamage (pPrev, pDamage); + pDamage = pDamage->pNextWin; + } + } +} + +static Bool +damageDestroyWindow (WindowPtr pWindow) +{ + DamagePtr pDamage; + ScreenPtr pScreen = pWindow->drawable.pScreen; + Bool ret; + damageScrPriv(pScreen); + + while ((pDamage = damageGetWinPriv(pWindow))) + { + DamageUnregister (&pWindow->drawable, pDamage); + DamageDestroy (pDamage); + } + unwrap (pScrPriv, pScreen, DestroyWindow); + ret = (*pScreen->DestroyWindow) (pWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + return ret; +} + +static Bool +damageCloseScreen (int i, ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, DestroyPixmap); + unwrap (pScrPriv, pScreen, CreateGC); + unwrap (pScrPriv, pScreen, PaintWindowBackground); + unwrap (pScrPriv, pScreen, PaintWindowBorder); + unwrap (pScrPriv, pScreen, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas); + xfree (pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +int damageScrPrivateIndex; +int damagePixPrivateIndex; +int damageGCPrivateIndex; +int damageWinPrivateIndex; +int damageGeneration; + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; +#ifdef RENDER + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); +#endif + + if (damageGeneration != serverGeneration) + { + damageScrPrivateIndex = AllocateScreenPrivateIndex (); + if (damageScrPrivateIndex == -1) + return FALSE; + damageGCPrivateIndex = AllocateGCPrivateIndex (); + if (damageGCPrivateIndex == -1) + return FALSE; + damagePixPrivateIndex = AllocatePixmapPrivateIndex (); + if (damagePixPrivateIndex == -1) + return FALSE; + damageWinPrivateIndex = AllocateWindowPrivateIndex (); + if (damageWinPrivateIndex == -1) + return FALSE; + damageGeneration = serverGeneration; + } + if (pScreen->devPrivates[damageScrPrivateIndex].ptr) + return TRUE; + + if (!AllocateGCPrivate (pScreen, damageGCPrivateIndex, sizeof (DamageGCPrivRec))) + return FALSE; + if (!AllocatePixmapPrivate (pScreen, damagePixPrivateIndex, 0)) + return FALSE; + if (!AllocateWindowPrivate (pScreen, damageWinPrivateIndex, 0)) + return FALSE; + + pScrPriv = (DamageScrPrivPtr) xalloc (sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + +#ifdef COMPOSITE + /* This is a kludge to ensure wrapping order with the composite wrapper. + * If it's done from compinit.c, then DamageSetup may be called before the + * extension init phase, so that cw will be higher in the wrapping chain and + * rewrite drawables before damage gets to it, causing confusion. + */ + if (!noCompositeExtension) + miInitializeCompositeWrapper (pScreen); +#endif + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, PaintWindowBackground, damagePaintWindow); + wrap (pScrPriv, pScreen, PaintWindowBorder, damagePaintWindow); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas, + damageRestoreAreas); +#ifdef RENDER + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + } +#endif + + pScreen->devPrivates[damageScrPrivateIndex].ptr = (pointer) pScrPriv; + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + DamagePtr pDamage; + + pDamage = xalloc (sizeof (DamageRec)); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + REGION_NULL(pScreen, &pDamage->damage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + + pDamage->damageReport = damageReport; + pDamage->damageDestroy = damageDestroy; + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef(pWindow); + +#if DAMAGE_VALIDATE_ENABLE + DamagePtr pOld; + + for (pOld = *pPrev; pOld; pOld = pOld->pNextWin) + if (pOld == pDamage) { + ErrorF ("Damage already on window list\n"); + abort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + if (pDrawable->type == DRAWABLE_WINDOW) + { + WindowPtr pWindow = (WindowPtr) pDrawable; + winDamageRef (pWindow); +#if DAMAGE_VALIDATE_ENABLE + int found = 0; +#endif + + while (*pPrev) + { + if (*pPrev == pDamage) + { + *pPrev = pDamage->pNextWin; +#if DAMAGE_VALIDATE_ENABLE + found = 1; +#endif + break; + } + pPrev = &(*pPrev)->pNextWin; + } +#if DAMAGE_VALIDATE_ENABLE + if (!found) { + ErrorF ("Damage not on window list\n"); + abort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + REGION_UNINIT (pDamage->pDrawable->pScreen, &pDamage->damage); + xfree (pDamage); +} + +Bool +DamageSubtract (DamagePtr pDamage, + const RegionPtr pRegion) +{ + RegionPtr pClip; + RegionRec pixmapClip; + DrawablePtr pDrawable = pDamage->pDrawable; + + REGION_SUBTRACT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pRegion); + if (pDrawable) + { + if (pDrawable->type == DRAWABLE_WINDOW) + pClip = &((WindowPtr) pDrawable)->borderClip; + else + { + BoxRec box; + + box.x1 = pDrawable->x; + box.y1 = pDrawable->y; + box.x2 = pDrawable->x + pDrawable->width; + box.y2 = pDrawable->y + pDrawable->height; + REGION_INIT (pDrawable->pScreen, &pixmapClip, &box, 1); + pClip = &pixmapClip; + } + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, pDrawable->x, pDrawable->y); + REGION_INTERSECT (pDrawable->pScreen, &pDamage->damage, &pDamage->damage, pClip); + REGION_TRANSLATE (pDrawable->pScreen, &pDamage->damage, -pDrawable->x, -pDrawable->y); + } + return REGION_NOTEMPTY (pDrawable->pScreen, &pDamage->damage); +} + +void +DamageEmpty (DamagePtr pDamage) +{ + REGION_EMPTY (pDamage->pDrawable->pScreen, &pDamage->damage); +} + +RegionPtr +DamageRegion (DamagePtr pDamage) +{ + return &pDamage->damage; +} + +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageDamageRegion (pDrawable, pRegion, FALSE); +} diff --git a/miext/damage/damagestr.h b/miext/damage/damagestr.h new file mode 100755 index 000000000..d975ee23b --- /dev/null +++ b/miext/damage/damagestr.h @@ -0,0 +1,107 @@ +/* + * $Id$ + * + * Copyright © 2003 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 _DAMAGESTR_H_ +#define _DAMAGESTR_H_ + +#include "damage.h" +#include "picturestr.h" + +typedef struct _damage { + DamagePtr pNext; + DamagePtr pNextWin; + RegionRec damage; + + DamageReportLevel damageLevel; + Bool isInternal; + void *closure; + Bool isWindow; + DrawablePtr pDrawable; + + DamageReportFunc damageReport; + DamageDestroyFunc damageDestroy; +} DamageRec; + +typedef struct _damageScrPriv { + int internalLevel; + + /* + * For DDXen which don't provide GetScreenPixmap, this provides + * a place to hook damage for windows on the screen + */ + DamagePtr pScreenDamage; + + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + CloseScreenProcPtr CloseScreen; + CreateGCProcPtr CreateGC; + DestroyPixmapProcPtr DestroyPixmap; + SetWindowPixmapProcPtr SetWindowPixmap; + DestroyWindowProcPtr DestroyWindow; +#ifdef RENDER + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; +#endif + BSFuncRec BackingStoreFuncs; +} DamageScrPrivRec, *DamageScrPrivPtr; + +typedef struct _damageGCPriv { + GCOps *ops; + GCFuncs *funcs; +} DamageGCPrivRec, *DamageGCPrivPtr; + +extern int damageScrPrivateIndex; +extern int damagePixPrivateIndex; +extern int damageGCPrivateIndex; +extern int damageWinPrivateIndex; + +#define damageGetScrPriv(pScr) \ + ((DamageScrPrivPtr) (pScr)->devPrivates[damageScrPrivateIndex].ptr) + +#define damageScrPriv(pScr) \ + DamageScrPrivPtr pScrPriv = damageGetScrPriv(pScr) + +#define damageGetPixPriv(pPix) \ + ((DamagePtr) (pPix)->devPrivates[damagePixPrivateIndex].ptr) + +#define damgeSetPixPriv(pPix,v) \ + ((pPix)->devPrivates[damagePixPrivateIndex].ptr = (pointer ) (v)) + +#define damagePixPriv(pPix) \ + DamagePtr pDamage = damageGetPixPriv(pPix) + +#define damageGetGCPriv(pGC) \ + ((DamageGCPrivPtr) (pGC)->devPrivates[damageGCPrivateIndex].ptr) + +#define damageGCPriv(pGC) \ + DamageGCPrivPtr pGCPriv = damageGetGCPriv(pGC) + +#define damageGetWinPriv(pWin) \ + ((DamagePtr) (pWin)->devPrivates[damageWinPrivateIndex].ptr) + +#define damageSetWinPriv(pWin,d) \ + ((pWin)->devPrivates[damageWinPrivateIndex].ptr = (d)) + +#endif /* _DAMAGESTR_H_ */ diff --git a/miext/rootless/rootless.h b/miext/rootless/rootless.h index aefefcab2..1bada3865 100644 --- a/miext/rootless/rootless.h +++ b/miext/rootless/rootless.h @@ -27,7 +27,7 @@ * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written authorization. */ -/* $XFree86: xc/programs/Xserver/miext/rootless/rootless.h,v 1.5 2003/10/18 00:00:34 torrey Exp $ */ +/* $XFree86: xc/programs/Xserver/miext/rootless/rootless.h,v 1.7 2004/07/02 01:30:33 torrey Exp $ */ #ifndef _ROOTLESS_H #define _ROOTLESS_H @@ -395,5 +395,16 @@ void RootlessStartDrawing(WindowPtr pWindow); */ void RootlessStopDrawing(WindowPtr pWindow, Bool flush); +/* + * Alocate a new screen pixmap. + * miCreateScreenResources does not do this properly with a null + * framebuffer pointer. + */ +void RootlessUpdateScreenPixmap(ScreenPtr pScreen); + +/* + * Reposition all windows on a screen to their correct positions. + */ +void RootlessRepositionWindows(ScreenPtr pScreen); #endif /* _ROOTLESS_H */ diff --git a/miext/rootless/rootlessCommon.c b/miext/rootless/rootlessCommon.c index 85655a9e1..b24d2a226 100644 --- a/miext/rootless/rootlessCommon.c +++ b/miext/rootless/rootlessCommon.c @@ -28,7 +28,7 @@ * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written authorization. */ -/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.c,v 1.4tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.c,v 1.6 2004/07/02 01:30:33 torrey Exp $ */ #include "rootlessCommon.h" @@ -166,8 +166,8 @@ void RootlessStopDrawing(WindowPtr pWindow, Bool flush) } if (flush && winRec->is_reorder_pending) { - winRec->is_reorder_pending = FALSE; - RootlessReorderWindow(pWindow); + winRec->is_reorder_pending = FALSE; + RootlessReorderWindow(pWindow); } } @@ -190,11 +190,11 @@ RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) pTop = TopLevelParent(pWindow); if (pTop == NULL) - return; + return; winRec = WINREC(pTop); if (winRec == NULL) - return; + return; /* We need to intersect the drawn region with the clip of the window to avoid marking places we didn't actually draw (which can cause @@ -208,43 +208,43 @@ RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) b2 = REGION_EXTENTS(pScreen, pRegion); if (EXTENTCHECK(b1, b2)) { - /* Regions may overlap. */ + /* Regions may overlap. */ - if (REGION_NUM_RECTS(pRegion) == 1) { - int in; + if (REGION_NUM_RECTS(pRegion) == 1) { + int in; - /* Damaged region only has a single rect, so we can - just compare that against the region */ + /* Damaged region only has a single rect, so we can + just compare that against the region */ - in = RECT_IN_REGION(pScreen, &pWindow->borderClip, + in = RECT_IN_REGION(pScreen, &pWindow->borderClip, REGION_RECTS (pRegion)); - if (in == rgnIN) { - /* clip totally contains pRegion */ + if (in == rgnIN) { + /* clip totally contains pRegion */ #ifdef ROOTLESS_TRACK_DAMAGE REGION_UNION(pScreen, &winRec->damage, - &winRec->damage, (pRegion)); + &winRec->damage, (pRegion)); #else - SCREENREC(pScreen)->imp->DamageRects(winRec->wid, + SCREENREC(pScreen)->imp->DamageRects(winRec->wid, REGION_NUM_RECTS(pRegion), - REGION_RECTS(pRegion), - -winRec->x, -winRec->y); + REGION_RECTS(pRegion), + -winRec->x, -winRec->y); #endif - RootlessQueueRedisplay(pTop->drawable.pScreen); - goto out; - } - else if (in == rgnOUT) { - /* clip doesn't contain pRegion */ + RootlessQueueRedisplay(pTop->drawable.pScreen); + goto out; + } + else if (in == rgnOUT) { + /* clip doesn't contain pRegion */ - goto out; - } - } + goto out; + } + } - /* clip overlaps pRegion, need to intersect */ + /* clip overlaps pRegion, need to intersect */ - REGION_NULL(pScreen, &clipped); - REGION_INTERSECT(pScreen, &clipped, &pWindow->borderClip, pRegion); + REGION_NULL(pScreen, &clipped); + REGION_INTERSECT(pScreen, &clipped, &pWindow->borderClip, pRegion); #ifdef ROOTLESS_TRACK_DAMAGE REGION_UNION(pScreen, &winRec->damage, @@ -256,9 +256,9 @@ RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) -winRec->x, -winRec->y); #endif - REGION_UNINIT(pScreen, &clipped); + REGION_UNINIT(pScreen, &clipped); - RootlessQueueRedisplay(pTop->drawable.pScreen); + RootlessQueueRedisplay(pTop->drawable.pScreen); } out: @@ -291,7 +291,7 @@ RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox) RootlessDamageRegion(pWindow, ®ion); - REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ + REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ } @@ -318,7 +318,7 @@ RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h) RootlessDamageRegion(pWindow, ®ion); - REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ + REGION_UNINIT(pWindow->drawable.pScreen, ®ion); /* no-op */ } @@ -350,7 +350,7 @@ RootlessRedisplay(WindowPtr pWindow) REGION_EMPTY(pScreen, &winRec->damage); } -#else /* !ROOTLESS_TRACK_DAMAGE */ +#else /* !ROOTLESS_TRACK_DAMAGE */ RootlessStopDrawing(pWindow, TRUE); @@ -359,6 +359,27 @@ RootlessRedisplay(WindowPtr pWindow) /* + * RootlessRepositionWindows + * Reposition all windows on a screen to their correct positions. + */ +void +RootlessRepositionWindows(ScreenPtr pScreen) +{ + WindowPtr root = WindowTable[pScreen->myNum]; + WindowPtr win; + + if (root != NULL) { + RootlessRepositionWindow(root); + + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win) != NULL) + RootlessRepositionWindow(win); + } + } +} + + +/* * RootlessRedisplayScreen * Walk every window on a screen and redisplay the damaged regions. */ diff --git a/miext/rootless/rootlessCommon.h b/miext/rootless/rootlessCommon.h index c75c45a2e..b5fcae7f9 100644 --- a/miext/rootless/rootlessCommon.h +++ b/miext/rootless/rootlessCommon.h @@ -3,7 +3,7 @@ */ /* * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,7 +27,7 @@ * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written authorization. */ -/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.h,v 1.3 2003/06/30 01:45:13 torrey Exp $ */ +/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessCommon.h,v 1.5 2004/07/02 01:30:33 torrey Exp $ */ #ifndef _ROOTLESSCOMMON_H #define _ROOTLESSCOMMON_H @@ -139,10 +139,10 @@ typedef struct _RootlessScreenRec { // Call a rootless implementation function. // Many rootless implementation functions are allowed to be NULL. -#define CallFrameProc(pScreen, proc, params) \ - if (SCREENREC(pScreen)->frameProcs.proc) { \ - RL_DEBUG_MSG("calling frame proc " #proc " "); \ - SCREENREC(pScreen)->frameProcs.proc params; \ +#define CallFrameProc(pScreen, proc, params) \ + if (SCREENREC(pScreen)->frameProcs.proc) { \ + RL_DEBUG_MSG("calling frame proc " #proc " "); \ + SCREENREC(pScreen)->frameProcs.proc params; \ } @@ -217,19 +217,19 @@ extern RegionRec rootlessHugeRoot; * Can't access the bits before the first word of the drawable's data in * rootless mode, so make sure our base address is always 32-bit aligned. */ -#define SetPixmapBaseToScreen(pix, _x, _y) { \ - PixmapPtr _pPix = (PixmapPtr) (pix); \ - _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \ - ((int)(_x) * _pPix->drawable.bitsPerPixel/8 + \ - (int)(_y) * _pPix->devKind); \ - if (_pPix->drawable.bitsPerPixel != FB_UNIT) { \ - unsigned _diff = ((unsigned) _pPix->devPrivate.ptr) & \ - (FB_UNIT / CHAR_BIT - 1); \ - _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \ - _diff; \ - _pPix->drawable.x = _diff / \ - (_pPix->drawable.bitsPerPixel / CHAR_BIT); \ - } \ +#define SetPixmapBaseToScreen(pix, _x, _y) { \ + PixmapPtr _pPix = (PixmapPtr) (pix); \ + _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \ + ((int)(_x) * _pPix->drawable.bitsPerPixel/8 + \ + (int)(_y) * _pPix->devKind); \ + if (_pPix->drawable.bitsPerPixel != FB_UNIT) { \ + unsigned _diff = ((unsigned) _pPix->devPrivate.ptr) & \ + (FB_UNIT / CHAR_BIT - 1); \ + _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \ + _diff; \ + _pPix->drawable.x = _diff / \ + (_pPix->drawable.bitsPerPixel / CHAR_BIT); \ + } \ } @@ -246,9 +246,12 @@ void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox); void RootlessRedisplay(WindowPtr pWindow); void RootlessRedisplayScreen(ScreenPtr pScreen); -void RootlessQueueRedisplay (ScreenPtr pScreen); +void RootlessQueueRedisplay(ScreenPtr pScreen); + +// Move a window to its proper location on the screen. +void RootlessRepositionWindow(WindowPtr pWin); // Move the window to it's correct place in the physical stacking order. -void RootlessReorderWindow (WindowPtr pWin); +void RootlessReorderWindow(WindowPtr pWin); #endif /* _ROOTLESSCOMMON_H */ diff --git a/miext/rootless/rootlessValTree.c b/miext/rootless/rootlessValTree.c index 7b0337bce..9e61603b5 100644 --- a/miext/rootless/rootlessValTree.c +++ b/miext/rootless/rootlessValTree.c @@ -81,7 +81,6 @@ dealings in this Software without prior written authorization from Digital Equipment Corporation. ******************************************************************/ - /* * Aug '86: Susan Angebranndt -- original code * July '87: Adam de Boor -- substantially modified and commented diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c index ddd0d1891..9f1cfa1e6 100644 --- a/miext/rootless/rootlessWindow.c +++ b/miext/rootless/rootlessWindow.c @@ -1,10 +1,10 @@ -/* $XdotOrg: xc/programs/Xserver/miext/rootless/rootlessWindow.c,v 1.1.4.1.4.1 2004/03/04 17:48:29 eich Exp $ */ +/* $XdotOrg: xc/programs/Xserver/miext/rootless/rootlessWindow.c,v 1.3 2004/07/30 19:12:17 torrey Exp $ */ /* * Rootless window management */ /* * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -29,7 +29,7 @@ * holders shall not be used in advertising or otherwise to promote the sale, * use or other dealings in this Software without prior written authorization. */ -/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessWindow.c,v 1.10 2003/11/13 20:26:31 torrey Exp $ */ +/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessWindow.c,v 1.12 2004/07/02 01:30:33 torrey Exp $ */ #include "rootlessCommon.h" #include "rootlessWindow.h" @@ -1219,6 +1219,31 @@ RootlessResizeWindow(WindowPtr pWin, int x, int y, /* + * RootlessRepositionWindow + * Called by the implementation when a window needs to be repositioned to + * its correct location on the screen. This routine is typically needed + * due to changes in the underlying window system, such as a screen layout + * change. + */ +void +RootlessRepositionWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (winRec == NULL) + return; + + RootlessStopDrawing(pWin, FALSE); + SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y); + + RootlessReorderWindow(pWin); +} + + +/* * RootlessReparentWindow * Called after a window has been reparented. Generally windows are not * framed until they are mapped. However, a window may be framed early by the @@ -1236,9 +1261,9 @@ RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) /* Check that window is not top-level now, but used to be. */ if (IsRoot(pWin) || IsRoot(pWin->parent) - || IsTopLevel(pWin) || winRec == NULL) + || IsTopLevel(pWin) || winRec == NULL) { - goto out; + goto out; } /* If the formerly top-level window has a frame, we want to give the @@ -1249,20 +1274,20 @@ RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) assert(pTopWin != pWin); if (WINREC(pTopWin) != NULL) { - /* We're screwed. */ - RootlessDestroyFrame(pWin, winRec); + /* We're screwed. */ + RootlessDestroyFrame(pWin, winRec); } else { - if (!pTopWin->realized && pWin->realized) { + if (!pTopWin->realized && pWin->realized) { SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); - } + } - /* Switch the frame record from one to the other. */ + /* Switch the frame record from one to the other. */ - WINREC(pWin) = NULL; - WINREC(pTopWin) = winRec; + WINREC(pWin) = NULL; + WINREC(pTopWin) = winRec; - RootlessInitializeFrame(pTopWin, winRec); - RootlessReshapeFrame(pTopWin); + RootlessInitializeFrame(pTopWin, winRec); + RootlessReshapeFrame(pTopWin); SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, winRec->x + SCREEN_TO_GLOBAL_X, @@ -1274,8 +1299,8 @@ RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); } - if (pTopWin->realized && !pWin->realized) - winRec->is_reorder_pending = TRUE; + if (pTopWin->realized && !pWin->realized) + winRec->is_reorder_pending = TRUE; } out: diff --git a/miext/rootless/safeAlpha/safeAlphaWindow.c b/miext/rootless/safeAlpha/safeAlphaWindow.c index 1c6a8a747..4e70a73e1 100644 --- a/miext/rootless/safeAlpha/safeAlphaWindow.c +++ b/miext/rootless/safeAlpha/safeAlphaWindow.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/programs/Xserver/miext/rootless/safeAlpha/safeAlphaWindow.c,v 1.1.4.2.2.2 2004/03/04 17:48:30 eich Exp $ */ +/* $XdotOrg: xc/programs/Xserver/miext/rootless/safeAlpha/safeAlphaWindow.c,v 1.2 2004/04/23 19:54:28 eich Exp $ */ /* * Specialized window functions to protect the alpha channel */ diff --git a/miext/shadow/shadow.h b/miext/shadow/shadow.h index d343a171f..d301916e4 100644 --- a/miext/shadow/shadow.h +++ b/miext/shadow/shadow.h @@ -163,6 +163,13 @@ void shadowUpdateRotate32_270 (ScreenPtr pScreen, shadowBufPtr pBuf); +typedef void (* shadowUpdateProc)(ScreenPtr, shadowBufPtr); + +shadowUpdateProc shadowUpdatePackedWeak(void); +shadowUpdateProc shadowUpdatePlanar4Weak(void); +shadowUpdateProc shadowUpdatePlanar4x8Weak(void); +shadowUpdateProc shadowUpdateRotatePackedWeak(void); + void shadowWrapGC (GCPtr pGC); diff --git a/miext/shadow/shpacked.c b/miext/shadow/shpacked.c index 441409776..de2643e9f 100644 --- a/miext/shadow/shpacked.c +++ b/miext/shadow/shpacked.c @@ -106,3 +106,5 @@ shadowUpdatePacked (ScreenPtr pScreen, pbox++; } } + +shadowUpdateProc shadowUpdatePackedWeak(void) { return shadowUpdatePacked; } diff --git a/miext/shadow/shplanar.c b/miext/shadow/shplanar.c index aaa6d58eb..3b842d57b 100644 --- a/miext/shadow/shplanar.c +++ b/miext/shadow/shplanar.c @@ -165,4 +165,11 @@ shadowUpdatePlanar4 (ScreenPtr pScreen, pbox++; } } - + +shadowUpdateProc shadowUpdatePlanar4Weak(void) { + return shadowUpdatePlanar4; +} + +shadowUpdateProc shadowUpdatePlanar4x8Weak(void) { + return shadowUpdatePlanar4x8; +} diff --git a/miext/shadow/shrotate.c b/miext/shadow/shrotate.c index a0f5b6e06..620559e69 100644 --- a/miext/shadow/shrotate.c +++ b/miext/shadow/shrotate.c @@ -304,3 +304,7 @@ shadowUpdateRotatePacked (ScreenPtr pScreen, } } } + +shadowUpdateProc shadowUpdateRotatePackedWeak(void) { + return shadowUpdateRotatePacked; +} |