2
* Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
4
* Permission to use, copy, modify, distribute, and sell this software and its
5
* documentation for any purpose is hereby granted without fee, provided that
6
* the above copyright notice appear in all copies and that both that copyright
7
* notice and this permission notice appear in supporting documentation, and
8
* that the name of Marc Aurele La France not be used in advertising or
9
* publicity pertaining to distribution of the software without specific,
10
* written prior permission. Marc Aurele La France makes no representations
11
* about the suitability of this software for any purpose. It is provided
12
* "as-is" without express or implied warranty.
14
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
16
* EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20
* PERFORMANCE OF THIS SOFTWARE.
24
* Copyright 1990,91,92,93 by Thomas Roell, Germany.
25
* Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
27
* Permission to use, copy, modify, distribute, and sell this software
28
* and its documentation for any purpose is hereby granted without fee,
29
* provided that the above copyright notice appear in all copies and
30
* that both that copyright notice and this permission notice appear
31
* in supporting documentation, and that the name of Thomas Roell nor
32
* SGCS be used in advertising or publicity pertaining to distribution
33
* of the software without specific, written prior permission.
34
* Thomas Roell nor SGCS makes no representations about the suitability
35
* of this software for any purpose. It is provided "as is" without
36
* express or implied warranty.
38
* THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
39
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
40
* FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
41
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
42
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
43
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
44
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47
/* $XFree86: xc/programs/Xserver/mi/mibank.c,v 1.15 2003/11/10 18:39:16 tsi Exp $ */
50
* This thing originated from an idea of Edwin Goei and his bank switching
51
* code for the DEC TX board.
55
* Heavily modified for the XFree86 Project to turn this into an mi wrapper.
56
* --- Marc Aurele La France (tsi@xfree86.org)
60
* "Heavily modified", indeed! By the time this is finalized, there probably
61
* won't be much left of Roell's code...
63
* Miscellaneous notes:
64
* - Pixels with imbedded bank boundaries are required to be off-screen. There
65
* >might< be a way to fool the underlying framebuffer into dealing with
67
* - Plans to generalise this to do (hardware) colour plane switching have been
68
* dropped due to colour flashing concerns.
71
* - Allow miModifyBanking() to change BankSize and nBankDepth.
72
* - Re-instate shared and double banking for framebuffers whose pixmap formats
73
* don't describe how the server "sees" the screen.
74
* - Remove remaining assumptions that a pixmap's devPrivate field points
75
* directly to its pixel data.
78
/* #define NO_ALLOCA 1 */
80
#ifdef HAVE_DIX_CONFIG_H
81
#include <dix-config.h>
86
#include "pixmapstr.h"
87
#include "scrnintstr.h"
88
#include "windowstr.h"
97
typedef struct _miBankScreen
99
miBankInfoRec BankInfo;
100
unsigned int nBankBPP;
103
unsigned long nBitsPerBank;
104
unsigned long nBitsPerScanline;
105
unsigned long nPixelsPerScanlinePadUnit;
107
PixmapPtr pScreenPixmap;
108
PixmapPtr pBankPixmap;
111
int nBanks, maxRects;
119
CreateScreenResourcesProcPtr CreateScreenResources;
120
ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
121
CloseScreenProcPtr CloseScreen;
122
GetImageProcPtr GetImage;
123
GetSpansProcPtr GetSpans;
124
CreateGCProcPtr CreateGC;
125
PaintWindowBackgroundProcPtr PaintWindowBackground;
126
PaintWindowBorderProcPtr PaintWindowBorder;
127
CopyWindowProcPtr CopyWindow;
128
BSFuncRec BackingStoreFuncs;
129
} miBankScreenRec, *miBankScreenPtr;
131
typedef struct _miBankGC
133
GCOps *wrappedOps, *unwrappedOps;
134
GCFuncs *wrappedFuncs, *unwrappedFuncs;
136
Bool fastCopy, fastPlane;
138
RegionPtr pBankedClips[1];
139
} miBankGCRec, *miBankGCPtr;
141
typedef struct _miBankQueue
144
unsigned short srcBankNo;
145
unsigned short dstBankNo;
153
* CAVEAT: This banking scheme requires that the DDX store Pixmap data in the
154
* server's address space.
157
#define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
158
(*pScreen->ModifyPixmapHeader)((_pPix), \
159
(_width), -1, -1, -1, (_devKind), (_pbits))
161
#define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \
162
ModifyPixmap(_pPix, _width, _devKind, \
163
(char *)pScreenPriv->BankInfo.pBankA + \
164
(*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \
165
(pScreenPriv->BankInfo.BankSize * (_no)))
167
#define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \
168
ModifyPixmap(_pPix, _width, _devKind, \
169
(char *)pScreenPriv->BankInfo.pBankA + \
170
(*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \
171
(pScreenPriv->BankInfo.BankSize * (_no)))
173
#define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \
174
ModifyPixmap(_pPix, _width, _devKind, \
175
(char *)pScreenPriv->BankInfo.pBankB + \
176
(*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \
177
(pScreenPriv->BankInfo.BankSize * (_no)))
179
#define ALLOCATE_LOCAL_ARRAY(atype, ntype) \
180
(atype *)ALLOCATE_LOCAL((ntype) * sizeof(atype))
182
static int miBankScreenIndex;
183
static int miBankGCIndex;
184
static unsigned long miBankGeneration = 0;
186
#define BANK_SCRPRIVLVAL pScreen->devPrivates[miBankScreenIndex].ptr
188
#define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
190
#define BANK_GCPRIVLVAL(pGC) (pGC)->devPrivates[miBankGCIndex].ptr
192
#define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
194
#define PIXMAP_STATUS(_pPix) \
195
pointer pbits = (_pPix)->devPrivate.ptr
197
#define PIXMAP_SAVE(_pPix) \
198
PIXMAP_STATUS(_pPix); \
199
if (pbits == (pointer)pScreenPriv) \
200
(_pPix)->devPrivate.ptr = pScreenPriv->pbits
202
#define PIXMAP_RESTORE(_pPix) \
203
(_pPix)->devPrivate.ptr = pbits
206
int width = pScreenPriv->pBankPixmap->drawable.width; \
207
int devKind = pScreenPriv->pBankPixmap->devKind; \
208
PIXMAP_SAVE(pScreenPriv->pBankPixmap)
210
#define BANK_RESTORE \
211
pScreenPriv->pBankPixmap->drawable.width = width; \
212
pScreenPriv->pBankPixmap->devKind = devKind; \
213
PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
215
#define SCREEN_STATUS \
216
PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
218
#define SCREEN_SAVE \
219
PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
221
#define SCREEN_RESTORE \
222
PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
224
#define SCREEN_INIT \
225
miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
227
#define SCREEN_UNWRAP(field) \
228
pScreen->field = pScreenPriv->field
230
#define SCREEN_WRAP(field, wrapper) \
231
pScreenPriv->field = pScreen->field; \
232
pScreen->field = wrapper
234
#define GC_INIT(pGC) \
235
miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
237
#define GC_UNWRAP(pGC) \
238
pGCPriv->unwrappedOps = (pGC)->ops; \
239
pGCPriv->unwrappedFuncs = (pGC)->funcs; \
240
(pGC)->ops = pGCPriv->wrappedOps; \
241
(pGC)->funcs = pGCPriv->wrappedFuncs
243
#define GC_WRAP(pGC) \
244
pGCPriv->wrappedOps = (pGC)->ops; \
245
pGCPriv->wrappedFuncs = (pGC)->funcs; \
246
(pGC)->ops = pGCPriv->unwrappedOps; \
247
(pGC)->funcs = pGCPriv->unwrappedFuncs
249
#define IS_BANKED(pDrawable) \
250
((pbits == (pointer)pScreenPriv) && \
251
(((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
254
RegionPtr pOrigCompositeClip = pGC->pCompositeClip
256
#define CLIP_RESTORE \
257
pGC->pCompositeClip = pOrigCompositeClip
260
ScreenPtr pScreen = pGC->pScreen; \
264
#define GCOP_UNWRAP \
270
#define GCOP_TOP_PART \
271
for (i = 0; i < pScreenPriv->nBanks; i++) \
273
if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
276
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
278
#define GCOP_BOTTOM_PART \
282
#define GCOP_SIMPLE(statement) \
287
if (!IS_BANKED(pDrawable)) \
305
#define GCOP_0D_ARGS mode,
307
#define GCOP_2D_ARGS shape, mode,
309
#define GCOP_COMPLEX(aop, atype) \
314
if (!IS_BANKED(pDrawable)) \
317
(*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
322
atype *aarg = pArray, *acopy; \
325
if ((acopy = ALLOCATE_LOCAL_ARRAY(atype, nArray))) \
329
memcpy(acopy, pArray, nArray * sizeof(atype)); \
330
(*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
332
DEALLOCATE_LOCAL(acopy); \
338
/*********************
339
* Utility functions *
340
*********************/
344
miBankScreenPtr pScreenPriv,
349
int iBank = ((x * (int)pScreenPriv->nBankBPP) +
350
(y * (long)pScreenPriv->nBitsPerScanline)) /
351
(long)pScreenPriv->nBitsPerBank;
355
else if (iBank >= pScreenPriv->nBanks)
356
iBank = pScreenPriv->nBanks - 1;
361
#define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
362
#define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
364
/* Determine banking type from the BankInfoRec */
368
miBankInfoPtr pBankInfo
373
if (pBankInfo->pBankA == pBankInfo->pBankB)
375
if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
377
if (pBankInfo->SetSourceAndDestinationBanks !=
378
pBankInfo->SetSourceBank)
385
if (pBankInfo->SetSourceAndDestinationBanks ==
386
pBankInfo->SetDestinationBank)
388
if (pBankInfo->SetSourceAndDestinationBanks ==
389
pBankInfo->SetSourceBank)
397
if ((unsigned long)abs((char *)pBankInfo->pBankA -
398
(char *)pBankInfo->pBankB) < pBankInfo->BankSize)
401
if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
403
if (pBankInfo->SetSourceAndDestinationBanks !=
404
pBankInfo->SetSourceBank)
409
if (pBankInfo->SetSourceAndDestinationBanks ==
410
pBankInfo->SetDestinationBank)
418
* Internal limitation: Currently, only single banking is supported when
419
* the pixmap format and the screen's pixel format are different. The
420
* following test is only partially successful at detecting this condition.
422
if (pBankInfo->nBankDepth != pScreen->rootDepth)
428
/* Least common multiple */
435
unsigned int m = x, n = y, o;
452
DrawablePtr pDrawable,
460
GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC,
461
nArray, pptInit, pwidthInit, fSorted));
466
DrawablePtr pDrawable,
475
GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc,
476
ppt, pwidth, nArray, fSorted));
481
DrawablePtr pDrawable,
493
if ((w > 0) && (h > 0))
498
if (!IS_BANKED(pDrawable))
502
(*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
503
leftPad, format, pImage);
513
i = FirstBankOf(x + pDrawable->x, y + pDrawable->y);
514
j = LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h);
517
if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
522
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
524
(*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
525
leftPad, format, pImage);
538
* Here the CopyArea/CopyPlane wrappers. First off, we have to clip against
539
* the source in order to make the minimal number of copies in case of slow
540
* systems. Also the exposure handling is quite tricky. Special attention
541
* is to be given to the way the copies are sequenced. The list of boxes after
542
* the source clip is used to build a workqueue, that contains the atomic
543
* copies (i.e. only from one bank to one bank). Doing so produces a minimal
544
* list of things to do.
561
int cx1, cy1, cx2, cy2;
562
int ns, nd, nse, nde, dx, dy, xorg = 0, yorg = 0;
563
int maxWidth = 0, maxHeight = 0, paddedWidth = 0;
564
int nBox, nBoxClipSrc, nBoxClipDst, nQueue;
565
BoxPtr pBox, pBoxClipSrc, pBoxClipDst;
566
BoxRec fastBox, ccBox;
567
RegionPtr ret = NULL, prgnSrcClip = NULL;
570
miBankQueue *pQueue, *pQueueNew, *Queue;
571
miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase;
572
Bool fastBlit, freeSrcClip, fastClip;
573
Bool fExpose = FALSE, fastExpose = FALSE;
578
if (!IS_BANKED(pSrc) && !IS_BANKED(pDst))
583
ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
584
srcx, srcy, w, h, dstx, dsty, plane);
586
ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
587
srcx, srcy, w, h, dstx, dsty);
591
else if (!IS_BANKED(pDst))
593
fExpose = pGC->fExpose;
594
pGC->fExpose = FALSE;
603
ns = FirstBankOf(srcx, srcy);
604
nse = LastBankOf(srcx + w, srcy + h);
605
for (; ns <= nse; ns++)
607
if (!pScreenPriv->pBanks[ns])
610
nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
611
pBox = REGION_RECTS(pScreenPriv->pBanks[ns]);
613
for (; nBox--; pBox++)
615
cx1 = max(pBox->x1, srcx);
616
cy1 = max(pBox->y1, srcy);
617
cx2 = min(pBox->x2, srcx + w);
618
cy2 = min(pBox->y2, srcy + h);
620
if ((cx1 >= cx2) || (cy1 >= cy2))
625
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns);
628
(*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
629
cx1 - xorg, cy1 - yorg,
630
cx2 - cx1, cy2 - cy1,
631
cx1 + dx - xorg, cy1 + dy - yorg, plane);
633
(*pGC->ops->CopyArea)(pSrc, pDst, pGC,
634
cx1 - xorg, cy1 - yorg,
635
cx2 - cx1, cy2 - cy1,
636
cx1 + dx - xorg, cy1 + dy - yorg);
642
pGC->fExpose = fExpose;
646
else if (!IS_BANKED(pSrc))
650
if (pGC->miTranslate)
660
nd = FirstBankOf(dstx, dsty);
661
nde = LastBankOf(dstx + w, dsty + h);
662
for (; nd <= nde; nd++)
664
if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd]))
668
* It's faster to let the lower-level CopyArea do the clipping
671
nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
672
pBox = REGION_RECTS(pScreenPriv->pBanks[nd]);
674
for (; nBox--; pBox++)
676
cx1 = max(pBox->x1, dstx);
677
cy1 = max(pBox->y1, dsty);
678
cx2 = min(pBox->x2, dstx + w);
679
cy2 = min(pBox->y2, dsty + h);
681
if ((cx1 >= cx2) || (cy1 >= cy2))
686
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd);
689
(*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
690
cx1 + dx - xorg, cy1 + dy - yorg,
691
cx2 - cx1, cy2 - cy1,
692
cx1 - xorg, cy1 - yorg, plane);
694
(*pGC->ops->CopyArea)(pSrc, pDst, pGC,
695
cx1 + dx - xorg, cy1 + dy - yorg,
696
cx2 - cx1, cy2 - cy1,
697
cx1 - xorg, cy1 - yorg);
705
else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
709
fExpose = pGC->fExpose;
711
fastBox.x1 = srcx + pSrc->x;
712
fastBox.y1 = srcy + pSrc->y;
713
fastBox.x2 = fastBox.x1 + w;
714
fastBox.y2 = fastBox.y1 + h;
716
dx = dstx - fastBox.x1;
717
dy = dsty - fastBox.y1;
718
if (pGC->miTranslate)
725
* Clip against the source. Otherwise we will blit too much for SINGLE
726
* and SHARED banked systems.
732
if (pGC->subWindowMode != IncludeInferiors)
733
prgnSrcClip = &((WindowPtr)pSrc)->clipList;
734
else if (!((WindowPtr)pSrc)->parent)
736
else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE))
737
prgnSrcClip = pGC->pCompositeClip;
740
prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc);
749
* Clip the source. If regions extend beyond the source size, make
750
* sure exposure events get sent.
752
if (fastBox.x1 < pSrc->x)
754
fastBox.x1 = pSrc->x;
757
if (fastBox.y1 < pSrc->y)
759
fastBox.y1 = pSrc->y;
762
if (fastBox.x2 > pSrc->x + (int) pSrc->width)
764
fastBox.x2 = pSrc->x + (int) pSrc->width;
767
if (fastBox.y2 > pSrc->y + (int) pSrc->height)
769
fastBox.y2 = pSrc->y + (int) pSrc->height;
778
REGION_INIT(pScreen, &rgnDst, &fastBox, 1);
779
REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrcClip);
780
pBox = REGION_RECTS(&rgnDst);
781
nBox = REGION_NUM_RECTS(&rgnDst);
785
* fastBlit can only be TRUE if we don't need to worry about attempts
786
* to read partial pixels through the destination bank.
789
fastBlit = pGCPriv->fastPlane;
791
fastBlit = pGCPriv->fastCopy;
793
nQueue = nBox * pScreenPriv->maxRects * 2;
794
pQueue = Queue = ALLOCATE_LOCAL_ARRAY(miBankQueue, nQueue);
798
for (; nBox--; pBox++)
800
ns = FirstBankOf(pBox->x1, pBox->y1);
801
nse = LastBankOf(pBox->x2, pBox->y2);
802
for (; ns <= nse; ns++)
804
if (!pScreenPriv->pBanks[ns])
807
nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
808
pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]);
810
for (; nBoxClipSrc--; pBoxClipSrc++)
812
cx1 = max(pBox->x1, pBoxClipSrc->x1);
813
cy1 = max(pBox->y1, pBoxClipSrc->y1);
814
cx2 = min(pBox->x2, pBoxClipSrc->x2);
815
cy2 = min(pBox->y2, pBoxClipSrc->y2);
817
/* Check to see if the region is empty */
818
if ((cx1 >= cx2) || (cy1 >= cy2))
821
/* Translate c[xy]* to destination coordinates */
827
nd = FirstBankOf(cx1, cy1);
828
nde = LastBankOf(cx2, cy2);
829
for (; nd <= nde; nd++)
831
if (!pGCPriv->pBankedClips[nd])
835
* Clients can send quite large clip descriptions,
836
* so use the bank clips here instead.
839
REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
841
REGION_RECTS(pScreenPriv->pBanks[nd]);
843
for (; nBoxClipDst--; pBoxClipDst++)
845
ccBox.x1 = max(cx1, pBoxClipDst->x1);
846
ccBox.y1 = max(cy1, pBoxClipDst->y1);
847
ccBox.x2 = min(cx2, pBoxClipDst->x2);
848
ccBox.y2 = min(cy2, pBoxClipDst->y2);
850
/* Check to see if the region is empty */
851
if ((ccBox.x1 >= ccBox.x2) ||
852
(ccBox.y1 >= ccBox.y2))
855
pQueue->srcBankNo = ns;
856
pQueue->dstBankNo = nd;
857
pQueue->x = ccBox.x1 - xorg;
858
pQueue->y = ccBox.y1 - yorg;
859
pQueue->w = ccBox.x2 - ccBox.x1;
860
pQueue->h = ccBox.y2 - ccBox.y1;
862
if (maxWidth < pQueue->w)
863
maxWidth = pQueue->w;
864
if (maxHeight < pQueue->h)
865
maxHeight = pQueue->h;
868
* When shared banking is used and the source
869
* and destination banks differ, prevent
870
* attempts to fetch partial scanline pad units
871
* through the destination bank.
873
pQueue->fastBlit = fastBlit;
875
(pScreenPriv->type == BANK_SHARED) &&
878
pScreenPriv->nPixelsPerScanlinePadUnit) ||
880
pScreenPriv->nPixelsPerScanlinePadUnit) ||
881
(RECT_IN_REGION(pScreen,
882
pGCPriv->pBankedClips[nd], &ccBox) !=
884
pQueue->fastBlit = FALSE;
895
REGION_UNINIT(pScreen, &rgnDst);
897
REGION_DESTROY(pScreen, prgnSrcClip);
901
nQueue = pQueue - Queue;
910
((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors)))
912
if ((srcy + pSrc->y) < (dsty + yorg))
914
/* Sort from bottom to top */
915
pQueueBase = pQueueNext = pQueue + nQueue - 1;
917
while (pQueueBase >= pQueue)
919
while ((pQueueNext >= pQueue) &&
920
(pQueueBase->y == pQueueNext->y))
923
pQueueTmp = pQueueNext + 1;
924
while (pQueueTmp <= pQueueBase)
925
*pQueueNew++ = *pQueueTmp++;
927
pQueueBase = pQueueNext;
935
if ((srcx + pSrc->x) < (dstx + xorg))
937
/* Sort from right to left */
938
pQueueBase = pQueueNext = pQueue;
940
while (pQueueBase < pQueue + nQueue)
942
while ((pQueueNext < pQueue + nQueue) &&
943
(pQueueNext->y == pQueueBase->y))
946
pQueueTmp = pQueueNext;
947
while (pQueueTmp != pQueueBase)
948
*pQueueNew++ = *--pQueueTmp;
950
pQueueBase = pQueueNext;
958
paddedWidth = PixmapBytePad(maxWidth,
959
pScreenPriv->pScreenPixmap->drawable.depth);
960
pImage = (char *)ALLOCATE_LOCAL(paddedWidth * maxHeight);
962
pGC->fExpose = FALSE;
966
pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo];
970
if (pQueue->srcBankNo == pQueue->dstBankNo)
972
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
973
-1, -1, pQueue->srcBankNo);
976
(*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
977
pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
978
pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
980
(*pGC->ops->CopyArea)(pSrc, pDst, pGC,
981
pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
982
pQueue->w, pQueue->h, pQueue->x, pQueue->y);
984
else if (pQueue->fastBlit)
986
SET_SOURCE_BANK (pScreenPriv->pBankPixmap,
987
pScreenPriv->pScreenPixmap->drawable.width,
988
pScreenPriv->pScreenPixmap->devKind,
990
SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap,
991
-1, -1, pQueue->dstBankNo);
994
(*pGC->ops->CopyPlane)(
995
(DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
996
pQueue->x - dx, pQueue->y - dy,
997
pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
999
(*pGC->ops->CopyArea)(
1000
(DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
1001
pQueue->x - dx, pQueue->y - dy,
1002
pQueue->w, pQueue->h, pQueue->x, pQueue->y);
1006
ModifyPixmap(pScreenPriv->pBankPixmap,
1007
maxWidth, paddedWidth, pImage);
1009
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
1010
-1, -1, pQueue->srcBankNo);
1012
(*pScreenPriv->pBankGC->ops->CopyArea)(
1013
pSrc, (DrawablePtr)pScreenPriv->pBankPixmap,
1014
pScreenPriv->pBankGC,
1015
pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
1016
pQueue->w, pQueue->h, 0, 0);
1018
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
1019
-1, -1, pQueue->dstBankNo);
1022
(*pGC->ops->CopyPlane)(
1023
(DrawablePtr)pScreenPriv->pBankPixmap,
1024
pDst, pGC, 0, 0, pQueue->w, pQueue->h,
1025
pQueue->x, pQueue->y, plane);
1027
(*pGC->ops->CopyArea)(
1028
(DrawablePtr)pScreenPriv->pBankPixmap,
1029
pDst, pGC, 0, 0, pQueue->w, pQueue->h,
1030
pQueue->x, pQueue->y);
1038
DEALLOCATE_LOCAL(pImage);
1045
pGC->fExpose = fExpose;
1047
DEALLOCATE_LOCAL(Queue);
1052
if (!fExpose || fastExpose)
1055
return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0);
1071
return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE);
1089
miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE);
1094
DrawablePtr pDrawable,
1101
# define GCOP_ARGS GCOP_0D_ARGS
1102
GCOP_COMPLEX(PolyPoint, xPoint);
1108
DrawablePtr pDrawable,
1115
# define GCOP_ARGS GCOP_0D_ARGS
1116
GCOP_COMPLEX(Polylines, DDXPointRec);
1122
DrawablePtr pDrawable,
1128
# define GCOP_ARGS GCOP_1D_ARGS
1129
GCOP_COMPLEX(PolySegment, xSegment);
1134
miBankPolyRectangle(
1135
DrawablePtr pDrawable,
1141
# define GCOP_ARGS GCOP_1D_ARGS
1142
GCOP_COMPLEX(PolyRectangle, xRectangle);
1148
DrawablePtr pDrawable,
1154
# define GCOP_ARGS GCOP_1D_ARGS
1155
GCOP_COMPLEX(PolyArc, xArc);
1161
DrawablePtr pDrawable,
1169
# define GCOP_ARGS GCOP_2D_ARGS
1170
GCOP_COMPLEX(FillPolygon, DDXPointRec);
1176
DrawablePtr pDrawable,
1182
# define GCOP_ARGS GCOP_1D_ARGS
1183
GCOP_COMPLEX(PolyFillRect, xRectangle);
1189
DrawablePtr pDrawable,
1195
# define GCOP_ARGS GCOP_1D_ARGS
1196
GCOP_COMPLEX(PolyFillArc, xArc);
1202
DrawablePtr pDrawable,
1212
GCOP_SIMPLE(retval =
1213
(*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar));
1220
DrawablePtr pDrawable,
1225
unsigned short *pchar
1230
GCOP_SIMPLE(retval =
1231
(*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar));
1238
DrawablePtr pDrawable,
1246
GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar));
1251
DrawablePtr pDrawable,
1256
unsigned short *pchar
1259
GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar));
1263
miBankImageGlyphBlt(
1264
DrawablePtr pDrawable,
1268
unsigned int nArray,
1273
GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC,
1274
x, y, nArray, ppci, pglyphBase));
1279
DrawablePtr pDrawable,
1283
unsigned int nArray,
1288
GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC,
1289
x, y, nArray, ppci, pglyphBase));
1296
DrawablePtr pDrawable,
1303
if ((w > 0) && (h > 0))
1308
if (!IS_BANKED(pDrawable))
1312
(*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
1322
i = FirstBankOf(x, y);
1323
j = LastBankOf(x + w, y + h);
1326
if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
1331
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
1333
(*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
1345
static GCOps miBankGCOps =
1355
miBankPolyRectangle,
1364
miBankImageGlyphBlt,
1367
#ifdef NEED_LINEHELPER
1368
NULL, /* LineHelper */
1370
{NULL} /* devPrivate */
1373
/********************
1374
* GCFuncs wrappers *
1375
********************/
1380
unsigned long changes,
1381
DrawablePtr pDrawable
1387
(*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
1389
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
1390
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
1392
ScreenPtr pScreen = pGC->pScreen;
1394
unsigned long planemask;
1400
if (IS_BANKED(pDrawable))
1402
for (i = 0; i < pScreenPriv->nBanks; i++)
1404
if (!pScreenPriv->pBanks[i])
1407
if (!(prgnClip = pGCPriv->pBankedClips[i]))
1408
prgnClip = REGION_CREATE(pScreen, NULL, 1);
1410
REGION_INTERSECT(pScreen, prgnClip,
1411
pScreenPriv->pBanks[i], pGC->pCompositeClip);
1413
if ((REGION_NUM_RECTS(prgnClip) <= 1) &&
1414
((prgnClip->extents.x1 == prgnClip->extents.x2) ||
1415
(prgnClip->extents.y1 == prgnClip->extents.y2)))
1417
REGION_DESTROY(pScreen, prgnClip);
1418
pGCPriv->pBankedClips[i] = NULL;
1421
pGCPriv->pBankedClips[i] = prgnClip;
1425
* fastCopy and fastPlane can only be TRUE if we don't need to
1426
* worry about attempts to read partial pixels through the
1429
switch (pScreenPriv->type)
1432
pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
1434
if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) &&
1435
(pGC->alu != GXcopyInverted) && (pGC->alu != GXset))
1438
if (pScreen->rootDepth == 1)
1439
pGCPriv->fastPlane = TRUE;
1441
/* This is probably paranoia */
1442
if ((pDrawable->depth != pScreen->rootDepth) ||
1443
(pDrawable->depth != pGC->depth))
1446
planemask = (1 << pGC->depth) - 1;
1447
if ((pGC->planemask & planemask) == planemask)
1448
pGCPriv->fastCopy = TRUE;
1453
pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE;
1457
pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
1464
* Here we are on a pixmap and don't need all that special clipping
1465
* stuff, hence free it.
1467
for (i = 0; i < pScreenPriv->nBanks; i++)
1469
if (!pGCPriv->pBankedClips[i])
1472
REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
1473
pGCPriv->pBankedClips[i] = NULL;
1492
(*pGC->funcs->ChangeGC)(pGC, mask);
1507
(*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
1517
ScreenPtr pScreen = pGC->pScreen;
1524
(*pGC->funcs->DestroyGC)(pGC);
1526
for (i = 0; i < pScreenPriv->nBanks; i++)
1528
if (!pGCPriv->pBankedClips[i])
1531
REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
1532
pGCPriv->pBankedClips[i] = NULL;
1549
(*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
1562
(*pGC->funcs->DestroyClip)(pGC);
1576
(*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
1581
static GCFuncs miBankGCFuncs =
1592
/*******************
1594
*******************/
1597
miBankCreateScreenResources(
1604
SCREEN_UNWRAP(CreateScreenResources);
1606
if ((retval = (*pScreen->CreateScreenResources)(pScreen)))
1608
/* Set screen buffer address to something recognizable */
1609
pScreenPriv->pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
1610
pScreenPriv->pbits = pScreenPriv->pScreenPixmap->devPrivate.ptr;
1611
pScreenPriv->pScreenPixmap->devPrivate.ptr = (pointer)pScreenPriv;
1613
/* Get shadow pixmap; width & height of 0 means no pixmap data */
1614
pScreenPriv->pBankPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0,
1615
pScreenPriv->pScreenPixmap->drawable.depth);
1616
if (!pScreenPriv->pBankPixmap)
1620
/* Shadow the screen */
1622
retval = (*pScreen->ModifyPixmapHeader)(pScreenPriv->pBankPixmap,
1623
pScreenPriv->pScreenPixmap->drawable.width,
1624
pScreenPriv->pScreenPixmap->drawable.height,
1625
pScreenPriv->pScreenPixmap->drawable.depth,
1626
pScreenPriv->pScreenPixmap->drawable.bitsPerPixel,
1627
pScreenPriv->pScreenPixmap->devKind, NULL);
1629
/* Create shadow GC */
1632
pScreenPriv->pBankGC = CreateScratchGC(pScreen,
1633
pScreenPriv->pBankPixmap->drawable.depth);
1634
if (!pScreenPriv->pBankGC)
1638
/* Validate shadow GC */
1641
pScreenPriv->pBankGC->graphicsExposures = FALSE;
1642
pScreenPriv->pBankGC->subWindowMode = IncludeInferiors;
1643
ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap,
1644
pScreenPriv->pBankGC);
1647
SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
1653
miBankModifyPixmapHeader(
1663
Bool retval = FALSE;
1667
ScreenPtr pScreen = pPixmap->drawable.pScreen;
1670
PIXMAP_SAVE(pPixmap);
1671
SCREEN_UNWRAP(ModifyPixmapHeader);
1673
retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height,
1674
depth, bitsPerPixel, devKind, pPixData);
1676
SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
1678
if (pbits == (pointer)pScreenPriv)
1680
pScreenPriv->pbits = pPixmap->devPrivate.ptr;
1681
pPixmap->devPrivate.ptr = pbits;
1698
/* Free shadow GC */
1699
FreeScratchGC(pScreenPriv->pBankGC);
1701
/* Free shadow pixmap */
1702
(*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap);
1704
/* Restore screen pixmap devPrivate pointer */
1705
pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits;
1707
/* Delete bank clips */
1708
for (i = 0; i < pScreenPriv->nBanks; i++)
1709
if (pScreenPriv->pBanks[i])
1710
REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
1712
Xfree(pScreenPriv->pBanks);
1714
SCREEN_UNWRAP(CreateScreenResources);
1715
SCREEN_UNWRAP(ModifyPixmapHeader);
1716
SCREEN_UNWRAP(CloseScreen);
1717
SCREEN_UNWRAP(GetImage);
1718
SCREEN_UNWRAP(GetSpans);
1719
SCREEN_UNWRAP(CreateGC);
1720
SCREEN_UNWRAP(PaintWindowBackground);
1721
SCREEN_UNWRAP(PaintWindowBorder);
1722
SCREEN_UNWRAP(CopyWindow);
1723
SCREEN_UNWRAP(BackingStoreFuncs);
1726
return (*pScreen->CloseScreen)(nIndex, pScreen);
1731
DrawablePtr pDrawable,
1736
unsigned int format,
1737
unsigned long planemask,
1741
if ((w > 0) && (h > 0))
1743
ScreenPtr pScreen = pDrawable->pScreen;
1747
SCREEN_UNWRAP(GetImage);
1749
if (!IS_BANKED(pDrawable))
1751
(*pScreen->GetImage)(pDrawable, sx, sy, w, h,
1752
format, planemask, pImage);
1759
paddedWidth = PixmapBytePad(w,
1760
pScreenPriv->pScreenPixmap->drawable.depth);
1761
pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth * h);
1767
ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth,
1770
(*pScreenPriv->pBankGC->ops->CopyArea)(
1771
(DrawablePtr)WindowTable[pScreen->myNum],
1772
(DrawablePtr)pScreenPriv->pBankPixmap,
1773
pScreenPriv->pBankGC,
1774
sx + pDrawable->x, sy + pDrawable->y, w, h, 0, 0);
1776
(*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap,
1777
0, 0, w, h, format, planemask, pImage);
1781
DEALLOCATE_LOCAL(pBankImage);
1785
SCREEN_WRAP(GetImage, miBankGetImage);
1791
DrawablePtr pDrawable,
1801
ScreenPtr pScreen = pDrawable->pScreen;
1805
SCREEN_UNWRAP(GetSpans);
1807
if (!IS_BANKED(pDrawable))
1809
(*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage);
1820
PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width,
1821
pScreenPriv->pScreenPixmap->drawable.depth);
1822
pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth);
1828
ModifyPixmap(pScreenPriv->pBankPixmap,
1829
pScreenPriv->pScreenPixmap->drawable.width,
1830
paddedWidth, pBankImage);
1832
for (; nspans--; ppt++, pwidth++)
1837
(*pScreenPriv->pBankGC->ops->CopyArea)(
1838
(DrawablePtr)WindowTable[pScreen->myNum],
1839
(DrawablePtr)pScreenPriv->pBankPixmap,
1840
pScreenPriv->pBankGC,
1841
ppt->x, ppt->y, *pwidth, 1, 0, 0);
1843
(*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap,
1844
wMax, &pt, pwidth, 1, pImage);
1846
pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth);
1851
DEALLOCATE_LOCAL(pBankImage);
1855
SCREEN_WRAP(GetSpans, miBankGetSpans);
1864
ScreenPtr pScreen = pGC->pScreen;
1865
miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC);
1869
SCREEN_UNWRAP(CreateGC);
1871
if ((ret = (*pScreen->CreateGC)(pGC)))
1873
pGCPriv->unwrappedOps = &miBankGCOps;
1874
pGCPriv->unwrappedFuncs = &miBankGCFuncs;
1877
memset(&pGCPriv->pBankedClips, 0,
1878
pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips));
1881
SCREEN_WRAP(CreateGC, miBankCreateGC);
1893
ScreenPtr pScreen = pWin->drawable.pScreen;
1896
PaintWindowProcPtr PaintWindow;
1901
if (what == PW_BORDER)
1903
SCREEN_UNWRAP(PaintWindowBorder);
1904
PaintWindow = pScreen->PaintWindowBorder;
1908
SCREEN_UNWRAP(PaintWindowBackground);
1909
PaintWindow = pScreen->PaintWindowBackground;
1912
if (!IS_BANKED(pWin))
1914
(*PaintWindow)(pWin, pRegion, what);
1918
REGION_NULL(pScreen, &tmpReg);
1920
for (i = 0; i < pScreenPriv->nBanks; i++)
1922
if (!pScreenPriv->pBanks[i])
1925
REGION_INTERSECT(pScreen, &tmpReg, pRegion,
1926
pScreenPriv->pBanks[i]);
1928
if (REGION_NIL(&tmpReg))
1931
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
1933
(*PaintWindow)(pWin, &tmpReg, what);
1936
REGION_UNINIT(pScreen, &tmpReg);
1939
if (what == PW_BORDER)
1941
SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
1945
SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
1954
DDXPointRec ptOldOrg,
1958
ScreenPtr pScreen = pWindow->drawable.pScreen;
1961
DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum];
1963
BoxPtr pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2;
1964
XID subWindowMode = IncludeInferiors;
1966
pGC = GetScratchGC(pDrawable->depth, pScreen);
1968
ChangeGC(pGC, GCSubwindowMode, &subWindowMode);
1969
ValidateGC(pDrawable, pGC);
1971
pRgnDst = REGION_CREATE(pScreen, NULL, 1);
1973
dx = ptOldOrg.x - pWindow->drawable.x;
1974
dy = ptOldOrg.y - pWindow->drawable.y;
1975
REGION_TRANSLATE(pScreen, pRgnSrc, -dx, -dy);
1976
REGION_INTERSECT(pScreen, pRgnDst, &pWindow->borderClip, pRgnSrc);
1978
pBox = REGION_RECTS(pRgnDst);
1979
nBox = REGION_NUM_RECTS(pRgnDst);
1988
/* Sort boxes from bottom to top */
1989
pBoxNew1 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
1993
pBoxBase = pBoxNext = pBox + nBox - 1;
1995
while (pBoxBase >= pBox)
1997
while ((pBoxNext >= pBox) &&
1998
(pBoxBase->y1 == pBoxNext->y1))
2001
pBoxTmp = pBoxNext + 1;
2003
while (pBoxTmp <= pBoxBase)
2004
*pBoxNew1++ = *pBoxTmp++;
2006
pBoxBase = pBoxNext;
2016
/* Sort boxes from right to left */
2017
pBoxNew2 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
2021
pBoxBase = pBoxNext = pBox;
2023
while (pBoxBase < pBox + nBox)
2025
while ((pBoxNext < pBox + nBox) &&
2026
(pBoxNext->y1 == pBoxBase->y1))
2031
while (pBoxTmp != pBoxBase)
2032
*pBoxNew2++ = *--pBoxTmp;
2034
pBoxBase = pBoxNext;
2045
(*pGC->ops->CopyArea)(pDrawable, pDrawable, pGC,
2046
pBox->x1 + dx, pBox->y1 + dy,
2047
pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
2048
pBox->x1, pBox->y1);
2055
REGION_DESTROY(pScreen, pRgnDst);
2057
DEALLOCATE_LOCAL(pBoxNew2);
2058
DEALLOCATE_LOCAL(pBoxNew1);
2061
/**************************
2062
* Backing store wrappers *
2063
**************************/
2074
ScreenPtr pScreen = pPixmap->drawable.pScreen;
2075
RegionRec rgnClipped;
2080
SCREEN_UNWRAP(BackingStoreFuncs.SaveAreas);
2082
if (!IS_BANKED(pWin))
2084
(*pScreen->BackingStoreFuncs.SaveAreas)(pPixmap, prgnSave, xorg, yorg,
2089
REGION_NULL(pScreen, &rgnClipped);
2090
REGION_TRANSLATE(pScreen, prgnSave, xorg, yorg);
2092
for (i = 0; i < pScreenPriv->nBanks; i++)
2094
if (!pScreenPriv->pBanks[i])
2097
REGION_INTERSECT(pScreen, &rgnClipped,
2098
prgnSave, pScreenPriv->pBanks[i]);
2100
if (REGION_NIL(&rgnClipped))
2103
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
2105
REGION_TRANSLATE(pScreen, &rgnClipped, -xorg, -yorg);
2107
(*pScreen->BackingStoreFuncs.SaveAreas)(pPixmap, &rgnClipped,
2111
REGION_TRANSLATE(pScreen, prgnSave, -xorg, -yorg);
2112
REGION_UNINIT(pScreen, &rgnClipped);
2115
SCREEN_WRAP(BackingStoreFuncs.SaveAreas, miBankSaveAreas);
2122
RegionPtr prgnRestore,
2128
ScreenPtr pScreen = pPixmap->drawable.pScreen;
2129
RegionRec rgnClipped;
2134
SCREEN_UNWRAP(BackingStoreFuncs.RestoreAreas);
2136
if (!IS_BANKED(pWin))
2138
(*pScreen->BackingStoreFuncs.RestoreAreas)(pPixmap, prgnRestore,
2143
REGION_NULL(pScreen, &rgnClipped);
2145
for (i = 0; i < pScreenPriv->nBanks; i++)
2147
if (!pScreenPriv->pBanks[i])
2150
REGION_INTERSECT(pScreen, &rgnClipped,
2151
prgnRestore, pScreenPriv->pBanks[i]);
2153
if (REGION_NIL(&rgnClipped))
2156
SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
2158
(*pScreen->BackingStoreFuncs.RestoreAreas)(pPixmap, &rgnClipped,
2162
REGION_UNINIT(pScreen, &rgnClipped);
2165
SCREEN_WRAP(BackingStoreFuncs.RestoreAreas, miBankRestoreAreas);
2170
miInitializeBanking(
2175
miBankInfoPtr pBankInfo
2178
miBankScreenPtr pScreenPriv;
2179
unsigned long nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit;
2180
unsigned long BankBase, ServerPad;
2181
unsigned int type, iBank, nBanks, maxRects, we, nBankBPP;
2184
if (!pBankInfo || !pBankInfo->BankSize)
2185
return TRUE; /* No banking required */
2189
if (!pScreen || !xsize || !ysize || (xsize > width) ||
2190
!pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
2191
!pBankInfo->SetSourceAndDestinationBanks ||
2192
!pBankInfo->pBankA || !pBankInfo->pBankB ||
2193
!pBankInfo->nBankDepth)
2197
* DDX *must* have registered a pixmap format whose depth is
2198
* pBankInfo->nBankDepth. This is not necessarily the rootDepth
2202
while (screenInfo.formats[i].depth != pBankInfo->nBankDepth)
2203
if (++i >= screenInfo.numPixmapFormats)
2205
nBankBPP = screenInfo.formats[i].bitsPerPixel;
2208
while (screenInfo.formats[i].depth != pScreen->rootDepth)
2209
if (++i >= screenInfo.numPixmapFormats)
2212
if (nBankBPP > screenInfo.formats[i].bitsPerPixel)
2215
/* Determine banking type */
2216
if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
2221
nBitsPerBank = pBankInfo->BankSize * 8;
2222
ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8;
2223
if (nBitsPerBank % ServerPad)
2225
nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8;
2226
nBanks = ((nBitsPerScanline * (ysize - 1)) +
2227
(nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank;
2228
nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP;
2232
if (miBankGeneration != serverGeneration)
2234
if (((miBankScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
2235
((miBankGCIndex = AllocateGCPrivateIndex()) < 0))
2238
miBankGeneration = serverGeneration;
2241
if (!AllocateGCPrivate(pScreen, miBankGCIndex,
2242
(nBanks * sizeof(RegionPtr)) +
2243
(sizeof(miBankGCRec) - sizeof(RegionPtr))))
2246
if (!(pScreenPriv = (miBankScreenPtr)Xcalloc(sizeof(miBankScreenRec))))
2249
if (!(pScreenPriv->pBanks = /* Allocate and clear */
2250
(RegionPtr *)Xcalloc(nBanks * sizeof(RegionPtr))))
2257
* Translate banks into clipping regions which are themselves clipped
2258
* against the screen. This also ensures that pixels with imbedded bank
2259
* boundaries are off-screen.
2265
for (iBank = 0; iBank < nBanks; iBank++)
2267
xRectangle pRects[3], *pRect = pRects;
2268
unsigned int xb, yb, xe, ye;
2270
xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP;
2271
yb = (BankBase + nBankBPP - 1) / nBitsPerScanline;
2286
BankBase += nBitsPerBank;
2288
we = (BankBase % nBitsPerScanline) % nBankBPP;
2289
xe = (BankBase % nBitsPerScanline) / nBankBPP;
2290
ye = BankBase / nBitsPerScanline;
2309
pRect->width = xe - xb;
2320
pRect->width = xsize - xb;
2330
pRect->width = xsize;
2331
pRect->height = ye - yb;
2332
maxRects += min(pRect->height, 3) + 1;
2347
pScreenPriv->pBanks[iBank] =
2348
RECTS_TO_REGION(pScreen, pRect - pRects, pRects, 0);
2349
if (!pScreenPriv->pBanks[iBank] ||
2350
REGION_NAR(pScreenPriv->pBanks[iBank]))
2357
if (we && (iBank < nBanks))
2359
for (i = iBank; i >= 0; i--)
2360
if (pScreenPriv->pBanks[i])
2361
REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
2363
Xfree(pScreenPriv->pBanks);
2369
/* Open for business */
2371
pScreenPriv->type = type;
2372
pScreenPriv->nBanks = nBanks;
2373
pScreenPriv->maxRects = maxRects;
2374
pScreenPriv->nBankBPP = nBankBPP;
2375
pScreenPriv->BankInfo = *pBankInfo;
2376
pScreenPriv->nBitsPerBank = nBitsPerBank;
2377
pScreenPriv->nBitsPerScanline = nBitsPerScanline;
2378
pScreenPriv->nPixelsPerScanlinePadUnit = nPixelsPerScanlinePadUnit;
2380
SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
2381
SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
2382
SCREEN_WRAP(CloseScreen, miBankCloseScreen);
2383
SCREEN_WRAP(GetImage, miBankGetImage);
2384
SCREEN_WRAP(GetSpans, miBankGetSpans);
2385
SCREEN_WRAP(CreateGC, miBankCreateGC);
2386
SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
2387
SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
2388
SCREEN_WRAP(CopyWindow, miBankCopyWindow);
2390
pScreenPriv->BackingStoreFuncs = pScreen->BackingStoreFuncs;
2392
pScreen->BackingStoreFuncs.SaveAreas = miBankSaveAreas;
2393
pScreen->BackingStoreFuncs.RestoreAreas = miBankRestoreAreas;
2394
/* ??????????????????????????????????????????????????????????????
2395
pScreen->BackingStoreFuncs.SetClipmaskRgn = miBankSetClipmaskRgn;
2396
?????????????????????????????????????????????????????????????? */
2398
BANK_SCRPRIVLVAL = (pointer)pScreenPriv;
2403
/* This is used to force GC revalidation when the banking type is changed */
2406
miBankNewSerialNumber(
2411
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
2412
return WT_WALKCHILDREN;
2415
/* This entry modifies the banking interface */
2419
miBankInfoPtr pBankInfo
2427
if (miBankGeneration == serverGeneration)
2433
if (!pBankInfo || !pBankInfo->BankSize ||
2434
!pBankInfo->pBankA || !pBankInfo->pBankB ||
2435
!pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
2436
!pBankInfo->SetSourceAndDestinationBanks)
2439
/* BankSize and nBankDepth cannot, as yet, be changed */
2440
if ((pScreenPriv->BankInfo.BankSize != pBankInfo->BankSize) ||
2441
(pScreenPriv->BankInfo.nBankDepth != pBankInfo->nBankDepth))
2444
if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
2447
/* Reset banking info */
2448
pScreenPriv->BankInfo = *pBankInfo;
2449
if (type != pScreenPriv->type)
2452
* Banking type is changing. Revalidate all window GC's.
2454
pScreenPriv->type = type;
2455
WalkTree(pScreen, miBankNewSerialNumber, 0);
2462
if (!pBankInfo || !pBankInfo->BankSize)
2463
return TRUE; /* No change requested */
2469
* Given various screen attributes, determine the minimum scanline width such
2470
* that each scanline is server and DDX padded and any pixels with imbedded
2471
* bank boundaries are off-screen. This function returns -1 if such a width
2472
* cannot exist. This function exists because the DDX needs to be able to
2473
* determine this width before initializing a frame buffer.
2477
unsigned int xsize, /* pixels */
2478
unsigned int ysize, /* pixels */
2479
unsigned int width, /* pixels */
2480
unsigned long BankSize, /* char's */
2481
PixmapFormatRec *pBankFormat,
2482
unsigned int nWidthUnit /* bits */
2485
unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
2486
unsigned long minBitsPerScanline, maxBitsPerScanline;
2490
if (!nWidthUnit || !pBankFormat)
2493
nBitsPerBank = BankSize * 8;
2494
if (nBitsPerBank % pBankFormat->scanlinePad)
2499
nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit);
2501
(((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
2502
nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
2503
width = nBitsPerScanline / pBankFormat->bitsPerPixel;
2505
if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
2509
* Scanlines will be server-pad aligned at this point. They will also be
2510
* a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
2511
* bank boundaries are off-screen.
2513
* It seems reasonable to limit total frame buffer size to 1/16 of the
2514
* theoretical maximum address space size. On a machine with 32-bit
2515
* addresses (to 8-bit quantities) this turns out to be 256MB. Not only
2516
* does this provide a simple limiting condition for the loops below, but
2517
* it also prevents unsigned long wraparounds.
2522
minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
2523
if (minBitsPerScanline > nBitsPerBank)
2529
maxBitsPerScanline =
2530
(((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
2531
while (nBitsPerScanline <= maxBitsPerScanline)
2533
unsigned long BankBase, BankUnit;
2535
BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
2537
if (!(BankUnit % nBitsPerScanline))
2540
for (BankBase = BankUnit; ; BankBase += nBitsPerBank)
2544
y = BankBase / nBitsPerScanline;
2548
x = BankBase % nBitsPerScanline;
2549
if (!(x % pBankFormat->bitsPerPixel))
2552
if (x < minBitsPerScanline)
2555
* Skip ahead certain widths by dividing the excess scanline
2558
y *= nBitsPerScanlinePadUnit;
2560
((x + y - 1) / y) * nBitsPerScanlinePadUnit;
2561
width = nBitsPerScanline / pBankFormat->bitsPerPixel;
2565
if (BankBase != BankUnit)
2568
if (!(nBitsPerScanline % x))
2571
BankBase = ((nBitsPerScanline - minBitsPerScanline) /
2572
(nBitsPerScanline - x)) * BankUnit;