#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xmd.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "regionstr.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include <X11/fonts/fontstruct.h>
#include "dixfontstr.h"
#include "dixstruct.h"
#include "mi.h"
#include "mibstorest.h"
#define SETUP_BACKING_TERSE(pGC) \
miBSGCPtr pGCPrivate = (miBSGCPtr)(pGC)->devPrivates[miBSGCIndex].ptr; \
GCFuncs *oldFuncs = pGC->funcs;
#define SETUP_BACKING(pDrawable,pGC) \
miBSWindowPtr pBackingStore = \
(miBSWindowPtr)((WindowPtr)(pDrawable))->backStorage; \
DrawablePtr pBackingDrawable = (DrawablePtr) \
pBackingStore->pBackingPixmap; \
SETUP_BACKING_TERSE(pGC) \
GCPtr pBackingGC = pGCPrivate->pBackingGC;
#define PROLOGUE(pGC) { \
pGC->ops = pGCPrivate->wrapOps;\
pGC->funcs = pGCPrivate->wrapFuncs; \
}
#define EPILOGUE(pGC) { \
pGCPrivate->wrapOps = (pGC)->ops; \
(pGC)->ops = &miBSGCOps; \
(pGC)->funcs = oldFuncs; \
}
static void miCreateBSPixmap(WindowPtr pWin, BoxPtr pExtents);
static void miDestroyBSPixmap(WindowPtr pWin);
static void miTileVirtualBS(WindowPtr pWin);
static void miBSAllocate(WindowPtr pWin), miBSFree(WindowPtr pWin);
static Bool miBSCreateGCPrivate(GCPtr pGC);
static void miBSClearBackingRegion(WindowPtr pWin, RegionPtr pRgn);
#define MoreCopy0 ;
#define MoreCopy2 *dstCopy++ = *srcCopy++; *dstCopy++ = *srcCopy++;
#define MoreCopy4 MoreCopy2 MoreCopy2
#define copyData(src,dst,n,morecopy) \
{ \
register short *srcCopy = (short *)(src); \
register short *dstCopy = (short *)(dst); \
register int i; \
register int bsx = pBackingStore->x; \
register int bsy = pBackingStore->y; \
for (i = n; --i >= 0; ) \
{ \
*dstCopy++ = *srcCopy++ - bsx; \
*dstCopy++ = *srcCopy++ - bsy; \
morecopy \
} \
}
#define copyPoints(src,dst,n,mode) \
if (mode == CoordModeOrigin) \
{ \
copyData(src,dst,n,MoreCopy0); \
} \
else \
{ \
memmove((char *)(dst), (char *)(src), (n) << 2); \
*((short *)(dst)) -= pBackingStore->x; \
*((short *)(dst) + 1) -= pBackingStore->y; \
}
static int miBSScreenIndex;
static unsigned long miBSGeneration = 0;
static Bool miBSCloseScreen(int i, ScreenPtr pScreen);
static void miBSGetImage(DrawablePtr pDrawable, int sx, int sy,
int w, int h, unsigned int format,
unsigned long planemask, char *pdstLine);
static void miBSGetSpans(DrawablePtr pDrawable, int wMax,
DDXPointPtr ppt, int *pwidth, int nspans,
char *pdstStart);
static Bool miBSChangeWindowAttributes(WindowPtr pWin,
unsigned long mask);
static Bool miBSCreateGC(GCPtr pGC);
static Bool miBSDestroyWindow(WindowPtr pWin);
static void miBSSaveDoomedAreas(WindowPtr pWin, RegionPtr pObscured,
int dx, int dy);
static RegionPtr miBSRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
static void miBSExposeCopy(WindowPtr pSrc, DrawablePtr pDst,
GCPtr pGC, RegionPtr prgnExposed,
int srcx, int srcy, int dstx, int dsty,
unsigned long plane);
static RegionPtr miBSTranslateBackingStore(WindowPtr pWin, int windx,
int windy, RegionPtr oldClip,
int oldx, int oldy);
static RegionPtr miBSClearBackingStore(WindowPtr pWin, int x, int y,
int w, int h, Bool generateExposures);
static void miBSDrawGuarantee(WindowPtr pWin, GCPtr pGC,
int guarantee);
static int miBSGCIndex;
static void miBSValidateGC(GCPtr pGC, unsigned long stateChanges,
DrawablePtr pDrawable);
static void miBSCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
static void miBSDestroyGC(GCPtr pGC);
static void miBSChangeGC(GCPtr pGC, unsigned long mask);
static void miBSChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
static void miBSDestroyClip(GCPtr pGC);
static void miBSCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
static GCFuncs miBSGCFuncs = {
miBSValidateGC,
miBSChangeGC,
miBSCopyGC,
miBSDestroyGC,
miBSChangeClip,
miBSDestroyClip,
miBSCopyClip,
};
static void miBSFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
DDXPointPtr pptInit, int *pwidthInit,
int fSorted);
static void miBSSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
DDXPointPtr ppt, int *pwidth, int nspans,
int fSorted);
static void miBSPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad,
int format, char *pBits);
static RegionPtr miBSCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
GCPtr pGC, int srcx, int srcy, int w, int h,
int dstx, int dsty);
static RegionPtr miBSCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
GCPtr pGC, int srcx, int srcy, int w, int h,
int dstx, int dsty, unsigned long plane);
static void miBSPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
int npt, xPoint *pptInit);
static void miBSPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
int npt, DDXPointPtr pptInit);
static void miBSPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
xSegment *pSegs);
static void miBSPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
int nrects, xRectangle *pRects);
static void miBSPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
xArc *parcs);
static void miBSFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
int shape, int mode, int count,
DDXPointPtr pPts);
static void miBSPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
int nrectFill, xRectangle *prectInit);
static void miBSPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
int narcs, xArc *parcs);
static int miBSPolyText8(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count, char *chars);
static int miBSPolyText16(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count,
unsigned short *chars);
static void miBSImageText8(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count, char *chars);
static void miBSImageText16(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, int count,
unsigned short *chars);
static void miBSImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase);
static void miBSPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
int x, int y, unsigned int nglyph,
CharInfoPtr *ppci, pointer pglyphBase);
static void miBSPushPixels(GCPtr pGC, PixmapPtr pBitMap,
DrawablePtr pDst, int w, int h,
int x, int y);
static GCOps miBSGCOps = {
miBSFillSpans, miBSSetSpans, miBSPutImage,
miBSCopyArea, miBSCopyPlane, miBSPolyPoint,
miBSPolylines, miBSPolySegment, miBSPolyRectangle,
miBSPolyArc, miBSFillPolygon, miBSPolyFillRect,
miBSPolyFillArc, miBSPolyText8, miBSPolyText16,
miBSImageText8, miBSImageText16, miBSImageGlyphBlt,
miBSPolyGlyphBlt, miBSPushPixels
};
#define FUNC_PROLOGUE(pGC, pPriv) \
((pGC)->funcs = pPriv->wrapFuncs),\
((pGC)->ops = pPriv->wrapOps)
#define FUNC_EPILOGUE(pGC, pPriv) \
((pGC)->funcs = &miBSGCFuncs),\
((pGC)->ops = &miBSGCOps)
static void miBSCheapValidateGC(GCPtr pGC, unsigned long stateChanges,
DrawablePtr pDrawable);
static void miBSCheapCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
static void miBSCheapDestroyGC(GCPtr pGC);
static void miBSCheapChangeGC(GCPtr pGC, unsigned long mask);
static void miBSCheapChangeClip(GCPtr pGC, int type, pointer pvalue,
int nrects);
static void miBSCheapDestroyClip(GCPtr pGC);
static void miBSCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
static GCFuncs miBSCheapGCFuncs = {
miBSCheapValidateGC,
miBSCheapChangeGC,
miBSCheapCopyGC,
miBSCheapDestroyGC,
miBSCheapChangeClip,
miBSCheapDestroyClip,
miBSCheapCopyClip,
};
#define CHEAP_FUNC_PROLOGUE(pGC) \
((pGC)->funcs = (GCFuncs *) (pGC)->devPrivates[miBSGCIndex].ptr)
#define CHEAP_FUNC_EPILOGUE(pGC) \
((pGC)->funcs = &miBSCheapGCFuncs)
_X_EXPORT void
miInitializeBackingStore (pScreen)
ScreenPtr pScreen;
{
miBSScreenPtr pScreenPriv;
if (miBSGeneration != serverGeneration)
{
miBSScreenIndex = AllocateScreenPrivateIndex ();
if (miBSScreenIndex < 0)
return;
miBSGCIndex = AllocateGCPrivateIndex ();
miBSGeneration = serverGeneration;
}
if (!AllocateGCPrivate(pScreen, miBSGCIndex, 0))
return;
pScreenPriv = (miBSScreenPtr) xalloc (sizeof (miBSScreenRec));
if (!pScreenPriv)
return;
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreenPriv->GetImage = pScreen->GetImage;
pScreenPriv->GetSpans = pScreen->GetSpans;
pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
pScreenPriv->CreateGC = pScreen->CreateGC;
pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
pScreen->CloseScreen = miBSCloseScreen;
pScreen->GetImage = miBSGetImage;
pScreen->GetSpans = miBSGetSpans;
pScreen->ChangeWindowAttributes = miBSChangeWindowAttributes;
pScreen->CreateGC = miBSCreateGC;
pScreen->DestroyWindow = miBSDestroyWindow;
pScreen->SaveDoomedAreas = miBSSaveDoomedAreas;
pScreen->RestoreAreas = miBSRestoreAreas;
pScreen->ExposeCopy = miBSExposeCopy;
pScreen->TranslateBackingStore = miBSTranslateBackingStore;
pScreen->ClearBackingStore = miBSClearBackingStore;
pScreen->DrawGuarantee = miBSDrawGuarantee;
pScreen->devPrivates[miBSScreenIndex].ptr = (pointer) pScreenPriv;
}
#define SCREEN_PROLOGUE(pScreen, field)\
((pScreen)->field = \
((miBSScreenPtr) \
(pScreen)->devPrivates[miBSScreenIndex].ptr)->field)
#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
((pScreen)->field = wrapper)
static Bool
miBSCloseScreen (i, pScreen)
int i;
ScreenPtr pScreen;
{
miBSScreenPtr pScreenPriv;
pScreenPriv = (miBSScreenPtr) pScreen->devPrivates[miBSScreenIndex].ptr;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->GetImage = pScreenPriv->GetImage;
pScreen->GetSpans = pScreenPriv->GetSpans;
pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes;
pScreen->CreateGC = pScreenPriv->CreateGC;
xfree ((pointer) pScreenPriv);
return (*pScreen->CloseScreen) (i, pScreen);
}
static void miBSFillVirtualBits(DrawablePtr pDrawable, GCPtr pGC,
RegionPtr pRgn, int x, int y, int state,
PixUnion pixunion, unsigned long planemask);
static void
miBSGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
DrawablePtr pDrawable;
int sx, sy, w, h;
unsigned int format;
unsigned long planemask;
char *pdstLine;
{
ScreenPtr pScreen = pDrawable->pScreen;
BoxRec bounds;
unsigned char depth;
SCREEN_PROLOGUE (pScreen, GetImage);
if (pDrawable->type != DRAWABLE_PIXMAP &&
((WindowPtr) pDrawable)->visibility != VisibilityUnobscured)
{
PixmapPtr pPixmap;
miBSWindowPtr pWindowPriv;
GCPtr pGC = NULL;
WindowPtr pWin, pSrcWin;
int xoff, yoff;
RegionRec Remaining;
RegionRec Border;
RegionRec Inside;
BoxPtr pBox;
int n;
pWin = (WindowPtr) pDrawable;
pPixmap = 0;
depth = pDrawable->depth;
bounds.x1 = sx + pDrawable->x;
bounds.y1 = sy + pDrawable->y;
bounds.x2 = bounds.x1 + w;
bounds.y2 = bounds.y1 + h;
REGION_INIT(pScreen, &Remaining, &bounds, 0);
for (;;)
{
bounds.x1 = sx + pDrawable->x - pWin->drawable.x;
bounds.y1 = sy + pDrawable->y - pWin->drawable.y;
bounds.x2 = bounds.x1 + w;
bounds.y2 = bounds.y1 + h;
if (pWin->viewable && pWin->backStorage &&
pWin->drawable.depth == depth &&
(RECT_IN_REGION(pScreen, &(pWindowPriv =
(miBSWindowPtr) pWin->backStorage)->SavedRegion,
&bounds) != rgnOUT ||
RECT_IN_REGION(pScreen, &Remaining,
REGION_EXTENTS(pScreen, &pWin->borderSize)) != rgnOUT))
{
if (!pPixmap)
{
XID subWindowMode = IncludeInferiors;
int x, y;
pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, depth);
if (!pPixmap)
goto punt;
pGC = GetScratchGC (depth, pScreen);
if (!pGC)
{
(*pScreen->DestroyPixmap) (pPixmap);
goto punt;
}
ChangeGC (pGC, GCSubwindowMode, &subWindowMode);
ValidateGC ((DrawablePtr)pPixmap, pGC);
REGION_NULL(pScreen, &Border);
REGION_NULL(pScreen, &Inside);
pSrcWin = (WindowPtr) pDrawable;
x = sx;
y = sy;
if (pSrcWin->parent)
{
x += pSrcWin->origin.x;
y += pSrcWin->origin.y;
pSrcWin = pSrcWin->parent;
}
(*pGC->ops->CopyArea) ((DrawablePtr)pSrcWin,
(DrawablePtr)pPixmap, pGC,
x, y, w, h,
0, 0);
REGION_SUBTRACT(pScreen, &Remaining, &Remaining,
&((WindowPtr) pDrawable)->borderClip);
}
REGION_INTERSECT(pScreen, &Inside, &Remaining, &pWin->winSize);
REGION_TRANSLATE(pScreen, &Inside,
-pWin->drawable.x,
-pWin->drawable.y);
REGION_INTERSECT(pScreen, &Inside, &Inside,
&pWindowPriv->SavedRegion);
xoff = pWin->drawable.x - pDrawable->x - sx;
yoff = pWin->drawable.y - pDrawable->y - sy;
if (REGION_NUM_RECTS(&Inside) > 0)
{
switch (pWindowPriv->status)
{
case StatusContents:
pBox = REGION_RECTS(&Inside);
for (n = REGION_NUM_RECTS(&Inside); --n >= 0;)
{
(*pGC->ops->CopyArea) (
(DrawablePtr)pWindowPriv->pBackingPixmap,
(DrawablePtr)pPixmap, pGC,
pBox->x1 - pWindowPriv->x,
pBox->y1 - pWindowPriv->y,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1,
pBox->x1 + xoff,
pBox->y1 + yoff);
++pBox;
}
break;
case StatusVirtual:
case StatusVDirty:
if (pWindowPriv->backgroundState == BackgroundPixmap ||
pWindowPriv->backgroundState == BackgroundPixel)
miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Inside,
xoff, yoff,
(int) pWindowPriv->backgroundState,
pWindowPriv->background, ~0L);
break;
}
}
REGION_SUBTRACT(pScreen, &Border, &pWin->borderSize,
&pWin->winSize);
REGION_INTERSECT(pScreen, &Border, &Border, &Remaining);
if (REGION_NUM_RECTS(&Border) > 0)
{
REGION_TRANSLATE(pScreen, &Border, -pWin->drawable.x,
-pWin->drawable.y);
miBSFillVirtualBits ((DrawablePtr) pPixmap, pGC, &Border,
xoff, yoff,
pWin->borderIsPixel ? (int)BackgroundPixel : (int)BackgroundPixmap,
pWin->border, ~0L);
}
}
if (pWin->viewable && pWin->firstChild)
pWin = pWin->firstChild;
else
{
while (!pWin->nextSib && pWin != (WindowPtr) pDrawable)
pWin = pWin->parent;
if (pWin == (WindowPtr) pDrawable)
break;
pWin = pWin->nextSib;
}
}
REGION_UNINIT(pScreen, &Remaining);
if (pPixmap)
{
REGION_UNINIT(pScreen, &Border);
REGION_UNINIT(pScreen, &Inside);
(*pScreen->GetImage) ((DrawablePtr) pPixmap,
0, 0, w, h, format, planemask, pdstLine);
(*pScreen->DestroyPixmap) (pPixmap);
FreeScratchGC (pGC);
}
else
{
goto punt;
}
}
else
{
punt: ;
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
format, planemask, pdstLine);
}
SCREEN_EPILOGUE (pScreen, GetImage, miBSGetImage);
}
static void
miBSGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
DrawablePtr pDrawable;
int wMax;
DDXPointPtr ppt;
int *pwidth;
int nspans;
char *pdstStart;
{
ScreenPtr pScreen = pDrawable->pScreen;
BoxRec bounds;
int i;
WindowPtr pWin;
int dx, dy;
SCREEN_PROLOGUE (pScreen, GetSpans);
if (pDrawable->type != DRAWABLE_PIXMAP && ((WindowPtr) pDrawable)->backStorage)
{
PixmapPtr pPixmap;
miBSWindowPtr pWindowPriv;
GCPtr pGC;
pWin = (WindowPtr) pDrawable;
pWindowPriv = (miBSWindowPtr) pWin->backStorage;
pPixmap = pWindowPriv->pBackingPixmap;
bounds.x1 = ppt->x;
bounds.y1 = ppt->y;
bounds.x2 = bounds.x1 + *pwidth;
bounds.y2 = ppt->y;
for (i = 0; i < nspans; i++)
{
if (ppt[i].x < bounds.x1)
bounds.x1 = ppt[i].x;
if (ppt[i].x + pwidth[i] > bounds.x2)
bounds.x2 = ppt[i].x + pwidth[i];
if (ppt[i].y < bounds.y1)
bounds.y1 = ppt[i].y;
else if (ppt[i].y > bounds.y2)
bounds.y2 = ppt[i].y;
}
switch (RECT_IN_REGION(pScreen, &pWindowPriv->SavedRegion, &bounds))
{
case rgnPART:
if (!pPixmap)
{
miCreateBSPixmap (pWin, NullBox);
if (!(pPixmap = pWindowPriv->pBackingPixmap))
break;
}
pWindowPriv->status = StatusNoPixmap;
pGC = GetScratchGC(pPixmap->drawable.depth,
pPixmap->drawable.pScreen);
if (pGC)
{
ValidateGC ((DrawablePtr) pPixmap, pGC);
(*pGC->ops->CopyArea)
(pDrawable, (DrawablePtr) pPixmap, pGC,
bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1,
bounds.x1 + pPixmap->drawable.x - pWin->drawable.x -
pWindowPriv->x,
bounds.y1 + pPixmap->drawable.y - pWin->drawable.y -
pWindowPriv->y);
FreeScratchGC(pGC);
}
pWindowPriv->status = StatusContents;
case rgnIN:
if (!pPixmap)
{
miCreateBSPixmap (pWin, NullBox);
if (!(pPixmap = pWindowPriv->pBackingPixmap))
break;
}
dx = pPixmap->drawable.x - pWin->drawable.x - pWindowPriv->x;
dy = pPixmap->drawable.y - pWin->drawable.y - pWindowPriv->y;
for (i = 0; i < nspans; i++)
{
ppt[i].x += dx;
ppt[i].y += dy;
}
(*pScreen->GetSpans) ((DrawablePtr) pPixmap, wMax, ppt, pwidth,
nspans, pdstStart);
break;
case rgnOUT:
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans,
pdstStart);
break;
}
}
else
{
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
}
SCREEN_EPILOGUE (pScreen, GetSpans, miBSGetSpans);
}
static Bool
miBSChangeWindowAttributes (pWin, mask)
WindowPtr pWin;
unsigned long mask;
{
ScreenPtr pScreen;
Bool ret;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes);
ret = (*pScreen->ChangeWindowAttributes) (pWin, mask);
if (ret && (mask & CWBackingStore))
{
if (pWin->backingStore != NotUseful || pWin->DIXsaveUnder)
miBSAllocate (pWin);
else
miBSFree (pWin);
}
SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, miBSChangeWindowAttributes);
return ret;
}
static Bool
miBSCreateGC (pGC)
GCPtr pGC;
{
ScreenPtr pScreen = pGC->pScreen;
Bool ret;
SCREEN_PROLOGUE (pScreen, CreateGC);
if ( (ret = (*pScreen->CreateGC) (pGC)) )
{
pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
pGC->funcs = &miBSCheapGCFuncs;
}
SCREEN_EPILOGUE (pScreen, CreateGC, miBSCreateGC);
return ret;
}
static Bool
miBSDestroyWindow (pWin)
WindowPtr pWin;
{
ScreenPtr pScreen = pWin->drawable.pScreen;
Bool ret;
SCREEN_PROLOGUE (pScreen, DestroyWindow);
ret = (*pScreen->DestroyWindow) (pWin);
miBSFree (pWin);
SCREEN_EPILOGUE (pScreen, DestroyWindow, miBSDestroyWindow);
return ret;
}
static void
miBSCheapValidateGC (pGC, stateChanges, pDrawable)
GCPtr pGC;
unsigned long stateChanges;
DrawablePtr pDrawable;
{
CHEAP_FUNC_PROLOGUE (pGC);
if (pDrawable->type != DRAWABLE_PIXMAP &&
((WindowPtr) pDrawable)->backStorage != NULL &&
miBSCreateGCPrivate (pGC))
{
(*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
}
else
{
(*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
pGC->devPrivates[miBSGCIndex].ptr = (pointer) pGC->funcs;
CHEAP_FUNC_EPILOGUE (pGC);
}
}
static void
miBSCheapChangeGC (pGC, mask)
GCPtr pGC;
unsigned long mask;
{
CHEAP_FUNC_PROLOGUE (pGC);
(*pGC->funcs->ChangeGC) (pGC, mask);
CHEAP_FUNC_EPILOGUE (pGC);
}
static void
miBSCheapCopyGC (pGCSrc, mask, pGCDst)
GCPtr pGCSrc, pGCDst;
unsigned long mask;
{
CHEAP_FUNC_PROLOGUE (pGCDst);
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
CHEAP_FUNC_EPILOGUE (pGCDst);
}
static void
miBSCheapDestroyGC (pGC)
GCPtr pGC;
{
CHEAP_FUNC_PROLOGUE (pGC);
(*pGC->funcs->DestroyGC) (pGC);
}
static void
miBSCheapChangeClip (pGC, type, pvalue, nrects)
GCPtr pGC;
int type;
pointer pvalue;
int nrects;
{
CHEAP_FUNC_PROLOGUE (pGC);
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
CHEAP_FUNC_EPILOGUE (pGC);
}
static void
miBSCheapCopyClip(pgcDst, pgcSrc)
GCPtr pgcDst, pgcSrc;
{
CHEAP_FUNC_PROLOGUE (pgcDst);
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
CHEAP_FUNC_EPILOGUE (pgcDst);
}
static void
miBSCheapDestroyClip(pGC)
GCPtr pGC;
{
CHEAP_FUNC_PROLOGUE (pGC);
(* pGC->funcs->DestroyClip)(pGC);
CHEAP_FUNC_EPILOGUE (pGC);
}
static Bool
miBSCreateGCPrivate (pGC)
GCPtr pGC;
{
miBSGCRec *pPriv;
pPriv = (miBSGCRec *) xalloc (sizeof (miBSGCRec));
if (!pPriv)
return FALSE;
pPriv->pBackingGC = NULL;
pPriv->guarantee = GuaranteeNothing;
pPriv->serialNumber = 0;
pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1;
pPriv->wrapOps = pGC->ops;
pPriv->wrapFuncs = pGC->funcs;
pGC->funcs = &miBSGCFuncs;
pGC->ops = &miBSGCOps;
pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv;
return TRUE;
}
static void
miBSDestroyGCPrivate (GCPtr pGC)
{
miBSGCRec *pPriv;
pPriv = (miBSGCRec *) pGC->devPrivates[miBSGCIndex].ptr;
if (pPriv)
{
pGC->devPrivates[miBSGCIndex].ptr = (pointer) pPriv->wrapFuncs;
pGC->funcs = &miBSCheapGCFuncs;
pGC->ops = pPriv->wrapOps;
if (pPriv->pBackingGC)
FreeGC (pPriv->pBackingGC, (GContext) 0);
xfree ((pointer) pPriv);
}
}
static void
miBSFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
DrawablePtr pDrawable;
GCPtr pGC;
int nInit;
DDXPointPtr pptInit;
int *pwidthInit;
int fSorted;
{
DDXPointPtr pptCopy, pptReset;
int *pwidthCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nInit*sizeof(DDXPointRec));
pwidthCopy=(int *)ALLOCATE_LOCAL(nInit*sizeof(int));
if (pptCopy && pwidthCopy)
{
copyData(pptInit, pptCopy, nInit, MoreCopy0);
memmove((char *)pwidthCopy,(char *)pwidthInit,nInit*sizeof(int));
(* pGC->ops->FillSpans)(pDrawable, pGC, nInit, pptInit,
pwidthInit, fSorted);
if (pGC->miTranslate)
{
int dx, dy;
int nReset;
pptReset = pptCopy;
dx = pDrawable->x - pBackingDrawable->x;
dy = pDrawable->y - pBackingDrawable->y;
nReset = nInit;
while (nReset--)
{
pptReset->x -= dx;
pptReset->y -= dy;
++pptReset;
}
}
(* pBackingGC->ops->FillSpans)(pBackingDrawable,
pBackingGC, nInit, pptCopy, pwidthCopy,
fSorted);
}
if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
EPILOGUE (pGC);
}
static void
miBSSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
DrawablePtr pDrawable;
GCPtr pGC;
char *psrc;
register DDXPointPtr ppt;
int *pwidth;
int nspans;
int fSorted;
{
DDXPointPtr pptCopy, pptReset;
int *pwidthCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec));
pwidthCopy=(int *)ALLOCATE_LOCAL(nspans*sizeof(int));
if (pptCopy && pwidthCopy)
{
copyData(ppt, pptCopy, nspans, MoreCopy0);
memmove((char *)pwidthCopy,(char *)pwidth,nspans*sizeof(int));
(* pGC->ops->SetSpans)(pDrawable, pGC, psrc, ppt, pwidth,
nspans, fSorted);
if (pGC->miTranslate)
{
int dx, dy;
int nReset;
pptReset = pptCopy;
dx = pDrawable->x - pBackingDrawable->x;
dy = pDrawable->y - pBackingDrawable->y;
nReset = nspans;
while (nReset--)
{
pptReset->x -= dx;
pptReset->y -= dy;
++pptReset;
}
}
(* pBackingGC->ops->SetSpans)(pBackingDrawable, pBackingGC,
psrc, pptCopy, pwidthCopy, nspans, fSorted);
}
if (pwidthCopy) DEALLOCATE_LOCAL(pwidthCopy);
if (pptCopy) DEALLOCATE_LOCAL(pptCopy);
EPILOGUE (pGC);
}
static void
miBSPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
DrawablePtr pDrawable;
GCPtr pGC;
int depth;
int x;
int y;
int w;
int h;
int leftPad;
int format;
char *pBits;
{
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
(*pGC->ops->PutImage)(pDrawable, pGC,
depth, x, y, w, h, leftPad, format, pBits);
(*pBackingGC->ops->PutImage)(pBackingDrawable, pBackingGC,
depth, x - pBackingStore->x, y - pBackingStore->y,
w, h, leftPad, format, pBits);
EPILOGUE (pGC);
}
typedef RegionPtr (* CopyAreaProcPtr)(DrawablePtr, DrawablePtr, GCPtr,
int, int, int, int, int, int);
typedef RegionPtr (* CopyPlaneProcPtr)(DrawablePtr, DrawablePtr, GCPtr,
int, int, int, int, int, int,
unsigned long bitPlane);
static Bool
miBSDoCopy(
WindowPtr pWin,
GCPtr pGC,
int srcx,
int srcy,
int w,
int h,
int dstx,
int dsty,
unsigned long plane,
CopyPlaneProcPtr copyProc,
RegionPtr *ppRgn)
{
RegionPtr pRgnExp;
RegionPtr pRgnObs;
BoxRec box;
struct BoxDraw {
BoxPtr pBox;
enum {
win, pix
} source;
} *boxes;
int *sequence;
register int i, j, k, l, y;
register BoxPtr pBox;
int dx, dy, nrects;
Bool graphicsExposures;
CopyPlaneProcPtr pixCopyProc;
int numRectsExp, numRectsObs;
BoxPtr pBoxExp, pBoxObs;
SETUP_BACKING (pWin, pGC);
(void)oldFuncs;
box.x1 = srcx + pWin->drawable.x;
box.x2 = box.x1 + w;
box.y1 = srcy + pWin->drawable.y;
box.y2 = box.y1 + h;
pRgnExp = REGION_CREATE(pGC->pScreen, &box, 1);
REGION_INTERSECT(pGC->pScreen, pRgnExp, pRgnExp, &pWin->clipList);
pRgnObs = REGION_CREATE(pGC->pScreen, NULL, 1);
REGION_INVERSE( pGC->pScreen, pRgnObs, pRgnExp, &box);
REGION_TRANSLATE(pGC->pScreen, pRgnExp,
-pWin->drawable.x,
-pWin->drawable.y);
REGION_TRANSLATE(pGC->pScreen, pRgnObs,
-pWin->drawable.x,
-pWin->drawable.y);
REGION_INTERSECT(pGC->pScreen, pRgnObs, pRgnObs, &pBackingStore->SavedRegion);
if (!REGION_NOTEMPTY(pGC->pScreen, pRgnObs))
{
REGION_DESTROY(pGC->pScreen, pRgnExp);
REGION_DESTROY(pGC->pScreen, pRgnObs);
return (FALSE);
}
numRectsExp = REGION_NUM_RECTS(pRgnExp);
pBoxExp = REGION_RECTS(pRgnExp);
pBoxObs = REGION_RECTS(pRgnObs);
numRectsObs = REGION_NUM_RECTS(pRgnObs);
nrects = numRectsExp + numRectsObs;
boxes = (struct BoxDraw *)ALLOCATE_LOCAL(nrects * sizeof(struct BoxDraw));
sequence = (int *) ALLOCATE_LOCAL(nrects * sizeof(int));
*ppRgn = NULL;
if (!boxes || !sequence)
{
if (sequence) DEALLOCATE_LOCAL(sequence);
if (boxes) DEALLOCATE_LOCAL(boxes);
REGION_DESTROY(pGC->pScreen, pRgnExp);
REGION_DESTROY(pGC->pScreen, pRgnObs);
return(TRUE);
}
for (i = 0, j = 0, k = 0;
(i < numRectsExp) && (j < numRectsObs);
k++)
{
if (pBoxExp[i].y1 < pBoxObs[j].y1)
{
boxes[k].pBox = &pBoxExp[i];
boxes[k].source = win;
i++;
}
else if ((pBoxObs[j].y1 < pBoxExp[i].y1) ||
(pBoxObs[j].x1 < pBoxExp[i].x1))
{
boxes[k].pBox = &pBoxObs[j];
boxes[k].source = pix;
j++;
}
else
{
boxes[k].pBox = &pBoxExp[i];
boxes[k].source = win;
i++;
}
}
if (i != numRectsExp)
{
do
{
boxes[k].pBox = &pBoxExp[i];
boxes[k].source = win;
i++;
k++;
} while (i < numRectsExp);
}
else
{
do
{
boxes[k].pBox = &pBoxObs[j];
boxes[k].source = pix;
j++;
k++;
} while (j < numRectsObs);
}
if (dsty <= srcy)
{
if (dstx <= srcx)
{
for (i = 0; i < nrects; i++)
{
sequence[i] = i;
}
}
else
{
for (i = 0, j = 1, k = 0;
i < nrects;
j = i + 1, k = i)
{
y = boxes[i].pBox->y1;
while ((j < nrects) && (boxes[j].pBox->y1 == y))
{
j++;
}
for (j--; j >= k; j--, i++)
{
sequence[i] = j;
}
}
}
}
else
{
if (dstx < srcx)
{
for (i = nrects - 1, j = i - 1, k = i, l = 0;
i >= 0;
j = i - 1, k = i)
{
y = boxes[i].pBox->y1;
while ((j >= 0) && (boxes[j].pBox->y1 == y))
{
j--;
}
for (j++; j <= k; j++, i--, l++)
{
sequence[l] = j;
}
}
}
else
{
for (i = 0, j = nrects - 1; i < nrects; i++, j--)
{
sequence[i] = j;
}
}
}
graphicsExposures = pGC->graphicsExposures;
pGC->graphicsExposures = FALSE;
dx = dstx - srcx;
dy = dsty - srcy;
if (plane != 0)
{
pixCopyProc = pBackingGC->ops->CopyPlane;
}
else
{
pixCopyProc = (CopyPlaneProcPtr)pBackingGC->ops->CopyArea;
}
for (i = 0; i < nrects; i++)
{
pBox = boxes[sequence[i]].pBox;
if (boxes[sequence[i]].source == pix)
{
(void) (* copyProc) (pBackingDrawable, &(pWin->drawable), pGC,
pBox->x1 - pBackingStore->x,
pBox->y1 - pBackingStore->y,
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
pBox->x1 + dx, pBox->y1 + dy, plane);
(void) (* pixCopyProc) (pBackingDrawable, pBackingDrawable, pBackingGC,
pBox->x1 - pBackingStore->x,
pBox->y1 - pBackingStore->y,
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
pBox->x1 + dx - pBackingStore->x,
pBox->y1 + dy - pBackingStore->y, plane);
}
else
{
(void) (* pixCopyProc) (&(pWin->drawable), pBackingDrawable, pBackingGC,
pBox->x1, pBox->y1,
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
pBox->x1 + dx - pBackingStore->x,
pBox->y1 + dy - pBackingStore->y, plane);
(void) (* copyProc) (&(pWin->drawable), &(pWin->drawable), pGC,
pBox->x1, pBox->y1,
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
pBox->x1 + dx, pBox->y1 + dy, plane);
}
}
DEALLOCATE_LOCAL(sequence);
DEALLOCATE_LOCAL(boxes);
pGC->graphicsExposures = graphicsExposures;
REGION_UNION(pGC->pScreen, pRgnExp, pRgnExp, pRgnObs);
box.x1 = srcx;
box.x2 = srcx + w;
box.y1 = srcy;
box.y2 = srcy + h;
if (RECT_IN_REGION(pGC->pScreen, pRgnExp, &box) == rgnIN)
{
REGION_EMPTY(pGC->pScreen, pRgnExp);
}
else
{
REGION_INVERSE( pGC->pScreen, pRgnExp, pRgnExp, &box);
REGION_TRANSLATE( pGC->pScreen, pRgnExp,
dx + pWin->drawable.x,
dy + pWin->drawable.y);
REGION_INTERSECT( pGC->pScreen, pRgnObs, pRgnExp, &pWin->clipList);
(*pWin->drawable.pScreen->PaintWindowBackground) (pWin,
pRgnObs, PW_BACKGROUND);
REGION_TRANSLATE( pGC->pScreen, pRgnExp,
-pWin->drawable.x,
-pWin->drawable.y);
miBSClearBackingRegion (pWin, pRgnExp);
}
if (graphicsExposures)
*ppRgn = pRgnExp;
else
REGION_DESTROY(pGC->pScreen, pRgnExp);
REGION_DESTROY(pGC->pScreen, pRgnObs);
return (TRUE);
}
static RegionPtr
miBSCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
DrawablePtr pSrc;
DrawablePtr pDst;
GCPtr pGC;
int srcx;
int srcy;
int w;
int h;
int dstx;
int dsty;
{
BoxPtr pExtents;
long dx, dy;
int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
RegionPtr pixExposed = 0, winExposed = 0;
SETUP_BACKING(pDst, pGC);
PROLOGUE(pGC);
if ((pSrc != pDst) ||
(!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
(unsigned long) 0, (CopyPlaneProcPtr)pGC->ops->CopyArea,
&winExposed)))
{
if (pGC->clientClipType != CT_PIXMAP)
{
pExtents = REGION_EXTENTS(pDst->pScreen,
(RegionPtr)pBackingGC->clientClip);
bsrcx = srcx;
bsrcy = srcy;
bw = w;
bh = h;
bdstx = dstx;
bdsty = dsty;
dx = pExtents->x1 - bdstx;
if (dx > 0)
{
bsrcx += dx;
bdstx += dx;
bw -= dx;
}
dy = pExtents->y1 - bdsty;
if (dy > 0)
{
bsrcy += dy;
bdsty += dy;
bh -= dy;
}
dx = (bdstx + bw) - pExtents->x2;
if (dx > 0)
bw -= dx;
dy = (bdsty + bh) - pExtents->y2;
if (dy > 0)
bh -= dy;
if (bw > 0 && bh > 0)
pixExposed = (* pBackingGC->ops->CopyArea) (pSrc,
pBackingDrawable, pBackingGC,
bsrcx, bsrcy, bw, bh, bdstx - pBackingStore->x,
bdsty - pBackingStore->y);
}
else
pixExposed = (* pBackingGC->ops->CopyArea) (pSrc,
pBackingDrawable, pBackingGC,
srcx, srcy, w, h,
dstx - pBackingStore->x, dsty - pBackingStore->y);
winExposed = (* pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
}
if (winExposed)
{
if (pixExposed){
REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
REGION_DESTROY(pDst->pScreen, pixExposed);
}
} else
winExposed = pixExposed;
EPILOGUE (pGC);
return winExposed;
}
static RegionPtr
miBSCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
DrawablePtr pSrc;
DrawablePtr pDst;
register GC *pGC;
int srcx,
srcy;
int w,
h;
int dstx,
dsty;
unsigned long plane;
{
BoxPtr pExtents;
long dx, dy;
int bsrcx, bsrcy, bw, bh, bdstx, bdsty;
RegionPtr winExposed = 0, pixExposed = 0;
SETUP_BACKING(pDst, pGC);
PROLOGUE(pGC);
if ((pSrc != pDst) ||
(!miBSDoCopy((WindowPtr)pSrc, pGC, srcx, srcy, w, h, dstx, dsty,
plane, pGC->ops->CopyPlane, &winExposed)))
{
if (pGC->clientClipType != CT_PIXMAP)
{
pExtents = REGION_EXTENTS(pDst->pScreen,
(RegionPtr)pBackingGC->clientClip);
bsrcx = srcx;
bsrcy = srcy;
bw = w;
bh = h;
bdstx = dstx;
bdsty = dsty;
dx = pExtents->x1 - bdstx;
if (dx > 0)
{
bsrcx += dx;
bdstx += dx;
bw -= dx;
}
dy = pExtents->y1 - bdsty;
if (dy > 0)
{
bsrcy += dy;
bdsty += dy;
bh -= dy;
}
dx = (bdstx + bw) - pExtents->x2;
if (dx > 0)
bw -= dx;
dy = (bdsty + bh) - pExtents->y2;
if (dy > 0)
bh -= dy;
if (bw > 0 && bh > 0)
pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
pBackingDrawable,
pBackingGC, bsrcx, bsrcy, bw, bh,
bdstx - pBackingStore->x,
bdsty - pBackingStore->y, plane);
}
else
pixExposed = (* pBackingGC->ops->CopyPlane) (pSrc,
pBackingDrawable,
pBackingGC, srcx, srcy, w, h,
dstx - pBackingStore->x,
dsty - pBackingStore->y, plane);
winExposed = (* pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
dstx, dsty, plane);
}
if (winExposed)
{
if (pixExposed)
{
REGION_UNION(pDst->pScreen, winExposed, winExposed, pixExposed);
REGION_DESTROY(pDst->pScreen, pixExposed);
}
} else
winExposed = pixExposed;
EPILOGUE (pGC);
return winExposed;
}
static void
miBSPolyPoint (pDrawable, pGC, mode, npt, pptInit)
DrawablePtr pDrawable;
GCPtr pGC;
int mode;
int npt;
xPoint *pptInit;
{
xPoint *pptCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pptCopy = (xPoint *)ALLOCATE_LOCAL(npt*sizeof(xPoint));
if (pptCopy)
{
copyPoints(pptInit, pptCopy, npt, mode);
(* pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
(* pBackingGC->ops->PolyPoint) (pBackingDrawable,
pBackingGC, mode, npt, pptCopy);
DEALLOCATE_LOCAL(pptCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolylines (pDrawable, pGC, mode, npt, pptInit)
DrawablePtr pDrawable;
GCPtr pGC;
int mode;
int npt;
DDXPointPtr pptInit;
{
DDXPointPtr pptCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pptCopy = (DDXPointPtr)ALLOCATE_LOCAL(npt*sizeof(DDXPointRec));
if (pptCopy)
{
copyPoints(pptInit, pptCopy, npt, mode);
(* pGC->ops->Polylines)(pDrawable, pGC, mode, npt, pptInit);
(* pBackingGC->ops->Polylines)(pBackingDrawable,
pBackingGC, mode, npt, pptCopy);
DEALLOCATE_LOCAL(pptCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolySegment(pDrawable, pGC, nseg, pSegs)
DrawablePtr pDrawable;
GCPtr pGC;
int nseg;
xSegment *pSegs;
{
xSegment *pSegsCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pSegsCopy = (xSegment *)ALLOCATE_LOCAL(nseg*sizeof(xSegment));
if (pSegsCopy)
{
copyData(pSegs, pSegsCopy, nseg << 1, MoreCopy0);
(* pGC->ops->PolySegment)(pDrawable, pGC, nseg, pSegs);
(* pBackingGC->ops->PolySegment)(pBackingDrawable,
pBackingGC, nseg, pSegsCopy);
DEALLOCATE_LOCAL(pSegsCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolyRectangle(pDrawable, pGC, nrects, pRects)
DrawablePtr pDrawable;
GCPtr pGC;
int nrects;
xRectangle *pRects;
{
xRectangle *pRectsCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pRectsCopy =(xRectangle *)ALLOCATE_LOCAL(nrects*sizeof(xRectangle));
if (pRectsCopy)
{
copyData(pRects, pRectsCopy, nrects, MoreCopy2);
(* pGC->ops->PolyRectangle)(pDrawable, pGC, nrects, pRects);
(* pBackingGC->ops->PolyRectangle)(pBackingDrawable,
pBackingGC, nrects, pRectsCopy);
DEALLOCATE_LOCAL(pRectsCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolyArc(pDrawable, pGC, narcs, parcs)
DrawablePtr pDrawable;
GCPtr pGC;
int narcs;
xArc *parcs;
{
xArc *pArcsCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
if (pArcsCopy)
{
copyData(parcs, pArcsCopy, narcs, MoreCopy4);
(* pGC->ops->PolyArc)(pDrawable, pGC, narcs, parcs);
(* pBackingGC->ops->PolyArc)(pBackingDrawable, pBackingGC,
narcs, pArcsCopy);
DEALLOCATE_LOCAL(pArcsCopy);
}
EPILOGUE (pGC);
}
static void
miBSFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
DrawablePtr pDrawable;
register GCPtr pGC;
int shape, mode;
register int count;
DDXPointPtr pPts;
{
DDXPointPtr pPtsCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pPtsCopy = (DDXPointPtr)ALLOCATE_LOCAL(count*sizeof(DDXPointRec));
if (pPtsCopy)
{
copyPoints(pPts, pPtsCopy, count, mode);
(* pGC->ops->FillPolygon)(pDrawable, pGC, shape, mode, count, pPts);
(* pBackingGC->ops->FillPolygon)(pBackingDrawable,
pBackingGC, shape, mode,
count, pPtsCopy);
DEALLOCATE_LOCAL(pPtsCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
DrawablePtr pDrawable;
GCPtr pGC;
int nrectFill;
xRectangle *prectInit;
{
xRectangle *pRectCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pRectCopy =
(xRectangle *)ALLOCATE_LOCAL(nrectFill*sizeof(xRectangle));
if (pRectCopy)
{
copyData(prectInit, pRectCopy, nrectFill, MoreCopy2);
(* pGC->ops->PolyFillRect)(pDrawable, pGC, nrectFill, prectInit);
(* pBackingGC->ops->PolyFillRect)(pBackingDrawable,
pBackingGC, nrectFill, pRectCopy);
DEALLOCATE_LOCAL(pRectCopy);
}
EPILOGUE (pGC);
}
static void
miBSPolyFillArc(pDrawable, pGC, narcs, parcs)
DrawablePtr pDrawable;
GCPtr pGC;
int narcs;
xArc *parcs;
{
xArc *pArcsCopy;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
pArcsCopy = (xArc *)ALLOCATE_LOCAL(narcs*sizeof(xArc));
if (pArcsCopy)
{
copyData(parcs, pArcsCopy, narcs, MoreCopy4);
(* pGC->ops->PolyFillArc)(pDrawable, pGC, narcs, parcs);
(* pBackingGC->ops->PolyFillArc)(pBackingDrawable,
pBackingGC, narcs, pArcsCopy);
DEALLOCATE_LOCAL(pArcsCopy);
}
EPILOGUE (pGC);
}
static int
miBSPolyText8(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
int result;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
result = (* pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
(* pBackingGC->ops->PolyText8)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
count, chars);
EPILOGUE (pGC);
return result;
}
static int
miBSPolyText16(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
int result;
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
result = (* pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
(* pBackingGC->ops->PolyText16)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
count, chars);
EPILOGUE (pGC);
return result;
}
static void
miBSImageText8(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
(* pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
(* pBackingGC->ops->ImageText8)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
count, chars);
EPILOGUE (pGC);
}
static void
miBSImageText16(pDrawable, pGC, x, y, count, chars)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
(* pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
(* pBackingGC->ops->ImageText16)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
count, chars);
EPILOGUE (pGC);
}
static void
miBSImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
pointer pglyphBase;
{
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
(* pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
pglyphBase);
(* pBackingGC->ops->ImageGlyphBlt)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
nglyph, ppci, pglyphBase);
EPILOGUE (pGC);
}
static void
miBSPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GCPtr pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci;
pointer pglyphBase;
{
SETUP_BACKING (pDrawable, pGC);
PROLOGUE(pGC);
(* pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph,
ppci, pglyphBase);
(* pBackingGC->ops->PolyGlyphBlt)(pBackingDrawable, pBackingGC,
x - pBackingStore->x, y - pBackingStore->y,
nglyph, ppci, pglyphBase);
EPILOGUE (pGC);
}
static void
miBSPushPixels(pGC, pBitMap, pDst, w, h, x, y)
GCPtr pGC;
PixmapPtr pBitMap;
DrawablePtr pDst;
int w, h, x, y;
{
SETUP_BACKING (pDst, pGC);
PROLOGUE(pGC);
(* pGC->ops->PushPixels)(pGC, pBitMap, pDst, w, h, x, y);
if (pGC->miTranslate) {
x -= pDst->x;
y -= pDst->y;
}
(* pBackingGC->ops->PushPixels)(pBackingGC, pBitMap,
pBackingDrawable, w, h,
x - pBackingStore->x, y - pBackingStore->y);
EPILOGUE (pGC);
}
static RegionPtr
miBSClearBackingStore(pWin, x, y, w, h, generateExposures)
WindowPtr pWin;
int x;
int y;
int w;
int h;
Bool generateExposures;
{
RegionPtr pRgn;
int i;
miBSWindowPtr pBackingStore;
ScreenPtr pScreen;
GCPtr pGC;
int ts_x_origin,
ts_y_origin;
pointer gcvalues[4];
unsigned long gcmask;
xRectangle *rects;
BoxPtr pBox;
BoxRec box;
PixUnion background;
char backgroundState;
int numRects;
pBackingStore = (miBSWindowPtr)pWin->backStorage;
pScreen = pWin->drawable.pScreen;
if ((pBackingStore->status == StatusNoPixmap) ||
(pBackingStore->status == StatusBadAlloc))
return NullRegion;
if (w == 0)
w = (int) pWin->drawable.width - x;
if (h == 0)
h = (int) pWin->drawable.height - y;
box.x1 = x;
box.y1 = y;
box.x2 = x + w;
box.y2 = y + h;
pRgn = REGION_CREATE(pWin->drawable.pScreen, &box, 1);
if (!pRgn)
return NullRegion;
REGION_INTERSECT( pScreen, pRgn, pRgn, &pBackingStore->SavedRegion);
if (REGION_NOTEMPTY( pScreen, pRgn))
{
if (x == 0 && y == 0 &&
w == pWin->drawable.width &&
h == pWin->drawable.height)
{
if (!pWin->parent)
miDestroyBSPixmap (pWin);
if (pBackingStore->status != StatusContents)
miTileVirtualBS (pWin);
}
ts_x_origin = ts_y_origin = 0;
backgroundState = pWin->backgroundState;
background = pWin->background;
if (backgroundState == ParentRelative) {
WindowPtr pParent;
pParent = pWin;
while (pParent->backgroundState == ParentRelative) {
ts_x_origin -= pParent->origin.x;
ts_y_origin -= pParent->origin.y;
pParent = pParent->parent;
}
backgroundState = pParent->backgroundState;
background = pParent->background;
}
if ((backgroundState != None) &&
((pBackingStore->status == StatusContents) ||
!SameBackground (pBackingStore->backgroundState,
pBackingStore->background,
backgroundState,
background)))
{
if (!pBackingStore->pBackingPixmap)
miCreateBSPixmap(pWin, NullBox);
pGC = GetScratchGC(pWin->drawable.depth, pScreen);
if (pGC && pBackingStore->pBackingPixmap)
{
if (backgroundState == BackgroundPixel)
{
gcvalues[0] = (pointer) background.pixel;
gcvalues[1] = (pointer)FillSolid;
gcmask = GCForeground|GCFillStyle;
}
else
{
gcvalues[0] = (pointer)FillTiled;
gcvalues[1] = (pointer) background.pixmap;
gcmask = GCFillStyle|GCTile;
}
gcvalues[2] = (pointer)(long)(ts_x_origin - pBackingStore->x);
gcvalues[3] = (pointer)(long)(ts_y_origin - pBackingStore->y);
gcmask |= GCTileStipXOrigin|GCTileStipYOrigin;
DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
ValidateGC((DrawablePtr)pBackingStore->pBackingPixmap, pGC);
numRects = REGION_NUM_RECTS(pRgn);
rects = (xRectangle *)ALLOCATE_LOCAL(numRects*sizeof(xRectangle));
if (rects)
{
for (i = 0, pBox = REGION_RECTS(pRgn);
i < numRects;
i++, pBox++)
{
rects[i].x = pBox->x1 - pBackingStore->x;
rects[i].y = pBox->y1 - pBackingStore->y;
rects[i].width = pBox->x2 - pBox->x1;
rects[i].height = pBox->y2 - pBox->y1;
}
(* pGC->ops->PolyFillRect) (
(DrawablePtr)pBackingStore->pBackingPixmap,
pGC, numRects, rects);
DEALLOCATE_LOCAL(rects);
}
FreeScratchGC(pGC);
}
}
if (!generateExposures)
{
REGION_DESTROY(pScreen, pRgn);
pRgn = NULL;
}
else
{
REGION_TRANSLATE(pScreen, pRgn, pWin->drawable.x,
pWin->drawable.y);
}
}
else
{
REGION_DESTROY( pScreen, pRgn);
pRgn = NULL;
}
return pRgn;
}
static void
miBSClearBackingRegion (pWin, pRgn)
WindowPtr pWin;
RegionPtr pRgn;
{
BoxPtr pBox;
int i;
i = REGION_NUM_RECTS(pRgn);
pBox = REGION_RECTS(pRgn);
while (i--)
{
(void) miBSClearBackingStore(pWin, pBox->x1, pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1,
FALSE);
pBox++;
}
}
static void
miBSFillVirtualBits (pDrawable, pGC, pRgn, x, y, state, pixunion, planeMask)
DrawablePtr pDrawable;
GCPtr pGC;
RegionPtr pRgn;
int x, y;
int state;
PixUnion pixunion;
unsigned long planeMask;
{
int i;
BITS32 gcmask;
pointer gcval[5];
xRectangle *pRect;
BoxPtr pBox;
WindowPtr pWin;
int numRects;
if (state == None)
return;
numRects = REGION_NUM_RECTS(pRgn);
pRect = (xRectangle *)ALLOCATE_LOCAL(numRects * sizeof(xRectangle));
if (!pRect)
return;
pWin = 0;
if (pDrawable->type != DRAWABLE_PIXMAP)
{
pWin = (WindowPtr) pDrawable;
if (!pWin->backStorage)
pWin = 0;
}
i = 0;
gcmask = 0;
gcval[i++] = (pointer)planeMask;
gcmask |= GCPlaneMask;
if (state == BackgroundPixel)
{
if (pGC->fgPixel != pixunion.pixel)
{
gcval[i++] = (pointer)pixunion.pixel;
gcmask |= GCForeground;
}
if (pGC->fillStyle != FillSolid)
{
gcval[i++] = (pointer)FillSolid;
gcmask |= GCFillStyle;
}
}
else
{
if (pGC->fillStyle != FillTiled)
{
gcval[i++] = (pointer)FillTiled;
gcmask |= GCFillStyle;
}
if (pGC->tileIsPixel || pGC->tile.pixmap != pixunion.pixmap)
{
gcval[i++] = (pointer)pixunion.pixmap;
gcmask |= GCTile;
}
if (pGC->patOrg.x != x)
{
gcval[i++] = (pointer)(long)x;
gcmask |= GCTileStipXOrigin;
}
if (pGC->patOrg.y != y)
{
gcval[i++] = (pointer)(long)y;
gcmask |= GCTileStipYOrigin;
}
}
if (gcmask)
DoChangeGC (pGC, gcmask, (XID *)gcval, 1);
if (pWin)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
if (pDrawable->serialNumber != pGC->serialNumber)
ValidateGC (pDrawable, pGC);
pBox = REGION_RECTS(pRgn);
for (i = numRects; --i >= 0; pBox++, pRect++)
{
pRect->x = pBox->x1 + x;
pRect->y = pBox->y1 + y;
pRect->width = pBox->x2 - pBox->x1;
pRect->height = pBox->y2 - pBox->y1;
}
pRect -= numRects;
(*pGC->ops->PolyFillRect) (pDrawable, pGC, numRects, pRect);
if (pWin)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
DEALLOCATE_LOCAL (pRect);
}
static void
miBSAllocate(pWin)
WindowPtr pWin;
{
register miBSWindowPtr pBackingStore;
register ScreenPtr pScreen;
if (pWin->drawable.pScreen->backingStoreSupport == NotUseful)
return;
pScreen = pWin->drawable.pScreen;
if (!(pBackingStore = (miBSWindowPtr)pWin->backStorage))
{
pBackingStore = (miBSWindowPtr)xalloc(sizeof(miBSWindowRec));
if (!pBackingStore)
return;
pBackingStore->pBackingPixmap = NullPixmap;
pBackingStore->x = 0;
pBackingStore->y = 0;
REGION_NULL( pScreen, &pBackingStore->SavedRegion);
pBackingStore->viewable = (char)pWin->viewable;
pBackingStore->status = StatusNoPixmap;
pBackingStore->backgroundState = None;
pWin->backStorage = (pointer) pBackingStore;
}
if (pBackingStore->status == StatusNoPixmap &&
((pWin->backingStore == WhenMapped && pWin->viewable) ||
(pWin->backingStore == Always)))
{
BoxRec box;
RegionPtr pSavedRegion;
pSavedRegion = &pBackingStore->SavedRegion;
box.x1 = pWin->drawable.x;
box.x2 = box.x1 + (int) pWin->drawable.width;
box.y1 = pWin->drawable.y;
box.y2 = pWin->drawable.y + (int) pWin->drawable.height;
REGION_INVERSE( pScreen, pSavedRegion, &pWin->clipList, &box);
REGION_TRANSLATE( pScreen, pSavedRegion,
-pWin->drawable.x,
-pWin->drawable.y);
#ifdef SHAPE
if (wBoundingShape (pWin))
REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
wBoundingShape (pWin));
if (wClipShape (pWin))
REGION_INTERSECT(pScreen, pSavedRegion, pSavedRegion,
wClipShape (pWin));
#endif
if (pWin->viewable)
pBackingStore->status = StatusVDirty;
miTileVirtualBS (pWin);
miSendExposures(pWin, pSavedRegion, 0, 0);
}
else if (!pWin->viewable)
{
if (pBackingStore->status != StatusNoPixmap)
{
REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
miDestroyBSPixmap (pWin);
}
}
}
static void
miBSFree(pWin)
WindowPtr pWin;
{
miBSWindowPtr pBackingStore;
register ScreenPtr pScreen;
pScreen = pWin->drawable.pScreen;
pBackingStore = (miBSWindowPtr)pWin->backStorage;
if (pBackingStore)
{
miDestroyBSPixmap (pWin);
REGION_UNINIT( pScreen, &pBackingStore->SavedRegion);
xfree(pBackingStore);
pWin->backStorage = NULL;
}
}
static void
miResizeBackingStore(
WindowPtr pWin,
int dx,
int dy,
Bool saveBits)
{
miBSWindowPtr pBackingStore;
PixmapPtr pBackingPixmap;
ScreenPtr pScreen;
GC *pGC;
BoxPtr extents;
PixmapPtr pNewPixmap;
int nx, ny;
int nw, nh;
pBackingStore = (miBSWindowPtr)(pWin->backStorage);
pBackingPixmap = pBackingStore->pBackingPixmap;
if (!pBackingPixmap)
return;
pScreen = pWin->drawable.pScreen;
extents = REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
pNewPixmap = pBackingPixmap;
nw = extents->x2 - extents->x1;
nh = extents->y2 - extents->y1;
if (nw != pBackingPixmap->drawable.width ||
nh != pBackingPixmap->drawable.height)
{
if (!saveBits || !nw || !nh)
{
pNewPixmap = NullPixmap;
pBackingStore->status = StatusNoPixmap;
}
else
{
pNewPixmap = (PixmapPtr)(*pScreen->CreatePixmap)
(pScreen,
nw, nh,
pWin->drawable.depth);
if (!pNewPixmap)
{
#ifdef BSEAGER
pBackingStore->status = StatusNoPixmap;
#else
pBackingStore->status = StatusBadAlloc;
#endif
}
}
}
if (!pNewPixmap)
{
pBackingStore->x = 0;
pBackingStore->y = 0;
}
else
{
nx = pBackingStore->x - extents->x1 + dx;
ny = pBackingStore->y - extents->y1 + dy;
pBackingStore->x = extents->x1;
pBackingStore->y = extents->y1;
if (saveBits && (pNewPixmap != pBackingPixmap || nx != 0 || ny != 0))
{
pGC = GetScratchGC(pNewPixmap->drawable.depth, pScreen);
if (pGC)
{
ValidateGC((DrawablePtr)pNewPixmap, pGC);
(*pGC->ops->CopyArea)((DrawablePtr)pBackingPixmap,
(DrawablePtr)pNewPixmap, pGC,
0, 0,
pBackingPixmap->drawable.width,
pBackingPixmap->drawable.height,
nx, ny);
FreeScratchGC(pGC);
}
}
}
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pNewPixmap != pBackingPixmap)
{
(* pScreen->DestroyPixmap)(pBackingPixmap);
pBackingStore->pBackingPixmap = pNewPixmap;
}
}
static void
miBSSaveDoomedAreas(pWin, pObscured, dx, dy)
register WindowPtr pWin;
RegionPtr pObscured;
int dx, dy;
{
miBSWindowPtr pBackingStore;
ScreenPtr pScreen;
int x, y;
pBackingStore = (miBSWindowPtr)pWin->backStorage;
pScreen = pWin->drawable.pScreen;
if (!pWin->realized)
{
pBackingStore->viewable = (char)pWin->viewable;
if (pWin->backingStore != Always)
{
REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
miDestroyBSPixmap (pWin);
return;
}
if (pBackingStore->status == StatusBadAlloc)
pBackingStore->status = StatusNoPixmap;
}
if ((pBackingStore->status == StatusVirtual) &&
(pBackingStore->backgroundState == None))
return;
if (REGION_NOTEMPTY(pScreen, pObscured))
{
BoxRec oldExtents;
x = pWin->drawable.x;
y = pWin->drawable.y;
REGION_TRANSLATE(pScreen, pObscured, -x, -y);
oldExtents = *REGION_EXTENTS(pScreen, &pBackingStore->SavedRegion);
REGION_UNION( pScreen, &pBackingStore->SavedRegion,
&pBackingStore->SavedRegion,
pObscured);
if (pBackingStore->status != StatusVirtual)
{
if (!pBackingStore->pBackingPixmap)
miCreateBSPixmap (pWin, &oldExtents);
else
miResizeBackingStore(pWin, 0, 0, TRUE);
if (pBackingStore->pBackingPixmap) {
if (pBackingStore->x | pBackingStore->y)
{
REGION_TRANSLATE( pScreen, pObscured,
-pBackingStore->x,
-pBackingStore->y);
x += pBackingStore->x;
y += pBackingStore->y;
}
(* pScreen->BackingStoreFuncs.SaveAreas)
(pBackingStore->pBackingPixmap, pObscured,
x - dx, y - dy, pWin);
}
}
REGION_TRANSLATE(pScreen, pObscured, x, y);
}
else
{
if (REGION_BROKEN (pScreen, pObscured))
{
REGION_EMPTY( pScreen, &pBackingStore->SavedRegion);
miDestroyBSPixmap (pWin);
return;
}
}
}
static RegionPtr
miBSRestoreAreas(pWin, prgnExposed)
register WindowPtr pWin;
RegionPtr prgnExposed;
{
PixmapPtr pBackingPixmap;
miBSWindowPtr pBackingStore;
RegionPtr prgnSaved;
RegionPtr prgnRestored;
register ScreenPtr pScreen;
RegionPtr exposures = prgnExposed;
pScreen = pWin->drawable.pScreen;
pBackingStore = (miBSWindowPtr)pWin->backStorage;
pBackingPixmap = pBackingStore->pBackingPixmap;
prgnSaved = &pBackingStore->SavedRegion;
if (pBackingStore->status == StatusContents)
{
REGION_TRANSLATE(pScreen, prgnSaved, pWin->drawable.x,
pWin->drawable.y);
prgnRestored = REGION_CREATE( pScreen, (BoxPtr)NULL, 1);
REGION_INTERSECT( pScreen, prgnRestored, prgnExposed, prgnSaved);
if (REGION_NOTEMPTY( pScreen, prgnRestored))
{
REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
REGION_SUBTRACT( pScreen, prgnExposed, prgnExposed, prgnRestored);
(* pScreen->BackingStoreFuncs.RestoreAreas) (pBackingPixmap,
prgnRestored,
pWin->drawable.x + pBackingStore->x,
pWin->drawable.y + pBackingStore->y,
pWin);
if (REGION_NOTEMPTY(pScreen, prgnSaved))
{
REGION_TRANSLATE(pScreen, prgnSaved,
-pWin->drawable.x,
-pWin->drawable.y);
miResizeBackingStore(pWin, 0, 0, TRUE);
}
else
miDestroyBSPixmap (pWin);
}
else
REGION_TRANSLATE(pScreen, prgnSaved,
-pWin->drawable.x, -pWin->drawable.y);
REGION_DESTROY( pScreen, prgnRestored);
}
else if ((pBackingStore->status == StatusVirtual) ||
(pBackingStore->status == StatusVDirty))
{
REGION_TRANSLATE(pScreen, prgnSaved,
pWin->drawable.x, pWin->drawable.y);
exposures = REGION_CREATE( pScreen, NullBox, 1);
if (SameBackground (pBackingStore->backgroundState,
pBackingStore->background,
pWin->backgroundState,
pWin->background))
{
REGION_SUBTRACT( pScreen, exposures, prgnExposed, prgnSaved);
}
else
{
miTileVirtualBS(pWin);
REGION_UNION( pScreen, exposures, prgnExposed, prgnSaved);
}
REGION_SUBTRACT( pScreen, prgnSaved, prgnSaved, prgnExposed);
REGION_TRANSLATE(pScreen, prgnSaved,
-pWin->drawable.x, -pWin->drawable.y);
}
else if (pWin->viewable && !pBackingStore->viewable &&
pWin->backingStore != Always)
{
BoxRec box;
prgnSaved = &pBackingStore->SavedRegion;
box.x1 = pWin->drawable.x;
box.x2 = box.x1 + (int) pWin->drawable.width;
box.y1 = pWin->drawable.y;
box.y2 = box.y1 + (int) pWin->drawable.height;
REGION_INVERSE( pScreen, prgnSaved, &pWin->clipList, &box);
REGION_TRANSLATE( pScreen, prgnSaved,
-pWin->drawable.x,
-pWin->drawable.y);
#ifdef SHAPE
if (wBoundingShape (pWin))
REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
wBoundingShape (pWin));
if (wClipShape (pWin))
REGION_INTERSECT(pScreen, prgnSaved, prgnSaved,
wClipShape (pWin));
#endif
miTileVirtualBS(pWin);
exposures = REGION_CREATE( pScreen, &box, 1);
}
pBackingStore->viewable = (char)pWin->viewable;
return exposures;
}
static RegionPtr
miBSTranslateBackingStore(pWin, windx, windy, oldClip, oldx, oldy)
WindowPtr pWin;
int windx;
int windy;
RegionPtr oldClip;
int oldx;
int oldy;
{
register miBSWindowPtr pBackingStore;
register RegionPtr pSavedRegion;
register RegionPtr newSaved, doomed;
register ScreenPtr pScreen;
BoxRec extents;
int scrdx;
int scrdy;
int dx;
int dy;
pScreen = pWin->drawable.pScreen;
pBackingStore = (miBSWindowPtr)(pWin->backStorage);
if ((pBackingStore->status == StatusNoPixmap) ||
(pBackingStore->status == StatusBadAlloc))
return NullRegion;
newSaved = REGION_CREATE( pScreen, NullBox, 1);
extents.x1 = pWin->drawable.x;
extents.x2 = pWin->drawable.x + (int) pWin->drawable.width;
extents.y1 = pWin->drawable.y;
extents.y2 = pWin->drawable.y + (int) pWin->drawable.height;
REGION_INVERSE( pScreen, newSaved, &pWin->clipList, &extents);
REGION_TRANSLATE( pScreen, newSaved,
-pWin->drawable.x, -pWin->drawable.y);
#ifdef SHAPE
if (wBoundingShape (pWin) || wClipShape (pWin)) {
if (wBoundingShape (pWin))
REGION_INTERSECT( pScreen, newSaved, newSaved,
wBoundingShape (pWin));
if (wClipShape (pWin))
REGION_INTERSECT( pScreen, newSaved, newSaved, wClipShape (pWin));
}
#endif
pSavedRegion = &pBackingStore->SavedRegion;
if (oldClip)
{
if (((windx != 0) || (windy != 0)) &&
(pBackingStore->status != StatusContents))
miCreateBSPixmap(pWin, NullBox);
dx = pWin->drawable.x - oldx;
dy = pWin->drawable.y - oldy;
scrdx = windx + dx;
scrdy = windy + dy;
REGION_TRANSLATE( pScreen, oldClip, windx - oldx, windy - oldy);
doomed = REGION_CREATE( pScreen, NullBox, 1);
REGION_INTERSECT( pScreen, doomed, oldClip, newSaved);
REGION_TRANSLATE( pScreen, oldClip, oldx - windx, oldy - windy);
REGION_TRANSLATE( pScreen, pSavedRegion, windx, windy);
REGION_UNION( pScreen, newSaved, newSaved, pSavedRegion);
{
RegionRec tmp;
tmp = *pSavedRegion;
*pSavedRegion = *newSaved;
*newSaved = tmp;
}
miResizeBackingStore (pWin, windx, windy, TRUE);
REGION_SUBTRACT( pScreen, newSaved, pSavedRegion, newSaved);
if (REGION_NOTEMPTY( pScreen, doomed))
{
REGION_SUBTRACT( pScreen, newSaved, newSaved, doomed);
REGION_TRANSLATE( pScreen, doomed,
pWin->drawable.x, pWin->drawable.y);
(* pScreen->SaveDoomedAreas) (pWin, doomed, scrdx, scrdy);
}
REGION_DESTROY(pScreen, doomed);
if (REGION_NOTEMPTY( pScreen, newSaved))
{
miBSClearBackingRegion (pWin, newSaved);
REGION_TRANSLATE(pScreen, newSaved,
pWin->drawable.x,
pWin->drawable.y);
}
else
{
REGION_DESTROY(pScreen, newSaved);
newSaved = NullRegion;
}
}
else
{
REGION_COPY( pScreen, pSavedRegion, newSaved);
REGION_TRANSLATE( pScreen, newSaved,
pWin->drawable.x, pWin->drawable.y);
miResizeBackingStore (pWin, 0, 0, FALSE);
(void) miBSClearBackingStore (pWin, 0, 0, 0, 0, FALSE);
}
return newSaved;
}
static void
miBSDrawGuarantee (pWin, pGC, guarantee)
WindowPtr pWin;
GCPtr pGC;
int guarantee;
{
miBSGCPtr pPriv;
if (pWin->backStorage)
{
pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
if (!pPriv)
(void) miBSCreateGCPrivate (pGC);
pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
if (pPriv)
{
switch (pPriv->guarantee)
{
case GuaranteeNothing:
case GuaranteeVisBack:
pPriv->guarantee = guarantee;
break;
}
}
}
}
#define noBackingCopy (GCGraphicsExposures|GCClipXOrigin|GCClipYOrigin| \
GCClipMask|GCSubwindowMode| \
GCTileStipXOrigin|GCTileStipYOrigin)
static void
miBSValidateGC (pGC, stateChanges, pDrawable)
GCPtr pGC;
unsigned long stateChanges;
DrawablePtr pDrawable;
{
GCPtr pBackingGC;
miBSWindowPtr pWindowPriv = NULL;
miBSGCPtr pPriv;
WindowPtr pWin;
int lift_functions;
RegionPtr backingCompositeClip = NULL;
if (pDrawable->type != DRAWABLE_PIXMAP)
{
pWin = (WindowPtr) pDrawable;
pWindowPriv = (miBSWindowPtr) pWin->backStorage;
lift_functions = (pWindowPriv == (miBSWindowPtr) NULL);
}
else
{
pWin = (WindowPtr) NULL;
lift_functions = TRUE;
}
pPriv = (miBSGCPtr)pGC->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGC, pPriv);
(*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable);
pPriv->wrapFuncs = pGC->funcs;
pPriv->wrapOps = pGC->ops;
if (!lift_functions && ((pPriv->guarantee == GuaranteeVisBack) ||
(pWindowPriv->status == StatusNoPixmap) ||
(pWindowPriv->status == StatusBadAlloc)))
lift_functions = TRUE;
if (!lift_functions &&
((pDrawable->serialNumber != pPriv->serialNumber) ||
(stateChanges&(GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode))))
{
if (REGION_NOTEMPTY(pGC->pScreen, &pWindowPriv->SavedRegion))
{
backingCompositeClip = REGION_CREATE(pGC->pScreen, NULL, 1);
if ((pGC->clientClipType == CT_NONE) ||
(pGC->clientClipType == CT_PIXMAP))
{
REGION_COPY(pGC->pScreen, backingCompositeClip,
&pWindowPriv->SavedRegion);
}
else
{
REGION_COPY(pGC->pScreen, backingCompositeClip,
pGC->clientClip);
REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
pGC->clipOrg.x,
pGC->clipOrg.y);
REGION_INTERSECT(pGC->pScreen, backingCompositeClip,
backingCompositeClip,
&pWindowPriv->SavedRegion);
}
if (pGC->subWindowMode == IncludeInferiors)
{
RegionPtr translatedClip;
translatedClip = NotClippedByChildren (pWin);
REGION_TRANSLATE(pGC->pScreen, translatedClip,
-pDrawable->x,
-pDrawable->y);
REGION_SUBTRACT(pGC->pScreen, backingCompositeClip,
backingCompositeClip, translatedClip);
REGION_DESTROY(pGC->pScreen, translatedClip);
}
if (!REGION_NOTEMPTY(pGC->pScreen, backingCompositeClip))
lift_functions = TRUE;
}
else
{
lift_functions = TRUE;
}
if (lift_functions && (pWindowPriv->status == StatusVirtual) &&
(pWin->parent || pGC->subWindowMode != IncludeInferiors))
pWindowPriv->status = StatusVDirty;
}
if (!lift_functions && !pWindowPriv->pBackingPixmap)
{
miCreateBSPixmap (pWin, NullBox);
if (!pWindowPriv->pBackingPixmap)
lift_functions = TRUE;
}
if (!lift_functions && !pPriv->pBackingGC)
{
int status;
XID noexpose = xFalse;
pBackingGC = CreateGC ((DrawablePtr)pWindowPriv->pBackingPixmap,
GCGraphicsExposures, &noexpose, &status);
if (status != Success)
lift_functions = TRUE;
else
pPriv->pBackingGC = pBackingGC;
}
pBackingGC = pPriv->pBackingGC;
pPriv->stateChanges |= stateChanges;
if (lift_functions)
{
if (backingCompositeClip)
REGION_DESTROY( pGC->pScreen, backingCompositeClip);
miBSDestroyGCPrivate (pGC);
return;
}
pPriv->stateChanges &= ~noBackingCopy;
if (pPriv->stateChanges)
CopyGC(pGC, pBackingGC, pPriv->stateChanges);
if ((pGC->patOrg.x - pWindowPriv->x) != pBackingGC->patOrg.x ||
(pGC->patOrg.y - pWindowPriv->y) != pBackingGC->patOrg.y)
{
XID vals[2];
vals[0] = pGC->patOrg.x - pWindowPriv->x;
vals[1] = pGC->patOrg.y - pWindowPriv->y;
DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0);
}
pPriv->stateChanges = 0;
if (backingCompositeClip)
{
XID vals[2];
if (pGC->clientClipType == CT_PIXMAP)
{
(*pBackingGC->funcs->CopyClip)(pBackingGC, pGC);
REGION_TRANSLATE(pGC->pScreen, backingCompositeClip,
-pGC->clipOrg.x, -pGC->clipOrg.y);
vals[0] = pGC->clipOrg.x - pWindowPriv->x;
vals[1] = pGC->clipOrg.y - pWindowPriv->y;
DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
(* pGC->pScreen->BackingStoreFuncs.SetClipmaskRgn)
(pBackingGC, backingCompositeClip);
REGION_DESTROY( pGC->pScreen, backingCompositeClip);
}
else
{
vals[0] = -pWindowPriv->x;
vals[1] = -pWindowPriv->y;
DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
(*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, backingCompositeClip, 0);
}
pPriv->serialNumber = pDrawable->serialNumber;
}
if (pWindowPriv->pBackingPixmap->drawable.serialNumber
!= pBackingGC->serialNumber)
{
ValidateGC((DrawablePtr)pWindowPriv->pBackingPixmap, pBackingGC);
}
if (pBackingGC->clientClip == 0)
ErrorF ("backing store clip list nil");
FUNC_EPILOGUE (pGC, pPriv);
}
static void
miBSChangeGC (pGC, mask)
GCPtr pGC;
unsigned long mask;
{
miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGC, pPriv);
(*pGC->funcs->ChangeGC) (pGC, mask);
FUNC_EPILOGUE (pGC, pPriv);
}
static void
miBSCopyGC (pGCSrc, mask, pGCDst)
GCPtr pGCSrc, pGCDst;
unsigned long mask;
{
miBSGCPtr pPriv = (miBSGCPtr) (pGCDst)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGCDst, pPriv);
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
FUNC_EPILOGUE (pGCDst, pPriv);
}
static void
miBSDestroyGC (pGC)
GCPtr pGC;
{
miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGC, pPriv);
if (pPriv->pBackingGC)
FreeGC(pPriv->pBackingGC, (GContext)0);
(*pGC->funcs->DestroyGC) (pGC);
FUNC_EPILOGUE (pGC, pPriv);
xfree(pPriv);
}
static void
miBSChangeClip(pGC, type, pvalue, nrects)
GCPtr pGC;
int type;
pointer pvalue;
int nrects;
{
miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGC, pPriv);
(* pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
FUNC_EPILOGUE (pGC, pPriv);
}
static void
miBSCopyClip(pgcDst, pgcSrc)
GCPtr pgcDst, pgcSrc;
{
miBSGCPtr pPriv = (miBSGCPtr) (pgcDst)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pgcDst, pPriv);
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
FUNC_EPILOGUE (pgcDst, pPriv);
}
static void
miBSDestroyClip(pGC)
GCPtr pGC;
{
miBSGCPtr pPriv = (miBSGCPtr) (pGC)->devPrivates[miBSGCIndex].ptr;
FUNC_PROLOGUE (pGC, pPriv);
(* pGC->funcs->DestroyClip)(pGC);
FUNC_EPILOGUE (pGC, pPriv);
}
static void
miDestroyBSPixmap (pWin)
WindowPtr pWin;
{
miBSWindowPtr pBackingStore;
ScreenPtr pScreen;
pScreen = pWin->drawable.pScreen;
pBackingStore = (miBSWindowPtr) pWin->backStorage;
if (pBackingStore->pBackingPixmap)
(* pScreen->DestroyPixmap)(pBackingStore->pBackingPixmap);
pBackingStore->pBackingPixmap = NullPixmap;
pBackingStore->x = 0;
pBackingStore->y = 0;
if (pBackingStore->backgroundState == BackgroundPixmap)
(* pScreen->DestroyPixmap)(pBackingStore->background.pixmap);
pBackingStore->backgroundState = None;
pBackingStore->status = StatusNoPixmap;
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
static void
miTileVirtualBS (pWin)
WindowPtr pWin;
{
miBSWindowPtr pBackingStore;
pBackingStore = (miBSWindowPtr) pWin->backStorage;
if (pBackingStore->backgroundState == BackgroundPixmap)
(* pWin->drawable.pScreen->DestroyPixmap)
(pBackingStore->background.pixmap);
pBackingStore->backgroundState = pWin->backgroundState;
pBackingStore->background = pWin->background;
if (pBackingStore->backgroundState == BackgroundPixmap)
pBackingStore->background.pixmap->refcnt++;
if (pBackingStore->status != StatusVDirty)
pBackingStore->status = StatusVirtual;
if (pBackingStore->backgroundState == ParentRelative)
miCreateBSPixmap (pWin, NullBox);
}
#ifdef DEBUG
static int BSAllocationsFailed = 0;
#define FAILEDSIZE 32
static struct { int w, h; } failedRecord[FAILEDSIZE];
static int failedIndex;
#endif
static void
miCreateBSPixmap (pWin, pExtents)
WindowPtr pWin;
BoxPtr pExtents;
{
miBSWindowPtr pBackingStore;
ScreenPtr pScreen;
PixUnion background;
char backgroundState = 0;
BoxPtr extents;
Bool backSet;
pScreen = pWin->drawable.pScreen;
pBackingStore = (miBSWindowPtr) pWin->backStorage;
if (pBackingStore->status == StatusBadAlloc)
return;
backSet = ((pBackingStore->status == StatusVirtual) ||
(pBackingStore->status == StatusVDirty));
extents = REGION_EXTENTS( pScreen, &pBackingStore->SavedRegion);
if (!pBackingStore->pBackingPixmap &&
extents->x2 != extents->x1 &&
extents->y2 != extents->y1)
{
pBackingStore->x = extents->x1;
pBackingStore->y = extents->y1;
pBackingStore->pBackingPixmap =
(PixmapPtr)(* pScreen->CreatePixmap)
(pScreen,
extents->x2 - extents->x1,
extents->y2 - extents->y1,
pWin->drawable.depth);
}
if (!pBackingStore->pBackingPixmap)
{
#ifdef DEBUG
BSAllocationsFailed++;
failedRecord[failedIndex].w = pWin->drawable.width;
failedRecord[failedIndex].h = pWin->drawable.height;
failedIndex++;
if (failedIndex == FAILEDSIZE)
failedIndex = 0;
#endif
#ifdef BSEAGER
pBackingStore->status = StatusNoPixmap;
#else
pBackingStore->status = StatusBadAlloc;
#endif
return;
}
pBackingStore->status = StatusContents;
if (backSet)
{
backgroundState = pWin->backgroundState;
background = pWin->background;
pWin->backgroundState = pBackingStore->backgroundState;
pWin->background = pBackingStore->background;
if (pWin->backgroundState == BackgroundPixmap)
pWin->background.pixmap->refcnt++;
}
if (!pExtents)
pExtents = extents;
if (pExtents->y1 != pExtents->y2)
{
RegionPtr exposed;
exposed = miBSClearBackingStore(pWin,
pExtents->x1, pExtents->y1,
pExtents->x2 - pExtents->x1,
pExtents->y2 - pExtents->y1,
!backSet);
if (exposed)
{
miSendExposures(pWin, exposed, pWin->drawable.x, pWin->drawable.y);
REGION_DESTROY( pScreen, exposed);
}
}
if (backSet)
{
if (pWin->backgroundState == BackgroundPixmap)
(* pScreen->DestroyPixmap) (pWin->background.pixmap);
pWin->backgroundState = backgroundState;
pWin->background = background;
if (pBackingStore->backgroundState == BackgroundPixmap)
(* pScreen->DestroyPixmap) (pBackingStore->background.pixmap);
pBackingStore->backgroundState = None;
}
}
static void
miBSExposeCopy (pSrc, pDst, pGC, prgnExposed, srcx, srcy, dstx, dsty, plane)
WindowPtr pSrc;
DrawablePtr pDst;
GCPtr pGC;
RegionPtr prgnExposed;
int srcx, srcy;
int dstx, dsty;
unsigned long plane;
{
RegionRec tempRgn;
miBSWindowPtr pBackingStore;
CopyPlaneProcPtr copyProc;
GCPtr pScratchGC;
register BoxPtr pBox;
register int i;
register int dx, dy;
BITS32 gcMask;
if (!REGION_NOTEMPTY(pGC->pScreen, prgnExposed))
return;
pBackingStore = (miBSWindowPtr)pSrc->backStorage;
if ((pBackingStore->status == StatusNoPixmap) ||
(pBackingStore->status == StatusBadAlloc))
return;
REGION_NULL( pGC->pScreen, &tempRgn);
REGION_INTERSECT( pGC->pScreen, &tempRgn, prgnExposed,
&pBackingStore->SavedRegion);
REGION_SUBTRACT( pGC->pScreen, prgnExposed, prgnExposed, &tempRgn);
if (plane != 0) {
copyProc = pGC->ops->CopyPlane;
} else {
copyProc = (CopyPlaneProcPtr)pGC->ops->CopyArea;
}
dx = dstx - srcx;
dy = dsty - srcy;
switch (pBackingStore->status) {
case StatusVirtual:
case StatusVDirty:
pScratchGC = GetScratchGC (pDst->depth, pDst->pScreen);
if (pScratchGC)
{
gcMask = 0;
if (pGC->alu != pScratchGC->alu)
gcMask = GCFunction;
if (pGC->planemask != pScratchGC->planemask)
gcMask |= GCPlaneMask;
if (gcMask)
CopyGC (pGC, pScratchGC, gcMask);
miBSFillVirtualBits (pDst, pScratchGC, &tempRgn, dx, dy,
(int) pBackingStore->backgroundState,
pBackingStore->background,
~0L);
FreeScratchGC (pScratchGC);
}
break;
case StatusContents:
for (i = REGION_NUM_RECTS(&tempRgn), pBox = REGION_RECTS(&tempRgn);
--i >= 0;
pBox++)
{
(* copyProc) (&(pBackingStore->pBackingPixmap->drawable), pDst, pGC,
pBox->x1 - pBackingStore->x,
pBox->y1 - pBackingStore->y,
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
pBox->x1 + dx, pBox->y1 + dy, plane);
}
break;
}
REGION_UNINIT( pGC->pScreen, &tempRgn);
}