diff options
Diffstat (limited to 'xorg-server/mi/mibank.c')
-rw-r--r-- | xorg-server/mi/mibank.c | 2314 |
1 files changed, 0 insertions, 2314 deletions
diff --git a/xorg-server/mi/mibank.c b/xorg-server/mi/mibank.c deleted file mode 100644 index 9e4d63162..000000000 --- a/xorg-server/mi/mibank.c +++ /dev/null @@ -1,2314 +0,0 @@ -/* - * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of Marc Aurele La France not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Marc Aurele La France makes no representations - * about the suitability of this software for any purpose. It is provided - * "as-is" without express or implied warranty. - * - * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL MARC AURELE LA FRANCE 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. - */ - -/* - * Copyright 1990,91,92,93 by Thomas Roell, Germany. - * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation, and that the name of Thomas Roell nor - * SGCS be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * Thomas Roell nor SGCS makes no representations about the suitability - * of this software for any purpose. It is provided "as is" without - * express or implied warranty. - * - * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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. - */ - - -/* - * This thing originated from an idea of Edwin Goei and his bank switching - * code for the DEC TX board. - */ - -/* - * Heavily modified for the XFree86 Project to turn this into an mi wrapper. - * --- Marc Aurele La France (tsi@xfree86.org) - */ - -/* - * "Heavily modified", indeed! By the time this is finalized, there probably - * won't be much left of Roell's code... - * - * Miscellaneous notes: - * - Pixels with imbedded bank boundaries are required to be off-screen. There - * >might< be a way to fool the underlying framebuffer into dealing with - * partial pixels. - * - Plans to generalise this to do (hardware) colour plane switching have been - * dropped due to colour flashing concerns. - * - * TODO: - * - Re-instate shared and double banking for framebuffers whose pixmap formats - * don't describe how the server "sees" the screen. - * - Remove remaining assumptions that a pixmap's devPrivate field points - * directly to its pixel data. - */ - -/* #define NO_ALLOCA 1 */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "servermd.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "mi.h" -#include "mibank.h" - -#define BANK_SINGLE 0 -#define BANK_SHARED 1 -#define BANK_DOUBLE 2 -#define BANK_NOBANK 3 - -typedef struct _miBankScreen -{ - miBankInfoRec BankInfo; - unsigned int nBankBPP; - unsigned int type; - - unsigned long nBitsPerBank; - unsigned long nBitsPerScanline; - unsigned long nPixelsPerScanlinePadUnit; - - PixmapPtr pScreenPixmap; - PixmapPtr pBankPixmap; - GCPtr pBankGC; - - int nBanks, maxRects; - RegionPtr *pBanks; - - pointer pbits; - - /* - * Screen Wrappers - */ - CreateScreenResourcesProcPtr CreateScreenResources; - ModifyPixmapHeaderProcPtr ModifyPixmapHeader; - CloseScreenProcPtr CloseScreen; - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - CreateGCProcPtr CreateGC; - CopyWindowProcPtr CopyWindow; -} miBankScreenRec, *miBankScreenPtr; - -typedef struct _miBankGC -{ - GCOps *wrappedOps, *unwrappedOps; - GCFuncs *wrappedFuncs, *unwrappedFuncs; - - Bool fastCopy, fastPlane; - - RegionPtr pBankedClips[1]; -} miBankGCRec, *miBankGCPtr; - -typedef struct _miBankQueue -{ - Bool fastBlit; - unsigned short srcBankNo; - unsigned short dstBankNo; - short x; - short y; - short w; - short h; -} miBankQueue; - -/* - * CAVEAT: This banking scheme requires that the DDX store Pixmap data in the - * server's address space. - */ - -#define ModifyPixmap(_pPix, _width, _devKind, _pbits) \ - (*pScreen->ModifyPixmapHeader)((_pPix), \ - (_width), -1, -1, -1, (_devKind), (_pbits)) - -#define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \ - ModifyPixmap(_pPix, _width, _devKind, \ - (char *)pScreenPriv->BankInfo.pBankA + \ - (*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \ - (pScreenPriv->BankInfo.BankSize * (_no))) - -#define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \ - ModifyPixmap(_pPix, _width, _devKind, \ - (char *)pScreenPriv->BankInfo.pBankA + \ - (*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \ - (pScreenPriv->BankInfo.BankSize * (_no))) - -#define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \ - ModifyPixmap(_pPix, _width, _devKind, \ - (char *)pScreenPriv->BankInfo.pBankB + \ - (*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \ - (pScreenPriv->BankInfo.BankSize * (_no))) - -#define xalloc_ARRAY(atype, ntype) xalloc((ntype) * sizeof(atype)) - -static int miBankScreenKeyIndex; -static DevPrivateKey miBankScreenKey = &miBankScreenKeyIndex; -static int miBankGCKeyIndex; -static DevPrivateKey miBankGCKey = &miBankGCKeyIndex; - -static unsigned long miBankGeneration = 0; - -#define BANK_SCRPRIVLVAL dixLookupPrivate(&pScreen->devPrivates, miBankScreenKey) - -#define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL)) - -#define BANK_GCPRIVLVAL(pGC) dixLookupPrivate(&(pGC)->devPrivates, miBankGCKey) - -#define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC))) - -#define PIXMAP_STATUS(_pPix) \ - pointer pbits = (_pPix)->devPrivate.ptr - -#define PIXMAP_SAVE(_pPix) \ - PIXMAP_STATUS(_pPix); \ - if (pbits == (pointer)pScreenPriv) \ - (_pPix)->devPrivate.ptr = pScreenPriv->pbits - -#define PIXMAP_RESTORE(_pPix) \ - (_pPix)->devPrivate.ptr = pbits - -#define BANK_SAVE \ - int width = pScreenPriv->pBankPixmap->drawable.width; \ - int devKind = pScreenPriv->pBankPixmap->devKind; \ - PIXMAP_SAVE(pScreenPriv->pBankPixmap) - -#define BANK_RESTORE \ - pScreenPriv->pBankPixmap->drawable.width = width; \ - pScreenPriv->pBankPixmap->devKind = devKind; \ - PIXMAP_RESTORE(pScreenPriv->pBankPixmap) - -#define SCREEN_STATUS \ - PIXMAP_STATUS(pScreenPriv->pScreenPixmap) - -#define SCREEN_SAVE \ - PIXMAP_SAVE(pScreenPriv->pScreenPixmap) - -#define SCREEN_RESTORE \ - PIXMAP_RESTORE(pScreenPriv->pScreenPixmap) - -#define SCREEN_INIT \ - miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE - -#define SCREEN_UNWRAP(field) \ - pScreen->field = pScreenPriv->field - -#define SCREEN_WRAP(field, wrapper) \ - pScreenPriv->field = pScreen->field; \ - pScreen->field = wrapper - -#define GC_INIT(pGC) \ - miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC) - -#define GC_UNWRAP(pGC) \ - pGCPriv->unwrappedOps = (pGC)->ops; \ - pGCPriv->unwrappedFuncs = (pGC)->funcs; \ - (pGC)->ops = pGCPriv->wrappedOps; \ - (pGC)->funcs = pGCPriv->wrappedFuncs - -#define GC_WRAP(pGC) \ - pGCPriv->wrappedOps = (pGC)->ops; \ - pGCPriv->wrappedFuncs = (pGC)->funcs; \ - (pGC)->ops = pGCPriv->unwrappedOps; \ - (pGC)->funcs = pGCPriv->unwrappedFuncs - -#define IS_BANKED(pDrawable) \ - ((pbits == (pointer)pScreenPriv) && \ - (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW)) - -#define CLIP_SAVE \ - RegionPtr pOrigCompositeClip = pGC->pCompositeClip - -#define CLIP_RESTORE \ - pGC->pCompositeClip = pOrigCompositeClip - -#define GCOP_INIT \ - ScreenPtr pScreen = pGC->pScreen; \ - SCREEN_INIT; \ - GC_INIT(pGC) - -#define GCOP_UNWRAP \ - GC_UNWRAP(pGC) - -#define GCOP_WRAP \ - GC_WRAP(pGC) - -#define GCOP_TOP_PART \ - for (i = 0; i < pScreenPriv->nBanks; i++) \ - { \ - if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \ - continue; \ - GCOP_UNWRAP; \ - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i) - -#define GCOP_BOTTOM_PART \ - GCOP_WRAP; \ - } - -#define GCOP_SIMPLE(statement) \ - if (nArray > 0) \ - { \ - GCOP_INIT; \ - SCREEN_SAVE; \ - if (!IS_BANKED(pDrawable)) \ - { \ - GCOP_UNWRAP; \ - statement; \ - GCOP_WRAP; \ - } \ - else \ - { \ - int i; \ - CLIP_SAVE; \ - GCOP_TOP_PART; \ - statement; \ - GCOP_BOTTOM_PART; \ - CLIP_RESTORE; \ - } \ - SCREEN_RESTORE; \ - } - -#define GCOP_0D_ARGS mode, -#define GCOP_1D_ARGS -#define GCOP_2D_ARGS shape, mode, - -#define GCOP_COMPLEX(aop, atype) \ - if (nArray > 0) \ - { \ - GCOP_INIT; \ - SCREEN_SAVE; \ - if (!IS_BANKED(pDrawable)) \ - { \ - GCOP_UNWRAP; \ - (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \ - GCOP_WRAP; \ - } \ - else \ - { \ - atype *aarg = pArray, *acopy; \ - int i; \ - CLIP_SAVE; \ - if ((acopy = xalloc_ARRAY(atype, nArray))) \ - aarg = acopy; \ - GCOP_TOP_PART; \ - if (acopy) \ - memcpy(acopy, pArray, nArray * sizeof(atype)); \ - (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \ - GCOP_BOTTOM_PART; \ - xfree(acopy); \ - CLIP_RESTORE; \ - } \ - SCREEN_RESTORE; \ - } - -/********************* - * Utility functions * - *********************/ - -static int -miBankOf( - miBankScreenPtr pScreenPriv, - int x, - int y -) -{ - int iBank = ((x * (int)pScreenPriv->nBankBPP) + - (y * (long)pScreenPriv->nBitsPerScanline)) / - (long)pScreenPriv->nBitsPerBank; - - if (iBank < 0) - iBank = 0; - else if (iBank >= pScreenPriv->nBanks) - iBank = pScreenPriv->nBanks - 1; - - return iBank; -} - -#define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y)) -#define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y)) - -/* Determine banking type from the BankInfoRec */ -static unsigned int -miBankDeriveType( - ScreenPtr pScreen, - miBankInfoPtr pBankInfo -) -{ - unsigned int type; - - if (pBankInfo->pBankA == pBankInfo->pBankB) - { - if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank) - { - if (pBankInfo->SetSourceAndDestinationBanks != - pBankInfo->SetSourceBank) - return BANK_NOBANK; - - type = BANK_SINGLE; - } - else - { - if (pBankInfo->SetSourceAndDestinationBanks == - pBankInfo->SetDestinationBank) - return BANK_NOBANK; - if (pBankInfo->SetSourceAndDestinationBanks == - pBankInfo->SetSourceBank) - return BANK_NOBANK; - - type = BANK_SHARED; - } - } - else - { - if ((unsigned long)abs((char *)pBankInfo->pBankA - - (char *)pBankInfo->pBankB) < pBankInfo->BankSize) - return BANK_NOBANK; - - if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank) - { - if (pBankInfo->SetSourceAndDestinationBanks != - pBankInfo->SetSourceBank) - return BANK_NOBANK; - } - else - { - if (pBankInfo->SetSourceAndDestinationBanks == - pBankInfo->SetDestinationBank) - return BANK_NOBANK; - } - - type = BANK_DOUBLE; - } - - /* - * Internal limitation: Currently, only single banking is supported when - * the pixmap format and the screen's pixel format are different. The - * following test is only partially successful at detecting this condition. - */ - if (pBankInfo->nBankDepth != pScreen->rootDepth) - type = BANK_SINGLE; - - return type; -} - -/* Least common multiple */ -static unsigned int -miLCM( - unsigned int x, - unsigned int y -) -{ - unsigned int m = x, n = y, o; - - while ((o = m % n)) - { - m = n; - n = o; - } - - return (x / n) * y; -} - -/****************** - * GCOps wrappers * - ******************/ - -static void -miBankFillSpans( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - DDXPointPtr pptInit, - int *pwidthInit, - int fSorted -) -{ - GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC, - nArray, pptInit, pwidthInit, fSorted)); -} - -static void -miBankSetSpans( - DrawablePtr pDrawable, - GCPtr pGC, - char *psrc, - DDXPointPtr ppt, - int *pwidth, - int nArray, - int fSorted -) -{ - GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc, - ppt, pwidth, nArray, fSorted)); -} - -static void -miBankPutImage( - DrawablePtr pDrawable, - GCPtr pGC, - int depth, - int x, - int y, - int w, - int h, - int leftPad, - int format, - char *pImage -) -{ - if ((w > 0) && (h > 0)) - { - GCOP_INIT; - SCREEN_SAVE; - - if (!IS_BANKED(pDrawable)) - { - GCOP_UNWRAP; - - (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, - leftPad, format, pImage); - - GCOP_WRAP; - } - else - { - int i, j; - - CLIP_SAVE; - - i = FirstBankOf(x + pDrawable->x, y + pDrawable->y); - j = LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h); - for (; i <= j; i++) - { - if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) - continue; - - GCOP_UNWRAP; - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i); - - (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h, - leftPad, format, pImage); - - GCOP_WRAP; - } - - CLIP_RESTORE; - } - - SCREEN_RESTORE; - } -} - -/* - * Here the CopyArea/CopyPlane wrappers. First off, we have to clip against - * the source in order to make the minimal number of copies in case of slow - * systems. Also the exposure handling is quite tricky. Special attention - * is to be given to the way the copies are sequenced. The list of boxes after - * the source clip is used to build a workqueue, that contains the atomic - * copies (i.e. only from one bank to one bank). Doing so produces a minimal - * list of things to do. - */ -static RegionPtr -miBankCopy( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, - int srcy, - int w, - int h, - int dstx, - int dsty, - unsigned long plane, - Bool SinglePlane -) -{ - int cx1, cy1, cx2, cy2; - int ns, nd, nse, nde, dx, dy, xorg = 0, yorg = 0; - int maxWidth = 0, maxHeight = 0, paddedWidth = 0; - int nBox, nBoxClipSrc, nBoxClipDst, nQueue; - BoxPtr pBox, pBoxClipSrc, pBoxClipDst; - BoxRec fastBox, ccBox; - RegionPtr ret = NULL, prgnSrcClip = NULL; - RegionRec rgnDst; - char *pImage = NULL; - miBankQueue *pQueue, *pQueueNew, *Queue; - miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase; - Bool fastBlit, freeSrcClip, fastClip; - Bool fExpose = FALSE, fastExpose = FALSE; - - GCOP_INIT; - SCREEN_SAVE; - - if (!IS_BANKED(pSrc) && !IS_BANKED(pDst)) - { - GCOP_UNWRAP; - - if (SinglePlane) - ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, - srcx, srcy, w, h, dstx, dsty, plane); - else - ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, - srcx, srcy, w, h, dstx, dsty); - - GCOP_WRAP; - } - else if (!IS_BANKED(pDst)) - { - fExpose = pGC->fExpose; - pGC->fExpose = FALSE; - - xorg = pSrc->x; - yorg = pSrc->y; - dx = dstx - srcx; - dy = dsty - srcy; - srcx += xorg; - srcy += yorg; - - ns = FirstBankOf(srcx, srcy); - nse = LastBankOf(srcx + w, srcy + h); - for (; ns <= nse; ns++) - { - if (!pScreenPriv->pBanks[ns]) - continue; - - nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]); - pBox = REGION_RECTS(pScreenPriv->pBanks[ns]); - - for (; nBox--; pBox++) - { - cx1 = max(pBox->x1, srcx); - cy1 = max(pBox->y1, srcy); - cx2 = min(pBox->x2, srcx + w); - cy2 = min(pBox->y2, srcy + h); - - if ((cx1 >= cx2) || (cy1 >= cy2)) - continue; - - GCOP_UNWRAP; - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns); - - if (SinglePlane) - (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, - cx1 - xorg, cy1 - yorg, - cx2 - cx1, cy2 - cy1, - cx1 + dx - xorg, cy1 + dy - yorg, plane); - else - (*pGC->ops->CopyArea)(pSrc, pDst, pGC, - cx1 - xorg, cy1 - yorg, - cx2 - cx1, cy2 - cy1, - cx1 + dx - xorg, cy1 + dy - yorg); - - GCOP_WRAP; - } - } - - pGC->fExpose = fExpose; - srcx -= xorg; - srcy -= yorg; - } - else if (!IS_BANKED(pSrc)) - { - CLIP_SAVE; - - if (pGC->miTranslate) - { - xorg = pDst->x; - yorg = pDst->y; - } - dx = srcx - dstx; - dy = srcy - dsty; - dstx += xorg; - dsty += yorg; - - nd = FirstBankOf(dstx, dsty); - nde = LastBankOf(dstx + w, dsty + h); - for (; nd <= nde; nd++) - { - if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd])) - continue; - - /* - * It's faster to let the lower-level CopyArea do the clipping - * within each bank. - */ - nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]); - pBox = REGION_RECTS(pScreenPriv->pBanks[nd]); - - for (; nBox--; pBox++) - { - cx1 = max(pBox->x1, dstx); - cy1 = max(pBox->y1, dsty); - cx2 = min(pBox->x2, dstx + w); - cy2 = min(pBox->y2, dsty + h); - - if ((cx1 >= cx2) || (cy1 >= cy2)) - continue; - - GCOP_UNWRAP; - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd); - - if (SinglePlane) - (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, - cx1 + dx - xorg, cy1 + dy - yorg, - cx2 - cx1, cy2 - cy1, - cx1 - xorg, cy1 - yorg, plane); - else - (*pGC->ops->CopyArea)(pSrc, pDst, pGC, - cx1 + dx - xorg, cy1 + dy - yorg, - cx2 - cx1, cy2 - cy1, - cx1 - xorg, cy1 - yorg); - - GCOP_WRAP; - } - } - - CLIP_RESTORE; - } - else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */ - { - CLIP_SAVE; - - fExpose = pGC->fExpose; - - fastBox.x1 = srcx + pSrc->x; - fastBox.y1 = srcy + pSrc->y; - fastBox.x2 = fastBox.x1 + w; - fastBox.y2 = fastBox.y1 + h; - - dx = dstx - fastBox.x1; - dy = dsty - fastBox.y1; - if (pGC->miTranslate) - { - xorg = pDst->x; - yorg = pDst->y; - } - - /* - * Clip against the source. Otherwise we will blit too much for SINGLE - * and SHARED banked systems. - */ - freeSrcClip = FALSE; - fastClip = FALSE; - fastExpose = FALSE; - - if (pGC->subWindowMode != IncludeInferiors) - prgnSrcClip = &((WindowPtr)pSrc)->clipList; - else if (!((WindowPtr)pSrc)->parent) - fastClip = TRUE; - else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE)) - prgnSrcClip = pGC->pCompositeClip; - else - { - prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc); - freeSrcClip = TRUE; - } - - if (fastClip) - { - fastExpose = TRUE; - - /* - * Clip the source. If regions extend beyond the source size, make - * sure exposure events get sent. - */ - if (fastBox.x1 < pSrc->x) - { - fastBox.x1 = pSrc->x; - fastExpose = FALSE; - } - if (fastBox.y1 < pSrc->y) - { - fastBox.y1 = pSrc->y; - fastExpose = FALSE; - } - if (fastBox.x2 > pSrc->x + (int) pSrc->width) - { - fastBox.x2 = pSrc->x + (int) pSrc->width; - fastExpose = FALSE; - } - if (fastBox.y2 > pSrc->y + (int) pSrc->height) - { - fastBox.y2 = pSrc->y + (int) pSrc->height; - fastExpose = FALSE; - } - - nBox = 1; - pBox = &fastBox; - } - else - { - REGION_INIT(pScreen, &rgnDst, &fastBox, 1); - REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrcClip); - pBox = REGION_RECTS(&rgnDst); - nBox = REGION_NUM_RECTS(&rgnDst); - } - - /* - * fastBlit can only be TRUE if we don't need to worry about attempts - * to read partial pixels through the destination bank. - */ - if (SinglePlane) - fastBlit = pGCPriv->fastPlane; - else - fastBlit = pGCPriv->fastCopy; - - nQueue = nBox * pScreenPriv->maxRects * 2; - pQueue = Queue = xalloc_ARRAY(miBankQueue, nQueue); - - if (Queue) - { - for (; nBox--; pBox++) - { - ns = FirstBankOf(pBox->x1, pBox->y1); - nse = LastBankOf(pBox->x2, pBox->y2); - for (; ns <= nse; ns++) - { - if (!pScreenPriv->pBanks[ns]) - continue; - - nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]); - pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]); - - for (; nBoxClipSrc--; pBoxClipSrc++) - { - cx1 = max(pBox->x1, pBoxClipSrc->x1); - cy1 = max(pBox->y1, pBoxClipSrc->y1); - cx2 = min(pBox->x2, pBoxClipSrc->x2); - cy2 = min(pBox->y2, pBoxClipSrc->y2); - - /* Check to see if the region is empty */ - if ((cx1 >= cx2) || (cy1 >= cy2)) - continue; - - /* Translate c[xy]* to destination coordinates */ - cx1 += dx + xorg; - cy1 += dy + yorg; - cx2 += dx + xorg; - cy2 += dy + yorg; - - nd = FirstBankOf(cx1, cy1); - nde = LastBankOf(cx2, cy2); - for (; nd <= nde; nd++) - { - if (!pGCPriv->pBankedClips[nd]) - continue; - - /* - * Clients can send quite large clip descriptions, - * so use the bank clips here instead. - */ - nBoxClipDst = - REGION_NUM_RECTS(pScreenPriv->pBanks[nd]); - pBoxClipDst = - REGION_RECTS(pScreenPriv->pBanks[nd]); - - for (; nBoxClipDst--; pBoxClipDst++) - { - ccBox.x1 = max(cx1, pBoxClipDst->x1); - ccBox.y1 = max(cy1, pBoxClipDst->y1); - ccBox.x2 = min(cx2, pBoxClipDst->x2); - ccBox.y2 = min(cy2, pBoxClipDst->y2); - - /* Check to see if the region is empty */ - if ((ccBox.x1 >= ccBox.x2) || - (ccBox.y1 >= ccBox.y2)) - continue; - - pQueue->srcBankNo = ns; - pQueue->dstBankNo = nd; - pQueue->x = ccBox.x1 - xorg; - pQueue->y = ccBox.y1 - yorg; - pQueue->w = ccBox.x2 - ccBox.x1; - pQueue->h = ccBox.y2 - ccBox.y1; - - if (maxWidth < pQueue->w) - maxWidth = pQueue->w; - if (maxHeight < pQueue->h) - maxHeight = pQueue->h; - - /* - * When shared banking is used and the source - * and destination banks differ, prevent - * attempts to fetch partial scanline pad units - * through the destination bank. - */ - pQueue->fastBlit = fastBlit; - if (fastBlit && - (pScreenPriv->type == BANK_SHARED) && - (ns != nd) && - ((ccBox.x1 % - pScreenPriv->nPixelsPerScanlinePadUnit) || - (ccBox.x2 % - pScreenPriv->nPixelsPerScanlinePadUnit) || - (RECT_IN_REGION(pScreen, - pGCPriv->pBankedClips[nd], &ccBox) != - rgnIN))) - pQueue->fastBlit = FALSE; - pQueue++; - } - } - } - } - } - } - - if (!fastClip) - { - REGION_UNINIT(pScreen, &rgnDst); - if (freeSrcClip) - REGION_DESTROY(pScreen, prgnSrcClip); - } - - pQueueNew = pQueue; - nQueue = pQueue - Queue; - - if (nQueue > 0) - { - BANK_SAVE; - - pQueue = Queue; - - if ((nQueue > 1) && - ((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors))) - { - if ((srcy + pSrc->y) < (dsty + yorg)) - { - /* Sort from bottom to top */ - pQueueBase = pQueueNext = pQueue + nQueue - 1; - - while (pQueueBase >= pQueue) - { - while ((pQueueNext >= pQueue) && - (pQueueBase->y == pQueueNext->y)) - pQueueNext--; - - pQueueTmp = pQueueNext + 1; - while (pQueueTmp <= pQueueBase) - *pQueueNew++ = *pQueueTmp++; - - pQueueBase = pQueueNext; - } - - pQueueNew -= nQueue; - pQueue = pQueueNew; - pQueueNew = Queue; - } - - if ((srcx + pSrc->x) < (dstx + xorg)) - { - /* Sort from right to left */ - pQueueBase = pQueueNext = pQueue; - - while (pQueueBase < pQueue + nQueue) - { - while ((pQueueNext < pQueue + nQueue) && - (pQueueNext->y == pQueueBase->y)) - pQueueNext++; - - pQueueTmp = pQueueNext; - while (pQueueTmp != pQueueBase) - *pQueueNew++ = *--pQueueTmp; - - pQueueBase = pQueueNext; - } - - pQueueNew -= nQueue; - pQueue = pQueueNew; - } - } - - paddedWidth = PixmapBytePad(maxWidth, - pScreenPriv->pScreenPixmap->drawable.depth); - pImage = xalloc(paddedWidth * maxHeight); - - pGC->fExpose = FALSE; - - while (nQueue--) - { - pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo]; - - GCOP_UNWRAP; - - if (pQueue->srcBankNo == pQueue->dstBankNo) - { - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, - -1, -1, pQueue->srcBankNo); - - if (SinglePlane) - (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, - pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y, - pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane); - else - (*pGC->ops->CopyArea)(pSrc, pDst, pGC, - pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y, - pQueue->w, pQueue->h, pQueue->x, pQueue->y); - } - else if (pQueue->fastBlit) - { - SET_SOURCE_BANK (pScreenPriv->pBankPixmap, - pScreenPriv->pScreenPixmap->drawable.width, - pScreenPriv->pScreenPixmap->devKind, - pQueue->srcBankNo); - SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap, - -1, -1, pQueue->dstBankNo); - - if (SinglePlane) - (*pGC->ops->CopyPlane)( - (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC, - pQueue->x - dx, pQueue->y - dy, - pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane); - else - (*pGC->ops->CopyArea)( - (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC, - pQueue->x - dx, pQueue->y - dy, - pQueue->w, pQueue->h, pQueue->x, pQueue->y); - } - else if (pImage) - { - ModifyPixmap(pScreenPriv->pBankPixmap, - maxWidth, paddedWidth, pImage); - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, - -1, -1, pQueue->srcBankNo); - - (*pScreenPriv->pBankGC->ops->CopyArea)( - pSrc, (DrawablePtr)pScreenPriv->pBankPixmap, - pScreenPriv->pBankGC, - pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y, - pQueue->w, pQueue->h, 0, 0); - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, - -1, -1, pQueue->dstBankNo); - - if (SinglePlane) - (*pGC->ops->CopyPlane)( - (DrawablePtr)pScreenPriv->pBankPixmap, - pDst, pGC, 0, 0, pQueue->w, pQueue->h, - pQueue->x, pQueue->y, plane); - else - (*pGC->ops->CopyArea)( - (DrawablePtr)pScreenPriv->pBankPixmap, - pDst, pGC, 0, 0, pQueue->w, pQueue->h, - pQueue->x, pQueue->y); - } - - GCOP_WRAP; - - pQueue++; - } - - xfree(pImage); - - BANK_RESTORE; - } - - CLIP_RESTORE; - - pGC->fExpose = fExpose; - - xfree(Queue); - } - - SCREEN_RESTORE; - - if (!fExpose || fastExpose) - return ret; - - return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0); -} - -static RegionPtr -miBankCopyArea( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, - int srcy, - int w, - int h, - int dstx, - int dsty -) -{ - return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE); -} - -static RegionPtr -miBankCopyPlane( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, - int srcy, - int w, - int h, - int dstx, - int dsty, - unsigned long plane -) -{ - return - miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE); -} - -static void -miBankPolyPoint( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int nArray, - xPoint *pArray -) -{ -# define GCOP_ARGS GCOP_0D_ARGS - GCOP_COMPLEX(PolyPoint, xPoint); -# undef GCOP_ARGS -} - -static void -miBankPolylines( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int nArray, - DDXPointPtr pArray -) -{ -# define GCOP_ARGS GCOP_0D_ARGS - GCOP_COMPLEX(Polylines, DDXPointRec); -# undef GCOP_ARGS -} - -static void -miBankPolySegment( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - xSegment *pArray -) -{ -# define GCOP_ARGS GCOP_1D_ARGS - GCOP_COMPLEX(PolySegment, xSegment); -# undef GCOP_ARGS -} - -static void -miBankPolyRectangle( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - xRectangle *pArray -) -{ -# define GCOP_ARGS GCOP_1D_ARGS - GCOP_COMPLEX(PolyRectangle, xRectangle); -# undef GCOP_ARGS -} - -static void -miBankPolyArc( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - xArc *pArray -) -{ -# define GCOP_ARGS GCOP_1D_ARGS - GCOP_COMPLEX(PolyArc, xArc); -# undef GCOP_ARGS -} - -static void -miBankFillPolygon( - DrawablePtr pDrawable, - GCPtr pGC, - int shape, - int mode, - int nArray, - DDXPointRec *pArray -) -{ -# define GCOP_ARGS GCOP_2D_ARGS - GCOP_COMPLEX(FillPolygon, DDXPointRec); -# undef GCOP_ARGS -} - -static void -miBankPolyFillRect( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - xRectangle *pArray -) -{ -# define GCOP_ARGS GCOP_1D_ARGS - GCOP_COMPLEX(PolyFillRect, xRectangle); -# undef GCOP_ARGS -} - -static void -miBankPolyFillArc( - DrawablePtr pDrawable, - GCPtr pGC, - int nArray, - xArc *pArray -) -{ -# define GCOP_ARGS GCOP_1D_ARGS - GCOP_COMPLEX(PolyFillArc, xArc); -# undef GCOP_ARGS -} - -static int -miBankPolyText8( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - int nArray, - char *pchar -) -{ - int retval = x; - - GCOP_SIMPLE(retval = - (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar)); - - return retval; -} - -static int -miBankPolyText16( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - int nArray, - unsigned short *pchar -) -{ - int retval = x; - - GCOP_SIMPLE(retval = - (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar)); - - return retval; -} - -static void -miBankImageText8( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - int nArray, - char *pchar -) -{ - GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar)); -} - -static void -miBankImageText16( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - int nArray, - unsigned short *pchar -) -{ - GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar)); -} - -static void -miBankImageGlyphBlt( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - unsigned int nArray, - CharInfoPtr *ppci, - pointer pglyphBase -) -{ - GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, - x, y, nArray, ppci, pglyphBase)); -} - -static void -miBankPolyGlyphBlt( - DrawablePtr pDrawable, - GCPtr pGC, - int x, - int y, - unsigned int nArray, - CharInfoPtr *ppci, - pointer pglyphBase -) -{ - GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, - x, y, nArray, ppci, pglyphBase)); -} - -static void -miBankPushPixels( - GCPtr pGC, - PixmapPtr pBitmap, - DrawablePtr pDrawable, - int w, - int h, - int x, - int y -) -{ - if ((w > 0) && (h > 0)) - { - GCOP_INIT; - SCREEN_SAVE; - - if (!IS_BANKED(pDrawable)) - { - GCOP_UNWRAP; - - (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y); - - GCOP_WRAP; - } - else - { - int i, j; - - CLIP_SAVE; - - i = FirstBankOf(x, y); - j = LastBankOf(x + w, y + h); - for (; i <= j; i++) - { - if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) - continue; - - GCOP_UNWRAP; - - SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i); - - (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y); - - GCOP_WRAP; - } - - CLIP_RESTORE; - } - - SCREEN_RESTORE; - } -} - -static GCOps miBankGCOps = -{ - miBankFillSpans, - miBankSetSpans, - miBankPutImage, - miBankCopyArea, - miBankCopyPlane, - miBankPolyPoint, - miBankPolylines, - miBankPolySegment, - miBankPolyRectangle, - miBankPolyArc, - miBankFillPolygon, - miBankPolyFillRect, - miBankPolyFillArc, - miBankPolyText8, - miBankPolyText16, - miBankImageText8, - miBankImageText16, - miBankImageGlyphBlt, - miBankPolyGlyphBlt, - miBankPushPixels, - {NULL} /* devPrivate */ -}; - -/******************** - * GCFuncs wrappers * - ********************/ - -static void -miBankValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDrawable -) -{ - GC_INIT(pGC); - GC_UNWRAP(pGC); - - (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); - - if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || - (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) - { - ScreenPtr pScreen = pGC->pScreen; - RegionPtr prgnClip; - unsigned long planemask; - int i; - - SCREEN_INIT; - SCREEN_SAVE; - - if (IS_BANKED(pDrawable)) - { - for (i = 0; i < pScreenPriv->nBanks; i++) - { - if (!pScreenPriv->pBanks[i]) - continue; - - if (!(prgnClip = pGCPriv->pBankedClips[i])) - prgnClip = REGION_CREATE(pScreen, NULL, 1); - - REGION_INTERSECT(pScreen, prgnClip, - pScreenPriv->pBanks[i], pGC->pCompositeClip); - - if ((REGION_NUM_RECTS(prgnClip) <= 1) && - ((prgnClip->extents.x1 == prgnClip->extents.x2) || - (prgnClip->extents.y1 == prgnClip->extents.y2))) - { - REGION_DESTROY(pScreen, prgnClip); - pGCPriv->pBankedClips[i] = NULL; - } - else - pGCPriv->pBankedClips[i] = prgnClip; - } - - /* - * fastCopy and fastPlane can only be TRUE if we don't need to - * worry about attempts to read partial pixels through the - * destination bank. - */ - switch (pScreenPriv->type) - { - case BANK_SHARED: - pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE; - - if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) && - (pGC->alu != GXcopyInverted) && (pGC->alu != GXset)) - break; - - if (pScreen->rootDepth == 1) - pGCPriv->fastPlane = TRUE; - - /* This is probably paranoia */ - if ((pDrawable->depth != pScreen->rootDepth) || - (pDrawable->depth != pGC->depth)) - break; - - planemask = (1 << pGC->depth) - 1; - if ((pGC->planemask & planemask) == planemask) - pGCPriv->fastCopy = TRUE; - - break; - - case BANK_DOUBLE: - pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE; - break; - - default: - pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE; - break; - } - } - else - { - /* - * Here we are on a pixmap and don't need all that special clipping - * stuff, hence free it. - */ - for (i = 0; i < pScreenPriv->nBanks; i++) - { - if (!pGCPriv->pBankedClips[i]) - continue; - - REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]); - pGCPriv->pBankedClips[i] = NULL; - } - } - - SCREEN_RESTORE; - } - - GC_WRAP(pGC); -} - -static void -miBankChangeGC( - GCPtr pGC, - unsigned long mask -) -{ - GC_INIT(pGC); - GC_UNWRAP(pGC); - - (*pGC->funcs->ChangeGC)(pGC, mask); - - GC_WRAP(pGC); -} - -static void -miBankCopyGC( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -) -{ - GC_INIT(pGCDst); - GC_UNWRAP(pGCDst); - - (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst); - - GC_WRAP(pGCDst); -} - -static void -miBankDestroyGC( - GCPtr pGC -) -{ - ScreenPtr pScreen = pGC->pScreen; - int i; - - SCREEN_INIT; - GC_INIT(pGC); - GC_UNWRAP(pGC); - - (*pGC->funcs->DestroyGC)(pGC); - - for (i = 0; i < pScreenPriv->nBanks; i++) - { - if (!pGCPriv->pBankedClips[i]) - continue; - - REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]); - pGCPriv->pBankedClips[i] = NULL; - } - - GC_WRAP(pGC); -} - -static void -miBankChangeClip( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -) -{ - GC_INIT(pGC); - GC_UNWRAP(pGC); - - (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects); - - GC_WRAP(pGC); -} - -static void -miBankDestroyClip( - GCPtr pGC -) -{ - GC_INIT(pGC); - GC_UNWRAP(pGC); - - (*pGC->funcs->DestroyClip)(pGC); - - GC_WRAP(pGC); -} - -static void -miBankCopyClip( - GCPtr pGCDst, - GCPtr pGCSrc -) -{ - GC_INIT(pGCDst); - GC_UNWRAP(pGCDst); - - (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc); - - GC_WRAP(pGCDst); -} - -static GCFuncs miBankGCFuncs = -{ - miBankValidateGC, - miBankChangeGC, - miBankCopyGC, - miBankDestroyGC, - miBankChangeClip, - miBankDestroyClip, - miBankCopyClip -}; - -/******************* - * Screen Wrappers * - *******************/ - -static Bool -miBankCreateScreenResources( - ScreenPtr pScreen -) -{ - Bool retval; - - SCREEN_INIT; - SCREEN_UNWRAP(CreateScreenResources); - - if ((retval = (*pScreen->CreateScreenResources)(pScreen))) - { - /* Set screen buffer address to something recognizable */ - pScreenPriv->pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen); - pScreenPriv->pbits = pScreenPriv->pScreenPixmap->devPrivate.ptr; - pScreenPriv->pScreenPixmap->devPrivate.ptr = (pointer)pScreenPriv; - - /* Get shadow pixmap; width & height of 0 means no pixmap data */ - pScreenPriv->pBankPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, - pScreenPriv->pScreenPixmap->drawable.depth, 0); - if (!pScreenPriv->pBankPixmap) - retval = FALSE; - } - - /* Shadow the screen */ - if (retval) - retval = (*pScreen->ModifyPixmapHeader)(pScreenPriv->pBankPixmap, - pScreenPriv->pScreenPixmap->drawable.width, - pScreenPriv->pScreenPixmap->drawable.height, - pScreenPriv->pScreenPixmap->drawable.depth, - pScreenPriv->pScreenPixmap->drawable.bitsPerPixel, - pScreenPriv->pScreenPixmap->devKind, NULL); - - /* Create shadow GC */ - if (retval) - { - pScreenPriv->pBankGC = CreateScratchGC(pScreen, - pScreenPriv->pBankPixmap->drawable.depth); - if (!pScreenPriv->pBankGC) - retval = FALSE; - } - - /* Validate shadow GC */ - if (retval) - { - pScreenPriv->pBankGC->graphicsExposures = FALSE; - pScreenPriv->pBankGC->subWindowMode = IncludeInferiors; - ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap, - pScreenPriv->pBankGC); - } - - SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources); - - return retval; -} - -static Bool -miBankModifyPixmapHeader( - PixmapPtr pPixmap, - int width, - int height, - int depth, - int bitsPerPixel, - int devKind, - pointer pPixData -) -{ - Bool retval = FALSE; - - if (pPixmap) - { - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - SCREEN_INIT; - PIXMAP_SAVE(pPixmap); - SCREEN_UNWRAP(ModifyPixmapHeader); - - retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height, - depth, bitsPerPixel, devKind, pPixData); - - SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader); - - if (pbits == (pointer)pScreenPriv) - { - pScreenPriv->pbits = pPixmap->devPrivate.ptr; - pPixmap->devPrivate.ptr = pbits; - } - } - - return retval; -} - -static Bool -miBankCloseScreen( - int nIndex, - ScreenPtr pScreen -) -{ - int i; - - SCREEN_INIT; - - /* Free shadow GC */ - FreeScratchGC(pScreenPriv->pBankGC); - - /* Free shadow pixmap */ - (*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap); - - /* Restore screen pixmap devPrivate pointer */ - pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits; - - /* Delete bank clips */ - for (i = 0; i < pScreenPriv->nBanks; i++) - if (pScreenPriv->pBanks[i]) - REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]); - - Xfree(pScreenPriv->pBanks); - - SCREEN_UNWRAP(CreateScreenResources); - SCREEN_UNWRAP(ModifyPixmapHeader); - SCREEN_UNWRAP(CloseScreen); - SCREEN_UNWRAP(GetImage); - SCREEN_UNWRAP(GetSpans); - SCREEN_UNWRAP(CreateGC); - SCREEN_UNWRAP(CopyWindow); - - Xfree(pScreenPriv); - return (*pScreen->CloseScreen)(nIndex, pScreen); -} - -static void -miBankGetImage( - DrawablePtr pDrawable, - int sx, - int sy, - int w, - int h, - unsigned int format, - unsigned long planemask, - char *pImage -) -{ - if ((w > 0) && (h > 0)) - { - ScreenPtr pScreen = pDrawable->pScreen; - - SCREEN_INIT; - SCREEN_STATUS; - SCREEN_UNWRAP(GetImage); - - if (!IS_BANKED(pDrawable)) - { - (*pScreen->GetImage)(pDrawable, sx, sy, w, h, - format, planemask, pImage); - } - else - { - int paddedWidth; - char *pBankImage; - - paddedWidth = PixmapBytePad(w, - pScreenPriv->pScreenPixmap->drawable.depth); - pBankImage = xalloc(paddedWidth * h); - - if (pBankImage) - { - BANK_SAVE; - - ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth, - pBankImage); - - (*pScreenPriv->pBankGC->ops->CopyArea)( - (DrawablePtr)WindowTable[pScreen->myNum], - (DrawablePtr)pScreenPriv->pBankPixmap, - pScreenPriv->pBankGC, - sx + pDrawable->x, sy + pDrawable->y, w, h, 0, 0); - - (*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap, - 0, 0, w, h, format, planemask, pImage); - - BANK_RESTORE; - - xfree(pBankImage); - } - } - - SCREEN_WRAP(GetImage, miBankGetImage); - } -} - -static void -miBankGetSpans( - DrawablePtr pDrawable, - int wMax, - DDXPointPtr ppt, - int *pwidth, - int nspans, - char *pImage -) -{ - if (nspans > 0) - { - ScreenPtr pScreen = pDrawable->pScreen; - - SCREEN_INIT; - SCREEN_STATUS; - SCREEN_UNWRAP(GetSpans); - - if (!IS_BANKED(pDrawable)) - { - (*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage); - } - else - { - char *pBankImage; - int paddedWidth; - DDXPointRec pt; - - pt.x = pt.y = 0; - - paddedWidth = - PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width, - pScreenPriv->pScreenPixmap->drawable.depth); - pBankImage = xalloc(paddedWidth); - - if (pBankImage) - { - BANK_SAVE; - - ModifyPixmap(pScreenPriv->pBankPixmap, - pScreenPriv->pScreenPixmap->drawable.width, - paddedWidth, pBankImage); - - for (; nspans--; ppt++, pwidth++) - { - if (*pwidth <= 0) - continue; - - (*pScreenPriv->pBankGC->ops->CopyArea)( - (DrawablePtr)WindowTable[pScreen->myNum], - (DrawablePtr)pScreenPriv->pBankPixmap, - pScreenPriv->pBankGC, - ppt->x, ppt->y, *pwidth, 1, 0, 0); - - (*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap, - wMax, &pt, pwidth, 1, pImage); - - pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth); - } - - BANK_RESTORE; - - xfree(pBankImage); - } - } - - SCREEN_WRAP(GetSpans, miBankGetSpans); - } -} - -static Bool -miBankCreateGC( - GCPtr pGC -) -{ - ScreenPtr pScreen = pGC->pScreen; - miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC); - Bool ret; - - SCREEN_INIT; - SCREEN_UNWRAP(CreateGC); - - if ((ret = (*pScreen->CreateGC)(pGC))) - { - pGCPriv->unwrappedOps = &miBankGCOps; - pGCPriv->unwrappedFuncs = &miBankGCFuncs; - GC_WRAP(pGC); - - memset(&pGCPriv->pBankedClips, 0, - pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips)); - } - - SCREEN_WRAP(CreateGC, miBankCreateGC); - - return ret; -} - -static void -miBankCopyWindow( - WindowPtr pWindow, - DDXPointRec ptOldOrg, - RegionPtr pRgnSrc -) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - GCPtr pGC; - int dx, dy, nBox; - DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum]; - RegionPtr pRgnDst; - BoxPtr pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2; - XID subWindowMode = IncludeInferiors; - - pGC = GetScratchGC(pDrawable->depth, pScreen); - - ChangeGC(pGC, GCSubwindowMode, &subWindowMode); - ValidateGC(pDrawable, pGC); - - pRgnDst = REGION_CREATE(pScreen, NULL, 1); - - dx = ptOldOrg.x - pWindow->drawable.x; - dy = ptOldOrg.y - pWindow->drawable.y; - REGION_TRANSLATE(pScreen, pRgnSrc, -dx, -dy); - REGION_INTERSECT(pScreen, pRgnDst, &pWindow->borderClip, pRgnSrc); - - pBox = REGION_RECTS(pRgnDst); - nBox = REGION_NUM_RECTS(pRgnDst); - - pBoxNew1 = NULL; - pBoxNew2 = NULL; - - if (nBox > 1) - { - if (dy < 0) - { - /* Sort boxes from bottom to top */ - pBoxNew1 = xalloc_ARRAY(BoxRec, nBox); - - if (pBoxNew1) - { - pBoxBase = pBoxNext = pBox + nBox - 1; - - while (pBoxBase >= pBox) - { - while ((pBoxNext >= pBox) && - (pBoxBase->y1 == pBoxNext->y1)) - pBoxNext--; - - pBoxTmp = pBoxNext + 1; - - while (pBoxTmp <= pBoxBase) - *pBoxNew1++ = *pBoxTmp++; - - pBoxBase = pBoxNext; - } - - pBoxNew1 -= nBox; - pBox = pBoxNew1; - } - } - - if (dx < 0) - { - /* Sort boxes from right to left */ - pBoxNew2 = xalloc_ARRAY(BoxRec, nBox); - - if (pBoxNew2) - { - pBoxBase = pBoxNext = pBox; - - while (pBoxBase < pBox + nBox) - { - while ((pBoxNext < pBox + nBox) && - (pBoxNext->y1 == pBoxBase->y1)) - pBoxNext++; - - pBoxTmp = pBoxNext; - - while (pBoxTmp != pBoxBase) - *pBoxNew2++ = *--pBoxTmp; - - pBoxBase = pBoxNext; - } - - pBoxNew2 -= nBox; - pBox = pBoxNew2; - } - } - } - - while (nBox--) - { - (*pGC->ops->CopyArea)(pDrawable, pDrawable, pGC, - pBox->x1 + dx, pBox->y1 + dy, - pBox->x2 - pBox->x1, pBox->y2 - pBox->y1, - pBox->x1, pBox->y1); - - pBox++; - } - - FreeScratchGC(pGC); - - REGION_DESTROY(pScreen, pRgnDst); - - xfree(pBoxNew2); - xfree(pBoxNew1); -} - -Bool -miInitializeBanking( - ScreenPtr pScreen, - unsigned int xsize, - unsigned int ysize, - unsigned int width, - miBankInfoPtr pBankInfo -) -{ - miBankScreenPtr pScreenPriv; - unsigned long nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit; - unsigned long BankBase, ServerPad; - unsigned int type, iBank, nBanks, maxRects, we, nBankBPP; - int i; - - if (!pBankInfo || !pBankInfo->BankSize) - return TRUE; /* No banking required */ - - /* Sanity checks */ - - if (!pScreen || !xsize || !ysize || (xsize > width) || - !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank || - !pBankInfo->SetSourceAndDestinationBanks || - !pBankInfo->pBankA || !pBankInfo->pBankB || - !pBankInfo->nBankDepth) - return FALSE; - - /* - * DDX *must* have registered a pixmap format whose depth is - * pBankInfo->nBankDepth. This is not necessarily the rootDepth - * pixmap format. - */ - i = 0; - while (screenInfo.formats[i].depth != pBankInfo->nBankDepth) - if (++i >= screenInfo.numPixmapFormats) - return FALSE; - nBankBPP = screenInfo.formats[i].bitsPerPixel; - - i = 0; - while (screenInfo.formats[i].depth != pScreen->rootDepth) - if (++i >= screenInfo.numPixmapFormats) - return FALSE; - - if (nBankBPP > screenInfo.formats[i].bitsPerPixel) - return FALSE; - - /* Determine banking type */ - if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK) - return FALSE; - - /* Internal data */ - - nBitsPerBank = pBankInfo->BankSize * 8; - ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8; - if (nBitsPerBank % ServerPad) - return FALSE; - nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8; - nBanks = ((nBitsPerScanline * (ysize - 1)) + - (nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank; - nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP; - - /* Private areas */ - - if (miBankGeneration != serverGeneration) - miBankGeneration = serverGeneration; - - if (!dixRequestPrivate(miBankGCKey, - (nBanks * sizeof(RegionPtr)) + - (sizeof(miBankGCRec) - sizeof(RegionPtr)))) - return FALSE; - - if (!(pScreenPriv = (miBankScreenPtr)Xcalloc(sizeof(miBankScreenRec)))) - return FALSE; - - if (!(pScreenPriv->pBanks = /* Allocate and clear */ - (RegionPtr *)Xcalloc(nBanks * sizeof(RegionPtr)))) - { - Xfree(pScreenPriv); - return FALSE; - } - - /* - * Translate banks into clipping regions which are themselves clipped - * against the screen. This also ensures that pixels with imbedded bank - * boundaries are off-screen. - */ - - BankBase = 0; - maxRects = 0; - we = 0; - for (iBank = 0; iBank < nBanks; iBank++) - { - xRectangle pRects[3], *pRect = pRects; - unsigned int xb, yb, xe, ye; - - xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP; - yb = (BankBase + nBankBPP - 1) / nBitsPerScanline; - if (xb >= xsize) - { - xb = we = 0; - yb++; - } - if (yb >= ysize) - { - we = 0; - break; - } - - if (we) - break; - - BankBase += nBitsPerBank; - - we = (BankBase % nBitsPerScanline) % nBankBPP; - xe = (BankBase % nBitsPerScanline) / nBankBPP; - ye = BankBase / nBitsPerScanline; - if (xe >= xsize) - { - we = xe = 0; - ye++; - } - if (ye >= ysize) - { - we = xe = 0; - ye = ysize; - } - - if (yb == ye) - { - if (xb >= xe) - continue; - - pRect->x = xb; - pRect->y = yb; - pRect->width = xe - xb; - pRect->height = 1; - maxRects += 2; - pRect++; - } - else - { - if (xb) - { - pRect->x = xb; - pRect->y = yb++; - pRect->width = xsize - xb; - pRect->height = 1; - maxRects += 2; - pRect++; - } - - if (yb < ye) - { - pRect->x = 0; - pRect->y = yb; - pRect->width = xsize; - pRect->height = ye - yb; - maxRects += min(pRect->height, 3) + 1; - pRect++; - } - - if (xe) - { - pRect->x = 0; - pRect->y = ye; - pRect->width = xe; - pRect->height = 1; - maxRects += 2; - pRect++; - } - } - - pScreenPriv->pBanks[iBank] = - RECTS_TO_REGION(pScreen, pRect - pRects, pRects, 0); - if (!pScreenPriv->pBanks[iBank] || - REGION_NAR(pScreenPriv->pBanks[iBank])) - { - we = 1; - break; - } - } - - if (we && (iBank < nBanks)) - { - for (i = iBank; i >= 0; i--) - if (pScreenPriv->pBanks[i]) - REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]); - - Xfree(pScreenPriv->pBanks); - Xfree(pScreenPriv); - - return FALSE; - } - - /* Open for business */ - - pScreenPriv->type = type; - pScreenPriv->nBanks = nBanks; - pScreenPriv->maxRects = maxRects; - pScreenPriv->nBankBPP = nBankBPP; - pScreenPriv->BankInfo = *pBankInfo; - pScreenPriv->nBitsPerBank = nBitsPerBank; - pScreenPriv->nBitsPerScanline = nBitsPerScanline; - pScreenPriv->nPixelsPerScanlinePadUnit = nPixelsPerScanlinePadUnit; - - SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources); - SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader); - SCREEN_WRAP(CloseScreen, miBankCloseScreen); - SCREEN_WRAP(GetImage, miBankGetImage); - SCREEN_WRAP(GetSpans, miBankGetSpans); - SCREEN_WRAP(CreateGC, miBankCreateGC); - SCREEN_WRAP(CopyWindow, miBankCopyWindow); - - dixSetPrivate(&pScreen->devPrivates, miBankScreenKey, pScreenPriv); - - return TRUE; -} - -/* - * Given various screen attributes, determine the minimum scanline width such - * that each scanline is server and DDX padded and any pixels with imbedded - * bank boundaries are off-screen. This function returns -1 if such a width - * cannot exist. This function exists because the DDX needs to be able to - * determine this width before initializing a frame buffer. - */ -int -miScanLineWidth( - unsigned int xsize, /* pixels */ - unsigned int ysize, /* pixels */ - unsigned int width, /* pixels */ - unsigned long BankSize, /* char's */ - PixmapFormatRec *pBankFormat, - unsigned int nWidthUnit /* bits */ -) -{ - unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit; - unsigned long minBitsPerScanline, maxBitsPerScanline; - - /* Sanity checks */ - - if (!nWidthUnit || !pBankFormat) - return -1; - - nBitsPerBank = BankSize * 8; - if (nBitsPerBank % pBankFormat->scanlinePad) - return -1; - - if (xsize > width) - width = xsize; - nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit); - nBitsPerScanline = - (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) / - nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit; - width = nBitsPerScanline / pBankFormat->bitsPerPixel; - - if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel)) - return (int)width; - - /* - * Scanlines will be server-pad aligned at this point. They will also be - * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded - * bank boundaries are off-screen. - * - * It seems reasonable to limit total frame buffer size to 1/16 of the - * theoretical maximum address space size. On a machine with 32-bit - * addresses (to 8-bit quantities) this turns out to be 256MB. Not only - * does this provide a simple limiting condition for the loops below, but - * it also prevents unsigned long wraparounds. - */ - if (!ysize) - return -1; - - minBitsPerScanline = xsize * pBankFormat->bitsPerPixel; - if (minBitsPerScanline > nBitsPerBank) - return -1; - - if (ysize == 1) - return (int)width; - - maxBitsPerScanline = - (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1); - while (nBitsPerScanline <= maxBitsPerScanline) - { - unsigned long BankBase, BankUnit; - - BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) * - nBitsPerBank; - if (!(BankUnit % nBitsPerScanline)) - return (int)width; - - for (BankBase = BankUnit; ; BankBase += nBitsPerBank) - { - unsigned long x, y; - - y = BankBase / nBitsPerScanline; - if (y >= ysize) - return (int)width; - - x = BankBase % nBitsPerScanline; - if (!(x % pBankFormat->bitsPerPixel)) - continue; - - if (x < minBitsPerScanline) - { - /* - * Skip ahead certain widths by dividing the excess scanline - * amongst the y's. - */ - y *= nBitsPerScanlinePadUnit; - nBitsPerScanline += - ((x + y - 1) / y) * nBitsPerScanlinePadUnit; - width = nBitsPerScanline / pBankFormat->bitsPerPixel; - break; - } - - if (BankBase != BankUnit) - continue; - - if (!(nBitsPerScanline % x)) - return (int)width; - - BankBase = ((nBitsPerScanline - minBitsPerScanline) / - (nBitsPerScanline - x)) * BankUnit; - } - } - - return -1; -} |