📄 mibstore.c
字号:
/* $XConsortium: mibstore.c,v 5.63 94/10/21 20:25:08 dpw Exp $ *//***********************************************************Copyright (c) 1987 X ConsortiumPermission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included inall copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER INAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR INCONNECTION 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 beused in advertising or otherwise to promote the sale, use or other dealingsin this Software without prior written authorization from the X Consortium.Copyright 1987 by the Regents of the University of California All Rights ReservedPermission to use, copy, modify, and distribute this software and itsdocumentation for any purpose and without fee is hereby granted, providedthat the above copyright notice appear in all copies and that both thatcopyright notice and this permission notice appear in supportingdocumentation, and that the name X Consortium not be used in advertising or publicitypertaining to distribution of the software without specific, written priorpermission. The University of California makes no representations about the suitabilityof this software for any purpose. It is provided "as is" without express orimplied warranty.******************************************************************/#define NEED_EVENTS#include "X.h"#include "Xmd.h"#include "Xproto.h"#include "misc.h"#include "regionstr.h"#include "scrnintstr.h"#include "gcstruct.h"#include "extnsionst.h"#include "windowstr.h"#include "pixmapstr.h"#include "fontstruct.h"#include "dixfontstr.h"#include "dixstruct.h" /* For requestingClient */#include "mi.h"#include "mibstorest.h"/* * When the server fails to allocate a backing store pixmap, if you want * it to dynamically retry to allocate backing store on every subsequent * graphics op, you can enable BSEAGER; otherwise, backing store will be * disabled on the window until it is unmapped and then remapped. *//* #define BSEAGER *//*- * NOTES ON USAGE: * * The functions in this file implement a machine-independent backing-store * scheme. To use it, the output library must do the following: * - Provide a SaveAreas function that takes a destination pixmap, a * region of the areas to save (in the pixmap's coordinate system) * and the screen origin of the region. It should copy the areas from * the screen into the pixmap. * - Provide a RestoreAreas function that takes a source pixmap, a region * of the areas to restore (in the screen's coordinate system) and the * origin of the pixmap on the screen. It should copy the areas from * the pixmap into the screen. * - Provide a SetClipmaskRgn function that takes a gc and a region * and merges the region into any CT_PIXMAP client clip that * is specified in the GC. This routine is only needed if * miValidateBackingStore will see CT_PIXMAP clip lists; not * true for any of the sample servers (which convert the PIXMAP * clip lists into CT_REGION clip lists; an expensive but simple * to code option). * - The function placed in a window's ClearToBackground vector must call * pScreen->ClearBackingStore with the window, followed by * the window-relative x and y coordinates, followed by the width and * height of the area to be cleared, followed by the generateExposures * flag. This has been taken care of in miClearToBackground. * - Whatever determines GraphicsExpose events for the CopyArea and * CopyPlane requests should call pWin->backStorage->ExposeCopy * with the source and destination drawables, the GC used, a source- * window-relative region of exposed areas, the source and destination * coordinates and the bitplane copied, if CopyPlane, or 0, if * CopyArea. * * JUSTIFICATION * This is a cross between saving everything and just saving the * obscued areas (as in Pike's layers.) This method has the advantage * of only doing each output operation once per pixel, visible or * invisible, and avoids having to do all the crufty storage * management of keeping several separate rectangles. Since the * ddx layer ouput primitives are required to draw through clipping * rectangles anyway, sending multiple drawing requests for each of * several rectangles isn't necessary. (Of course, it could be argued * that the ddx routines should just take one rectangle each and * get called multiple times, but that would make taking advantage of * smart hardware harder, and probably be slower as well.) */#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();static void miDestroyBSPixmap();static void miTileVirtualBS();static void miBSAllocate(), miBSFree();static Bool miBSCreateGCPrivate ();static void miBSClearBackingRegion ();#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; \}/* * wrappers for screen funcs */static int miBSScreenIndex;static unsigned long miBSGeneration = 0;static Bool miBSCloseScreen();static void miBSGetImage();static void miBSGetSpans();static Bool miBSChangeWindowAttributes();static Bool miBSCreateGC();static Bool miBSDestroyWindow();/* * backing store screen functions */static void miBSSaveDoomedAreas();static RegionPtr miBSRestoreAreas();static void miBSExposeCopy();static RegionPtr miBSTranslateBackingStore(), miBSClearBackingStore();static void miBSDrawGuarantee();/* * wrapper vectors for GC funcs and ops */static int miBSGCIndex;static void miBSValidateGC (), miBSCopyGC (), miBSDestroyGC();static void miBSChangeGC();static void miBSChangeClip(), miBSDestroyClip(), miBSCopyClip();static GCFuncs miBSGCFuncs = { miBSValidateGC, miBSChangeGC, miBSCopyGC, miBSDestroyGC, miBSChangeClip, miBSDestroyClip, miBSCopyClip,};static void miBSFillSpans(), miBSSetSpans(), miBSPutImage();static RegionPtr miBSCopyArea(), miBSCopyPlane();static void miBSPolyPoint(), miBSPolylines(), miBSPolySegment();static void miBSPolyRectangle(),miBSPolyArc(), miBSFillPolygon();static void miBSPolyFillRect(), miBSPolyFillArc();static int miBSPolyText8(), miBSPolyText16();static void miBSImageText8(), miBSImageText16();static void miBSImageGlyphBlt(),miBSPolyGlyphBlt();static void miBSPushPixels();#ifdef NEED_LINEHELPERstatic void miBSLineHelper();#endifstatic GCOps miBSGCOps = { miBSFillSpans, miBSSetSpans, miBSPutImage, miBSCopyArea, miBSCopyPlane, miBSPolyPoint, miBSPolylines, miBSPolySegment, miBSPolyRectangle, miBSPolyArc, miBSFillPolygon, miBSPolyFillRect, miBSPolyFillArc, miBSPolyText8, miBSPolyText16, miBSImageText8, miBSImageText16, miBSImageGlyphBlt, miBSPolyGlyphBlt, miBSPushPixels#ifdef NEED_LINEHELPER , miBSLineHelper#endif};#define FUNC_PROLOGUE(pGC, pPriv) \ ((pGC)->funcs = pPriv->wrapFuncs),\ ((pGC)->ops = pPriv->wrapOps)#define FUNC_EPILOGUE(pGC, pPriv) \ ((pGC)->funcs = &miBSGCFuncs),\ ((pGC)->ops = &miBSGCOps)/* * every GC in the server is initially wrapped with these * "cheap" functions. This allocates no memory and is used * to discover GCs used with windows which have backing * store enabled */static void miBSCheapValidateGC(), miBSCheapCopyGC(), miBSCheapDestroyGC();static void miBSCheapChangeGC ();static void miBSCheapChangeClip(), miBSCheapDestroyClip();static void miBSCheapCopyClip();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)/* * called from device screen initialization proc. Gets a GCPrivateIndex * and wraps appropriate per-screen functions */voidmiInitializeBackingStore (pScreen, funcs) ScreenPtr pScreen; miBSFuncPtr funcs;{ 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; pScreenPriv->funcs = funcs; 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;}/* * Screen function wrappers */#define SCREEN_PROLOGUE(pScreen, field)\ ((pScreen)->field = \ ((miBSScreenPtr) \ (pScreen)->devPrivates[miBSScreenIndex].ptr)->field)#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ ((pScreen)->field = wrapper)/* * CloseScreen wrapper -- unwrap everything, free the private data * and call the wrapped function */static BoolmiBSCloseScreen (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();static voidmiBSGetImage (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; 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_INIT(pScreen, &Border, NullBox, 0); REGION_INIT(pScreen, &Inside, NullBox, 0); 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); /* offset of sub-window in GetImage pixmap */ 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -