From c38dead3ea7e177728d90cd815cf4eead0c9f534 Mon Sep 17 00:00:00 2001 From: marha Date: Sat, 15 May 2010 16:28:11 +0000 Subject: xserver git update 15/5/2010 --- xorg-server/miext/cw/cw.c | 1044 +++---- xorg-server/miext/cw/cw_render.c | 938 +++--- xorg-server/miext/damage/damage.c | 4332 +++++++++++++-------------- xorg-server/miext/rootless/rootlessScreen.c | 1510 +++++----- xorg-server/miext/rootless/rootlessWindow.c | 3312 ++++++++++---------- xorg-server/miext/shadow/shadow.c | 498 +-- xorg-server/miext/shadow/shalloc.c | 100 +- 7 files changed, 5867 insertions(+), 5867 deletions(-) (limited to 'xorg-server/miext') diff --git a/xorg-server/miext/cw/cw.c b/xorg-server/miext/cw/cw.c index 247cb83e1..72a90c699 100644 --- a/xorg-server/miext/cw/cw.c +++ b/xorg-server/miext/cw/cw.c @@ -1,522 +1,522 @@ -/* - * 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. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#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 - -static int cwGCKeyIndex; -DevPrivateKey cwGCKey = &cwGCKeyIndex; -static int cwScreenKeyIndex; -DevPrivateKey cwScreenKey = &cwScreenKeyIndex; -static int cwWindowKeyIndex; -DevPrivateKey cwWindowKey = &cwWindowKeyIndex; -static int cwPictureKeyIndex; -DevPrivateKey cwPictureKey = &cwPictureKeyIndex; -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, (XID)0, serverClient); - 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)dixLookupPrivate(&pGC->devPrivates, cwGCKey); - - 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)dixLookupPrivate(&pGCDst->devPrivates, cwGCKey); - - FUNC_PROLOGUE(pGCDst, pPriv); - - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - - FUNC_EPILOGUE(pGCDst, pPriv); -} - -static void -cwDestroyGC(GCPtr pGC) -{ - cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey); - - 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)dixLookupPrivate(&pGC->devPrivates, cwGCKey); - - 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)dixLookupPrivate(&pgcDst->devPrivates, cwGCKey); - - FUNC_PROLOGUE(pgcDst, pPriv); - - (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - - FUNC_EPILOGUE(pgcDst, pPriv); -} - -static void -cwDestroyClip(GCPtr pGC) -{ - cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey); - - 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 -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; - Bool has_render = GetPictureScreenIfSet(pScreen) != NULL; - - if (!dixRequestPrivate(cwGCKey, sizeof(cwGCRec))) - return; - - pScreenPriv = xalloc(sizeof(cwScreenRec)); - if (!pScreenPriv) - return; - - dixSetPrivate(&pScreen->devPrivates, cwScreenKey, pScreenPriv); - - SCREEN_EPILOGUE(pScreen, CloseScreen, cwCloseScreen); - SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); - SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); - SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); - SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); - - SCREEN_EPILOGUE(pScreen, SetWindowPixmap, cwSetWindowPixmap); - SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); - - if (has_render) - cwInitializeRender(pScreen); -} - -static Bool -cwCloseScreen (int i, ScreenPtr pScreen) -{ - cwScreenPtr pScreenPriv; - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - pScreenPriv = (cwScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - cwScreenKey); - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->GetImage = pScreenPriv->GetImage; - pScreen->GetSpans = pScreenPriv->GetSpans; - pScreen->CreateGC = pScreenPriv->CreateGC; - pScreen->CopyWindow = pScreenPriv->CopyWindow; - - if (ps) - cwFiniRender(pScreen); - - xfree((pointer)pScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} +/* + * 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#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 + +static int cwGCKeyIndex; +DevPrivateKey cwGCKey = &cwGCKeyIndex; +static int cwScreenKeyIndex; +DevPrivateKey cwScreenKey = &cwScreenKeyIndex; +static int cwWindowKeyIndex; +DevPrivateKey cwWindowKey = &cwWindowKeyIndex; +static int cwPictureKeyIndex; +DevPrivateKey cwPictureKey = &cwPictureKeyIndex; +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, (XID)0, serverClient); + if (status != Success) + return FALSE; + + pPriv->serialNumber = 0; + pPriv->stateChanges = GCAllBits; + + 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))) + { + ChangeGCVal 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].val = x_off - pDrawable->x; + vals[1].val = y_off - pDrawable->y; + ChangeGC(NullClient, pBackingGC, + (GCClipXOrigin | GCClipYOrigin), vals); + + 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) + { + ChangeGCVal vals[2]; + vals[0].val = pGC->patOrg.x + x_off; + vals[1].val = pGC->patOrg.y + y_off; + ChangeGC(NullClient, pBackingGC, + (GCTileStipXOrigin | GCTileStipYOrigin), vals); + } + + ValidateGC(pBackingDrawable, pBackingGC); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwChangeGC(GCPtr pGC, unsigned long mask) +{ + cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + 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)dixLookupPrivate(&pGCDst->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGCDst, pPriv); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + FUNC_EPILOGUE(pGCDst, pPriv); +} + +static void +cwDestroyGC(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + 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)dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + 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)dixLookupPrivate(&pgcDst->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pgcDst, pPriv); + + (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + + FUNC_EPILOGUE(pgcDst, pPriv); +} + +static void +cwDestroyClip(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + 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 +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; + Bool has_render = GetPictureScreenIfSet(pScreen) != NULL; + + if (!dixRequestPrivate(cwGCKey, sizeof(cwGCRec))) + return; + + pScreenPriv = malloc(sizeof(cwScreenRec)); + if (!pScreenPriv) + return; + + dixSetPrivate(&pScreen->devPrivates, cwScreenKey, pScreenPriv); + + SCREEN_EPILOGUE(pScreen, CloseScreen, cwCloseScreen); + SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); + SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); + SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); + SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); + + SCREEN_EPILOGUE(pScreen, SetWindowPixmap, cwSetWindowPixmap); + SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); + + if (has_render) + cwInitializeRender(pScreen); +} + +static Bool +cwCloseScreen (int i, ScreenPtr pScreen) +{ + cwScreenPtr pScreenPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + pScreenPriv = (cwScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + cwScreenKey); + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + + if (ps) + cwFiniRender(pScreen); + + free((pointer)pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} diff --git a/xorg-server/miext/cw/cw_render.c b/xorg-server/miext/cw/cw_render.c index dfe2681e0..260509ce0 100644 --- a/xorg-server/miext/cw/cw_render.c +++ b/xorg-server/miext/cw/cw_render.c @@ -1,469 +1,469 @@ -/* - * 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. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include "gcstruct.h" -#include "windowstr.h" -#include "cw.h" - -#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 -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(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(CompositeRects); - cwPsUnwrap(Trapezoids); - cwPsUnwrap(Triangles); - cwPsUnwrap(TriStrip); - cwPsUnwrap(TriFan); -} - +/* + * 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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "gcstruct.h" +#include "windowstr.h" +#include "cw.h" + +#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 = malloc(sizeof (cwPictureRec)); + if (!pPicturePrivate) + return NULL; + + pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable, + pPicture->pFormat, + 0, 0, serverClient, + &error); + if (!pPicturePrivate->pBackingPicture) + { + free(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); + free(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 +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(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(CompositeRects); + cwPsUnwrap(Trapezoids); + cwPsUnwrap(Triangles); + cwPsUnwrap(TriStrip); + cwPsUnwrap(TriFan); +} + diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index de1857355..f662e928c 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -1,2166 +1,2166 @@ -/* - * 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_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include "scrnintstr.h" -#include "windowstr.h" -#include -#include "dixfontstr.h" -#include -#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 *) \ - dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey)) - -#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) - -static int damageScrPrivateKeyIndex; -static DevPrivateKey damageScrPrivateKey = &damageScrPrivateKeyIndex; -static int damagePixPrivateKeyIndex; -static DevPrivateKey damagePixPrivateKey = &damagePixPrivateKeyIndex; -static int damageGCPrivateKeyIndex; -static DevPrivateKey damageGCPrivateKey = &damageGCPrivateKeyIndex; -static int damageWinPrivateKeyIndex; -static DevPrivateKey damageWinPrivateKey = &damageWinPrivateKeyIndex; - -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 *) \ - dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey) - -static void -damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) -{ - BoxRec tmpBox; - RegionRec tmpRegion; - Bool was_empty; - - switch (pDamage->damageLevel) { - case DamageReportRawRegion: - REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, - pDamageRegion); - (*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); - } - REGION_UNINIT(pScreen, &tmpRegion); - 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; - } -} - -static void -damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion) -{ - BoxRec tmpBox; - RegionRec tmpRegion, newDamage; - Bool was_empty; - - REGION_UNION(pScreem, &newDamage, pOldDamage, pDamageRegion); - - switch (pDamage->damageLevel) { - case DamageReportRawRegion: - (*pDamage->damageReportPostRendering) (pDamage, pDamageRegion, pDamage->closure); - break; - case DamageReportDeltaRegion: - REGION_NULL (pScreen, &tmpRegion); - REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, pOldDamage); - if (REGION_NOTEMPTY (pScreen, &tmpRegion)) { - (*pDamage->damageReportPostRendering) (pDamage, &tmpRegion, pDamage->closure); - } - REGION_UNINIT(pScreen, &tmpRegion); - break; - case DamageReportBoundingBox: - tmpBox = *REGION_EXTENTS (pScreen, pOldDamage); - if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &newDamage))) { - (*pDamage->damageReportPostRendering) (pDamage, &newDamage, - pDamage->closure); - } - break; - case DamageReportNonEmpty: - was_empty = !REGION_NOTEMPTY(pScreen, pOldDamage); - if (was_empty && REGION_NOTEMPTY(pScreen, &newDamage)) { - (*pDamage->damageReportPostRendering) (pDamage, &newDamage, - pDamage->closure); - } - break; - case DamageReportNone: - break; - } - - REGION_UNINIT(pScreen, &newDamage); -} - -#if DAMAGE_DEBUG_ENABLE -static void -_damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) -#define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__) -#else -static void -damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, - int subWindowMode) -#endif -{ - ScreenPtr pScreen = pDrawable->pScreen; - damageScrPriv(pScreen); - drawableDamage(pDrawable); - DamagePtr pNext; - RegionRec clippedRec; - RegionPtr pDamageRegion; - RegionRec pixClip; - 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 - - if (pDrawable->type == DRAWABLE_WINDOW && - ((WindowPtr)(pDrawable))->backingStore == NotUseful) - { - if (subWindowMode == ClipByChildren) - { - REGION_INTERSECT(pScreen, pRegion, pRegion, - &((WindowPtr)(pDrawable))->clipList); - } - else if (subWindowMode == IncludeInferiors) - { - RegionPtr pTempRegion = - NotClippedByChildren((WindowPtr)(pDrawable)); - REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); - REGION_DESTROY(pScreen, pTempRegion); - } - /* If subWindowMode is set to an invalid value, don't perform - * any drawable-based clipping. */ - } - - - 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) - { - 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) { - REGION_INTERSECT (pScreen, pDamageRegion, pRegion, - &((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); - REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); - REGION_UNINIT(pScreen, &pixClip); - } - /* - * 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); - - /* Store damage region if needed after submission. */ - if (pDamage->reportAfter || pDamage->damageMarker) - REGION_UNION(pScreen, &pDamage->pendingDamage, - &pDamage->pendingDamage, pDamageRegion); - - /* Duplicate current damage if needed. */ - if (pDamage->damageMarker) - REGION_COPY(pScreen, &pDamage->backupDamage, &pDamage->damage); - - /* Report damage now, if desired. */ - if (!pDamage->reportAfter) { - if (pDamage->damageReport) - damageReportDamage (pDamage, pDamageRegion); - else - REGION_UNION(pScreen, &pDamage->damage, - &pDamage->damage, pDamageRegion); - } - - /* - * 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); -} - -static void -damageRegionProcessPending (DrawablePtr pDrawable) -{ - drawableDamage(pDrawable); - - for (; pDamage != NULL; pDamage = pDamage->pNext) - { - /* submit damage marker whenever possible. */ - if (pDamage->damageMarker) - (*pDamage->damageMarker) (pDrawable, pDamage, &pDamage->backupDamage, &pDamage->pendingDamage, pDamage->closure); - if (pDamage->reportAfter) { - /* It's possible that there is only interest in postRendering reporting. */ - if (pDamage->damageReport) - damageReportDamage (pDamage, &pDamage->pendingDamage); - else - REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, - &pDamage->pendingDamage); - } - - if (pDamage->reportAfter || pDamage->damageMarker) - REGION_EMPTY (pScreen, &pDamage->pendingDamage); - if (pDamage->damageMarker) - REGION_EMPTY (pScreen, &pDamage->backupDamage); - } - -} - -#if DAMAGE_DEBUG_ENABLE -#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) -static void -_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) -#else -static void -damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) -#endif -{ - RegionRec region; - - REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); -#if DAMAGE_DEBUG_ENABLE - _damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode, where); -#else - damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode); -#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); - -static GCFuncs damageGCFuncs = { - damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, - damageChangeClip, damageDestroyClip, damageCopyClip -}; - -static 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))) - -#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, pDst->subWindowMode); - } - unwrap (pScrPriv, ps, Composite); - (*ps->Composite) (op, - pSrc, - pMask, - pDst, - xSrc, - ySrc, - xMask, - yMask, - xDst, - yDst, - width, - height); - damageRegionProcessPending (pDst->pDrawable); - 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, pDst->subWindowMode); - } - unwrap (pScrPriv, ps, Glyphs); - (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - damageRegionProcessPending (pDst->pDrawable); - wrap (pScrPriv, ps, Glyphs, damageGlyphs); -} - -static void -damageAddTraps (PicturePtr pPicture, - INT16 x_off, - INT16 y_off, - int ntrap, - xTrap *traps) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - damageScrPriv(pScreen); - - if (checkPictureDamage (pPicture)) - { - BoxRec box; - int i; - int x, y; - xTrap *t = traps; - - box.x1 = 32767; - box.y1 = 32767; - box.x2 = -32767; - box.y2 = -32767; - x = pPicture->pDrawable->x + x_off; - y = pPicture->pDrawable->y + y_off; - for (i = 0; i < ntrap; i++) - { - pixman_fixed_t l = min (t->top.l, t->bot.l); - pixman_fixed_t r = max (t->top.r, t->bot.r); - int x1 = x + pixman_fixed_to_int (l); - int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r)); - int y1 = y + pixman_fixed_to_int (t->top.y); - int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y)); - - if (x1 < box.x1) - box.x1 = x1; - if (x2 > box.x2) - box.x2 = x2; - if (y1 < box.y1) - box.y1 = y1; - if (y2 > box.y2) - box.y2 = y2; - } - TRIM_PICTURE_BOX (box, pPicture); - if (BOX_NOT_EMPTY(box)) - damageDamageBox (pPicture->pDrawable, &box, pPicture->subWindowMode); - } - unwrap (pScrPriv, ps, AddTraps); - (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps); - damageRegionProcessPending (pPicture->pDrawable); - wrap (pScrPriv, ps, AddTraps, damageAddTraps); -} - -/**********************************************************/ - - -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->subWindowMode); - } - - (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); - - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, - leftPad, format, pImage); - damageRegionProcessPending (pDrawable); - 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->type == DRAWABLE_WINDOW && - ((WindowPtr)pSrc)->viewable) - { - (*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, pGC->subWindowMode); - } - - ret = (*pGC->ops->CopyArea)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty); - damageRegionProcessPending (pDst); - 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->type == DRAWABLE_WINDOW && - ((WindowPtr)pSrc)->viewable) - { - (*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, pGC->subWindowMode); - } - - ret = (*pGC->ops->CopyPlane)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); - damageRegionProcessPending (pDst); - 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->subWindowMode); - } - (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); - damageRegionProcessPending (pDrawable); - 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, pGC->subWindowMode); - - 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, pGC->subWindowMode); - - 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, pGC->subWindowMode); - - 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, pGC->subWindowMode); - - pRectsTmp++; - } - } - (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - - (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); - damageRegionProcessPending (pDrawable); - 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, - int subWindowMode) -{ - 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, subWindowMode); -} - -/* - * 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 = xalloc(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, pGC->subWindowMode); - 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)); - } - xfree(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)) - x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, - Linear8Bit, TT_POLY8); - else - x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); - damageRegionProcessPending (pDrawable); - 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)) - x = 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); - damageRegionProcessPending (pDrawable); - 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); - damageRegionProcessPending (pDrawable); - 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); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, - ppci, pglyphBase); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, - ppci, pglyphBase); - damageRegionProcessPending (pDrawable); - 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->subWindowMode); - } - (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); - damageRegionProcessPending (pDrawable); - 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"); - OsAbort (); -#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"); - OsAbort (); - } -#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 -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); - damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1); - REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); - } - unwrap (pScrPriv, pScreen, CopyWindow); - (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); - damageRegionProcessPending (&pWindow->drawable); - wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); -} - -static GCOps damageGCOps = { - damageFillSpans, damageSetSpans, - damagePutImage, damageCopyArea, - damageCopyPlane, damagePolyPoint, - damagePolylines, damagePolySegment, - damagePolyRectangle, damagePolyArc, - damageFillPolygon, damagePolyFillRect, - damagePolyFillArc, damagePolyText8, - damagePolyText16, damageImageText8, - damageImageText16, damageImageGlyphBlt, - damagePolyGlyphBlt, damagePushPixels, - {NULL} /* devPrivate */ -}; - -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, CopyWindow); - unwrap (pScrPriv, pScreen, CloseScreen); - xfree (pScrPriv); - return (*pScreen->CloseScreen) (i, pScreen); -} - -/** - * Default implementations of the damage management functions. - */ -void miDamageCreate (DamagePtr pDamage) -{ -} - -void miDamageRegister (DrawablePtr pDrawable, DamagePtr pDamage) -{ -} - -void miDamageUnregister (DrawablePtr pDrawable, DamagePtr pDamage) -{ -} - -void miDamageDestroy (DamagePtr pDamage) -{ -} - -/** - * Public functions for consumption outside this file. - */ - -Bool -DamageSetup (ScreenPtr pScreen) -{ - DamageScrPrivPtr pScrPriv; - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - const DamageScreenFuncsRec miFuncs = { - miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy - }; - - if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey)) - return TRUE; - - if (!dixRequestPrivate(damageGCPrivateKey, sizeof(DamageGCPrivRec))) - return FALSE; - - pScrPriv = xalloc (sizeof (DamageScrPrivRec)); - if (!pScrPriv) - return FALSE; - - pScrPriv->internalLevel = 0; - pScrPriv->pScreenDamage = 0; - - wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); - wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); - wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); - wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); - wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); - wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); - if (ps) { - wrap (pScrPriv, ps, Glyphs, damageGlyphs); - wrap (pScrPriv, ps, Composite, damageComposite); - wrap (pScrPriv, ps, AddTraps, damageAddTraps); - } - - pScrPriv->funcs = miFuncs; - - dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv); - return TRUE; -} - -DamagePtr -DamageCreate (DamageReportFunc damageReport, - DamageDestroyFunc damageDestroy, - DamageReportLevel damageLevel, - Bool isInternal, - ScreenPtr pScreen, - void *closure) -{ - damageScrPriv(pScreen); - DamagePtr pDamage; - - pDamage = xalloc (sizeof (DamageRec)); - if (!pDamage) - return 0; - pDamage->pNext = 0; - pDamage->pNextWin = 0; - REGION_NULL(pScreen, &pDamage->damage); - REGION_NULL(pScreen, &pDamage->pendingDamage); - - pDamage->damageLevel = damageLevel; - pDamage->isInternal = isInternal; - pDamage->closure = closure; - pDamage->isWindow = FALSE; - pDamage->pDrawable = 0; - pDamage->reportAfter = FALSE; - - pDamage->damageReport = damageReport; - pDamage->damageReportPostRendering = NULL; - pDamage->damageDestroy = damageDestroy; - pDamage->damageMarker = NULL; - pDamage->pScreen = pScreen; - pDamage->devPrivates = NULL; - - (*pScrPriv->funcs.Create) (pDamage); - - return pDamage; -} - -void -DamageRegister (DrawablePtr pDrawable, - DamagePtr pDamage) -{ - ScreenPtr pScreen = pDrawable->pScreen; - damageScrPriv(pScreen); - -#if DAMAGE_VALIDATE_ENABLE - if (pDrawable->pScreen != pDamage->pScreen) - { - ErrorF ("DamageRegister called with mismatched screens\n"); - OsAbort (); - } -#endif - - 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"); - OsAbort (); - } -#endif - pDamage->pNextWin = *pPrev; - *pPrev = pDamage; - pDamage->isWindow = TRUE; - } - else - pDamage->isWindow = FALSE; - pDamage->pDrawable = pDrawable; - damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); - (*pScrPriv->funcs.Register) (pDrawable, pDamage); -} - -void -DamageDrawInternal (ScreenPtr pScreen, Bool enable) -{ - damageScrPriv (pScreen); - - pScrPriv->internalLevel += enable ? 1 : -1; -} - -void -DamageUnregister (DrawablePtr pDrawable, - DamagePtr pDamage) -{ - ScreenPtr pScreen = pDrawable->pScreen; - damageScrPriv(pScreen); - - (*pScrPriv->funcs.Unregister) (pDrawable, 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"); - OsAbort (); - } -#endif - } - pDamage->pDrawable = 0; - damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); -} - -void -DamageDestroy (DamagePtr pDamage) -{ - ScreenPtr pScreen = pDamage->pScreen; - damageScrPriv(pScreen); - - if (pDamage->damageDestroy) - (*pDamage->damageDestroy) (pDamage, pDamage->closure); - (*pScrPriv->funcs.Destroy) (pDamage); - dixFreePrivates(pDamage->devPrivates); - pDamage->devPrivates = NULL; - REGION_UNINIT (pScreen, &pDamage->damage); - REGION_UNINIT (pScreen, &pDamage->pendingDamage); - 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); - if (pDrawable->type != DRAWABLE_WINDOW) - REGION_UNINIT(pDrawable->pScreen, &pixmapClip); - } - 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; -} - -RegionPtr -DamagePendingRegion (DamagePtr pDamage) -{ - return &pDamage->pendingDamage; -} - -void -DamageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion) -{ - damageRegionAppend (pDrawable, pRegion, FALSE, -1); -} - -void -DamageRegionProcessPending (DrawablePtr pDrawable) -{ - damageRegionProcessPending (pDrawable); -} - -/* If a damage marker is provided, then this function must be called after rendering is done. */ -/* Please do call back so any future enhancements can assume this function is called. */ -/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */ -void -DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion) -{ - if (pDamage->damageReportPostRendering) - damageReportDamagePostRendering (pDamage, pOldDamage, pRegion); -} - -/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */ -void -DamageDamageRegion (DrawablePtr pDrawable, - RegionPtr pRegion) -{ - damageRegionAppend (pDrawable, pRegion, FALSE, -1); - - /* Go back and report this damage for DamagePtrs with reportAfter set, since - * this call isn't part of an in-progress drawing op in the call chain and - * the DDX probably just wants to know about it right away. - */ - damageRegionProcessPending (pDrawable); -} - -void -DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) -{ - pDamage->reportAfter = reportAfter; -} - -void -DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, - DamageMarkerFunc damageMarker) -{ - pDamage->damageReportPostRendering = damageReportPostRendering; - pDamage->damageMarker = damageMarker; -} - -DamageScreenFuncsPtr -DamageGetScreenFuncs (ScreenPtr pScreen) -{ - damageScrPriv(pScreen); - return &pScrPriv->funcs; -} +/* + * 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_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include +#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 *) \ + dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey)) + +#define pixmapDamage(pPixmap) damagePixPriv(pPixmap) + +static int damageScrPrivateKeyIndex; +static DevPrivateKey damageScrPrivateKey = &damageScrPrivateKeyIndex; +static int damagePixPrivateKeyIndex; +static DevPrivateKey damagePixPrivateKey = &damagePixPrivateKeyIndex; +static int damageGCPrivateKeyIndex; +static DevPrivateKey damageGCPrivateKey = &damageGCPrivateKeyIndex; +static int damageWinPrivateKeyIndex; +static DevPrivateKey damageWinPrivateKey = &damageWinPrivateKeyIndex; + +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 *) \ + dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey) + +static void +damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion; + Bool was_empty; + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + pDamageRegion); + (*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); + } + REGION_UNINIT(pScreen, &tmpRegion); + 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; + } +} + +static void +damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion, newDamage; + Bool was_empty; + + REGION_UNION(pScreem, &newDamage, pOldDamage, pDamageRegion); + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + (*pDamage->damageReportPostRendering) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + REGION_NULL (pScreen, &tmpRegion); + REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, pOldDamage); + if (REGION_NOTEMPTY (pScreen, &tmpRegion)) { + (*pDamage->damageReportPostRendering) (pDamage, &tmpRegion, pDamage->closure); + } + REGION_UNINIT(pScreen, &tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *REGION_EXTENTS (pScreen, pOldDamage); + if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &newDamage))) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNonEmpty: + was_empty = !REGION_NOTEMPTY(pScreen, pOldDamage); + if (was_empty && REGION_NOTEMPTY(pScreen, &newDamage)) { + (*pDamage->damageReportPostRendering) (pDamage, &newDamage, + pDamage->closure); + } + break; + case DamageReportNone: + break; + } + + REGION_UNINIT(pScreen, &newDamage); +} + +#if DAMAGE_DEBUG_ENABLE +static void +_damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, int subWindowMode, const char *where) +#define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__) +#else +static void +damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, + int subWindowMode) +#endif +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + drawableDamage(pDrawable); + DamagePtr pNext; + RegionRec clippedRec; + RegionPtr pDamageRegion; + RegionRec pixClip; + 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 + + if (pDrawable->type == DRAWABLE_WINDOW && + ((WindowPtr)(pDrawable))->backingStore == NotUseful) + { + if (subWindowMode == ClipByChildren) + { + REGION_INTERSECT(pScreen, pRegion, pRegion, + &((WindowPtr)(pDrawable))->clipList); + } + else if (subWindowMode == IncludeInferiors) + { + RegionPtr pTempRegion = + NotClippedByChildren((WindowPtr)(pDrawable)); + REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); + REGION_DESTROY(pScreen, pTempRegion); + } + /* If subWindowMode is set to an invalid value, don't perform + * any drawable-based clipping. */ + } + + + 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) + { + 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) { + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, + &((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); + REGION_INTERSECT (pScreen, pDamageRegion, pRegion, &pixClip); + REGION_UNINIT(pScreen, &pixClip); + } + /* + * 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); + + /* Store damage region if needed after submission. */ + if (pDamage->reportAfter || pDamage->damageMarker) + REGION_UNION(pScreen, &pDamage->pendingDamage, + &pDamage->pendingDamage, pDamageRegion); + + /* Duplicate current damage if needed. */ + if (pDamage->damageMarker) + REGION_COPY(pScreen, &pDamage->backupDamage, &pDamage->damage); + + /* Report damage now, if desired. */ + if (!pDamage->reportAfter) { + if (pDamage->damageReport) + damageReportDamage (pDamage, pDamageRegion); + else + REGION_UNION(pScreen, &pDamage->damage, + &pDamage->damage, pDamageRegion); + } + + /* + * 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); +} + +static void +damageRegionProcessPending (DrawablePtr pDrawable) +{ + drawableDamage(pDrawable); + + for (; pDamage != NULL; pDamage = pDamage->pNext) + { + /* submit damage marker whenever possible. */ + if (pDamage->damageMarker) + (*pDamage->damageMarker) (pDrawable, pDamage, &pDamage->backupDamage, &pDamage->pendingDamage, pDamage->closure); + if (pDamage->reportAfter) { + /* It's possible that there is only interest in postRendering reporting. */ + if (pDamage->damageReport) + damageReportDamage (pDamage, &pDamage->pendingDamage); + else + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, + &pDamage->pendingDamage); + } + + if (pDamage->reportAfter || pDamage->damageMarker) + REGION_EMPTY (pScreen, &pDamage->pendingDamage); + if (pDamage->damageMarker) + REGION_EMPTY (pScreen, &pDamage->backupDamage); + } + +} + +#if DAMAGE_DEBUG_ENABLE +#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__) +static void +_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode, const char *where) +#else +static void +damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode) +#endif +{ + RegionRec region; + + REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1); +#if DAMAGE_DEBUG_ENABLE + _damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode, where); +#else + damageRegionAppend (pDrawable, ®ion, TRUE, subWindowMode); +#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); + +static GCFuncs damageGCFuncs = { + damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, + damageChangeClip, damageDestroyClip, damageCopyClip +}; + +static 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))) + +#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, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + damageRegionProcessPending (pDst->pDrawable); + 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, pDst->subWindowMode); + } + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + damageRegionProcessPending (pDst->pDrawable); + wrap (pScrPriv, ps, Glyphs, damageGlyphs); +} + +static void +damageAddTraps (PicturePtr pPicture, + INT16 x_off, + INT16 y_off, + int ntrap, + xTrap *traps) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + damageScrPriv(pScreen); + + if (checkPictureDamage (pPicture)) + { + BoxRec box; + int i; + int x, y; + xTrap *t = traps; + + box.x1 = 32767; + box.y1 = 32767; + box.x2 = -32767; + box.y2 = -32767; + x = pPicture->pDrawable->x + x_off; + y = pPicture->pDrawable->y + y_off; + for (i = 0; i < ntrap; i++) + { + pixman_fixed_t l = min (t->top.l, t->bot.l); + pixman_fixed_t r = max (t->top.r, t->bot.r); + int x1 = x + pixman_fixed_to_int (l); + int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r)); + int y1 = y + pixman_fixed_to_int (t->top.y); + int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y)); + + if (x1 < box.x1) + box.x1 = x1; + if (x2 > box.x2) + box.x2 = x2; + if (y1 < box.y1) + box.y1 = y1; + if (y2 > box.y2) + box.y2 = y2; + } + TRIM_PICTURE_BOX (box, pPicture); + if (BOX_NOT_EMPTY(box)) + damageDamageBox (pPicture->pDrawable, &box, pPicture->subWindowMode); + } + unwrap (pScrPriv, ps, AddTraps); + (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps); + damageRegionProcessPending (pPicture->pDrawable); + wrap (pScrPriv, ps, AddTraps, damageAddTraps); +} + +/**********************************************************/ + + +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->subWindowMode); + } + + (*pGC->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted); + + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->SetSpans)(pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, + leftPad, format, pImage); + damageRegionProcessPending (pDrawable); + 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->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*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, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + damageRegionProcessPending (pDst); + 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->type == DRAWABLE_WINDOW && + ((WindowPtr)pSrc)->viewable) + { + (*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, pGC->subWindowMode); + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + damageRegionProcessPending (pDst); + 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->subWindowMode); + } + (*pGC->ops->PolyPoint)(pDrawable, pGC, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->Polylines)(pDrawable, pGC, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PolySegment)(pDrawable, pGC, nSeg, pSeg); + damageRegionProcessPending (pDrawable); + 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, pGC->subWindowMode); + + 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, pGC->subWindowMode); + + 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, pGC->subWindowMode); + + 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, pGC->subWindowMode); + + pRectsTmp++; + } + } + (*pGC->ops->PolyRectangle)(pDrawable, pGC, nRects, pRects); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PolyArc)(pDrawable, pGC, nArcs, pArcs); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + + (*pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, npt, ppt); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PolyFillRect)(pDrawable, pGC, nRects, pRects); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PolyFillArc)(pDrawable, pGC, nArcs, pArcs); + damageRegionProcessPending (pDrawable); + 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, + int subWindowMode) +{ + 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, subWindowMode); +} + +/* + * 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 = malloc(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, pGC->subWindowMode); + 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)); + } + free(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)) + x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars, + Linear8Bit, TT_POLY8); + else + x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars); + damageRegionProcessPending (pDrawable); + 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)) + x = 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); + damageRegionProcessPending (pDrawable); + 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); + damageRegionProcessPending (pDrawable); + 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); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, + ppci, pglyphBase); + damageRegionProcessPending (pDrawable); + 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->subWindowMode); + } + (*pGC->ops->PushPixels)(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg); + damageRegionProcessPending (pDrawable); + 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"); + OsAbort (); +#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"); + OsAbort (); + } +#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 +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); + damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1); + REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); + } + unwrap (pScrPriv, pScreen, CopyWindow); + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + damageRegionProcessPending (&pWindow->drawable); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); +} + +static GCOps damageGCOps = { + damageFillSpans, damageSetSpans, + damagePutImage, damageCopyArea, + damageCopyPlane, damagePolyPoint, + damagePolylines, damagePolySegment, + damagePolyRectangle, damagePolyArc, + damageFillPolygon, damagePolyFillRect, + damagePolyFillArc, damagePolyText8, + damagePolyText16, damageImageText8, + damageImageText16, damageImageGlyphBlt, + damagePolyGlyphBlt, damagePushPixels, + {NULL} /* devPrivate */ +}; + +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, CopyWindow); + unwrap (pScrPriv, pScreen, CloseScreen); + free(pScrPriv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +/** + * Default implementations of the damage management functions. + */ +void miDamageCreate (DamagePtr pDamage) +{ +} + +void miDamageRegister (DrawablePtr pDrawable, DamagePtr pDamage) +{ +} + +void miDamageUnregister (DrawablePtr pDrawable, DamagePtr pDamage) +{ +} + +void miDamageDestroy (DamagePtr pDamage) +{ +} + +/** + * Public functions for consumption outside this file. + */ + +Bool +DamageSetup (ScreenPtr pScreen) +{ + DamageScrPrivPtr pScrPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + const DamageScreenFuncsRec miFuncs = { + miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy + }; + + if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey)) + return TRUE; + + if (!dixRequestPrivate(damageGCPrivateKey, sizeof(DamageGCPrivRec))) + return FALSE; + + pScrPriv = malloc(sizeof (DamageScrPrivRec)); + if (!pScrPriv) + return FALSE; + + pScrPriv->internalLevel = 0; + pScrPriv->pScreenDamage = 0; + + wrap (pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap); + wrap (pScrPriv, pScreen, CreateGC, damageCreateGC); + wrap (pScrPriv, pScreen, DestroyWindow, damageDestroyWindow); + wrap (pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap); + wrap (pScrPriv, pScreen, CopyWindow, damageCopyWindow); + wrap (pScrPriv, pScreen, CloseScreen, damageCloseScreen); + if (ps) { + wrap (pScrPriv, ps, Glyphs, damageGlyphs); + wrap (pScrPriv, ps, Composite, damageComposite); + wrap (pScrPriv, ps, AddTraps, damageAddTraps); + } + + pScrPriv->funcs = miFuncs; + + dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv); + return TRUE; +} + +DamagePtr +DamageCreate (DamageReportFunc damageReport, + DamageDestroyFunc damageDestroy, + DamageReportLevel damageLevel, + Bool isInternal, + ScreenPtr pScreen, + void *closure) +{ + damageScrPriv(pScreen); + DamagePtr pDamage; + + pDamage = malloc(sizeof (DamageRec)); + if (!pDamage) + return 0; + pDamage->pNext = 0; + pDamage->pNextWin = 0; + REGION_NULL(pScreen, &pDamage->damage); + REGION_NULL(pScreen, &pDamage->pendingDamage); + + pDamage->damageLevel = damageLevel; + pDamage->isInternal = isInternal; + pDamage->closure = closure; + pDamage->isWindow = FALSE; + pDamage->pDrawable = 0; + pDamage->reportAfter = FALSE; + + pDamage->damageReport = damageReport; + pDamage->damageReportPostRendering = NULL; + pDamage->damageDestroy = damageDestroy; + pDamage->damageMarker = NULL; + pDamage->pScreen = pScreen; + pDamage->devPrivates = NULL; + + (*pScrPriv->funcs.Create) (pDamage); + + return pDamage; +} + +void +DamageRegister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + +#if DAMAGE_VALIDATE_ENABLE + if (pDrawable->pScreen != pDamage->pScreen) + { + ErrorF ("DamageRegister called with mismatched screens\n"); + OsAbort (); + } +#endif + + 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"); + OsAbort (); + } +#endif + pDamage->pNextWin = *pPrev; + *pPrev = pDamage; + pDamage->isWindow = TRUE; + } + else + pDamage->isWindow = FALSE; + pDamage->pDrawable = pDrawable; + damageInsertDamage (getDrawableDamageRef (pDrawable), pDamage); + (*pScrPriv->funcs.Register) (pDrawable, pDamage); +} + +void +DamageDrawInternal (ScreenPtr pScreen, Bool enable) +{ + damageScrPriv (pScreen); + + pScrPriv->internalLevel += enable ? 1 : -1; +} + +void +DamageUnregister (DrawablePtr pDrawable, + DamagePtr pDamage) +{ + ScreenPtr pScreen = pDrawable->pScreen; + damageScrPriv(pScreen); + + (*pScrPriv->funcs.Unregister) (pDrawable, 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"); + OsAbort (); + } +#endif + } + pDamage->pDrawable = 0; + damageRemoveDamage (getDrawableDamageRef (pDrawable), pDamage); +} + +void +DamageDestroy (DamagePtr pDamage) +{ + ScreenPtr pScreen = pDamage->pScreen; + damageScrPriv(pScreen); + + if (pDamage->damageDestroy) + (*pDamage->damageDestroy) (pDamage, pDamage->closure); + (*pScrPriv->funcs.Destroy) (pDamage); + dixFreePrivates(pDamage->devPrivates); + pDamage->devPrivates = NULL; + REGION_UNINIT (pScreen, &pDamage->damage); + REGION_UNINIT (pScreen, &pDamage->pendingDamage); + free(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); + if (pDrawable->type != DRAWABLE_WINDOW) + REGION_UNINIT(pDrawable->pScreen, &pixmapClip); + } + 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; +} + +RegionPtr +DamagePendingRegion (DamagePtr pDamage) +{ + return &pDamage->pendingDamage; +} + +void +DamageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion) +{ + damageRegionAppend (pDrawable, pRegion, FALSE, -1); +} + +void +DamageRegionProcessPending (DrawablePtr pDrawable) +{ + damageRegionProcessPending (pDrawable); +} + +/* If a damage marker is provided, then this function must be called after rendering is done. */ +/* Please do call back so any future enhancements can assume this function is called. */ +/* There are no strict timing requirements for calling this function, just as soon as (is cheaply) possible. */ +void +DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion) +{ + if (pDamage->damageReportPostRendering) + damageReportDamagePostRendering (pDamage, pOldDamage, pRegion); +} + +/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */ +void +DamageDamageRegion (DrawablePtr pDrawable, + RegionPtr pRegion) +{ + damageRegionAppend (pDrawable, pRegion, FALSE, -1); + + /* Go back and report this damage for DamagePtrs with reportAfter set, since + * this call isn't part of an in-progress drawing op in the call chain and + * the DDX probably just wants to know about it right away. + */ + damageRegionProcessPending (pDrawable); +} + +void +DamageSetReportAfterOp (DamagePtr pDamage, Bool reportAfter) +{ + pDamage->reportAfter = reportAfter; +} + +void +DamageSetPostRenderingFunctions(DamagePtr pDamage, DamageReportFunc damageReportPostRendering, + DamageMarkerFunc damageMarker) +{ + pDamage->damageReportPostRendering = damageReportPostRendering; + pDamage->damageMarker = damageMarker; +} + +DamageScreenFuncsPtr +DamageGetScreenFuncs (ScreenPtr pScreen) +{ + damageScrPriv(pScreen); + return &pScrPriv->funcs; +} diff --git a/xorg-server/miext/rootless/rootlessScreen.c b/xorg-server/miext/rootless/rootlessScreen.c index 5f249467b..6f9341d85 100644 --- a/xorg-server/miext/rootless/rootlessScreen.c +++ b/xorg-server/miext/rootless/rootlessScreen.c @@ -1,755 +1,755 @@ -/* - * Screen routines for generic rootless X server - */ -/* - * Copyright (c) 2001 Greg Parker. All Rights Reserved. - * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "mi.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "mivalidate.h" -#include "picturestr.h" -#include "colormapst.h" - -#include -#include -#include -#include - -#include "rootlessCommon.h" -#include "rootlessWindow.h" - -/* In milliseconds */ -#ifndef ROOTLESS_REDISPLAY_DELAY -#define ROOTLESS_REDISPLAY_DELAY 10 -#endif - -extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, - VTKind kind); -extern Bool RootlessCreateGC(GCPtr pGC); - -// Initialize globals -static int rootlessGCPrivateKeyIndex; -DevPrivateKey rootlessGCPrivateKey = &rootlessGCPrivateKeyIndex; -static int rootlessScreenPrivateKeyIndex; -DevPrivateKey rootlessScreenPrivateKey = &rootlessScreenPrivateKeyIndex; -static int rootlessWindowPrivateKeyIndex; -DevPrivateKey rootlessWindowPrivateKey = &rootlessWindowPrivateKeyIndex; -static int rootlessWindowOldPixmapPrivateKeyIndex; -DevPrivateKey rootlessWindowOldPixmapPrivateKey = &rootlessWindowOldPixmapPrivateKeyIndex; - - -/* - * RootlessUpdateScreenPixmap - * miCreateScreenResources does not like a null framebuffer pointer, - * it leaves the screen pixmap with an uninitialized data pointer. - * Thus, rootless implementations typically set the framebuffer width - * to zero so that miCreateScreenResources does not allocate a screen - * pixmap for us. We allocate our own screen pixmap here since we need - * the screen pixmap to be valid (e.g. CopyArea from the root window). - */ -void -RootlessUpdateScreenPixmap(ScreenPtr pScreen) -{ - RootlessScreenRec *s = SCREENREC(pScreen); - PixmapPtr pPix; - unsigned int rowbytes; - - pPix = (*pScreen->GetScreenPixmap)(pScreen); - if (pPix == NULL) { - pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); - (*pScreen->SetScreenPixmap)(pPix); - } - - rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); - - if (s->pixmap_data_size < rowbytes) { - if (s->pixmap_data != NULL) - xfree(s->pixmap_data); - - s->pixmap_data_size = rowbytes; - s->pixmap_data = xalloc(s->pixmap_data_size); - if (s->pixmap_data == NULL) - return; - - memset(s->pixmap_data, 0xFF, s->pixmap_data_size); - - pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, - pScreen->rootDepth, - BitsPerPixel(pScreen->rootDepth), - 0, s->pixmap_data); - /* ModifyPixmapHeader ignores zero arguments, so install rowbytes - by hand. */ - pPix->devKind = 0; - } -} - - -/* - * RootlessCreateScreenResources - * Rootless implementations typically set a null framebuffer pointer, which - * causes problems with miCreateScreenResources. We fix things up here. - */ -static Bool -RootlessCreateScreenResources(ScreenPtr pScreen) -{ - Bool ret = TRUE; - - SCREEN_UNWRAP(pScreen, CreateScreenResources); - - if (pScreen->CreateScreenResources != NULL) - ret = (*pScreen->CreateScreenResources)(pScreen); - - SCREEN_WRAP(pScreen, CreateScreenResources); - - if (!ret) - return ret; - - /* Make sure we have a valid screen pixmap. */ - - RootlessUpdateScreenPixmap(pScreen); - - return ret; -} - - -static Bool -RootlessCloseScreen(int i, ScreenPtr pScreen) -{ - RootlessScreenRec *s; - - s = SCREENREC(pScreen); - - // fixme unwrap everything that was wrapped? - pScreen->CloseScreen = s->CloseScreen; - - if (s->pixmap_data != NULL) { - xfree (s->pixmap_data); - s->pixmap_data = NULL; - s->pixmap_data_size = 0; - } - - xfree(s); - return pScreen->CloseScreen(i, pScreen); -} - - -static void -RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planeMask, char *pdstLine) -{ - ScreenPtr pScreen = pDrawable->pScreen; - SCREEN_UNWRAP(pScreen, GetImage); - - if (pDrawable->type == DRAWABLE_WINDOW) { - int x0, y0, x1, y1; - RootlessWindowRec *winRec; - - // Many apps use GetImage to sync with the visible frame buffer - // FIXME: entire screen or just window or all screens? - RootlessRedisplayScreen(pScreen); - - // RedisplayScreen stops drawing, so we need to start it again - RootlessStartDrawing((WindowPtr)pDrawable); - - /* Check that we have some place to read from. */ - winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); - if (winRec == NULL) - goto out; - - /* Clip to top-level window bounds. */ - /* FIXME: fbGetImage uses the width parameter to calculate the - stride of the destination pixmap. If w is clipped, the data - returned will be garbage, although we will not crash. */ - - x0 = pDrawable->x + sx; - y0 = pDrawable->y + sy; - x1 = x0 + w; - y1 = y0 + h; - - x0 = max (x0, winRec->x); - y0 = max (y0, winRec->y); - x1 = min (x1, winRec->x + winRec->width); - y1 = min (y1, winRec->y + winRec->height); - - sx = x0 - pDrawable->x; - sy = y0 - pDrawable->y; - w = x1 - x0; - h = y1 - y0; - - if (w <= 0 || h <= 0) - goto out; - } - - pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); - -out: - SCREEN_WRAP(pScreen, GetImage); -} - - -/* - * RootlessSourceValidate - * CopyArea and CopyPlane use a GC tied to the destination drawable. - * StartDrawing/StopDrawing wrappers won't be called if source is - * a visible window but the destination isn't. So, we call StartDrawing - * here and leave StopDrawing for the block handler. - */ -static void -RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h) -{ - SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); - if (pDrawable->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDrawable; - RootlessStartDrawing(pWin); - } - if (pDrawable->pScreen->SourceValidate) { - pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h); - } - SCREEN_WRAP(pDrawable->pScreen, SourceValidate); -} - -static void -RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - WindowPtr srcWin, dstWin, maskWin = NULL; - - if (pMask) { // pMask can be NULL - maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pMask->pDrawable : NULL; - } - srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pSrc->pDrawable : NULL; - dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pDst->pDrawable : NULL; - - // SCREEN_UNWRAP(ps, Composite); - ps->Composite = SCREENREC(pScreen)->Composite; - - if (srcWin && IsFramedWindow(srcWin)) - RootlessStartDrawing(srcWin); - if (maskWin && IsFramedWindow(maskWin)) - RootlessStartDrawing(maskWin); - if (dstWin && IsFramedWindow(dstWin)) - RootlessStartDrawing(dstWin); - - ps->Composite(op, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); - - if (dstWin && IsFramedWindow(dstWin)) { - RootlessDamageRect(dstWin, xDst, yDst, width, height); - } - - ps->Composite = RootlessComposite; - // SCREEN_WRAP(ps, Composite); -} - - -static void -RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int nlist, GlyphListPtr list, GlyphPtr *glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - int x, y; - int n; - GlyphPtr glyph; - WindowPtr srcWin, dstWin; - - srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pSrc->pDrawable : NULL; - dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pDst->pDrawable : NULL; - - if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); - if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); - - //SCREEN_UNWRAP(ps, Glyphs); - ps->Glyphs = SCREENREC(pScreen)->Glyphs; - ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - ps->Glyphs = RootlessGlyphs; - //SCREEN_WRAP(ps, Glyphs); - - if (dstWin && IsFramedWindow(dstWin)) { - x = xSrc; - y = ySrc; - - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - - /* Calling DamageRect for the bounding box of each glyph is - inefficient. So compute the union of all glyphs in a list - and damage that. */ - - if (n > 0) { - BoxRec box; - - glyph = *glyphs++; - - box.x1 = x - glyph->info.x; - box.y1 = y - glyph->info.y; - box.x2 = box.x1 + glyph->info.width; - box.y2 = box.y2 + glyph->info.height; - - x += glyph->info.xOff; - y += glyph->info.yOff; - - while (--n > 0) { - short x1, y1, x2, y2; - - glyph = *glyphs++; - - x1 = x - glyph->info.x; - y1 = y - glyph->info.y; - x2 = x1 + glyph->info.width; - y2 = y1 + glyph->info.height; - - box.x1 = max (box.x1, x1); - box.y1 = max (box.y1, y1); - box.x2 = max (box.x2, x2); - box.y2 = max (box.y2, y2); - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - - RootlessDamageBox(dstWin, &box); - } - list++; - } - } -} - - -/* - * RootlessValidateTree - * ValidateTree is modified in two ways: - * - top-level windows don't clip each other - * - windows aren't clipped against root. - * These only matter when validating from the root. - */ -static int -RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) -{ - int result; - RegionRec saveRoot; - ScreenPtr pScreen = pParent->drawable.pScreen; - - SCREEN_UNWRAP(pScreen, ValidateTree); - RL_DEBUG_MSG("VALIDATETREE start "); - - // Use our custom version to validate from root - if (IsRoot(pParent)) { - RL_DEBUG_MSG("custom "); - result = RootlessMiValidateTree(pParent, pChild, kind); - } else { - HUGE_ROOT(pParent); - result = pScreen->ValidateTree(pParent, pChild, kind); - NORMAL_ROOT(pParent); - } - - SCREEN_WRAP(pScreen, ValidateTree); - RL_DEBUG_MSG("VALIDATETREE end\n"); - - return result; -} - - -/* - * RootlessMarkOverlappedWindows - * MarkOverlappedWindows is modified to ignore overlapping - * top-level windows. - */ -static Bool -RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, - WindowPtr *ppLayerWin) -{ - RegionRec saveRoot; - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); - RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); - - HUGE_ROOT(pWin); - if (IsRoot(pWin)) { - // root - mark nothing - RL_DEBUG_MSG("is root not marking "); - result = FALSE; - } - else if (! IsTopLevel(pWin)) { - // not top-level window - mark normally - result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); - } - else { - //top-level window - mark children ONLY - NO overlaps with sibs (?) - // This code copied from miMarkOverlappedWindows() - - register WindowPtr pChild; - Bool anyMarked = FALSE; - MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; - - RL_DEBUG_MSG("is top level! "); - /* single layered systems are easy */ - if (ppLayerWin) *ppLayerWin = pWin; - - if (pWin == pFirst) { - /* Blindly mark pWin and all of its inferiors. This is a slight - * overkill if there are mapped windows that outside pWin's border, - * but it's better than wasting time on RectIn checks. - */ - pChild = pWin; - while (1) { - if (pChild->viewable) { - if (REGION_BROKEN (pScreen, &pChild->winSize)) - SetWinSize (pChild); - if (REGION_BROKEN (pScreen, &pChild->borderSize)) - SetBorderSize (pChild); - (* MarkWindow)(pChild); - if (pChild->firstChild) { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pWin)) - pChild = pChild->parent; - if (pChild == pWin) - break; - pChild = pChild->nextSib; - } - anyMarked = TRUE; - pFirst = pFirst->nextSib; - } - if (anyMarked) - (* MarkWindow)(pWin->parent); - result = anyMarked; - } - NORMAL_ROOT(pWin); - SCREEN_WRAP(pScreen, MarkOverlappedWindows); - RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); - - return result; -} - -static void expose_1 (WindowPtr pWin) { - WindowPtr pChild; - - if (!pWin->realized) - return; - - miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); - - /* FIXME: comments in windowstr.h indicate that borderClip doesn't - include subwindow visibility. But I'm not so sure.. so we may - be exposing too much.. */ - - miSendExposures (pWin, &pWin->borderClip, - pWin->drawable.x, pWin->drawable.y); - - for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) - expose_1 (pChild); -} - -void -RootlessScreenExpose (ScreenPtr pScreen) -{ - expose_1 (WindowTable[pScreen->myNum]); -} - - -ColormapPtr -RootlessGetColormap (ScreenPtr pScreen) -{ - RootlessScreenRec *s = SCREENREC (pScreen); - - return s->colormap; -} - -static void -RootlessInstallColormap (ColormapPtr pMap) -{ - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); - - SCREEN_UNWRAP(pScreen, InstallColormap); - - if (s->colormap != pMap) { - s->colormap = pMap; - s->colormap_changed = TRUE; - RootlessQueueRedisplay (pScreen); - } - - pScreen->InstallColormap (pMap); - - SCREEN_WRAP (pScreen, InstallColormap); -} - -static void -RootlessUninstallColormap (ColormapPtr pMap) -{ - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); - - SCREEN_UNWRAP(pScreen, UninstallColormap); - - if (s->colormap == pMap) - s->colormap = NULL; - - pScreen->UninstallColormap (pMap); - - SCREEN_WRAP(pScreen, UninstallColormap); -} - -static void -RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) -{ - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); - - SCREEN_UNWRAP(pScreen, StoreColors); - - if (s->colormap == pMap && ndef > 0) { - s->colormap_changed = TRUE; - RootlessQueueRedisplay (pScreen); - } - - pScreen->StoreColors (pMap, ndef, pdef); - - SCREEN_WRAP(pScreen, StoreColors); -} - - -static CARD32 -RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) -{ - RootlessScreenRec *screenRec = arg; - - if (!screenRec->redisplay_queued) { - /* No update needed. Stop the timer. */ - - screenRec->redisplay_timer_set = FALSE; - return 0; - } - - screenRec->redisplay_queued = FALSE; - - /* Mark that we should redisplay before waiting for I/O next time */ - screenRec->redisplay_expired = TRUE; - - /* Reinstall the timer immediately, so we get as close to our - redisplay interval as possible. */ - - return ROOTLESS_REDISPLAY_DELAY; -} - - -/* - * RootlessQueueRedisplay - * Queue a redisplay after a timer delay to ensure we do not redisplay - * too frequently. - */ -void -RootlessQueueRedisplay(ScreenPtr pScreen) -{ - RootlessScreenRec *screenRec = SCREENREC(pScreen); - - screenRec->redisplay_queued = TRUE; - - if (screenRec->redisplay_timer_set) - return; - - screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, - 0, ROOTLESS_REDISPLAY_DELAY, - RootlessRedisplayCallback, - screenRec); - screenRec->redisplay_timer_set = TRUE; -} - - -/* - * RootlessBlockHandler - * If the redisplay timer has expired, flush drawing before blocking - * on select(). - */ -static void -RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) -{ - ScreenPtr pScreen = pbdata; - RootlessScreenRec *screenRec = SCREENREC(pScreen); - - if (screenRec->redisplay_expired) { - screenRec->redisplay_expired = FALSE; - - RootlessRedisplayScreen(pScreen); - } -} - - -static void -RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) -{ - // nothing here -} - - -static Bool -RootlessAllocatePrivates(ScreenPtr pScreen) -{ - RootlessScreenRec *s; - - // no allocation needed for screen privates - if (!dixRequestPrivate(rootlessGCPrivateKey, sizeof(RootlessGCRec))) - return FALSE; - - s = xalloc(sizeof(RootlessScreenRec)); - if (! s) return FALSE; - SETSCREENREC(pScreen, s); - - s->pixmap_data = NULL; - s->pixmap_data_size = 0; - - s->redisplay_timer = NULL; - s->redisplay_timer_set = FALSE; - - return TRUE; -} - - -static void -RootlessWrap(ScreenPtr pScreen) -{ - RootlessScreenRec *s = SCREENREC(pScreen); - -#define WRAP(a) \ - if (pScreen->a) { \ - s->a = pScreen->a; \ - } else { \ - RL_DEBUG_MSG("null screen fn " #a "\n"); \ - s->a = NULL; \ - } \ - pScreen->a = Rootless##a - - WRAP(CreateScreenResources); - WRAP(CloseScreen); - WRAP(CreateGC); - WRAP(CopyWindow); - WRAP(GetImage); - WRAP(SourceValidate); - WRAP(CreateWindow); - WRAP(DestroyWindow); - WRAP(RealizeWindow); - WRAP(UnrealizeWindow); - WRAP(MoveWindow); - WRAP(PositionWindow); - WRAP(ResizeWindow); - WRAP(RestackWindow); - WRAP(ReparentWindow); - WRAP(ChangeBorderWidth); - WRAP(MarkOverlappedWindows); - WRAP(ValidateTree); - WRAP(ChangeWindowAttributes); - WRAP(InstallColormap); - WRAP(UninstallColormap); - WRAP(StoreColors); - - WRAP(SetShape); - - { - // Composite and Glyphs don't use normal screen wrapping - PictureScreenPtr ps = GetPictureScreen(pScreen); - s->Composite = ps->Composite; - ps->Composite = RootlessComposite; - s->Glyphs = ps->Glyphs; - ps->Glyphs = RootlessGlyphs; - } - - // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? - -#undef WRAP -} - - -/* - * RootlessInit - * Called by the rootless implementation to initialize the rootless layer. - * Rootless wraps lots of stuff and needs a bunch of devPrivates. - */ -Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) -{ - RootlessScreenRec *s; - - if (!RootlessAllocatePrivates(pScreen)) - return FALSE; - - s = SCREENREC(pScreen); - - s->imp = procs; - s->colormap = NULL; - s->redisplay_expired = FALSE; - - RootlessWrap(pScreen); - - if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, - RootlessWakeupHandler, - (pointer) pScreen)) - { - return FALSE; - } - - return TRUE; -} - -void RootlessUpdateRooted (Bool state) { - int i; - - if (!state) - { - for (i = 0; i < screenInfo.numScreens; i++) - RootlessDisableRoot (screenInfo.screens[i]); - } - else - { - for (i = 0; i < screenInfo.numScreens; i++) - RootlessEnableRoot (screenInfo.screens[i]); - } -} +/* + * Screen routines for generic rootless X server + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "mivalidate.h" +#include "picturestr.h" +#include "colormapst.h" + +#include +#include +#include +#include + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +/* In milliseconds */ +#ifndef ROOTLESS_REDISPLAY_DELAY +#define ROOTLESS_REDISPLAY_DELAY 10 +#endif + +extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, + VTKind kind); +extern Bool RootlessCreateGC(GCPtr pGC); + +// Initialize globals +static int rootlessGCPrivateKeyIndex; +DevPrivateKey rootlessGCPrivateKey = &rootlessGCPrivateKeyIndex; +static int rootlessScreenPrivateKeyIndex; +DevPrivateKey rootlessScreenPrivateKey = &rootlessScreenPrivateKeyIndex; +static int rootlessWindowPrivateKeyIndex; +DevPrivateKey rootlessWindowPrivateKey = &rootlessWindowPrivateKeyIndex; +static int rootlessWindowOldPixmapPrivateKeyIndex; +DevPrivateKey rootlessWindowOldPixmapPrivateKey = &rootlessWindowOldPixmapPrivateKeyIndex; + + +/* + * RootlessUpdateScreenPixmap + * miCreateScreenResources does not like a null framebuffer pointer, + * it leaves the screen pixmap with an uninitialized data pointer. + * Thus, rootless implementations typically set the framebuffer width + * to zero so that miCreateScreenResources does not allocate a screen + * pixmap for us. We allocate our own screen pixmap here since we need + * the screen pixmap to be valid (e.g. CopyArea from the root window). + */ +void +RootlessUpdateScreenPixmap(ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC(pScreen); + PixmapPtr pPix; + unsigned int rowbytes; + + pPix = (*pScreen->GetScreenPixmap)(pScreen); + if (pPix == NULL) { + pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); + (*pScreen->SetScreenPixmap)(pPix); + } + + rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); + + if (s->pixmap_data_size < rowbytes) { + if (s->pixmap_data != NULL) + free(s->pixmap_data); + + s->pixmap_data_size = rowbytes; + s->pixmap_data = malloc(s->pixmap_data_size); + if (s->pixmap_data == NULL) + return; + + memset(s->pixmap_data, 0xFF, s->pixmap_data_size); + + pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, + pScreen->rootDepth, + BitsPerPixel(pScreen->rootDepth), + 0, s->pixmap_data); + /* ModifyPixmapHeader ignores zero arguments, so install rowbytes + by hand. */ + pPix->devKind = 0; + } +} + + +/* + * RootlessCreateScreenResources + * Rootless implementations typically set a null framebuffer pointer, which + * causes problems with miCreateScreenResources. We fix things up here. + */ +static Bool +RootlessCreateScreenResources(ScreenPtr pScreen) +{ + Bool ret = TRUE; + + SCREEN_UNWRAP(pScreen, CreateScreenResources); + + if (pScreen->CreateScreenResources != NULL) + ret = (*pScreen->CreateScreenResources)(pScreen); + + SCREEN_WRAP(pScreen, CreateScreenResources); + + if (!ret) + return ret; + + /* Make sure we have a valid screen pixmap. */ + + RootlessUpdateScreenPixmap(pScreen); + + return ret; +} + + +static Bool +RootlessCloseScreen(int i, ScreenPtr pScreen) +{ + RootlessScreenRec *s; + + s = SCREENREC(pScreen); + + // fixme unwrap everything that was wrapped? + pScreen->CloseScreen = s->CloseScreen; + + if (s->pixmap_data != NULL) { + free(s->pixmap_data); + s->pixmap_data = NULL; + s->pixmap_data_size = 0; + } + + free(s); + return pScreen->CloseScreen(i, pScreen); +} + + +static void +RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planeMask, char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_UNWRAP(pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) { + int x0, y0, x1, y1; + RootlessWindowRec *winRec; + + // Many apps use GetImage to sync with the visible frame buffer + // FIXME: entire screen or just window or all screens? + RootlessRedisplayScreen(pScreen); + + // RedisplayScreen stops drawing, so we need to start it again + RootlessStartDrawing((WindowPtr)pDrawable); + + /* Check that we have some place to read from. */ + winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); + if (winRec == NULL) + goto out; + + /* Clip to top-level window bounds. */ + /* FIXME: fbGetImage uses the width parameter to calculate the + stride of the destination pixmap. If w is clipped, the data + returned will be garbage, although we will not crash. */ + + x0 = pDrawable->x + sx; + y0 = pDrawable->y + sy; + x1 = x0 + w; + y1 = y0 + h; + + x0 = max (x0, winRec->x); + y0 = max (y0, winRec->y); + x1 = min (x1, winRec->x + winRec->width); + y1 = min (y1, winRec->y + winRec->height); + + sx = x0 - pDrawable->x; + sy = y0 - pDrawable->y; + w = x1 - x0; + h = y1 - y0; + + if (w <= 0 || h <= 0) + goto out; + } + + pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + +out: + SCREEN_WRAP(pScreen, GetImage); +} + + +/* + * RootlessSourceValidate + * CopyArea and CopyPlane use a GC tied to the destination drawable. + * StartDrawing/StopDrawing wrappers won't be called if source is + * a visible window but the destination isn't. So, we call StartDrawing + * here and leave StopDrawing for the block handler. + */ +static void +RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h) +{ + SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); + if (pDrawable->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDrawable; + RootlessStartDrawing(pWin); + } + if (pDrawable->pScreen->SourceValidate) { + pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h); + } + SCREEN_WRAP(pDrawable->pScreen, SourceValidate); +} + +static void +RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr srcWin, dstWin, maskWin = NULL; + + if (pMask) { // pMask can be NULL + maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pMask->pDrawable : NULL; + } + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + // SCREEN_UNWRAP(ps, Composite); + ps->Composite = SCREENREC(pScreen)->Composite; + + if (srcWin && IsFramedWindow(srcWin)) + RootlessStartDrawing(srcWin); + if (maskWin && IsFramedWindow(maskWin)) + RootlessStartDrawing(maskWin); + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); + + ps->Composite(op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + + if (dstWin && IsFramedWindow(dstWin)) { + RootlessDamageRect(dstWin, xDst, yDst, width, height); + } + + ps->Composite = RootlessComposite; + // SCREEN_WRAP(ps, Composite); +} + + +static void +RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + int x, y; + int n; + GlyphPtr glyph; + WindowPtr srcWin, dstWin; + + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); + if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); + + //SCREEN_UNWRAP(ps, Glyphs); + ps->Glyphs = SCREENREC(pScreen)->Glyphs; + ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + ps->Glyphs = RootlessGlyphs; + //SCREEN_WRAP(ps, Glyphs); + + if (dstWin && IsFramedWindow(dstWin)) { + x = xSrc; + y = ySrc; + + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + + /* Calling DamageRect for the bounding box of each glyph is + inefficient. So compute the union of all glyphs in a list + and damage that. */ + + if (n > 0) { + BoxRec box; + + glyph = *glyphs++; + + box.x1 = x - glyph->info.x; + box.y1 = y - glyph->info.y; + box.x2 = box.x1 + glyph->info.width; + box.y2 = box.y2 + glyph->info.height; + + x += glyph->info.xOff; + y += glyph->info.yOff; + + while (--n > 0) { + short x1, y1, x2, y2; + + glyph = *glyphs++; + + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + + box.x1 = max (box.x1, x1); + box.y1 = max (box.y1, y1); + box.x2 = max (box.x2, x2); + box.y2 = max (box.y2, y2); + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + RootlessDamageBox(dstWin, &box); + } + list++; + } + } +} + + +/* + * RootlessValidateTree + * ValidateTree is modified in two ways: + * - top-level windows don't clip each other + * - windows aren't clipped against root. + * These only matter when validating from the root. + */ +static int +RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + int result; + RegionRec saveRoot; + ScreenPtr pScreen = pParent->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE start "); + + // Use our custom version to validate from root + if (IsRoot(pParent)) { + RL_DEBUG_MSG("custom "); + result = RootlessMiValidateTree(pParent, pChild, kind); + } else { + HUGE_ROOT(pParent); + result = pScreen->ValidateTree(pParent, pChild, kind); + NORMAL_ROOT(pParent); + } + + SCREEN_WRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE end\n"); + + return result; +} + + +/* + * RootlessMarkOverlappedWindows + * MarkOverlappedWindows is modified to ignore overlapping + * top-level windows. + */ +static Bool +RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, + WindowPtr *ppLayerWin) +{ + RegionRec saveRoot; + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); + + HUGE_ROOT(pWin); + if (IsRoot(pWin)) { + // root - mark nothing + RL_DEBUG_MSG("is root not marking "); + result = FALSE; + } + else if (! IsTopLevel(pWin)) { + // not top-level window - mark normally + result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); + } + else { + //top-level window - mark children ONLY - NO overlaps with sibs (?) + // This code copied from miMarkOverlappedWindows() + + register WindowPtr pChild; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; + + RL_DEBUG_MSG("is top level! "); + /* single layered systems are easy */ + if (ppLayerWin) *ppLayerWin = pWin; + + if (pWin == pFirst) { + /* Blindly mark pWin and all of its inferiors. This is a slight + * overkill if there are mapped windows that outside pWin's border, + * but it's better than wasting time on RectIn checks. + */ + pChild = pWin; + while (1) { + if (pChild->viewable) { + if (REGION_BROKEN (pScreen, &pChild->winSize)) + SetWinSize (pChild); + if (REGION_BROKEN (pScreen, &pChild->borderSize)) + SetBorderSize (pChild); + (* MarkWindow)(pChild); + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + anyMarked = TRUE; + pFirst = pFirst->nextSib; + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + result = anyMarked; + } + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); + + return result; +} + +static void expose_1 (WindowPtr pWin) { + WindowPtr pChild; + + if (!pWin->realized) + return; + + miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); + + /* FIXME: comments in windowstr.h indicate that borderClip doesn't + include subwindow visibility. But I'm not so sure.. so we may + be exposing too much.. */ + + miSendExposures (pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + + for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) + expose_1 (pChild); +} + +void +RootlessScreenExpose (ScreenPtr pScreen) +{ + expose_1 (WindowTable[pScreen->myNum]); +} + + +ColormapPtr +RootlessGetColormap (ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC (pScreen); + + return s->colormap; +} + +static void +RootlessInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, InstallColormap); + + if (s->colormap != pMap) { + s->colormap = pMap; + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->InstallColormap (pMap); + + SCREEN_WRAP (pScreen, InstallColormap); +} + +static void +RootlessUninstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, UninstallColormap); + + if (s->colormap == pMap) + s->colormap = NULL; + + pScreen->UninstallColormap (pMap); + + SCREEN_WRAP(pScreen, UninstallColormap); +} + +static void +RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, StoreColors); + + if (s->colormap == pMap && ndef > 0) { + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->StoreColors (pMap, ndef, pdef); + + SCREEN_WRAP(pScreen, StoreColors); +} + + +static CARD32 +RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) +{ + RootlessScreenRec *screenRec = arg; + + if (!screenRec->redisplay_queued) { + /* No update needed. Stop the timer. */ + + screenRec->redisplay_timer_set = FALSE; + return 0; + } + + screenRec->redisplay_queued = FALSE; + + /* Mark that we should redisplay before waiting for I/O next time */ + screenRec->redisplay_expired = TRUE; + + /* Reinstall the timer immediately, so we get as close to our + redisplay interval as possible. */ + + return ROOTLESS_REDISPLAY_DELAY; +} + + +/* + * RootlessQueueRedisplay + * Queue a redisplay after a timer delay to ensure we do not redisplay + * too frequently. + */ +void +RootlessQueueRedisplay(ScreenPtr pScreen) +{ + RootlessScreenRec *screenRec = SCREENREC(pScreen); + + screenRec->redisplay_queued = TRUE; + + if (screenRec->redisplay_timer_set) + return; + + screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, + 0, ROOTLESS_REDISPLAY_DELAY, + RootlessRedisplayCallback, + screenRec); + screenRec->redisplay_timer_set = TRUE; +} + + +/* + * RootlessBlockHandler + * If the redisplay timer has expired, flush drawing before blocking + * on select(). + */ +static void +RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = pbdata; + RootlessScreenRec *screenRec = SCREENREC(pScreen); + + if (screenRec->redisplay_expired) { + screenRec->redisplay_expired = FALSE; + + RootlessRedisplayScreen(pScreen); + } +} + + +static void +RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) +{ + // nothing here +} + + +static Bool +RootlessAllocatePrivates(ScreenPtr pScreen) +{ + RootlessScreenRec *s; + + // no allocation needed for screen privates + if (!dixRequestPrivate(rootlessGCPrivateKey, sizeof(RootlessGCRec))) + return FALSE; + + s = malloc(sizeof(RootlessScreenRec)); + if (! s) return FALSE; + SETSCREENREC(pScreen, s); + + s->pixmap_data = NULL; + s->pixmap_data_size = 0; + + s->redisplay_timer = NULL; + s->redisplay_timer_set = FALSE; + + return TRUE; +} + + +static void +RootlessWrap(ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC(pScreen); + +#define WRAP(a) \ + if (pScreen->a) { \ + s->a = pScreen->a; \ + } else { \ + RL_DEBUG_MSG("null screen fn " #a "\n"); \ + s->a = NULL; \ + } \ + pScreen->a = Rootless##a + + WRAP(CreateScreenResources); + WRAP(CloseScreen); + WRAP(CreateGC); + WRAP(CopyWindow); + WRAP(GetImage); + WRAP(SourceValidate); + WRAP(CreateWindow); + WRAP(DestroyWindow); + WRAP(RealizeWindow); + WRAP(UnrealizeWindow); + WRAP(MoveWindow); + WRAP(PositionWindow); + WRAP(ResizeWindow); + WRAP(RestackWindow); + WRAP(ReparentWindow); + WRAP(ChangeBorderWidth); + WRAP(MarkOverlappedWindows); + WRAP(ValidateTree); + WRAP(ChangeWindowAttributes); + WRAP(InstallColormap); + WRAP(UninstallColormap); + WRAP(StoreColors); + + WRAP(SetShape); + + { + // Composite and Glyphs don't use normal screen wrapping + PictureScreenPtr ps = GetPictureScreen(pScreen); + s->Composite = ps->Composite; + ps->Composite = RootlessComposite; + s->Glyphs = ps->Glyphs; + ps->Glyphs = RootlessGlyphs; + } + + // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? + +#undef WRAP +} + + +/* + * RootlessInit + * Called by the rootless implementation to initialize the rootless layer. + * Rootless wraps lots of stuff and needs a bunch of devPrivates. + */ +Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) +{ + RootlessScreenRec *s; + + if (!RootlessAllocatePrivates(pScreen)) + return FALSE; + + s = SCREENREC(pScreen); + + s->imp = procs; + s->colormap = NULL; + s->redisplay_expired = FALSE; + + RootlessWrap(pScreen); + + if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, + RootlessWakeupHandler, + (pointer) pScreen)) + { + return FALSE; + } + + return TRUE; +} + +void RootlessUpdateRooted (Bool state) { + int i; + + if (!state) + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessDisableRoot (screenInfo.screens[i]); + } + else + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessEnableRoot (screenInfo.screens[i]); + } +} diff --git a/xorg-server/miext/rootless/rootlessWindow.c b/xorg-server/miext/rootless/rootlessWindow.c index 55c7b9689..2f412ee43 100644 --- a/xorg-server/miext/rootless/rootlessWindow.c +++ b/xorg-server/miext/rootless/rootlessWindow.c @@ -1,1656 +1,1656 @@ -/* - * Rootless window management - */ -/* - * Copyright (c) 2001 Greg Parker. 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 - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include /* For NULL */ -#include /* For CHAR_BIT */ -#include -#include -#ifdef __APPLE__ -#include -#include "mi.h" -#include "pixmapstr.h" -#include "windowstr.h" -//#include -extern int darwinMainScreenX, darwinMainScreenY; -extern Bool no_configure_window; -#endif -#include "fb.h" - -#include "rootlessCommon.h" -#include "rootlessWindow.h" - -#ifdef ROOTLESS_GLOBAL_COORDS -#define SCREEN_TO_GLOBAL_X \ - (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX) -#define SCREEN_TO_GLOBAL_Y \ - (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY) -#else -#define SCREEN_TO_GLOBAL_X 0 -#define SCREEN_TO_GLOBAL_Y 0 -#endif - -#define DEFINE_ATOM_HELPER(func,atom_name) \ - static Atom func (void) { \ - static unsigned int generation = 0; \ - static Atom atom; \ - if (generation != serverGeneration) { \ - generation = serverGeneration; \ - atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ - } \ - return atom; \ - } - -DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") - -static Bool windows_hidden; -// TODO - abstract xp functions - -#ifdef __APPLE__ - -// XXX: identical to x_cvt_vptr_to_uint ? -#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) - -void -RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) -{ - RootlessWindowRec *winRec; - - if (pWin == NULL) return; - - winRec = WINREC (pWin); - if (winRec == NULL) return; - - winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); - winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); - pWin->rootlessUnhittable = winRec->is_offscreen; -} - -void RootlessNativeWindowMoved (WindowPtr pWin) { - xp_box bounds; - int sx, sy, err; - XID vlist[2]; - Mask mask; - ClientPtr pClient; - RootlessWindowRec *winRec; - - winRec = WINREC(pWin); - - if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; - - sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX; - sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY; - - /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ - vlist[0] = (INT16) bounds.x1 - sx; - vlist[1] = (INT16) bounds.y1 - sy; - mask = CWX | CWY; - - /* pretend we're the owner of the window! */ - err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess); - if(err != Success) { - ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); - return; - } - - /* Don't want to do anything to the physical window (avoids - notification-response feedback loops) */ - - no_configure_window = TRUE; - ConfigureWindow (pWin, mask, vlist, pClient); - no_configure_window = FALSE; -} - -#endif /* __APPLE__ */ - -/* - * RootlessCreateWindow - * For now, don't create a physical window until either the window is - * realized, or we really need it (e.g. to attach VRAM surfaces to). - * Do reset the window size so it's not clipped by the root window. - */ -Bool -RootlessCreateWindow(WindowPtr pWin) -{ - Bool result; - RegionRec saveRoot; - - SETWINREC(pWin, NULL); - dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); - - SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); - - if (!IsRoot(pWin)) { - /* win/border size set by DIX, not by wrapped CreateWindow, so - correct it here. Don't HUGE_ROOT when pWin is the root! */ - - HUGE_ROOT(pWin); - SetWinSize(pWin); - SetBorderSize(pWin); - } - - result = pWin->drawable.pScreen->CreateWindow(pWin); - - if (pWin->parent) { - NORMAL_ROOT(pWin); - } - - SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); - - return result; -} - - -/* - * RootlessDestroyFrame - * Destroy the physical window associated with the given window. - */ -static void -RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid); - -#ifdef ROOTLESS_TRACK_DAMAGE - REGION_UNINIT(pScreen, &winRec->damage); -#endif - - xfree(winRec); - SETWINREC(pWin, NULL); -} - - -/* - * RootlessDestroyWindow - * Destroy the physical window associated with the given window. - */ -Bool -RootlessDestroyWindow(WindowPtr pWin) -{ - RootlessWindowRec *winRec = WINREC(pWin); - Bool result; - - if (winRec != NULL) { - RootlessDestroyFrame(pWin, winRec); - } - - SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); - result = pWin->drawable.pScreen->DestroyWindow(pWin); - SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); - - return result; -} - - - -static Bool -RootlessGetShape(WindowPtr pWin, RegionPtr pShape) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - /* - * Avoid a warning. - * REGION_NULL and the other macros don't actually seem to use pScreen. - */ - (void)pScreen; - - if (wBoundingShape(pWin) == NULL) - return FALSE; - - /* wBoundingShape is relative to *inner* origin of window. - Translate by borderWidth to get the outside-relative position. */ - - REGION_NULL(pScreen, pShape); - REGION_COPY(pScreen, pShape, wBoundingShape(pWin)); - REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth); - - return TRUE; -} - - -/* - * RootlessReshapeFrame - * Set the frame shape. - */ -static void RootlessReshapeFrame(WindowPtr pWin) -{ - RootlessWindowRec *winRec = WINREC(pWin); - ScreenPtr pScreen = pWin->drawable.pScreen; - RegionRec newShape; - RegionPtr pShape; - - // If the window is not yet framed, do nothing - if (winRec == NULL) - return; - - if (IsRoot(pWin)) - return; - - RootlessStopDrawing(pWin, FALSE); - - pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; - -#ifdef ROOTLESSDEBUG - RL_DEBUG_MSG("reshaping..."); - if (pShape != NULL) { - RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", - REGION_NUM_RECTS(&newShape), - newShape.extents.x1, newShape.extents.y1, - newShape.extents.x2, newShape.extents.y2); - } else { - RL_DEBUG_MSG("no shape "); - } -#endif - - SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape); - - if (pShape != NULL) - REGION_UNINIT(pScreen, &newShape); -} - - -/* - * RootlessSetShape - * Shape is usually set before a window is mapped and the window will - * not have a frame associated with it. In this case, the frame will be - * shaped when the window is framed. - */ -void -RootlessSetShape(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - SCREEN_UNWRAP(pScreen, SetShape); - pScreen->SetShape(pWin); - SCREEN_WRAP(pScreen, SetShape); - - RootlessReshapeFrame(pWin); -} - - - -/* Disallow ParentRelative background on top-level windows - because the root window doesn't really have the right background. - */ -Bool -RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) -{ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - - RL_DEBUG_MSG("change window attributes start "); - - SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); - result = pScreen->ChangeWindowAttributes(pWin, vmask); - SCREEN_WRAP(pScreen, ChangeWindowAttributes); - - if (WINREC(pWin)) { - // disallow ParentRelative background state - if (pWin->backgroundState == ParentRelative) { - XID pixel = 0; - ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); - } - } - - RL_DEBUG_MSG("change window attributes end\n"); - return result; -} - - -/* - * RootlessPositionWindow - * This is a hook for when DIX moves or resizes a window. - * Update the frame position now although the physical window is moved - * in RootlessMoveWindow. (x, y) are *inside* position. After this, - * mi and fb are expecting the pixmap to be at the new location. - */ -Bool -RootlessPositionWindow(WindowPtr pWin, int x, int y) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec = WINREC(pWin); - Bool result; - - RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); - - if (winRec) { - if (winRec->is_drawing) { - // Reset frame's pixmap and move it to the new position. - int bw = wBorderWidth(pWin); - - winRec->pixmap->devPrivate.ptr = winRec->pixelData; - SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); - -#ifdef ROOTLESS_TRACK_DAMAGE - // Move damaged region to correspond to new window position - if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { - REGION_TRANSLATE(pScreen, &winRec->damage, - x - bw - winRec->x, - y - bw - winRec->y); - } -#endif - } - } - - SCREEN_UNWRAP(pScreen, PositionWindow); - result = pScreen->PositionWindow(pWin, x, y); - SCREEN_WRAP(pScreen, PositionWindow); - - RL_DEBUG_MSG("positionwindow end\n"); - return result; -} - - -/* - * RootlessInitializeFrame - * Initialize some basic attributes of the frame. Note that winRec - * may already have valid data in it, so don't overwrite anything - * valuable. - */ -static void -RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) -{ - DrawablePtr d = &pWin->drawable; - int bw = wBorderWidth(pWin); - - winRec->win = pWin; - - winRec->x = d->x - bw; - winRec->y = d->y - bw; - winRec->width = d->width + 2*bw; - winRec->height = d->height + 2*bw; - winRec->borderWidth = bw; - -#ifdef ROOTLESS_TRACK_DAMAGE - REGION_NULL(pScreen, &winRec->damage); -#endif -} - -/* - * RootlessEnsureFrame - * Make sure the given window is framed. If the window doesn't have a - * physical window associated with it, attempt to create one. If that - * is unsuccessful, return NULL. - */ -static RootlessWindowRec * -RootlessEnsureFrame(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec; - RegionRec shape; - RegionPtr pShape = NULL; - - if (WINREC(pWin) != NULL) - return WINREC(pWin); - - if (!IsTopLevel(pWin) && !IsRoot(pWin)) - return NULL; - - if (pWin->drawable.class != InputOutput) - return NULL; - - winRec = xalloc(sizeof(RootlessWindowRec)); - - if (!winRec) - return NULL; - - RootlessInitializeFrame(pWin, winRec); - - winRec->is_drawing = FALSE; - winRec->is_reorder_pending = FALSE; - winRec->pixmap = NULL; - winRec->wid = NULL; - winRec->level = 0; - - SETWINREC(pWin, winRec); - - // Set the frame's shape if the window is shaped - if (RootlessGetShape(pWin, &shape)) - pShape = &shape; - - RL_DEBUG_MSG("creating frame "); - - if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, - winRec->x + SCREEN_TO_GLOBAL_X, - winRec->y + SCREEN_TO_GLOBAL_Y, - pShape)) - { - RL_DEBUG_MSG("implementation failed to create frame!\n"); - xfree(winRec); - SETWINREC(pWin, NULL); - return NULL; - } - - if (pWin->drawable.depth == 8) - RootlessFlushWindowColormap(pWin); - - if (pShape != NULL) - REGION_UNINIT(pScreen, &shape); - - return winRec; -} - - -/* - * RootlessRealizeWindow - * The frame is usually created here and not in CreateWindow so that - * windows do not eat memory until they are realized. - */ -Bool -RootlessRealizeWindow(WindowPtr pWin) -{ - Bool result; - RegionRec saveRoot; - ScreenPtr pScreen = pWin->drawable.pScreen; - - RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); - - if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { - RootlessWindowRec *winRec; - - winRec = RootlessEnsureFrame(pWin); - if (winRec == NULL) - return FALSE; - - winRec->is_reorder_pending = TRUE; - - RL_DEBUG_MSG("Top level window "); - - // Disallow ParentRelative background state on top-level windows. - // This might have been set before the window was mapped. - if (pWin->backgroundState == ParentRelative) { - XID pixel = 0; - ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); - } - } - - if (!IsRoot(pWin)) HUGE_ROOT(pWin); - SCREEN_UNWRAP(pScreen, RealizeWindow); - result = pScreen->RealizeWindow(pWin); - SCREEN_WRAP(pScreen, RealizeWindow); - if (!IsRoot(pWin)) NORMAL_ROOT(pWin); - - RL_DEBUG_MSG("realizewindow end\n"); - return result; -} - - -/* - * RootlessFrameForWindow - * Returns the frame ID for the physical window displaying the given window. - * If CREATE is true and the window has no frame, attempt to create one. - */ -RootlessFrameID -RootlessFrameForWindow(WindowPtr pWin, Bool create) -{ - WindowPtr pTopWin; - RootlessWindowRec *winRec; - - pTopWin = TopLevelParent(pWin); - if (pTopWin == NULL) - return NULL; - - winRec = WINREC(pTopWin); - - if (winRec == NULL && create && pWin->drawable.class == InputOutput) { - winRec = RootlessEnsureFrame(pTopWin); - } - - if (winRec == NULL) - return NULL; - - return winRec->wid; -} - - -/* - * RootlessUnrealizeWindow - * Unmap the physical window. - */ -Bool -RootlessUnrealizeWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec = WINREC(pWin); - Bool result; - - RL_DEBUG_MSG("unrealizewindow start "); - - if (winRec) { - RootlessStopDrawing(pWin, FALSE); - - SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); - - winRec->is_reorder_pending = FALSE; - } - - SCREEN_UNWRAP(pScreen, UnrealizeWindow); - result = pScreen->UnrealizeWindow(pWin); - SCREEN_WRAP(pScreen, UnrealizeWindow); - - RL_DEBUG_MSG("unrealizewindow end\n"); - return result; -} - - -/* - * RootlessReorderWindow - * Reorder the frame associated with the given window so that it's - * physically above the window below it in the X stacking order. - */ -void -RootlessReorderWindow(WindowPtr pWin) -{ - RootlessWindowRec *winRec = WINREC(pWin); - - if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { - WindowPtr newPrevW; - RootlessWindowRec *newPrev; - RootlessFrameID newPrevID; - ScreenPtr pScreen = pWin->drawable.pScreen; - - /* Check if the implementation wants the frame to not be reordered - even though the X11 window is restacked. This can be useful if - frames are ordered-in with animation so that the reordering is not - done until the animation is complete. */ - if (SCREENREC(pScreen)->imp->DoReorderWindow) { - if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) - return; - } - - RootlessStopDrawing(pWin, FALSE); - - /* Find the next window above this one that has a mapped frame. */ - - newPrevW = pWin->prevSib; - while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized)) - newPrevW = newPrevW->prevSib; - - newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; - newPrevID = newPrev != NULL ? newPrev->wid : 0; - - /* If it exists, reorder the frame above us first. */ - - if (newPrev && newPrev->is_reorder_pending) { - newPrev->is_reorder_pending = FALSE; - RootlessReorderWindow(newPrevW); - } - - SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); - } -} - - -/* - * RootlessRestackWindow - * This is a hook for when DIX changes the window stacking order. - * The window has already been inserted into its new position in the - * DIX window stack. We need to change the order of the physical - * window to match. - */ -void -RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) -{ - RegionRec saveRoot; - RootlessWindowRec *winRec = WINREC(pWin); - ScreenPtr pScreen = pWin->drawable.pScreen; - - RL_DEBUG_MSG("restackwindow start "); - if (winRec) - RL_DEBUG_MSG("restack top level \n"); - - HUGE_ROOT(pWin); - SCREEN_UNWRAP(pScreen, RestackWindow); - - if (pScreen->RestackWindow) - pScreen->RestackWindow(pWin, pOldNextSib); - - SCREEN_WRAP(pScreen, RestackWindow); - NORMAL_ROOT(pWin); - - if (winRec && pWin->viewable) { - RootlessReorderWindow(pWin); - } - - RL_DEBUG_MSG("restackwindow end\n"); -} - -/* - * Specialized window copy procedures - */ - -// Globals needed during window resize and move. -static pointer gResizeDeathBits = NULL; -static int gResizeDeathCount = 0; -static PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; -static BoxRec gResizeDeathBounds[2]; -static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; - -/* - * RootlessNoCopyWindow - * CopyWindow() that doesn't do anything. For MoveWindow() of - * top-level windows. - */ -static void -RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, - RegionPtr prgnSrc) -{ - // some code expects the region to be translated - int dx = ptOldOrg.x - pWin->drawable.x; - int dy = ptOldOrg.y - pWin->drawable.y; - - RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); - - REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); -} - - -/* - * RootlessResizeCopyWindow - * CopyWindow used during ResizeWindow for gravity moves. Based on - * fbCopyWindow. The original always draws on the root pixmap, which - * we don't have. Instead, draw on the parent window's pixmap. - * Resize version: the old location's pixels are in gResizeCopyWindowSource. - */ -static void -RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, - RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RegionRec rgnDst; - int dx, dy; - - RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); - - /* Don't unwrap pScreen->CopyWindow. - The bogus rewrap with RootlessCopyWindow causes a crash if - CopyWindow is called again during the same resize. */ - - if (gResizeDeathCount == 0) - return; - - RootlessStartDrawing(pWin); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); - REGION_NULL(pScreen, &rgnDst); - REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); - - if (gResizeDeathCount == 1) { - /* Simple case, we only have a single source pixmap. */ - - fbCopyRegion(&gResizeDeathPix[0]->drawable, - &pScreen->GetWindowPixmap(pWin)->drawable, 0, - &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); - } - else { - int i; - RegionRec clip, clipped; - - /* More complex case, N source pixmaps (usually two). So we - intersect the destination with each source and copy those bits. */ - - for (i = 0; i < gResizeDeathCount; i++) { - REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1); - REGION_NULL(pScreen, &clipped); - REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped); - - fbCopyRegion(&gResizeDeathPix[i]->drawable, - &pScreen->GetWindowPixmap(pWin)->drawable, 0, - &clipped, dx, dy, fbCopyWindowProc, 0, 0); - - REGION_UNINIT(pScreen, &clipped); - REGION_UNINIT(pScreen, &clip); - } - } - - /* Don't update - resize will update everything */ - REGION_UNINIT(pScreen, &rgnDst); - - fbValidateDrawable(&pWin->drawable); - - RL_DEBUG_MSG("resizecopywindowFB end\n"); -} - - -/* - * RootlessCopyWindow - * Update *new* location of window. Old location is redrawn with - * miPaintWindow. Cloned from fbCopyWindow. - * The original always draws on the root pixmap, which we don't have. - * Instead, draw on the parent window's pixmap. - */ -void -RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RegionRec rgnDst; - int dx, dy; - BoxPtr extents; - int area; - - RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); - - SCREEN_UNWRAP(pScreen, CopyWindow); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); - - REGION_NULL(pScreen, &rgnDst); - REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); - - extents = REGION_EXTENTS(pScreen, &rgnDst); - area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); - - /* If the area exceeds threshold, use the implementation's - accelerated version. */ - if (area > rootless_CopyWindow_threshold && - SCREENREC(pScreen)->imp->CopyWindow) - { - RootlessWindowRec *winRec; - WindowPtr top; - - top = TopLevelParent(pWin); - if (top == NULL) { - RL_DEBUG_MSG("no parent\n"); - goto out; - } - - winRec = WINREC(top); - if (winRec == NULL) { - RL_DEBUG_MSG("not framed\n"); - goto out; - } - - /* Move region to window local coords */ - REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y); - - RootlessStopDrawing(pWin, FALSE); - - SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, - REGION_NUM_RECTS(&rgnDst), - REGION_RECTS(&rgnDst), - dx, dy); - } - else { - RootlessStartDrawing(pWin); - - fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, - 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); - - /* prgnSrc has been translated to dst position */ - RootlessDamageRegion(pWin, prgnSrc); - } - -out: - REGION_UNINIT(pScreen, &rgnDst); - fbValidateDrawable(&pWin->drawable); - - SCREEN_WRAP(pScreen, CopyWindow); - - RL_DEBUG_MSG("copywindowFB end\n"); -} - - -/* - * Window resize procedures - */ - -enum { - WIDTH_SMALLER = 1, - HEIGHT_SMALLER = 2, -}; - - -/* - * ResizeWeighting - * Choose gravity to avoid local copies. Do that by looking for - * a corner that doesn't move _relative to the screen_. - */ -static inline unsigned int -ResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, - int newX1, int newY1, int newX2, int newY2, int newBW) -{ -#ifdef ROOTLESS_RESIZE_GRAVITY - if (newBW != oldBW) - return RL_GRAVITY_NONE; - - if (newX1 == oldX1 && newY1 == oldY1) - return RL_GRAVITY_NORTH_WEST; - else if (newX1 == oldX1 && newY2 == oldY2) - return RL_GRAVITY_SOUTH_WEST; - else if (newX2 == oldX2 && newY2 == oldY2) - return RL_GRAVITY_SOUTH_EAST; - else if (newX2 == oldX2 && newY1 == oldY1) - return RL_GRAVITY_NORTH_EAST; - else - return RL_GRAVITY_NONE; -#else - return RL_GRAVITY_NONE; -#endif -} - - -/* - * StartFrameResize - * Prepare to resize a top-level window. The old window's pixels are - * saved and the implementation is told to change the window size. - * (x,y,w,h) is outer frame of window (outside border) - */ -static Bool -StartFrameResize(WindowPtr pWin, Bool gravity, - int oldX, int oldY, int oldW, int oldH, int oldBW, - int newX, int newY, int newW, int newH, int newBW) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec = WINREC(pWin); - Bool need_window_source = FALSE, resize_after = FALSE; - - BoxRec rect; - int oldX2, newX2; - int oldY2, newY2; - unsigned int weight; - - oldX2 = oldX + oldW, newX2 = newX + newW; - oldY2 = oldY + oldH, newY2 = newY + newH; - - /* Decide which resize weighting to use */ - weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - - /* Compute intersection between old and new rects */ - rect.x1 = max(oldX, newX); - rect.y1 = max(oldY, newY); - rect.x2 = min(oldX2, newX2); - rect.y2 = min(oldY2, newY2); - - RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); - RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", - oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - - RootlessRedisplay(pWin); - - /* If gravity is true, then we need to have a way of recovering all - the original bits in the window for when X rearranges the contents - based on the various gravity settings. The obvious way is to just - snapshot the entire backing store before resizing it, but that - it slow on large windows. - - So the optimization here is to use the implementation's resize - weighting options (if available) to allow us to reason about what - is left in the backing store after the resize. We can then only - copy what won't be there after the resize, and do a two-stage copy - operation. - - Most of these optimizations are only applied when the top-left - corner of the window is fixed, since that's the common case. They - could probably be extended with some thought. */ - - gResizeDeathCount = 0; - - if (gravity && weight == RL_GRAVITY_NORTH_WEST) { - unsigned int code = 0; - - /* Top left corner is anchored. We never need to copy the - entire window. */ - - need_window_source = TRUE; - - /* These comparisons were chosen to avoid setting bits when the sizes - are the same. (So the fastest case automatically gets taken when - dimensions are unchanging.) */ - - if (newW < oldW) - code |= WIDTH_SMALLER; - if (newH < oldH) - code |= HEIGHT_SMALLER; - - if (((code ^ (code >> 1)) & 1) == 0) { - /* Both dimensions are either getting larger, or both - are getting smaller. No need to copy anything. */ - - if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { - /* Since the window is getting smaller, we can do gravity - repair on it with it's current size, then resize it - afterwards. */ - - resize_after = TRUE; - } - - gResizeDeathCount = 1; - } - else { - unsigned int copy_rowbytes, Bpp; - unsigned int copy_rect_width, copy_rect_height; - BoxRec copy_rect; - - /* We can get away with a partial copy. 'rect' is the - intersection between old and new bounds, so copy - everything to the right of or below the intersection. */ - - RootlessStartDrawing(pWin); - - if (code == WIDTH_SMALLER) { - copy_rect.x1 = rect.x2; - copy_rect.y1 = rect.y1; - copy_rect.x2 = oldX2; - copy_rect.y2 = oldY2; - } - else if (code == HEIGHT_SMALLER) { - copy_rect.x1 = rect.x1; - copy_rect.y1 = rect.y2; - copy_rect.x2 = oldX2; - copy_rect.y2 = oldY2; - } - else - OsAbort(); - - Bpp = winRec->win->drawable.bitsPerPixel / 8; - copy_rect_width = copy_rect.x2 - copy_rect.x1; - copy_rect_height = copy_rect.y2 - copy_rect.y1; - copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; - gResizeDeathBits = xalloc(copy_rowbytes - * copy_rect_height); - - if (copy_rect_width * copy_rect_height > - rootless_CopyBytes_threshold && - SCREENREC(pScreen)->imp->CopyBytes) - { - SCREENREC(pScreen)->imp->CopyBytes( - copy_rect_width * Bpp, copy_rect_height, - ((char *) winRec->pixelData) - + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) - + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, - gResizeDeathBits, copy_rowbytes); - } else { - fbBlt((FbBits *) (winRec->pixelData - + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) - + (copy_rect.x1 - oldX) * Bpp), - winRec->bytesPerRow / sizeof(FbBits), 0, - (FbBits *) gResizeDeathBits, - copy_rowbytes / sizeof(FbBits), 0, - copy_rect_width * Bpp, copy_rect_height, - GXcopy, FB_ALLONES, Bpp, 0, 0); - } - - gResizeDeathBounds[1] = copy_rect; - gResizeDeathPix[1] - = GetScratchPixmapHeader(pScreen, copy_rect_width, - copy_rect_height, - winRec->win->drawable.depth, - winRec->win->drawable.bitsPerPixel, - winRec->bytesPerRow, - (void *) gResizeDeathBits); - - SetPixmapBaseToScreen(gResizeDeathPix[1], - copy_rect.x1, copy_rect.y1); - - gResizeDeathCount = 2; - } - } - else if (gravity) { - /* The general case. Just copy everything. */ - - RootlessStartDrawing(pWin); - - gResizeDeathBits = xalloc(winRec->bytesPerRow * winRec->height); - - memcpy(gResizeDeathBits, winRec->pixelData, - winRec->bytesPerRow * winRec->height); - - gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; - gResizeDeathPix[0] - = GetScratchPixmapHeader(pScreen, winRec->width, - winRec->height, - winRec->win->drawable.depth, - winRec->win->drawable.bitsPerPixel, - winRec->bytesPerRow, - (void *) gResizeDeathBits); - - SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); - gResizeDeathCount = 1; - } - - RootlessStopDrawing(pWin, FALSE); - - winRec->x = newX; - winRec->y = newY; - winRec->width = newW; - winRec->height = newH; - winRec->borderWidth = newBW; - - /* Unless both dimensions are getting smaller, Resize the frame - before doing gravity repair */ - - if (!resize_after) { - SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, - newX + SCREEN_TO_GLOBAL_X, - newY + SCREEN_TO_GLOBAL_Y, - newW, newH, weight); - } - - RootlessStartDrawing(pWin); - - /* If necessary, create a source pixmap pointing at the current - window bits. */ - - if (need_window_source) { - gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; - gResizeDeathPix[0] - = GetScratchPixmapHeader(pScreen, oldW, oldH, - winRec->win->drawable.depth, - winRec->win->drawable.bitsPerPixel, - winRec->bytesPerRow, winRec->pixelData); - - SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); - } - - /* Use custom CopyWindow when moving gravity bits around - ResizeWindow assumes the old window contents are in the same - pixmap, but here they're in deathPix instead. */ - - if (gravity) { - gResizeOldCopyWindowProc = pScreen->CopyWindow; - pScreen->CopyWindow = RootlessResizeCopyWindow; - } - - /* If we can't rely on the window server preserving the bits we - need in the position we need, copy the pixels in the - intersection from src to dst. ResizeWindow assumes these pixels - are already present when making gravity adjustments. pWin - currently has new-sized pixmap but is in old position. - - FIXME: border width change! (?) */ - - if (gravity && weight == RL_GRAVITY_NONE) { - PixmapPtr src, dst; - - assert(gResizeDeathCount == 1); - - src = gResizeDeathPix[0]; - dst = pScreen->GetWindowPixmap(pWin); - - RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", - rect.x1, rect.y1, rect.x2, rect.y2); - - /* rect is the intersection of the old location and new location */ - if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { - /* The window drawable still has the old frame position, which - means that DST doesn't actually point at the origin of our - physical backing store when adjusted by the drawable.x,y - position. So sneakily adjust it temporarily while copying.. */ - - ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; - SetPixmapBaseToScreen(dst, newX, newY); - - fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, - &rect, 1, 0, 0, FALSE, FALSE, 0, 0); - - ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; - SetPixmapBaseToScreen(dst, oldX, oldY); - } - } - - return resize_after; -} - - -static void -FinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, - unsigned int oldW, unsigned int oldH, unsigned int oldBW, - int newX, int newY, unsigned int newW, unsigned int newH, - unsigned int newBW, Bool resize_now) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec = WINREC(pWin); - int i; - - RootlessStopDrawing(pWin, FALSE); - - if (resize_now) { - unsigned int weight; - - /* We didn't resize anything earlier, so do it now, now that - we've finished gravitating the bits. */ - - weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - - SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, - newX + SCREEN_TO_GLOBAL_X, - newY + SCREEN_TO_GLOBAL_Y, - newW, newH, weight); - } - - /* Redraw everything. FIXME: there must be times when we don't need - to do this. Perhaps when top-left weighting and no gravity? */ - - RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); - - for (i = 0; i < 2; i++) { - if (gResizeDeathPix[i] != NULL) { - FreeScratchPixmapHeader(gResizeDeathPix[i]); - gResizeDeathPix[i] = NULL; - } - } - - if (gResizeDeathBits != NULL) { - xfree(gResizeDeathBits); - gResizeDeathBits = NULL; - } - - if (gravity) { - pScreen->CopyWindow = gResizeOldCopyWindowProc; - } -} - - -/* - * RootlessMoveWindow - * If kind==VTOther, window border is resizing (and borderWidth is - * already changed!!@#$) This case works like window resize, not move. - */ -void -RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) -{ - RootlessWindowRec *winRec = WINREC(pWin); - ScreenPtr pScreen = pWin->drawable.pScreen; - CopyWindowProcPtr oldCopyWindowProc = NULL; - int oldX = 0, oldY = 0, newX = 0, newY = 0; - unsigned int oldW = 0, oldH = 0, oldBW = 0; - unsigned int newW = 0, newH = 0, newBW = 0; - Bool resize_after = FALSE; - RegionRec saveRoot; - - RL_DEBUG_MSG("movewindow start \n"); - - if (winRec) { - if (kind == VTMove) { - oldX = winRec->x; - oldY = winRec->y; - RootlessRedisplay(pWin); - RootlessStartDrawing(pWin); - } else { - RL_DEBUG_MSG("movewindow border resizing "); - - oldBW = winRec->borderWidth; - oldX = winRec->x; - oldY = winRec->y; - oldW = winRec->width; - oldH = winRec->height; - - newBW = wBorderWidth(pWin); - newX = x; - newY = y; - newW = pWin->drawable.width + 2*newBW; - newH = pWin->drawable.height + 2*newBW; - - resize_after = StartFrameResize(pWin, FALSE, - oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - } - } - - HUGE_ROOT(pWin); - SCREEN_UNWRAP(pScreen, MoveWindow); - - if (winRec) { - oldCopyWindowProc = pScreen->CopyWindow; - pScreen->CopyWindow = RootlessNoCopyWindow; - } - pScreen->MoveWindow(pWin, x, y, pSib, kind); - if (winRec) { - pScreen->CopyWindow = oldCopyWindowProc; - } - - NORMAL_ROOT(pWin); - SCREEN_WRAP(pScreen, MoveWindow); - - if (winRec) { - if (kind == VTMove) { - winRec->x = x; - winRec->y = y; - RootlessStopDrawing(pWin, FALSE); - SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, - x + SCREEN_TO_GLOBAL_X, - y + SCREEN_TO_GLOBAL_Y); - } else { - FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW, resize_after); - } - } - - RL_DEBUG_MSG("movewindow end\n"); -} - - -/* - * RootlessResizeWindow - * Note: (x, y, w, h) as passed to this procedure don't match the frame - * definition. (x,y) is corner of very outer edge, *outside* border. - * w,h is width and height *inside* border, *ignoring* border width. - * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) - * is total rect and (x+bw, y+bw, w, h) is inner rect. - */ -void -RootlessResizeWindow(WindowPtr pWin, int x, int y, - unsigned int w, unsigned int h, WindowPtr pSib) -{ - RootlessWindowRec *winRec = WINREC(pWin); - ScreenPtr pScreen = pWin->drawable.pScreen; - int oldX = 0, oldY = 0, newX = 0, newY = 0; - unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; - Bool resize_after = FALSE; - RegionRec saveRoot; - - RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); - - if(pWin->parent) { - if (winRec) { - oldBW = winRec->borderWidth; - oldX = winRec->x; - oldY = winRec->y; - oldW = winRec->width; - oldH = winRec->height; - - newBW = oldBW; - newX = x; - newY = y; - newW = w + 2*newBW; - newH = h + 2*newBW; - - resize_after = StartFrameResize(pWin, TRUE, - oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - } - - HUGE_ROOT(pWin); - SCREEN_UNWRAP(pScreen, ResizeWindow); - pScreen->ResizeWindow(pWin, x, y, w, h, pSib); - SCREEN_WRAP(pScreen, ResizeWindow); - NORMAL_ROOT(pWin); - - if (winRec) { - FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW, resize_after); - } - } else { - /* Special case for resizing the root window */ - BoxRec box; - - pWin->drawable.x = x; - pWin->drawable.y = y; - pWin->drawable.width = w; - pWin->drawable.height = h; - - box.x1 = x; box.y1 = y; - box.x2 = x + w; box.y2 = y + h; - REGION_UNINIT(pScreen, &pWin->winSize); - REGION_INIT(pScreen, &pWin->winSize, &box, 1); - REGION_COPY(pScreen, &pWin->borderSize, &pWin->winSize); - REGION_COPY(pScreen, &pWin->clipList, &pWin->winSize); - REGION_COPY(pScreen, &pWin->borderClip, &pWin->winSize); - - miSendExposures(pWin, &pWin->borderClip, - pWin->drawable.x, pWin->drawable.y); - } - - RL_DEBUG_MSG("resizewindow end\n"); -} - - -/* - * 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 - * implementation calling RootlessFrameForWindow. (e.g. this could be needed - * to attach a VRAM surface to it.) If the window is subsequently reparented - * by the window manager before being mapped, we need to give the frame to - * the new top-level window. - */ -void -RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - RootlessWindowRec *winRec = WINREC(pWin); - WindowPtr pTopWin; - - /* Check that window is not top-level now, but used to be. */ - if (IsRoot(pWin) || IsRoot(pWin->parent) - || IsTopLevel(pWin) || winRec == NULL) - { - goto out; - } - - /* If the formerly top-level window has a frame, we want to give the - frame to its new top-level parent. If we can't do that, we'll just - have to jettison it... */ - - pTopWin = TopLevelParent(pWin); - assert(pTopWin != pWin); - - pWin->rootlessUnhittable = FALSE; - - DeleteProperty (serverClient, pWin, xa_native_window_id ()); - - if (WINREC(pTopWin) != NULL) { - /* We're screwed. */ - RootlessDestroyFrame(pWin, winRec); - } else { - if (!pTopWin->realized && pWin->realized) { - SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); - } - - /* Switch the frame record from one to the other. */ - - SETWINREC(pWin, NULL); - SETWINREC(pTopWin, winRec); - - RootlessInitializeFrame(pTopWin, winRec); - RootlessReshapeFrame(pTopWin); - - SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, - winRec->x + SCREEN_TO_GLOBAL_X, - winRec->y + SCREEN_TO_GLOBAL_Y, - winRec->width, winRec->height, - RL_GRAVITY_NONE); - - if (SCREENREC(pScreen)->imp->SwitchWindow) { - SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); - } - - if (pTopWin->realized && !pWin->realized) - winRec->is_reorder_pending = TRUE; - } - -out: - if (SCREENREC(pScreen)->ReparentWindow) { - SCREEN_UNWRAP(pScreen, ReparentWindow); - pScreen->ReparentWindow(pWin, pPriorParent); - SCREEN_WRAP(pScreen, ReparentWindow); - } -} - - -void -RootlessFlushWindowColormap (WindowPtr pWin) -{ - RootlessWindowRec *winRec = WINREC (pWin); - ScreenPtr pScreen = pWin->drawable.pScreen; - - if (winRec == NULL) - return; - - RootlessStopDrawing (pWin, FALSE); - - if (SCREENREC(pScreen)->imp->UpdateColormap) - SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); -} - -/* - * RootlessChangeBorderWidth - * FIXME: untested! - * pWin inside corner stays the same; pWin->drawable.[xy] stays the same - * Frame moves and resizes. - */ -void -RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) -{ - RegionRec saveRoot; - Bool resize_after = FALSE; - - RL_DEBUG_MSG("change border width "); - - if (width != wBorderWidth(pWin)) { - RootlessWindowRec *winRec = WINREC(pWin); - int oldX = 0, oldY = 0, newX = 0, newY = 0; - unsigned int oldW = 0, oldH = 0, oldBW = 0; - unsigned int newW = 0, newH = 0, newBW = 0; - - if (winRec) { - oldBW = winRec->borderWidth; - oldX = winRec->x; - oldY = winRec->y; - oldW = winRec->width; - oldH = winRec->height; - - newBW = width; - newX = pWin->drawable.x - newBW; - newY = pWin->drawable.y - newBW; - newW = pWin->drawable.width + 2*newBW; - newH = pWin->drawable.height + 2*newBW; - - resize_after = StartFrameResize(pWin, FALSE, - oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW); - } - - HUGE_ROOT(pWin); - SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); - pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); - SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); - NORMAL_ROOT(pWin); - - if (winRec) { - FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, - newX, newY, newW, newH, newBW, resize_after); - } - } - - RL_DEBUG_MSG("change border width end\n"); -} - -/* - * RootlessOrderAllWindows - * Brings all X11 windows to the top of the window stack - * (i.e in front of Aqua windows) -- called when X11.app is given focus - */ -void -RootlessOrderAllWindows (void) -{ - int i; - WindowPtr pWin; - - if (windows_hidden) - return; - - RL_DEBUG_MSG("RootlessOrderAllWindows() "); - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i] == NULL) continue; - pWin = WindowTable[i]; - if (pWin == NULL) continue; - - for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { - if (!pWin->realized) continue; - if (RootlessEnsureFrame(pWin) == NULL) continue; - RootlessReorderWindow (pWin); - } - } - RL_DEBUG_MSG("RootlessOrderAllWindows() done"); -} - -void -RootlessEnableRoot (ScreenPtr pScreen) -{ - WindowPtr pRoot; - pRoot = WindowTable[pScreen->myNum]; - - RootlessEnsureFrame (pRoot); - (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); - RootlessReorderWindow (pRoot); -} - -void -RootlessDisableRoot (ScreenPtr pScreen) -{ - WindowPtr pRoot; - RootlessWindowRec *winRec; - - pRoot = WindowTable[pScreen->myNum]; - winRec = WINREC (pRoot); - - if (NULL == winRec) - return; - - RootlessDestroyFrame (pRoot, winRec); - DeleteProperty (serverClient, pRoot, xa_native_window_id ()); -} - -void -RootlessHideAllWindows (void) -{ - int i; - ScreenPtr pScreen; - WindowPtr pWin; - RootlessWindowRec *winRec; - - if (windows_hidden) - return; - - windows_hidden = TRUE; - - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - pWin = WindowTable[i]; - if (pScreen == NULL || pWin == NULL) - continue; - - for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) - { - if (!pWin->realized) - continue; - - RootlessStopDrawing (pWin, FALSE); - - winRec = WINREC (pWin); - if (winRec != NULL) - { - if (SCREENREC(pScreen)->imp->HideWindow) - SCREENREC(pScreen)->imp->HideWindow(winRec->wid); - } - } - } -} - -void -RootlessShowAllWindows (void) -{ - int i; - ScreenPtr pScreen; - WindowPtr pWin; - RootlessWindowRec *winRec; - - if (!windows_hidden) - return; - - windows_hidden = FALSE; - - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - pWin = WindowTable[i]; - if (pScreen == NULL || pWin == NULL) - continue; - - for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) - { - if (!pWin->realized) - continue; - - winRec = RootlessEnsureFrame (pWin); - if (winRec == NULL) - continue; - - RootlessReorderWindow (pWin); - } - - RootlessScreenExpose (pScreen); - } -} - -/* - * SetPixmapOfAncestors - * Set the Pixmaps on all ParentRelative windows up the ancestor chain. - */ -void -RootlessSetPixmapOfAncestors(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr topWin = TopLevelParent(pWin); - RootlessWindowRec *topWinRec = WINREC(topWin); - - while (pWin->backgroundState == ParentRelative) { - if (pWin == topWin) { - // disallow ParentRelative background state on top level - XID pixel = 0; - ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); - RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); - break; - } - - pWin = pWin->parent; - pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); - } -} - +/* + * Rootless window management + */ +/* + * Copyright (c) 2001 Greg Parker. 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 + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include /* For NULL */ +#include /* For CHAR_BIT */ +#include +#include +#ifdef __APPLE__ +#include +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +//#include +extern int darwinMainScreenX, darwinMainScreenY; +extern Bool no_configure_window; +#endif +#include "fb.h" + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +#ifdef ROOTLESS_GLOBAL_COORDS +#define SCREEN_TO_GLOBAL_X \ + (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX) +#define SCREEN_TO_GLOBAL_Y \ + (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY) +#else +#define SCREEN_TO_GLOBAL_X 0 +#define SCREEN_TO_GLOBAL_Y 0 +#endif + +#define DEFINE_ATOM_HELPER(func,atom_name) \ + static Atom func (void) { \ + static unsigned int generation = 0; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ + } + +DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") + +static Bool windows_hidden; +// TODO - abstract xp functions + +#ifdef __APPLE__ + +// XXX: identical to x_cvt_vptr_to_uint ? +#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) + +void +RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) +{ + RootlessWindowRec *winRec; + + if (pWin == NULL) return; + + winRec = WINREC (pWin); + if (winRec == NULL) return; + + winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); + winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); + pWin->rootlessUnhittable = winRec->is_offscreen; +} + +void RootlessNativeWindowMoved (WindowPtr pWin) { + xp_box bounds; + int sx, sy, err; + XID vlist[2]; + Mask mask; + ClientPtr pClient; + RootlessWindowRec *winRec; + + winRec = WINREC(pWin); + + if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; + + sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX; + sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY; + + /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ + vlist[0] = (INT16) bounds.x1 - sx; + vlist[1] = (INT16) bounds.y1 - sy; + mask = CWX | CWY; + + /* pretend we're the owner of the window! */ + err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess); + if(err != Success) { + ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); + return; + } + + /* Don't want to do anything to the physical window (avoids + notification-response feedback loops) */ + + no_configure_window = TRUE; + ConfigureWindow (pWin, mask, vlist, pClient); + no_configure_window = FALSE; +} + +#endif /* __APPLE__ */ + +/* + * RootlessCreateWindow + * For now, don't create a physical window until either the window is + * realized, or we really need it (e.g. to attach VRAM surfaces to). + * Do reset the window size so it's not clipped by the root window. + */ +Bool +RootlessCreateWindow(WindowPtr pWin) +{ + Bool result; + RegionRec saveRoot; + + SETWINREC(pWin, NULL); + dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); + + SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); + + if (!IsRoot(pWin)) { + /* win/border size set by DIX, not by wrapped CreateWindow, so + correct it here. Don't HUGE_ROOT when pWin is the root! */ + + HUGE_ROOT(pWin); + SetWinSize(pWin); + SetBorderSize(pWin); + } + + result = pWin->drawable.pScreen->CreateWindow(pWin); + + if (pWin->parent) { + NORMAL_ROOT(pWin); + } + + SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); + + return result; +} + + +/* + * RootlessDestroyFrame + * Destroy the physical window associated with the given window. + */ +static void +RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid); + +#ifdef ROOTLESS_TRACK_DAMAGE + REGION_UNINIT(pScreen, &winRec->damage); +#endif + + free(winRec); + SETWINREC(pWin, NULL); +} + + +/* + * RootlessDestroyWindow + * Destroy the physical window associated with the given window. + */ +Bool +RootlessDestroyWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + if (winRec != NULL) { + RootlessDestroyFrame(pWin, winRec); + } + + SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); + result = pWin->drawable.pScreen->DestroyWindow(pWin); + SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); + + return result; +} + + + +static Bool +RootlessGetShape(WindowPtr pWin, RegionPtr pShape) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* + * Avoid a warning. + * REGION_NULL and the other macros don't actually seem to use pScreen. + */ + (void)pScreen; + + if (wBoundingShape(pWin) == NULL) + return FALSE; + + /* wBoundingShape is relative to *inner* origin of window. + Translate by borderWidth to get the outside-relative position. */ + + REGION_NULL(pScreen, pShape); + REGION_COPY(pScreen, pShape, wBoundingShape(pWin)); + REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth); + + return TRUE; +} + + +/* + * RootlessReshapeFrame + * Set the frame shape. + */ +static void RootlessReshapeFrame(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec newShape; + RegionPtr pShape; + + // If the window is not yet framed, do nothing + if (winRec == NULL) + return; + + if (IsRoot(pWin)) + return; + + RootlessStopDrawing(pWin, FALSE); + + pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; + +#ifdef ROOTLESSDEBUG + RL_DEBUG_MSG("reshaping..."); + if (pShape != NULL) { + RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", + REGION_NUM_RECTS(&newShape), + newShape.extents.x1, newShape.extents.y1, + newShape.extents.x2, newShape.extents.y2); + } else { + RL_DEBUG_MSG("no shape "); + } +#endif + + SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape); + + if (pShape != NULL) + REGION_UNINIT(pScreen, &newShape); +} + + +/* + * RootlessSetShape + * Shape is usually set before a window is mapped and the window will + * not have a frame associated with it. In this case, the frame will be + * shaped when the window is framed. + */ +void +RootlessSetShape(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, SetShape); + pScreen->SetShape(pWin); + SCREEN_WRAP(pScreen, SetShape); + + RootlessReshapeFrame(pWin); +} + + + +/* Disallow ParentRelative background on top-level windows + because the root window doesn't really have the right background. + */ +Bool +RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("change window attributes start "); + + SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); + result = pScreen->ChangeWindowAttributes(pWin, vmask); + SCREEN_WRAP(pScreen, ChangeWindowAttributes); + + if (WINREC(pWin)) { + // disallow ParentRelative background state + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + } + + RL_DEBUG_MSG("change window attributes end\n"); + return result; +} + + +/* + * RootlessPositionWindow + * This is a hook for when DIX moves or resizes a window. + * Update the frame position now although the physical window is moved + * in RootlessMoveWindow. (x, y) are *inside* position. After this, + * mi and fb are expecting the pixmap to be at the new location. + */ +Bool +RootlessPositionWindow(WindowPtr pWin, int x, int y) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); + + if (winRec) { + if (winRec->is_drawing) { + // Reset frame's pixmap and move it to the new position. + int bw = wBorderWidth(pWin); + + winRec->pixmap->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); + +#ifdef ROOTLESS_TRACK_DAMAGE + // Move damaged region to correspond to new window position + if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { + REGION_TRANSLATE(pScreen, &winRec->damage, + x - bw - winRec->x, + y - bw - winRec->y); + } +#endif + } + } + + SCREEN_UNWRAP(pScreen, PositionWindow); + result = pScreen->PositionWindow(pWin, x, y); + SCREEN_WRAP(pScreen, PositionWindow); + + RL_DEBUG_MSG("positionwindow end\n"); + return result; +} + + +/* + * RootlessInitializeFrame + * Initialize some basic attributes of the frame. Note that winRec + * may already have valid data in it, so don't overwrite anything + * valuable. + */ +static void +RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) +{ + DrawablePtr d = &pWin->drawable; + int bw = wBorderWidth(pWin); + + winRec->win = pWin; + + winRec->x = d->x - bw; + winRec->y = d->y - bw; + winRec->width = d->width + 2*bw; + winRec->height = d->height + 2*bw; + winRec->borderWidth = bw; + +#ifdef ROOTLESS_TRACK_DAMAGE + REGION_NULL(pScreen, &winRec->damage); +#endif +} + +/* + * RootlessEnsureFrame + * Make sure the given window is framed. If the window doesn't have a + * physical window associated with it, attempt to create one. If that + * is unsuccessful, return NULL. + */ +static RootlessWindowRec * +RootlessEnsureFrame(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec; + RegionRec shape; + RegionPtr pShape = NULL; + + if (WINREC(pWin) != NULL) + return WINREC(pWin); + + if (!IsTopLevel(pWin) && !IsRoot(pWin)) + return NULL; + + if (pWin->drawable.class != InputOutput) + return NULL; + + winRec = malloc(sizeof(RootlessWindowRec)); + + if (!winRec) + return NULL; + + RootlessInitializeFrame(pWin, winRec); + + winRec->is_drawing = FALSE; + winRec->is_reorder_pending = FALSE; + winRec->pixmap = NULL; + winRec->wid = NULL; + winRec->level = 0; + + SETWINREC(pWin, winRec); + + // Set the frame's shape if the window is shaped + if (RootlessGetShape(pWin, &shape)) + pShape = &shape; + + RL_DEBUG_MSG("creating frame "); + + if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y, + pShape)) + { + RL_DEBUG_MSG("implementation failed to create frame!\n"); + free(winRec); + SETWINREC(pWin, NULL); + return NULL; + } + + if (pWin->drawable.depth == 8) + RootlessFlushWindowColormap(pWin); + + if (pShape != NULL) + REGION_UNINIT(pScreen, &shape); + + return winRec; +} + + +/* + * RootlessRealizeWindow + * The frame is usually created here and not in CreateWindow so that + * windows do not eat memory until they are realized. + */ +Bool +RootlessRealizeWindow(WindowPtr pWin) +{ + Bool result; + RegionRec saveRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); + + if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { + RootlessWindowRec *winRec; + + winRec = RootlessEnsureFrame(pWin); + if (winRec == NULL) + return FALSE; + + winRec->is_reorder_pending = TRUE; + + RL_DEBUG_MSG("Top level window "); + + // Disallow ParentRelative background state on top-level windows. + // This might have been set before the window was mapped. + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + } + + if (!IsRoot(pWin)) HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RealizeWindow); + result = pScreen->RealizeWindow(pWin); + SCREEN_WRAP(pScreen, RealizeWindow); + if (!IsRoot(pWin)) NORMAL_ROOT(pWin); + + RL_DEBUG_MSG("realizewindow end\n"); + return result; +} + + +/* + * RootlessFrameForWindow + * Returns the frame ID for the physical window displaying the given window. + * If CREATE is true and the window has no frame, attempt to create one. + */ +RootlessFrameID +RootlessFrameForWindow(WindowPtr pWin, Bool create) +{ + WindowPtr pTopWin; + RootlessWindowRec *winRec; + + pTopWin = TopLevelParent(pWin); + if (pTopWin == NULL) + return NULL; + + winRec = WINREC(pTopWin); + + if (winRec == NULL && create && pWin->drawable.class == InputOutput) { + winRec = RootlessEnsureFrame(pTopWin); + } + + if (winRec == NULL) + return NULL; + + return winRec->wid; +} + + +/* + * RootlessUnrealizeWindow + * Unmap the physical window. + */ +Bool +RootlessUnrealizeWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + RL_DEBUG_MSG("unrealizewindow start "); + + if (winRec) { + RootlessStopDrawing(pWin, FALSE); + + SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); + + winRec->is_reorder_pending = FALSE; + } + + SCREEN_UNWRAP(pScreen, UnrealizeWindow); + result = pScreen->UnrealizeWindow(pWin); + SCREEN_WRAP(pScreen, UnrealizeWindow); + + RL_DEBUG_MSG("unrealizewindow end\n"); + return result; +} + + +/* + * RootlessReorderWindow + * Reorder the frame associated with the given window so that it's + * physically above the window below it in the X stacking order. + */ +void +RootlessReorderWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + + if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { + WindowPtr newPrevW; + RootlessWindowRec *newPrev; + RootlessFrameID newPrevID; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* Check if the implementation wants the frame to not be reordered + even though the X11 window is restacked. This can be useful if + frames are ordered-in with animation so that the reordering is not + done until the animation is complete. */ + if (SCREENREC(pScreen)->imp->DoReorderWindow) { + if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) + return; + } + + RootlessStopDrawing(pWin, FALSE); + + /* Find the next window above this one that has a mapped frame. */ + + newPrevW = pWin->prevSib; + while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized)) + newPrevW = newPrevW->prevSib; + + newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; + newPrevID = newPrev != NULL ? newPrev->wid : 0; + + /* If it exists, reorder the frame above us first. */ + + if (newPrev && newPrev->is_reorder_pending) { + newPrev->is_reorder_pending = FALSE; + RootlessReorderWindow(newPrevW); + } + + SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); + } +} + + +/* + * RootlessRestackWindow + * This is a hook for when DIX changes the window stacking order. + * The window has already been inserted into its new position in the + * DIX window stack. We need to change the order of the physical + * window to match. + */ +void +RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) +{ + RegionRec saveRoot; + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("restackwindow start "); + if (winRec) + RL_DEBUG_MSG("restack top level \n"); + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RestackWindow); + + if (pScreen->RestackWindow) + pScreen->RestackWindow(pWin, pOldNextSib); + + SCREEN_WRAP(pScreen, RestackWindow); + NORMAL_ROOT(pWin); + + if (winRec && pWin->viewable) { + RootlessReorderWindow(pWin); + } + + RL_DEBUG_MSG("restackwindow end\n"); +} + +/* + * Specialized window copy procedures + */ + +// Globals needed during window resize and move. +static pointer gResizeDeathBits = NULL; +static int gResizeDeathCount = 0; +static PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; +static BoxRec gResizeDeathBounds[2]; +static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; + +/* + * RootlessNoCopyWindow + * CopyWindow() that doesn't do anything. For MoveWindow() of + * top-level windows. + */ +static void +RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + // some code expects the region to be translated + int dx = ptOldOrg.x - pWin->drawable.x; + int dy = ptOldOrg.y - pWin->drawable.y; + + RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); + + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); +} + + +/* + * RootlessResizeCopyWindow + * CopyWindow used during ResizeWindow for gravity moves. Based on + * fbCopyWindow. The original always draws on the root pixmap, which + * we don't have. Instead, draw on the parent window's pixmap. + * Resize version: the old location's pixels are in gResizeCopyWindowSource. + */ +static void +RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rgnDst; + int dx, dy; + + RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); + + /* Don't unwrap pScreen->CopyWindow. + The bogus rewrap with RootlessCopyWindow causes a crash if + CopyWindow is called again during the same resize. */ + + if (gResizeDeathCount == 0) + return; + + RootlessStartDrawing(pWin); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_NULL(pScreen, &rgnDst); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + if (gResizeDeathCount == 1) { + /* Simple case, we only have a single source pixmap. */ + + fbCopyRegion(&gResizeDeathPix[0]->drawable, + &pScreen->GetWindowPixmap(pWin)->drawable, 0, + &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + } + else { + int i; + RegionRec clip, clipped; + + /* More complex case, N source pixmaps (usually two). So we + intersect the destination with each source and copy those bits. */ + + for (i = 0; i < gResizeDeathCount; i++) { + REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1); + REGION_NULL(pScreen, &clipped); + REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped); + + fbCopyRegion(&gResizeDeathPix[i]->drawable, + &pScreen->GetWindowPixmap(pWin)->drawable, 0, + &clipped, dx, dy, fbCopyWindowProc, 0, 0); + + REGION_UNINIT(pScreen, &clipped); + REGION_UNINIT(pScreen, &clip); + } + } + + /* Don't update - resize will update everything */ + REGION_UNINIT(pScreen, &rgnDst); + + fbValidateDrawable(&pWin->drawable); + + RL_DEBUG_MSG("resizecopywindowFB end\n"); +} + + +/* + * RootlessCopyWindow + * Update *new* location of window. Old location is redrawn with + * miPaintWindow. Cloned from fbCopyWindow. + * The original always draws on the root pixmap, which we don't have. + * Instead, draw on the parent window's pixmap. + */ +void +RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rgnDst; + int dx, dy; + BoxPtr extents; + int area; + + RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); + + SCREEN_UNWRAP(pScreen, CopyWindow); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + + REGION_NULL(pScreen, &rgnDst); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + extents = REGION_EXTENTS(pScreen, &rgnDst); + area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); + + /* If the area exceeds threshold, use the implementation's + accelerated version. */ + if (area > rootless_CopyWindow_threshold && + SCREENREC(pScreen)->imp->CopyWindow) + { + RootlessWindowRec *winRec; + WindowPtr top; + + top = TopLevelParent(pWin); + if (top == NULL) { + RL_DEBUG_MSG("no parent\n"); + goto out; + } + + winRec = WINREC(top); + if (winRec == NULL) { + RL_DEBUG_MSG("not framed\n"); + goto out; + } + + /* Move region to window local coords */ + REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y); + + RootlessStopDrawing(pWin, FALSE); + + SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, + REGION_NUM_RECTS(&rgnDst), + REGION_RECTS(&rgnDst), + dx, dy); + } + else { + RootlessStartDrawing(pWin); + + fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, + 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + + /* prgnSrc has been translated to dst position */ + RootlessDamageRegion(pWin, prgnSrc); + } + +out: + REGION_UNINIT(pScreen, &rgnDst); + fbValidateDrawable(&pWin->drawable); + + SCREEN_WRAP(pScreen, CopyWindow); + + RL_DEBUG_MSG("copywindowFB end\n"); +} + + +/* + * Window resize procedures + */ + +enum { + WIDTH_SMALLER = 1, + HEIGHT_SMALLER = 2, +}; + + +/* + * ResizeWeighting + * Choose gravity to avoid local copies. Do that by looking for + * a corner that doesn't move _relative to the screen_. + */ +static inline unsigned int +ResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, + int newX1, int newY1, int newX2, int newY2, int newBW) +{ +#ifdef ROOTLESS_RESIZE_GRAVITY + if (newBW != oldBW) + return RL_GRAVITY_NONE; + + if (newX1 == oldX1 && newY1 == oldY1) + return RL_GRAVITY_NORTH_WEST; + else if (newX1 == oldX1 && newY2 == oldY2) + return RL_GRAVITY_SOUTH_WEST; + else if (newX2 == oldX2 && newY2 == oldY2) + return RL_GRAVITY_SOUTH_EAST; + else if (newX2 == oldX2 && newY1 == oldY1) + return RL_GRAVITY_NORTH_EAST; + else + return RL_GRAVITY_NONE; +#else + return RL_GRAVITY_NONE; +#endif +} + + +/* + * StartFrameResize + * Prepare to resize a top-level window. The old window's pixels are + * saved and the implementation is told to change the window size. + * (x,y,w,h) is outer frame of window (outside border) + */ +static Bool +StartFrameResize(WindowPtr pWin, Bool gravity, + int oldX, int oldY, int oldW, int oldH, int oldBW, + int newX, int newY, int newW, int newH, int newBW) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool need_window_source = FALSE, resize_after = FALSE; + + BoxRec rect; + int oldX2, newX2; + int oldY2, newY2; + unsigned int weight; + + oldX2 = oldX + oldW, newX2 = newX + newW; + oldY2 = oldY + oldH, newY2 = newY + newH; + + /* Decide which resize weighting to use */ + weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + /* Compute intersection between old and new rects */ + rect.x1 = max(oldX, newX); + rect.y1 = max(oldY, newY); + rect.x2 = min(oldX2, newX2); + rect.y2 = min(oldY2, newY2); + + RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); + RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + RootlessRedisplay(pWin); + + /* If gravity is true, then we need to have a way of recovering all + the original bits in the window for when X rearranges the contents + based on the various gravity settings. The obvious way is to just + snapshot the entire backing store before resizing it, but that + it slow on large windows. + + So the optimization here is to use the implementation's resize + weighting options (if available) to allow us to reason about what + is left in the backing store after the resize. We can then only + copy what won't be there after the resize, and do a two-stage copy + operation. + + Most of these optimizations are only applied when the top-left + corner of the window is fixed, since that's the common case. They + could probably be extended with some thought. */ + + gResizeDeathCount = 0; + + if (gravity && weight == RL_GRAVITY_NORTH_WEST) { + unsigned int code = 0; + + /* Top left corner is anchored. We never need to copy the + entire window. */ + + need_window_source = TRUE; + + /* These comparisons were chosen to avoid setting bits when the sizes + are the same. (So the fastest case automatically gets taken when + dimensions are unchanging.) */ + + if (newW < oldW) + code |= WIDTH_SMALLER; + if (newH < oldH) + code |= HEIGHT_SMALLER; + + if (((code ^ (code >> 1)) & 1) == 0) { + /* Both dimensions are either getting larger, or both + are getting smaller. No need to copy anything. */ + + if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { + /* Since the window is getting smaller, we can do gravity + repair on it with it's current size, then resize it + afterwards. */ + + resize_after = TRUE; + } + + gResizeDeathCount = 1; + } + else { + unsigned int copy_rowbytes, Bpp; + unsigned int copy_rect_width, copy_rect_height; + BoxRec copy_rect; + + /* We can get away with a partial copy. 'rect' is the + intersection between old and new bounds, so copy + everything to the right of or below the intersection. */ + + RootlessStartDrawing(pWin); + + if (code == WIDTH_SMALLER) { + copy_rect.x1 = rect.x2; + copy_rect.y1 = rect.y1; + copy_rect.x2 = oldX2; + copy_rect.y2 = oldY2; + } + else if (code == HEIGHT_SMALLER) { + copy_rect.x1 = rect.x1; + copy_rect.y1 = rect.y2; + copy_rect.x2 = oldX2; + copy_rect.y2 = oldY2; + } + else + OsAbort(); + + Bpp = winRec->win->drawable.bitsPerPixel / 8; + copy_rect_width = copy_rect.x2 - copy_rect.x1; + copy_rect_height = copy_rect.y2 - copy_rect.y1; + copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; + gResizeDeathBits = malloc(copy_rowbytes + * copy_rect_height); + + if (copy_rect_width * copy_rect_height > + rootless_CopyBytes_threshold && + SCREENREC(pScreen)->imp->CopyBytes) + { + SCREENREC(pScreen)->imp->CopyBytes( + copy_rect_width * Bpp, copy_rect_height, + ((char *) winRec->pixelData) + + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) + + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, + gResizeDeathBits, copy_rowbytes); + } else { + fbBlt((FbBits *) (winRec->pixelData + + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) + + (copy_rect.x1 - oldX) * Bpp), + winRec->bytesPerRow / sizeof(FbBits), 0, + (FbBits *) gResizeDeathBits, + copy_rowbytes / sizeof(FbBits), 0, + copy_rect_width * Bpp, copy_rect_height, + GXcopy, FB_ALLONES, Bpp, 0, 0); + } + + gResizeDeathBounds[1] = copy_rect; + gResizeDeathPix[1] + = GetScratchPixmapHeader(pScreen, copy_rect_width, + copy_rect_height, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, + (void *) gResizeDeathBits); + + SetPixmapBaseToScreen(gResizeDeathPix[1], + copy_rect.x1, copy_rect.y1); + + gResizeDeathCount = 2; + } + } + else if (gravity) { + /* The general case. Just copy everything. */ + + RootlessStartDrawing(pWin); + + gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); + + memcpy(gResizeDeathBits, winRec->pixelData, + winRec->bytesPerRow * winRec->height); + + gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; + gResizeDeathPix[0] + = GetScratchPixmapHeader(pScreen, winRec->width, + winRec->height, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, + (void *) gResizeDeathBits); + + SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); + gResizeDeathCount = 1; + } + + RootlessStopDrawing(pWin, FALSE); + + winRec->x = newX; + winRec->y = newY; + winRec->width = newW; + winRec->height = newH; + winRec->borderWidth = newBW; + + /* Unless both dimensions are getting smaller, Resize the frame + before doing gravity repair */ + + if (!resize_after) { + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + newX + SCREEN_TO_GLOBAL_X, + newY + SCREEN_TO_GLOBAL_Y, + newW, newH, weight); + } + + RootlessStartDrawing(pWin); + + /* If necessary, create a source pixmap pointing at the current + window bits. */ + + if (need_window_source) { + gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; + gResizeDeathPix[0] + = GetScratchPixmapHeader(pScreen, oldW, oldH, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, winRec->pixelData); + + SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); + } + + /* Use custom CopyWindow when moving gravity bits around + ResizeWindow assumes the old window contents are in the same + pixmap, but here they're in deathPix instead. */ + + if (gravity) { + gResizeOldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessResizeCopyWindow; + } + + /* If we can't rely on the window server preserving the bits we + need in the position we need, copy the pixels in the + intersection from src to dst. ResizeWindow assumes these pixels + are already present when making gravity adjustments. pWin + currently has new-sized pixmap but is in old position. + + FIXME: border width change! (?) */ + + if (gravity && weight == RL_GRAVITY_NONE) { + PixmapPtr src, dst; + + assert(gResizeDeathCount == 1); + + src = gResizeDeathPix[0]; + dst = pScreen->GetWindowPixmap(pWin); + + RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", + rect.x1, rect.y1, rect.x2, rect.y2); + + /* rect is the intersection of the old location and new location */ + if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { + /* The window drawable still has the old frame position, which + means that DST doesn't actually point at the origin of our + physical backing store when adjusted by the drawable.x,y + position. So sneakily adjust it temporarily while copying.. */ + + ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(dst, newX, newY); + + fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, + &rect, 1, 0, 0, FALSE, FALSE, 0, 0); + + ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(dst, oldX, oldY); + } + } + + return resize_after; +} + + +static void +FinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, + unsigned int oldW, unsigned int oldH, unsigned int oldBW, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int newBW, Bool resize_now) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + int i; + + RootlessStopDrawing(pWin, FALSE); + + if (resize_now) { + unsigned int weight; + + /* We didn't resize anything earlier, so do it now, now that + we've finished gravitating the bits. */ + + weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + newX + SCREEN_TO_GLOBAL_X, + newY + SCREEN_TO_GLOBAL_Y, + newW, newH, weight); + } + + /* Redraw everything. FIXME: there must be times when we don't need + to do this. Perhaps when top-left weighting and no gravity? */ + + RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); + + for (i = 0; i < 2; i++) { + if (gResizeDeathPix[i] != NULL) { + FreeScratchPixmapHeader(gResizeDeathPix[i]); + gResizeDeathPix[i] = NULL; + } + } + + if (gResizeDeathBits != NULL) { + free(gResizeDeathBits); + gResizeDeathBits = NULL; + } + + if (gravity) { + pScreen->CopyWindow = gResizeOldCopyWindowProc; + } +} + + +/* + * RootlessMoveWindow + * If kind==VTOther, window border is resizing (and borderWidth is + * already changed!!@#$) This case works like window resize, not move. + */ +void +RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + CopyWindowProcPtr oldCopyWindowProc = NULL; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0; + unsigned int newW = 0, newH = 0, newBW = 0; + Bool resize_after = FALSE; + RegionRec saveRoot; + + RL_DEBUG_MSG("movewindow start \n"); + + if (winRec) { + if (kind == VTMove) { + oldX = winRec->x; + oldY = winRec->y; + RootlessRedisplay(pWin); + RootlessStartDrawing(pWin); + } else { + RL_DEBUG_MSG("movewindow border resizing "); + + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = wBorderWidth(pWin); + newX = x; + newY = y; + newW = pWin->drawable.width + 2*newBW; + newH = pWin->drawable.height + 2*newBW; + + resize_after = StartFrameResize(pWin, FALSE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, MoveWindow); + + if (winRec) { + oldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessNoCopyWindow; + } + pScreen->MoveWindow(pWin, x, y, pSib, kind); + if (winRec) { + pScreen->CopyWindow = oldCopyWindowProc; + } + + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MoveWindow); + + if (winRec) { + if (kind == VTMove) { + winRec->x = x; + winRec->y = y; + RootlessStopDrawing(pWin, FALSE); + SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, + x + SCREEN_TO_GLOBAL_X, + y + SCREEN_TO_GLOBAL_Y); + } else { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } + + RL_DEBUG_MSG("movewindow end\n"); +} + + +/* + * RootlessResizeWindow + * Note: (x, y, w, h) as passed to this procedure don't match the frame + * definition. (x,y) is corner of very outer edge, *outside* border. + * w,h is width and height *inside* border, *ignoring* border width. + * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) + * is total rect and (x+bw, y+bw, w, h) is inner rect. + */ +void +RootlessResizeWindow(WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; + Bool resize_after = FALSE; + RegionRec saveRoot; + + RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); + + if(pWin->parent) { + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = oldBW; + newX = x; + newY = y; + newW = w + 2*newBW; + newH = h + 2*newBW; + + resize_after = StartFrameResize(pWin, TRUE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, ResizeWindow); + pScreen->ResizeWindow(pWin, x, y, w, h, pSib); + SCREEN_WRAP(pScreen, ResizeWindow); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } else { + /* Special case for resizing the root window */ + BoxRec box; + + pWin->drawable.x = x; + pWin->drawable.y = y; + pWin->drawable.width = w; + pWin->drawable.height = h; + + box.x1 = x; box.y1 = y; + box.x2 = x + w; box.y2 = y + h; + REGION_UNINIT(pScreen, &pWin->winSize); + REGION_INIT(pScreen, &pWin->winSize, &box, 1); + REGION_COPY(pScreen, &pWin->borderSize, &pWin->winSize); + REGION_COPY(pScreen, &pWin->clipList, &pWin->winSize); + REGION_COPY(pScreen, &pWin->borderClip, &pWin->winSize); + + miSendExposures(pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + } + + RL_DEBUG_MSG("resizewindow end\n"); +} + + +/* + * 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 + * implementation calling RootlessFrameForWindow. (e.g. this could be needed + * to attach a VRAM surface to it.) If the window is subsequently reparented + * by the window manager before being mapped, we need to give the frame to + * the new top-level window. + */ +void +RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + WindowPtr pTopWin; + + /* Check that window is not top-level now, but used to be. */ + if (IsRoot(pWin) || IsRoot(pWin->parent) + || IsTopLevel(pWin) || winRec == NULL) + { + goto out; + } + + /* If the formerly top-level window has a frame, we want to give the + frame to its new top-level parent. If we can't do that, we'll just + have to jettison it... */ + + pTopWin = TopLevelParent(pWin); + assert(pTopWin != pWin); + + pWin->rootlessUnhittable = FALSE; + + DeleteProperty (serverClient, pWin, xa_native_window_id ()); + + if (WINREC(pTopWin) != NULL) { + /* We're screwed. */ + RootlessDestroyFrame(pWin, winRec); + } else { + if (!pTopWin->realized && pWin->realized) { + SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); + } + + /* Switch the frame record from one to the other. */ + + SETWINREC(pWin, NULL); + SETWINREC(pTopWin, winRec); + + RootlessInitializeFrame(pTopWin, winRec); + RootlessReshapeFrame(pTopWin); + + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y, + winRec->width, winRec->height, + RL_GRAVITY_NONE); + + if (SCREENREC(pScreen)->imp->SwitchWindow) { + SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); + } + + if (pTopWin->realized && !pWin->realized) + winRec->is_reorder_pending = TRUE; + } + +out: + if (SCREENREC(pScreen)->ReparentWindow) { + SCREEN_UNWRAP(pScreen, ReparentWindow); + pScreen->ReparentWindow(pWin, pPriorParent); + SCREEN_WRAP(pScreen, ReparentWindow); + } +} + + +void +RootlessFlushWindowColormap (WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC (pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (winRec == NULL) + return; + + RootlessStopDrawing (pWin, FALSE); + + if (SCREENREC(pScreen)->imp->UpdateColormap) + SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); +} + +/* + * RootlessChangeBorderWidth + * FIXME: untested! + * pWin inside corner stays the same; pWin->drawable.[xy] stays the same + * Frame moves and resizes. + */ +void +RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) +{ + RegionRec saveRoot; + Bool resize_after = FALSE; + + RL_DEBUG_MSG("change border width "); + + if (width != wBorderWidth(pWin)) { + RootlessWindowRec *winRec = WINREC(pWin); + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0; + unsigned int newW = 0, newH = 0, newBW = 0; + + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = width; + newX = pWin->drawable.x - newBW; + newY = pWin->drawable.y - newBW; + newW = pWin->drawable.width + 2*newBW; + newH = pWin->drawable.height + 2*newBW; + + resize_after = StartFrameResize(pWin, FALSE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); + pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); + SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } + + RL_DEBUG_MSG("change border width end\n"); +} + +/* + * RootlessOrderAllWindows + * Brings all X11 windows to the top of the window stack + * (i.e in front of Aqua windows) -- called when X11.app is given focus + */ +void +RootlessOrderAllWindows (void) +{ + int i; + WindowPtr pWin; + + if (windows_hidden) + return; + + RL_DEBUG_MSG("RootlessOrderAllWindows() "); + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i] == NULL) continue; + pWin = WindowTable[i]; + if (pWin == NULL) continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { + if (!pWin->realized) continue; + if (RootlessEnsureFrame(pWin) == NULL) continue; + RootlessReorderWindow (pWin); + } + } + RL_DEBUG_MSG("RootlessOrderAllWindows() done"); +} + +void +RootlessEnableRoot (ScreenPtr pScreen) +{ + WindowPtr pRoot; + pRoot = WindowTable[pScreen->myNum]; + + RootlessEnsureFrame (pRoot); + (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); + RootlessReorderWindow (pRoot); +} + +void +RootlessDisableRoot (ScreenPtr pScreen) +{ + WindowPtr pRoot; + RootlessWindowRec *winRec; + + pRoot = WindowTable[pScreen->myNum]; + winRec = WINREC (pRoot); + + if (NULL == winRec) + return; + + RootlessDestroyFrame (pRoot, winRec); + DeleteProperty (serverClient, pRoot, xa_native_window_id ()); +} + +void +RootlessHideAllWindows (void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + + if (windows_hidden) + return; + + windows_hidden = TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pWin = WindowTable[i]; + if (pScreen == NULL || pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) + { + if (!pWin->realized) + continue; + + RootlessStopDrawing (pWin, FALSE); + + winRec = WINREC (pWin); + if (winRec != NULL) + { + if (SCREENREC(pScreen)->imp->HideWindow) + SCREENREC(pScreen)->imp->HideWindow(winRec->wid); + } + } + } +} + +void +RootlessShowAllWindows (void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + + if (!windows_hidden) + return; + + windows_hidden = FALSE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + pWin = WindowTable[i]; + if (pScreen == NULL || pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) + { + if (!pWin->realized) + continue; + + winRec = RootlessEnsureFrame (pWin); + if (winRec == NULL) + continue; + + RootlessReorderWindow (pWin); + } + + RootlessScreenExpose (pScreen); + } +} + +/* + * SetPixmapOfAncestors + * Set the Pixmaps on all ParentRelative windows up the ancestor chain. + */ +void +RootlessSetPixmapOfAncestors(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr topWin = TopLevelParent(pWin); + RootlessWindowRec *topWinRec = WINREC(topWin); + + while (pWin->backgroundState == ParentRelative) { + if (pWin == topWin) { + // disallow ParentRelative background state on top level + XID pixel = 0; + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); + break; + } + + pWin = pWin->parent; + pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); + } +} + diff --git a/xorg-server/miext/shadow/shadow.c b/xorg-server/miext/shadow/shadow.c index 608ccd234..2dcee60b1 100644 --- a/xorg-server/miext/shadow/shadow.c +++ b/xorg-server/miext/shadow/shadow.c @@ -1,249 +1,249 @@ -/* - * Copyright © 2000 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include "scrnintstr.h" -#include "windowstr.h" -#include "dixfontstr.h" -#include "mi.h" -#include "regionstr.h" -#include "globals.h" -#include "gcstruct.h" -#include "shadow.h" - -static int shadowScrPrivateKeyIndex; -DevPrivateKey shadowScrPrivateKey = &shadowScrPrivateKeyIndex; - -#define wrap(priv, real, mem) {\ - priv->mem = real->mem; \ - real->mem = shadow##mem; \ -} - -#define unwrap(priv, real, mem) {\ - real->mem = priv->mem; \ -} - -static void -shadowRedisplay(ScreenPtr pScreen) -{ - shadowBuf(pScreen); - RegionPtr pRegion; - - if (!pBuf || !pBuf->pDamage || !pBuf->update) - return; - pRegion = DamageRegion(pBuf->pDamage); - if (REGION_NOTEMPTY(pScreen, pRegion)) { - (*pBuf->update)(pScreen, pBuf); - DamageEmpty(pBuf->pDamage); - } -} - -static void -shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) -{ - ScreenPtr pScreen = (ScreenPtr) data; - - shadowRedisplay(pScreen); -} - -static void -shadowWakeupHandler(pointer data, int i, pointer LastSelectMask) -{ -} - -static void -shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planeMask, char *pdstLine) -{ - ScreenPtr pScreen = pDrawable->pScreen; - shadowBuf(pScreen); - - /* Many apps use GetImage to sync with the visable frame buffer */ - if (pDrawable->type == DRAWABLE_WINDOW) - shadowRedisplay(pScreen); - unwrap(pBuf, pScreen, GetImage); - pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); - wrap(pBuf, pScreen, GetImage); -} - -#define BACKWARDS_COMPATIBILITY - -static Bool -shadowCloseScreen(int i, ScreenPtr pScreen) -{ - shadowBuf(pScreen); - - unwrap(pBuf, pScreen, GetImage); - unwrap(pBuf, pScreen, CloseScreen); - shadowRemove(pScreen, pBuf->pPixmap); - DamageDestroy(pBuf->pDamage); -#ifdef BACKWARDS_COMPATIBILITY - REGION_UNINIT(pScreen, &pBuf->damage); /* bc */ -#endif - if (pBuf->pPixmap) - pScreen->DestroyPixmap(pBuf->pPixmap); - xfree(pBuf); - return pScreen->CloseScreen(i, pScreen); -} - -#ifdef BACKWARDS_COMPATIBILITY -static void -shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - ScreenPtr pScreen = closure; - shadowBufPtr pBuf = (shadowBufPtr) - dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey); - - /* Register the damaged region, use DamageReportNone below when we - * want to break BC below... */ - REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pRegion); - - /* - * BC hack. In 7.0 and earlier several drivers would inspect the - * 'damage' member directly, so we have to keep it existing. - */ - REGION_COPY(pScreen, &pBuf->damage, pRegion); -} -#endif - -Bool -shadowSetup(ScreenPtr pScreen) -{ - shadowBufPtr pBuf; - - if (!DamageSetup(pScreen)) - return FALSE; - - pBuf = xalloc(sizeof(shadowBufRec)); - if (!pBuf) - return FALSE; -#ifdef BACKWARDS_COMPATIBILITY - pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc, - (DamageDestroyFunc)NULL, - DamageReportRawRegion, - TRUE, pScreen, pScreen); -#else - pBuf->pDamage = DamageCreate((DamageReportFunc)NULL, - (DamageDestroyFunc)NULL, - DamageReportNone, - TRUE, pScreen, pScreen); -#endif - if (!pBuf->pDamage) { - xfree(pBuf); - return FALSE; - } - - wrap(pBuf, pScreen, CloseScreen); - wrap(pBuf, pScreen, GetImage); - pBuf->update = 0; - pBuf->window = 0; - pBuf->pPixmap = 0; - pBuf->closure = 0; - pBuf->randr = 0; -#ifdef BACKWARDS_COMPATIBILITY - REGION_NULL(pScreen, &pBuf->damage); /* bc */ -#endif - - dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); - return TRUE; -} - -Bool -shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, - ShadowWindowProc window, int randr, void *closure) -{ - shadowBuf(pScreen); - - if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, - (pointer)pScreen)) - return FALSE; - - /* - * Map simple rotation values to bitmasks; fortunately, - * these are all unique - */ - switch (randr) { - case 0: - randr = SHADOW_ROTATE_0; - break; - case 90: - randr = SHADOW_ROTATE_90; - break; - case 180: - randr = SHADOW_ROTATE_180; - break; - case 270: - randr = SHADOW_ROTATE_270; - break; - } - pBuf->update = update; - pBuf->window = window; - pBuf->randr = randr; - pBuf->closure = closure; - pBuf->pPixmap = pPixmap; - DamageRegister(&pPixmap->drawable, pBuf->pDamage); - return TRUE; -} - -void -shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) -{ - shadowBuf(pScreen); - - if (pBuf->pPixmap) { - DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage); - pBuf->update = 0; - pBuf->window = 0; - pBuf->randr = 0; - pBuf->closure = 0; - pBuf->pPixmap = 0; - } - - RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, - (pointer) pScreen); -} - -Bool -shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) -{ - PixmapPtr pPixmap; - - pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, - pScreen->rootDepth, 0); - if (!pPixmap) - return FALSE; - - if (!shadowSetup(pScreen)) { - pScreen->DestroyPixmap(pPixmap); - return FALSE; - } - - shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0); - - return TRUE; -} +/* + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" + +static int shadowScrPrivateKeyIndex; +DevPrivateKey shadowScrPrivateKey = &shadowScrPrivateKeyIndex; + +#define wrap(priv, real, mem) {\ + priv->mem = real->mem; \ + real->mem = shadow##mem; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +static void +shadowRedisplay(ScreenPtr pScreen) +{ + shadowBuf(pScreen); + RegionPtr pRegion; + + if (!pBuf || !pBuf->pDamage || !pBuf->update) + return; + pRegion = DamageRegion(pBuf->pDamage); + if (REGION_NOTEMPTY(pScreen, pRegion)) { + (*pBuf->update)(pScreen, pBuf); + DamageEmpty(pBuf->pDamage); + } +} + +static void +shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + ScreenPtr pScreen = (ScreenPtr) data; + + shadowRedisplay(pScreen); +} + +static void +shadowWakeupHandler(pointer data, int i, pointer LastSelectMask) +{ +} + +static void +shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planeMask, char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + shadowBuf(pScreen); + + /* Many apps use GetImage to sync with the visable frame buffer */ + if (pDrawable->type == DRAWABLE_WINDOW) + shadowRedisplay(pScreen); + unwrap(pBuf, pScreen, GetImage); + pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + wrap(pBuf, pScreen, GetImage); +} + +#define BACKWARDS_COMPATIBILITY + +static Bool +shadowCloseScreen(int i, ScreenPtr pScreen) +{ + shadowBuf(pScreen); + + unwrap(pBuf, pScreen, GetImage); + unwrap(pBuf, pScreen, CloseScreen); + shadowRemove(pScreen, pBuf->pPixmap); + DamageDestroy(pBuf->pDamage); +#ifdef BACKWARDS_COMPATIBILITY + REGION_UNINIT(pScreen, &pBuf->damage); /* bc */ +#endif + if (pBuf->pPixmap) + pScreen->DestroyPixmap(pBuf->pPixmap); + free(pBuf); + return pScreen->CloseScreen(i, pScreen); +} + +#ifdef BACKWARDS_COMPATIBILITY +static void +shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + ScreenPtr pScreen = closure; + shadowBufPtr pBuf = (shadowBufPtr) + dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey); + + /* Register the damaged region, use DamageReportNone below when we + * want to break BC below... */ + REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pRegion); + + /* + * BC hack. In 7.0 and earlier several drivers would inspect the + * 'damage' member directly, so we have to keep it existing. + */ + REGION_COPY(pScreen, &pBuf->damage, pRegion); +} +#endif + +Bool +shadowSetup(ScreenPtr pScreen) +{ + shadowBufPtr pBuf; + + if (!DamageSetup(pScreen)) + return FALSE; + + pBuf = malloc(sizeof(shadowBufRec)); + if (!pBuf) + return FALSE; +#ifdef BACKWARDS_COMPATIBILITY + pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc, + (DamageDestroyFunc)NULL, + DamageReportRawRegion, + TRUE, pScreen, pScreen); +#else + pBuf->pDamage = DamageCreate((DamageReportFunc)NULL, + (DamageDestroyFunc)NULL, + DamageReportNone, + TRUE, pScreen, pScreen); +#endif + if (!pBuf->pDamage) { + free(pBuf); + return FALSE; + } + + wrap(pBuf, pScreen, CloseScreen); + wrap(pBuf, pScreen, GetImage); + pBuf->update = 0; + pBuf->window = 0; + pBuf->pPixmap = 0; + pBuf->closure = 0; + pBuf->randr = 0; +#ifdef BACKWARDS_COMPATIBILITY + REGION_NULL(pScreen, &pBuf->damage); /* bc */ +#endif + + dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); + return TRUE; +} + +Bool +shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, + ShadowWindowProc window, int randr, void *closure) +{ + shadowBuf(pScreen); + + if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, + (pointer)pScreen)) + return FALSE; + + /* + * Map simple rotation values to bitmasks; fortunately, + * these are all unique + */ + switch (randr) { + case 0: + randr = SHADOW_ROTATE_0; + break; + case 90: + randr = SHADOW_ROTATE_90; + break; + case 180: + randr = SHADOW_ROTATE_180; + break; + case 270: + randr = SHADOW_ROTATE_270; + break; + } + pBuf->update = update; + pBuf->window = window; + pBuf->randr = randr; + pBuf->closure = closure; + pBuf->pPixmap = pPixmap; + DamageRegister(&pPixmap->drawable, pBuf->pDamage); + return TRUE; +} + +void +shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) +{ + shadowBuf(pScreen); + + if (pBuf->pPixmap) { + DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage); + pBuf->update = 0; + pBuf->window = 0; + pBuf->randr = 0; + pBuf->closure = 0; + pBuf->pPixmap = 0; + } + + RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, + (pointer) pScreen); +} + +Bool +shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) +{ + PixmapPtr pPixmap; + + pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, + pScreen->rootDepth, 0); + if (!pPixmap) + return FALSE; + + if (!shadowSetup(pScreen)) { + pScreen->DestroyPixmap(pPixmap); + return FALSE; + } + + shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0); + + return TRUE; +} diff --git a/xorg-server/miext/shadow/shalloc.c b/xorg-server/miext/shadow/shalloc.c index 72aa28b14..ebeaaaee6 100644 --- a/xorg-server/miext/shadow/shalloc.c +++ b/xorg-server/miext/shadow/shalloc.c @@ -1,50 +1,50 @@ -/* - * Copyright © 2000 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include "scrnintstr.h" -#include "windowstr.h" -#include -#include "dixfontstr.h" -#include -#include "mi.h" -#include "regionstr.h" -#include "globals.h" -#include "gcstruct.h" -#include "shadow.h" - -void * -shadowAlloc (int width, int height, int bpp) -{ - int stride; - void *fb; - - /* Cant use PixmapBytePad -- the structure is probably not initialized yet */ - stride = BitmapBytePad (width * bpp); - fb = xalloc (stride * height); - return fb; -} +/* + * Copyright © 2000 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include +#include "dixfontstr.h" +#include +#include "mi.h" +#include "regionstr.h" +#include "globals.h" +#include "gcstruct.h" +#include "shadow.h" + +void * +shadowAlloc (int width, int height, int bpp) +{ + int stride; + void *fb; + + /* Cant use PixmapBytePad -- the structure is probably not initialized yet */ + stride = BitmapBytePad (width * bpp); + fb = malloc(stride * height); + return fb; +} -- cgit v1.2.3