X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2Fmi%2Fmiexpose.c;fp=Xserver%2Fprograms%2FXserver%2Fmi%2Fmiexpose.c;h=b1e4d16e44a5f1597e5f9dc64ce202cfae6a8e7f;hp=0000000000000000000000000000000000000000;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hpb=e3340a110a3b01756b8e67531395a33b40a17d37 diff --git a/Xserver/programs/Xserver/mi/miexpose.c b/Xserver/programs/Xserver/mi/miexpose.c new file mode 100644 index 0000000..b1e4d16 --- /dev/null +++ b/Xserver/programs/Xserver/mi/miexpose.c @@ -0,0 +1,829 @@ +/*********************************************************** + +Copyright (c) 1987 X Consortium + +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 +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* $XConsortium: miexpose.c /main/43 1996/08/01 19:25:26 dpw $ */ +/* $XFree86: xc/programs/Xserver/mi/miexpose.c,v 3.1 1996/12/23 07:09:44 dawes Exp $ */ + +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "Xprotostr.h" + +#include "misc.h" +#include "regionstr.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "input.h" + +#include "dixstruct.h" +#include "mi.h" +#include "Xmd.h" + +extern WindowPtr *WindowTable; + +/* + machine-independent graphics exposure code. any device that uses +the region package can call this. +*/ + +#ifndef RECTLIMIT +#define RECTLIMIT 25 /* pick a number, any number > 8 */ +#endif + +/* miHandleExposures + generate a region for exposures for areas that were copied from obscured or +non-existent areas to non-obscured areas of the destination. Paint the +background for the region, if the destination is a window. + +NOTE: + this should generally be called, even if graphicsExposures is false, +because this is where bits get recovered from backing store. + +NOTE: + added argument 'plane' is used to indicate how exposures from backing +store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea +should be used, else a CopyPlane of the indicated plane will be used. The +exposing is done by the backing store's GraphicsExpose function, of course. + +*/ + +RegionPtr +miHandleExposures(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane) + register DrawablePtr pSrcDrawable; + register DrawablePtr pDstDrawable; + GCPtr pGC; + int srcx, srcy; + int width, height; + int dstx, dsty; + unsigned long plane; +{ + register ScreenPtr pscr = pGC->pScreen; + RegionPtr prgnSrcClip; /* drawable-relative source clip */ + RegionRec rgnSrcRec; + RegionPtr prgnDstClip; /* drawable-relative dest clip */ + RegionRec rgnDstRec; + BoxRec srcBox; /* unclipped source */ + RegionRec rgnExposed; /* exposed region, calculated source- + relative, made dst relative to + intersect with visible parts of + dest and send events to client, + and then screen relative to paint + the window background + */ + WindowPtr pSrcWin; + BoxRec expBox; + Bool extents; + + /* avoid work if we can */ + if (!pGC->graphicsExposures && + (pDstDrawable->type == DRAWABLE_PIXMAP) && + ((pSrcDrawable->type == DRAWABLE_PIXMAP) || + (((WindowPtr)pSrcDrawable)->backStorage == NULL))) + return NULL; + + srcBox.x1 = srcx; + srcBox.y1 = srcy; + srcBox.x2 = srcx+width; + srcBox.y2 = srcy+height; + + if (pSrcDrawable->type != DRAWABLE_PIXMAP) + { + BoxRec TsrcBox; + + TsrcBox.x1 = srcx + pSrcDrawable->x; + TsrcBox.y1 = srcy + pSrcDrawable->y; + TsrcBox.x2 = TsrcBox.x1 + width; + TsrcBox.y2 = TsrcBox.y1 + height; + pSrcWin = (WindowPtr) pSrcDrawable; + if (pGC->subWindowMode == IncludeInferiors) + { + prgnSrcClip = NotClippedByChildren (pSrcWin); + if ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN) + { + REGION_DESTROY(pscr, prgnSrcClip); + return NULL; + } + } + else + { + if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN) + return NULL; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, NullBox, 0); + REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList); + } + REGION_TRANSLATE(pscr, prgnSrcClip, + -pSrcDrawable->x, -pSrcDrawable->y); + } + else + { + BoxRec box; + + if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && + (srcBox.x2 <= pSrcDrawable->width) && + (srcBox.y2 <= pSrcDrawable->height)) + return NULL; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pSrcDrawable->width; + box.y2 = pSrcDrawable->height; + prgnSrcClip = &rgnSrcRec; + REGION_INIT(pscr, prgnSrcClip, &box, 1); + pSrcWin = (WindowPtr)NULL; + } + + if (pDstDrawable == pSrcDrawable) + { + prgnDstClip = prgnSrcClip; + } + else if (pDstDrawable->type != DRAWABLE_PIXMAP) + { + if (pGC->subWindowMode == IncludeInferiors) + { + prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); + } + else + { + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, NullBox, 0); + REGION_COPY(pscr, prgnDstClip, + &((WindowPtr)pDstDrawable)->clipList); + } + REGION_TRANSLATE(pscr, prgnDstClip, + -pDstDrawable->x, -pDstDrawable->y); + } + else + { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDstDrawable->width; + box.y2 = pDstDrawable->height; + prgnDstClip = &rgnDstRec; + REGION_INIT(pscr, prgnDstClip, &box, 1); + } + + /* drawable-relative source region */ + REGION_INIT(pscr, &rgnExposed, &srcBox, 1); + + /* now get the hidden parts of the source box*/ + REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip); + + if (pSrcWin && pSrcWin->backStorage) + { + /* + * Copy any areas from the source backing store. Modifies + * rgnExposed. + */ + (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable, + pDstDrawable, + pGC, + &rgnExposed, + srcx, srcy, + dstx, dsty, + plane); + } + + /* move them over the destination */ + REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy); + + /* intersect with visible areas of dest */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip); + + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-) + * for windows. + */ + extents = pGC->graphicsExposures && + (REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) && + (pDstDrawable->type != DRAWABLE_PIXMAP); +#ifdef SHAPE + if (pSrcWin) + { + RegionPtr region; + if (!(region = wClipShape (pSrcWin))) + region = wBoundingShape (pSrcWin); + /* + * If you try to CopyArea the extents of a shaped window, compacting the + * exposed region will undo all our work! + */ + if (extents && pSrcWin && region && + (RECT_IN_REGION(pscr, region, &srcBox) != rgnIN)) + extents = FALSE; + } +#endif + if (extents) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + expBox = *REGION_EXTENTS(pscr, &rgnExposed); + REGION_RESET(pscr, &rgnExposed, &expBox); + /* need to clear out new areas of backing store */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + expBox.x1, + expBox.y1, + expBox.x2 - expBox.x1, + expBox.y2 - expBox.y1, + FALSE); + } + if ((pDstDrawable->type != DRAWABLE_PIXMAP) && + (((WindowPtr)pDstDrawable)->backgroundState != None)) + { + WindowPtr pWin = (WindowPtr)pDstDrawable; + + /* make the exposed area screen-relative */ + REGION_TRANSLATE(pscr, &rgnExposed, + pDstDrawable->x, pDstDrawable->y); + + if (extents) + { + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList); + } + (*pWin->drawable.pScreen->PaintWindowBackground)( + (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); + + if (extents) + { + REGION_RESET(pscr, &rgnExposed, &expBox); + } + else + REGION_TRANSLATE(pscr, &rgnExposed, + -pDstDrawable->x, -pDstDrawable->y); + } + if (prgnDstClip == &rgnDstRec) + { + REGION_UNINIT(pscr, prgnDstClip); + } + else if (prgnDstClip != prgnSrcClip) + { + REGION_DESTROY(pscr, prgnDstClip); + } + + if (prgnSrcClip == &rgnSrcRec) + { + REGION_UNINIT(pscr, prgnSrcClip); + } + else + { + REGION_DESTROY(pscr, prgnSrcClip); + } + + if (pGC->graphicsExposures) + { + /* don't look */ + RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0); + *exposed = rgnExposed; + return exposed; + } + else + { + REGION_UNINIT(pscr, &rgnExposed); + return NULL; + } +} + +/* send GraphicsExpose events, or a NoExpose event, based on the region */ + +void +miSendGraphicsExpose (client, pRgn, drawable, major, minor) + ClientPtr client; + RegionPtr pRgn; + XID drawable; + int major; + int minor; +{ + if (pRgn && !REGION_NIL(pRgn)) + { + xEvent *pEvent; + register xEvent *pe; + register BoxPtr pBox; + register int i; + int numRects; + + numRects = REGION_NUM_RECTS(pRgn); + pBox = REGION_RECTS(pRgn); + if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + pe = pEvent; + + for (i=1; i<=numRects; i++, pe++, pBox++) + { + pe->u.u.type = GraphicsExpose; + pe->u.graphicsExposure.drawable = drawable; + pe->u.graphicsExposure.x = pBox->x1; + pe->u.graphicsExposure.y = pBox->y1; + pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; + pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; + pe->u.graphicsExposure.count = numRects - i; + pe->u.graphicsExposure.majorEvent = major; + pe->u.graphicsExposure.minorEvent = minor; + } + TryClientEvents(client, pEvent, numRects, + (Mask)0, NoEventMask, NullGrab); + DEALLOCATE_LOCAL(pEvent); + } + else + { + xEvent event; + event.u.u.type = NoExpose; + event.u.noExposure.drawable = drawable; + event.u.noExposure.majorEvent = major; + event.u.noExposure.minorEvent = minor; + TryClientEvents(client, &event, 1, + (Mask)0, NoEventMask, NullGrab); + } +} + +void +miSendExposures(pWin, pRgn, dx, dy) + WindowPtr pWin; + RegionPtr pRgn; + register int dx, dy; +{ + register BoxPtr pBox; + int numRects; + register xEvent *pEvent, *pe; + register int i; + + pBox = REGION_RECTS(pRgn); + numRects = REGION_NUM_RECTS(pRgn); + if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent)))) + return; + + for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) + { + pe->u.u.type = Expose; + pe->u.expose.window = pWin->drawable.id; + pe->u.expose.x = pBox->x1 - dx; + pe->u.expose.y = pBox->y1 - dy; + pe->u.expose.width = pBox->x2 - pBox->x1; + pe->u.expose.height = pBox->y2 - pBox->y1; + pe->u.expose.count = i; + } + DeliverEvents(pWin, pEvent, numRects, NullWindow); + DEALLOCATE_LOCAL(pEvent); +} + +void +miWindowExposures(pWin, prgn, other_exposed) + WindowPtr pWin; + register RegionPtr prgn, other_exposed; +{ + RegionPtr exposures = prgn; + if (pWin->backStorage && prgn) + /* + * in some cases, backing store will cause a different + * region to be exposed than needs to be repainted + * (like when a window is mapped). RestoreAreas is + * allowed to return a region other than prgn, + * in which case this routine will free the resultant + * region. If exposures is null, then no events will + * be sent to the client; if prgn is empty + * no areas will be repainted. + */ + exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn); + if ((prgn && !REGION_NIL(prgn)) || + (exposures && !REGION_NIL(exposures)) || other_exposed) + { + RegionRec expRec; + int clientInterested; + + /* + * Restore from backing-store FIRST. + */ + clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; + if (other_exposed) + { + if (exposures) + { + REGION_UNION(pWin->drawable.pScreen, other_exposed, + exposures, + other_exposed); + if (exposures != prgn) + REGION_DESTROY(pWin->drawable.pScreen, exposures); + } + exposures = other_exposed; + } + if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT)) + { + /* + * If we have LOTS of rectangles, we decide to take the extents + * and force an exposure on that. This should require much less + * work overall, on both client and server. This is cheating, but + * isn't prohibited by the protocol ("spontaneous combustion" :-). + */ + BoxRec box; + + box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures); + if (exposures == prgn) { + exposures = &expRec; + REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1); + REGION_RESET( pWin->drawable.pScreen, prgn, &box); + } else { + REGION_RESET( pWin->drawable.pScreen, exposures, &box); + REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures); + } + /* PaintWindowBackground doesn't clip, so we have to */ + REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList); + /* need to clear out new areas of backing store, too */ + if (pWin->backStorage) + (void) (* pWin->drawable.pScreen->ClearBackingStore)( + pWin, + box.x1 - pWin->drawable.x, + box.y1 - pWin->drawable.y, + box.x2 - box.x1, + box.y2 - box.y1, + FALSE); + } + if (prgn && !REGION_NIL(prgn)) + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !REGION_NIL(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) + { + REGION_UNINIT( pWin->drawable.pScreen, exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + REGION_DESTROY( pWin->drawable.pScreen, exposures); + if (prgn) + REGION_EMPTY( pWin->drawable.pScreen, prgn); + } + else if (exposures && exposures != prgn) + REGION_DESTROY( pWin->drawable.pScreen, exposures); +} + + +/* + this code is highly unlikely. it is not haile selassie. + + there is some hair here. we can't just use the window's +clip region as it is, because if we are painting the border, +the border is not in the client area and so we will be excluded +when we validate the GC, and if we are painting a parent-relative +background, the area we want to paint is in some other window. +since we trust the code calling us to tell us to paint only areas +that are really ours, we will temporarily give the window a +clipList the size of the whole screen and an origin at (0,0). +this more or less assumes that ddX code will do translation +based on the window's absolute position, and that ValidateGC will +look at clipList, and that no other fields from the +window will be used. it's not possible to just draw +in the root because it may be a different depth. + +to get the tile to align correctly we set the GC's tile origin to +be the (x,y) of the window's upper left corner, after which we +get the right bits when drawing into the root. + +because the clip_mask is being set to None, we may call DoChangeGC with +fPointer set true, thus we no longer need to install the background or +border tile in the resource table. +*/ + +static RESTYPE ResType = 0; +static int numGCs = 0; +static GCPtr screenContext[MAXSCREENS]; + +/*ARGSUSED*/ +static int +tossGC (value, id) +pointer value; +XID id; +{ + GCPtr pGC = (GCPtr)value; + screenContext[pGC->pScreen->myNum] = (GCPtr)NULL; + FreeGC (pGC, id); + numGCs--; + if (!numGCs) + ResType = 0; +} + + +void +miPaintWindow(pWin, prgn, what) +register WindowPtr pWin; +RegionPtr prgn; +int what; +{ + int status; + + Bool usingScratchGC = FALSE; + WindowPtr pRoot; + +#define FUNCTION 0 +#define FOREGROUND 1 +#define TILE 2 +#define FILLSTYLE 3 +#define ABSX 4 +#define ABSY 5 +#define CLIPMASK 6 +#define SUBWINDOW 7 +#define COUNT_BITS 8 + + ChangeGCVal gcval[7]; + ChangeGCVal newValues [COUNT_BITS]; + + BITS32 gcmask, index, mask; + RegionRec prgnWin; + DDXPointRec oldCorner; + BoxRec box; + WindowPtr pBgWin; + GCPtr pGC; + register int i; + register BoxPtr pbox; + register ScreenPtr pScreen = pWin->drawable.pScreen; + register xRectangle *prect; + int numRects; + + gcmask = 0; + + if (what == PW_BACKGROUND) + { + switch (pWin->backgroundState) { + case None: + return; + case ParentRelative: + (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what); + return; + case BackgroundPixel: + newValues[FOREGROUND].val = pWin->background.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + break; + case BackgroundPixmap: + newValues[TILE].ptr = (pointer)pWin->background.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + break; + } + } + else + { + if (pWin->borderIsPixel) + { + newValues[FOREGROUND].val = pWin->border.pixel; + newValues[FILLSTYLE].val = FillSolid; + gcmask |= GCForeground | GCFillStyle; + } + else + { + newValues[TILE].ptr = (pointer)pWin->border.pixmap; + newValues[FILLSTYLE].val = FillTiled; + gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin; + } + } + + prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) * + sizeof(xRectangle)); + if (!prect) + return; + + newValues[FUNCTION].val = GXcopy; + gcmask |= GCFunction | GCClipMask; + + i = pScreen->myNum; + pRoot = WindowTable[i]; + + pBgWin = pWin; + if (what == PW_BORDER) + { + while (pBgWin->backgroundState == ParentRelative) + pBgWin = pBgWin->parent; + } + + if ((pWin->drawable.depth != pRoot->drawable.depth) || + (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel)) + { + usingScratchGC = TRUE; + pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen); + if (!pGC) + { + DEALLOCATE_LOCAL(prect); + return; + } + /* + * mash the clip list so we can paint the border by + * mangling the window in place, pretending it + * spans the entire screen + */ + if (what == PW_BORDER) + { + prgnWin = pWin->clipList; + oldCorner.x = pWin->drawable.x; + oldCorner.y = pWin->drawable.y; + pWin->drawable.x = pWin->drawable.y = 0; + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, &pWin->clipList, &box, 1); + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + } + else + { + newValues[ABSX].val = 0; + newValues[ABSY].val = 0; + } + } else { + /* + * draw the background to the root window + */ + if (screenContext[i] == (GCPtr)NULL) + { + if (!ResType && !(ResType = CreateNewResourceType(tossGC))) + return; + screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0, + (XID *)NULL, &status); + if (!screenContext[i]) + return; + numGCs++; + if (!AddResource(FakeClientID(0), ResType, + (pointer)screenContext[i])) + return; + } + pGC = screenContext[i]; + newValues[SUBWINDOW].val = IncludeInferiors; + newValues[ABSX].val = pBgWin->drawable.x; + newValues[ABSY].val = pBgWin->drawable.y; + gcmask |= GCSubwindowMode; + pWin = pRoot; + } + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); + + mask = gcmask; + gcmask = 0; + i = 0; + while (mask) { + index = lowbit (mask); + mask &= ~index; + switch (index) { + case GCFunction: + if (pGC->alu != newValues[FUNCTION].val) { + gcmask |= index; + gcval[i++].val = newValues[FUNCTION].val; + } + break; + case GCTileStipXOrigin: + if ( pGC->patOrg.x != newValues[ABSX].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSX].val; + } + break; + case GCTileStipYOrigin: + if ( pGC->patOrg.y != newValues[ABSY].val) { + gcmask |= index; + gcval[i++].val = newValues[ABSY].val; + } + break; + case GCClipMask: + if ( pGC->clientClipType != CT_NONE) { + gcmask |= index; + gcval[i++].val = CT_NONE; + } + break; + case GCSubwindowMode: + if ( pGC->subWindowMode != newValues[SUBWINDOW].val) { + gcmask |= index; + gcval[i++].val = newValues[SUBWINDOW].val; + } + break; + case GCTile: + if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr) + { + gcmask |= index; + gcval[i++].ptr = newValues[TILE].ptr; + } + break; + case GCFillStyle: + if ( pGC->fillStyle != newValues[FILLSTYLE].val) { + gcmask |= index; + gcval[i++].val = newValues[FILLSTYLE].val; + } + break; + case GCForeground: + if ( pGC->fgPixel != newValues[FOREGROUND].val) { + gcmask |= index; + gcval[i++].val = newValues[FOREGROUND].val; + } + break; + } + } + + if (gcmask) + dixChangeGC(NullClient, pGC, gcmask, NULL, gcval); + + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC((DrawablePtr)pWin, pGC); + + numRects = REGION_NUM_RECTS(prgn); + pbox = REGION_RECTS(prgn); + for (i= numRects; --i >= 0; pbox++, prect++) + { + prect->x = pbox->x1 - pWin->drawable.x; + prect->y = pbox->y1 - pWin->drawable.y; + prect->width = pbox->x2 - pbox->x1; + prect->height = pbox->y2 - pbox->y1; + } + prect -= numRects; + (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect); + DEALLOCATE_LOCAL(prect); + + if (pWin->backStorage) + (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing); + + if (usingScratchGC) + { + if (what == PW_BORDER) + { + REGION_UNINIT(pScreen, &pWin->clipList); + pWin->clipList = prgnWin; + pWin->drawable.x = oldCorner.x; + pWin->drawable.y = oldCorner.y; + pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + FreeScratchGC(pGC); + } +} + + +/* MICLEARDRAWABLE -- sets the entire drawable to the background color of + * the GC. Useful when we have a scratch drawable and need to initialize + * it. */ +miClearDrawable(pDraw, pGC) + DrawablePtr pDraw; + GCPtr pGC; +{ + XID fg = pGC->fgPixel; + XID bg = pGC->bgPixel; + xRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = pDraw->width; + rect.height = pDraw->height; + DoChangeGC(pGC, GCForeground, &bg, 0); + ValidateGC(pDraw, pGC); + (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); + DoChangeGC(pGC, GCForeground, &fg, 0); + ValidateGC(pDraw, pGC); +}