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.
49 * This thing originated from an idea of Edwin Goei and his bank switching
50 * code for the DEC TX board.
54 * Heavily modified for the XFree86 Project to turn this into an mi wrapper.
55 * --- Marc Aurele La France (tsi@xfree86.org)
59 * "Heavily modified", indeed! By the time this is finalized, there probably
60 * won't be much left of Roell's code...
62 * Miscellaneous notes:
63 * - Pixels with imbedded bank boundaries are required to be off-screen. There
64 * >might< be a way to fool the underlying framebuffer into dealing with
66 * - Plans to generalise this to do (hardware) colour plane switching have been
67 * dropped due to colour flashing concerns.
70 * - Allow miModifyBanking() to change BankSize and nBankDepth.
71 * - Re-instate shared and double banking for framebuffers whose pixmap formats
72 * don't describe how the server "sees" the screen.
73 * - Remove remaining assumptions that a pixmap's devPrivate field points
74 * directly to its pixel data.
77 /* #define NO_ALLOCA 1 */
79 #ifdef HAVE_DIX_CONFIG_H
80 #include <dix-config.h>
85 #include "pixmapstr.h"
86 #include "scrnintstr.h"
87 #include "windowstr.h"
96 typedef struct _miBankScreen
98 miBankInfoRec BankInfo
;
99 unsigned int nBankBPP
;
102 unsigned long nBitsPerBank
;
103 unsigned long nBitsPerScanline
;
104 unsigned long nPixelsPerScanlinePadUnit
;
106 PixmapPtr pScreenPixmap
;
107 PixmapPtr pBankPixmap
;
110 int nBanks
, maxRects
;
118 CreateScreenResourcesProcPtr CreateScreenResources
;
119 ModifyPixmapHeaderProcPtr ModifyPixmapHeader
;
120 CloseScreenProcPtr CloseScreen
;
121 GetImageProcPtr GetImage
;
122 GetSpansProcPtr GetSpans
;
123 CreateGCProcPtr CreateGC
;
124 PaintWindowBackgroundProcPtr PaintWindowBackground
;
125 PaintWindowBorderProcPtr PaintWindowBorder
;
126 CopyWindowProcPtr CopyWindow
;
127 BSFuncRec BackingStoreFuncs
;
128 } miBankScreenRec
, *miBankScreenPtr
;
130 typedef struct _miBankGC
132 GCOps
*wrappedOps
, *unwrappedOps
;
133 GCFuncs
*wrappedFuncs
, *unwrappedFuncs
;
135 Bool fastCopy
, fastPlane
;
137 RegionPtr pBankedClips
[1];
138 } miBankGCRec
, *miBankGCPtr
;
140 typedef struct _miBankQueue
143 unsigned short srcBankNo
;
144 unsigned short dstBankNo
;
152 * CAVEAT: This banking scheme requires that the DDX store Pixmap data in the
153 * server's address space.
156 #define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
157 (*pScreen->ModifyPixmapHeader)((_pPix), \
158 (_width), -1, -1, -1, (_devKind), (_pbits))
160 #define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \
161 ModifyPixmap(_pPix, _width, _devKind, \
162 (char *)pScreenPriv->BankInfo.pBankA + \
163 (*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \
164 (pScreenPriv->BankInfo.BankSize * (_no)))
166 #define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \
167 ModifyPixmap(_pPix, _width, _devKind, \
168 (char *)pScreenPriv->BankInfo.pBankA + \
169 (*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \
170 (pScreenPriv->BankInfo.BankSize * (_no)))
172 #define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \
173 ModifyPixmap(_pPix, _width, _devKind, \
174 (char *)pScreenPriv->BankInfo.pBankB + \
175 (*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \
176 (pScreenPriv->BankInfo.BankSize * (_no)))
178 #define ALLOCATE_LOCAL_ARRAY(atype, ntype) \
179 (atype *)ALLOCATE_LOCAL((ntype) * sizeof(atype))
181 static int miBankScreenIndex
;
182 static int miBankGCIndex
;
183 static unsigned long miBankGeneration
= 0;
185 #define BANK_SCRPRIVLVAL pScreen->devPrivates[miBankScreenIndex].ptr
187 #define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
189 #define BANK_GCPRIVLVAL(pGC) (pGC)->devPrivates[miBankGCIndex].ptr
191 #define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
193 #define PIXMAP_STATUS(_pPix) \
194 pointer pbits = (_pPix)->devPrivate.ptr
196 #define PIXMAP_SAVE(_pPix) \
197 PIXMAP_STATUS(_pPix); \
198 if (pbits == (pointer)pScreenPriv) \
199 (_pPix)->devPrivate.ptr = pScreenPriv->pbits
201 #define PIXMAP_RESTORE(_pPix) \
202 (_pPix)->devPrivate.ptr = pbits
205 int width = pScreenPriv->pBankPixmap->drawable.width; \
206 int devKind = pScreenPriv->pBankPixmap->devKind; \
207 PIXMAP_SAVE(pScreenPriv->pBankPixmap)
209 #define BANK_RESTORE \
210 pScreenPriv->pBankPixmap->drawable.width = width; \
211 pScreenPriv->pBankPixmap->devKind = devKind; \
212 PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
214 #define SCREEN_STATUS \
215 PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
217 #define SCREEN_SAVE \
218 PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
220 #define SCREEN_RESTORE \
221 PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
223 #define SCREEN_INIT \
224 miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
226 #define SCREEN_UNWRAP(field) \
227 pScreen->field = pScreenPriv->field
229 #define SCREEN_WRAP(field, wrapper) \
230 pScreenPriv->field = pScreen->field; \
231 pScreen->field = wrapper
233 #define GC_INIT(pGC) \
234 miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
236 #define GC_UNWRAP(pGC) \
237 pGCPriv->unwrappedOps = (pGC)->ops; \
238 pGCPriv->unwrappedFuncs = (pGC)->funcs; \
239 (pGC)->ops = pGCPriv->wrappedOps; \
240 (pGC)->funcs = pGCPriv->wrappedFuncs
242 #define GC_WRAP(pGC) \
243 pGCPriv->wrappedOps = (pGC)->ops; \
244 pGCPriv->wrappedFuncs = (pGC)->funcs; \
245 (pGC)->ops = pGCPriv->unwrappedOps; \
246 (pGC)->funcs = pGCPriv->unwrappedFuncs
248 #define IS_BANKED(pDrawable) \
249 ((pbits == (pointer)pScreenPriv) && \
250 (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
253 RegionPtr pOrigCompositeClip = pGC->pCompositeClip
255 #define CLIP_RESTORE \
256 pGC->pCompositeClip = pOrigCompositeClip
259 ScreenPtr pScreen = pGC->pScreen; \
263 #define GCOP_UNWRAP \
269 #define GCOP_TOP_PART \
270 for (i = 0; i < pScreenPriv->nBanks; i++) \
272 if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
275 SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
277 #define GCOP_BOTTOM_PART \
281 #define GCOP_SIMPLE(statement) \
286 if (!IS_BANKED(pDrawable)) \
304 #define GCOP_0D_ARGS mode,
306 #define GCOP_2D_ARGS shape, mode,
308 #define GCOP_COMPLEX(aop, atype) \
313 if (!IS_BANKED(pDrawable)) \
316 (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
321 atype *aarg = pArray, *acopy; \
324 if ((acopy = ALLOCATE_LOCAL_ARRAY(atype, nArray))) \
328 memcpy(acopy, pArray, nArray * sizeof(atype)); \
329 (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
331 DEALLOCATE_LOCAL(acopy); \
337 /*********************
338 * Utility functions *
339 *********************/
343 miBankScreenPtr pScreenPriv
,
348 int iBank
= ((x
* (int)pScreenPriv
->nBankBPP
) +
349 (y
* (long)pScreenPriv
->nBitsPerScanline
)) /
350 (long)pScreenPriv
->nBitsPerBank
;
354 else if (iBank
>= pScreenPriv
->nBanks
)
355 iBank
= pScreenPriv
->nBanks
- 1;
360 #define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
361 #define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
363 /* Determine banking type from the BankInfoRec */
367 miBankInfoPtr pBankInfo
372 if (pBankInfo
->pBankA
== pBankInfo
->pBankB
)
374 if (pBankInfo
->SetSourceBank
== pBankInfo
->SetDestinationBank
)
376 if (pBankInfo
->SetSourceAndDestinationBanks
!=
377 pBankInfo
->SetSourceBank
)
384 if (pBankInfo
->SetSourceAndDestinationBanks
==
385 pBankInfo
->SetDestinationBank
)
387 if (pBankInfo
->SetSourceAndDestinationBanks
==
388 pBankInfo
->SetSourceBank
)
396 if ((unsigned long)abs((char *)pBankInfo
->pBankA
-
397 (char *)pBankInfo
->pBankB
) < pBankInfo
->BankSize
)
400 if (pBankInfo
->SetSourceBank
== pBankInfo
->SetDestinationBank
)
402 if (pBankInfo
->SetSourceAndDestinationBanks
!=
403 pBankInfo
->SetSourceBank
)
408 if (pBankInfo
->SetSourceAndDestinationBanks
==
409 pBankInfo
->SetDestinationBank
)
417 * Internal limitation: Currently, only single banking is supported when
418 * the pixmap format and the screen's pixel format are different. The
419 * following test is only partially successful at detecting this condition.
421 if (pBankInfo
->nBankDepth
!= pScreen
->rootDepth
)
427 /* Least common multiple */
434 unsigned int m
= x
, n
= y
, o
;
451 DrawablePtr pDrawable
,
459 GCOP_SIMPLE((*pGC
->ops
->FillSpans
)(pDrawable
, pGC
,
460 nArray
, pptInit
, pwidthInit
, fSorted
));
465 DrawablePtr pDrawable
,
474 GCOP_SIMPLE((*pGC
->ops
->SetSpans
)(pDrawable
, pGC
, psrc
,
475 ppt
, pwidth
, nArray
, fSorted
));
480 DrawablePtr pDrawable
,
492 if ((w
> 0) && (h
> 0))
497 if (!IS_BANKED(pDrawable
))
501 (*pGC
->ops
->PutImage
)(pDrawable
, pGC
, depth
, x
, y
, w
, h
,
502 leftPad
, format
, pImage
);
512 i
= FirstBankOf(x
+ pDrawable
->x
, y
+ pDrawable
->y
);
513 j
= LastBankOf(x
+ pDrawable
->x
+ w
, y
+ pDrawable
->y
+ h
);
516 if (!(pGC
->pCompositeClip
= pGCPriv
->pBankedClips
[i
]))
521 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, i
);
523 (*pGC
->ops
->PutImage
)(pDrawable
, pGC
, depth
, x
, y
, w
, h
,
524 leftPad
, format
, pImage
);
537 * Here the CopyArea/CopyPlane wrappers. First off, we have to clip against
538 * the source in order to make the minimal number of copies in case of slow
539 * systems. Also the exposure handling is quite tricky. Special attention
540 * is to be given to the way the copies are sequenced. The list of boxes after
541 * the source clip is used to build a workqueue, that contains the atomic
542 * copies (i.e. only from one bank to one bank). Doing so produces a minimal
543 * list of things to do.
560 int cx1
, cy1
, cx2
, cy2
;
561 int ns
, nd
, nse
, nde
, dx
, dy
, xorg
= 0, yorg
= 0;
562 int maxWidth
= 0, maxHeight
= 0, paddedWidth
= 0;
563 int nBox
, nBoxClipSrc
, nBoxClipDst
, nQueue
;
564 BoxPtr pBox
, pBoxClipSrc
, pBoxClipDst
;
565 BoxRec fastBox
, ccBox
;
566 RegionPtr ret
= NULL
, prgnSrcClip
= NULL
;
569 miBankQueue
*pQueue
, *pQueueNew
, *Queue
;
570 miBankQueue
*pQueueTmp
, *pQueueNext
, *pQueueBase
;
571 Bool fastBlit
, freeSrcClip
, fastClip
;
572 Bool fExpose
= FALSE
, fastExpose
= FALSE
;
577 if (!IS_BANKED(pSrc
) && !IS_BANKED(pDst
))
582 ret
= (*pGC
->ops
->CopyPlane
)(pSrc
, pDst
, pGC
,
583 srcx
, srcy
, w
, h
, dstx
, dsty
, plane
);
585 ret
= (*pGC
->ops
->CopyArea
)(pSrc
, pDst
, pGC
,
586 srcx
, srcy
, w
, h
, dstx
, dsty
);
590 else if (!IS_BANKED(pDst
))
592 fExpose
= pGC
->fExpose
;
593 pGC
->fExpose
= FALSE
;
602 ns
= FirstBankOf(srcx
, srcy
);
603 nse
= LastBankOf(srcx
+ w
, srcy
+ h
);
604 for (; ns
<= nse
; ns
++)
606 if (!pScreenPriv
->pBanks
[ns
])
609 nBox
= REGION_NUM_RECTS(pScreenPriv
->pBanks
[ns
]);
610 pBox
= REGION_RECTS(pScreenPriv
->pBanks
[ns
]);
612 for (; nBox
--; pBox
++)
614 cx1
= max(pBox
->x1
, srcx
);
615 cy1
= max(pBox
->y1
, srcy
);
616 cx2
= min(pBox
->x2
, srcx
+ w
);
617 cy2
= min(pBox
->y2
, srcy
+ h
);
619 if ((cx1
>= cx2
) || (cy1
>= cy2
))
624 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, ns
);
627 (*pGC
->ops
->CopyPlane
)(pSrc
, pDst
, pGC
,
628 cx1
- xorg
, cy1
- yorg
,
629 cx2
- cx1
, cy2
- cy1
,
630 cx1
+ dx
- xorg
, cy1
+ dy
- yorg
, plane
);
632 (*pGC
->ops
->CopyArea
)(pSrc
, pDst
, pGC
,
633 cx1
- xorg
, cy1
- yorg
,
634 cx2
- cx1
, cy2
- cy1
,
635 cx1
+ dx
- xorg
, cy1
+ dy
- yorg
);
641 pGC
->fExpose
= fExpose
;
645 else if (!IS_BANKED(pSrc
))
649 if (pGC
->miTranslate
)
659 nd
= FirstBankOf(dstx
, dsty
);
660 nde
= LastBankOf(dstx
+ w
, dsty
+ h
);
661 for (; nd
<= nde
; nd
++)
663 if (!(pGC
->pCompositeClip
= pGCPriv
->pBankedClips
[nd
]))
667 * It's faster to let the lower-level CopyArea do the clipping
670 nBox
= REGION_NUM_RECTS(pScreenPriv
->pBanks
[nd
]);
671 pBox
= REGION_RECTS(pScreenPriv
->pBanks
[nd
]);
673 for (; nBox
--; pBox
++)
675 cx1
= max(pBox
->x1
, dstx
);
676 cy1
= max(pBox
->y1
, dsty
);
677 cx2
= min(pBox
->x2
, dstx
+ w
);
678 cy2
= min(pBox
->y2
, dsty
+ h
);
680 if ((cx1
>= cx2
) || (cy1
>= cy2
))
685 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, nd
);
688 (*pGC
->ops
->CopyPlane
)(pSrc
, pDst
, pGC
,
689 cx1
+ dx
- xorg
, cy1
+ dy
- yorg
,
690 cx2
- cx1
, cy2
- cy1
,
691 cx1
- xorg
, cy1
- yorg
, plane
);
693 (*pGC
->ops
->CopyArea
)(pSrc
, pDst
, pGC
,
694 cx1
+ dx
- xorg
, cy1
+ dy
- yorg
,
695 cx2
- cx1
, cy2
- cy1
,
696 cx1
- xorg
, cy1
- yorg
);
704 else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
708 fExpose
= pGC
->fExpose
;
710 fastBox
.x1
= srcx
+ pSrc
->x
;
711 fastBox
.y1
= srcy
+ pSrc
->y
;
712 fastBox
.x2
= fastBox
.x1
+ w
;
713 fastBox
.y2
= fastBox
.y1
+ h
;
715 dx
= dstx
- fastBox
.x1
;
716 dy
= dsty
- fastBox
.y1
;
717 if (pGC
->miTranslate
)
724 * Clip against the source. Otherwise we will blit too much for SINGLE
725 * and SHARED banked systems.
731 if (pGC
->subWindowMode
!= IncludeInferiors
)
732 prgnSrcClip
= &((WindowPtr
)pSrc
)->clipList
;
733 else if (!((WindowPtr
)pSrc
)->parent
)
735 else if ((pSrc
== pDst
) && (pGC
->clientClipType
== CT_NONE
))
736 prgnSrcClip
= pGC
->pCompositeClip
;
739 prgnSrcClip
= NotClippedByChildren((WindowPtr
)pSrc
);
748 * Clip the source. If regions extend beyond the source size, make
749 * sure exposure events get sent.
751 if (fastBox
.x1
< pSrc
->x
)
753 fastBox
.x1
= pSrc
->x
;
756 if (fastBox
.y1
< pSrc
->y
)
758 fastBox
.y1
= pSrc
->y
;
761 if (fastBox
.x2
> pSrc
->x
+ (int) pSrc
->width
)
763 fastBox
.x2
= pSrc
->x
+ (int) pSrc
->width
;
766 if (fastBox
.y2
> pSrc
->y
+ (int) pSrc
->height
)
768 fastBox
.y2
= pSrc
->y
+ (int) pSrc
->height
;
777 REGION_INIT(pScreen
, &rgnDst
, &fastBox
, 1);
778 REGION_INTERSECT(pScreen
, &rgnDst
, &rgnDst
, prgnSrcClip
);
779 pBox
= REGION_RECTS(&rgnDst
);
780 nBox
= REGION_NUM_RECTS(&rgnDst
);
784 * fastBlit can only be TRUE if we don't need to worry about attempts
785 * to read partial pixels through the destination bank.
788 fastBlit
= pGCPriv
->fastPlane
;
790 fastBlit
= pGCPriv
->fastCopy
;
792 nQueue
= nBox
* pScreenPriv
->maxRects
* 2;
793 pQueue
= Queue
= ALLOCATE_LOCAL_ARRAY(miBankQueue
, nQueue
);
797 for (; nBox
--; pBox
++)
799 ns
= FirstBankOf(pBox
->x1
, pBox
->y1
);
800 nse
= LastBankOf(pBox
->x2
, pBox
->y2
);
801 for (; ns
<= nse
; ns
++)
803 if (!pScreenPriv
->pBanks
[ns
])
806 nBoxClipSrc
= REGION_NUM_RECTS(pScreenPriv
->pBanks
[ns
]);
807 pBoxClipSrc
= REGION_RECTS(pScreenPriv
->pBanks
[ns
]);
809 for (; nBoxClipSrc
--; pBoxClipSrc
++)
811 cx1
= max(pBox
->x1
, pBoxClipSrc
->x1
);
812 cy1
= max(pBox
->y1
, pBoxClipSrc
->y1
);
813 cx2
= min(pBox
->x2
, pBoxClipSrc
->x2
);
814 cy2
= min(pBox
->y2
, pBoxClipSrc
->y2
);
816 /* Check to see if the region is empty */
817 if ((cx1
>= cx2
) || (cy1
>= cy2
))
820 /* Translate c[xy]* to destination coordinates */
826 nd
= FirstBankOf(cx1
, cy1
);
827 nde
= LastBankOf(cx2
, cy2
);
828 for (; nd
<= nde
; nd
++)
830 if (!pGCPriv
->pBankedClips
[nd
])
834 * Clients can send quite large clip descriptions,
835 * so use the bank clips here instead.
838 REGION_NUM_RECTS(pScreenPriv
->pBanks
[nd
]);
840 REGION_RECTS(pScreenPriv
->pBanks
[nd
]);
842 for (; nBoxClipDst
--; pBoxClipDst
++)
844 ccBox
.x1
= max(cx1
, pBoxClipDst
->x1
);
845 ccBox
.y1
= max(cy1
, pBoxClipDst
->y1
);
846 ccBox
.x2
= min(cx2
, pBoxClipDst
->x2
);
847 ccBox
.y2
= min(cy2
, pBoxClipDst
->y2
);
849 /* Check to see if the region is empty */
850 if ((ccBox
.x1
>= ccBox
.x2
) ||
851 (ccBox
.y1
>= ccBox
.y2
))
854 pQueue
->srcBankNo
= ns
;
855 pQueue
->dstBankNo
= nd
;
856 pQueue
->x
= ccBox
.x1
- xorg
;
857 pQueue
->y
= ccBox
.y1
- yorg
;
858 pQueue
->w
= ccBox
.x2
- ccBox
.x1
;
859 pQueue
->h
= ccBox
.y2
- ccBox
.y1
;
861 if (maxWidth
< pQueue
->w
)
862 maxWidth
= pQueue
->w
;
863 if (maxHeight
< pQueue
->h
)
864 maxHeight
= pQueue
->h
;
867 * When shared banking is used and the source
868 * and destination banks differ, prevent
869 * attempts to fetch partial scanline pad units
870 * through the destination bank.
872 pQueue
->fastBlit
= fastBlit
;
874 (pScreenPriv
->type
== BANK_SHARED
) &&
877 pScreenPriv
->nPixelsPerScanlinePadUnit
) ||
879 pScreenPriv
->nPixelsPerScanlinePadUnit
) ||
880 (RECT_IN_REGION(pScreen
,
881 pGCPriv
->pBankedClips
[nd
], &ccBox
) !=
883 pQueue
->fastBlit
= FALSE
;
894 REGION_UNINIT(pScreen
, &rgnDst
);
896 REGION_DESTROY(pScreen
, prgnSrcClip
);
900 nQueue
= pQueue
- Queue
;
909 ((pSrc
== pDst
) || (pGC
->subWindowMode
== IncludeInferiors
)))
911 if ((srcy
+ pSrc
->y
) < (dsty
+ yorg
))
913 /* Sort from bottom to top */
914 pQueueBase
= pQueueNext
= pQueue
+ nQueue
- 1;
916 while (pQueueBase
>= pQueue
)
918 while ((pQueueNext
>= pQueue
) &&
919 (pQueueBase
->y
== pQueueNext
->y
))
922 pQueueTmp
= pQueueNext
+ 1;
923 while (pQueueTmp
<= pQueueBase
)
924 *pQueueNew
++ = *pQueueTmp
++;
926 pQueueBase
= pQueueNext
;
934 if ((srcx
+ pSrc
->x
) < (dstx
+ xorg
))
936 /* Sort from right to left */
937 pQueueBase
= pQueueNext
= pQueue
;
939 while (pQueueBase
< pQueue
+ nQueue
)
941 while ((pQueueNext
< pQueue
+ nQueue
) &&
942 (pQueueNext
->y
== pQueueBase
->y
))
945 pQueueTmp
= pQueueNext
;
946 while (pQueueTmp
!= pQueueBase
)
947 *pQueueNew
++ = *--pQueueTmp
;
949 pQueueBase
= pQueueNext
;
957 paddedWidth
= PixmapBytePad(maxWidth
,
958 pScreenPriv
->pScreenPixmap
->drawable
.depth
);
959 pImage
= (char *)ALLOCATE_LOCAL(paddedWidth
* maxHeight
);
961 pGC
->fExpose
= FALSE
;
965 pGC
->pCompositeClip
= pGCPriv
->pBankedClips
[pQueue
->dstBankNo
];
969 if (pQueue
->srcBankNo
== pQueue
->dstBankNo
)
971 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
,
972 -1, -1, pQueue
->srcBankNo
);
975 (*pGC
->ops
->CopyPlane
)(pSrc
, pDst
, pGC
,
976 pQueue
->x
- dx
- pSrc
->x
, pQueue
->y
- dy
- pSrc
->y
,
977 pQueue
->w
, pQueue
->h
, pQueue
->x
, pQueue
->y
, plane
);
979 (*pGC
->ops
->CopyArea
)(pSrc
, pDst
, pGC
,
980 pQueue
->x
- dx
- pSrc
->x
, pQueue
->y
- dy
- pSrc
->y
,
981 pQueue
->w
, pQueue
->h
, pQueue
->x
, pQueue
->y
);
983 else if (pQueue
->fastBlit
)
985 SET_SOURCE_BANK (pScreenPriv
->pBankPixmap
,
986 pScreenPriv
->pScreenPixmap
->drawable
.width
,
987 pScreenPriv
->pScreenPixmap
->devKind
,
989 SET_DESTINATION_BANK(pScreenPriv
->pScreenPixmap
,
990 -1, -1, pQueue
->dstBankNo
);
993 (*pGC
->ops
->CopyPlane
)(
994 (DrawablePtr
)pScreenPriv
->pBankPixmap
, pDst
, pGC
,
995 pQueue
->x
- dx
, pQueue
->y
- dy
,
996 pQueue
->w
, pQueue
->h
, pQueue
->x
, pQueue
->y
, plane
);
998 (*pGC
->ops
->CopyArea
)(
999 (DrawablePtr
)pScreenPriv
->pBankPixmap
, pDst
, pGC
,
1000 pQueue
->x
- dx
, pQueue
->y
- dy
,
1001 pQueue
->w
, pQueue
->h
, pQueue
->x
, pQueue
->y
);
1005 ModifyPixmap(pScreenPriv
->pBankPixmap
,
1006 maxWidth
, paddedWidth
, pImage
);
1008 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
,
1009 -1, -1, pQueue
->srcBankNo
);
1011 (*pScreenPriv
->pBankGC
->ops
->CopyArea
)(
1012 pSrc
, (DrawablePtr
)pScreenPriv
->pBankPixmap
,
1013 pScreenPriv
->pBankGC
,
1014 pQueue
->x
- dx
- pSrc
->x
, pQueue
->y
- dy
- pSrc
->y
,
1015 pQueue
->w
, pQueue
->h
, 0, 0);
1017 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
,
1018 -1, -1, pQueue
->dstBankNo
);
1021 (*pGC
->ops
->CopyPlane
)(
1022 (DrawablePtr
)pScreenPriv
->pBankPixmap
,
1023 pDst
, pGC
, 0, 0, pQueue
->w
, pQueue
->h
,
1024 pQueue
->x
, pQueue
->y
, plane
);
1026 (*pGC
->ops
->CopyArea
)(
1027 (DrawablePtr
)pScreenPriv
->pBankPixmap
,
1028 pDst
, pGC
, 0, 0, pQueue
->w
, pQueue
->h
,
1029 pQueue
->x
, pQueue
->y
);
1037 DEALLOCATE_LOCAL(pImage
);
1044 pGC
->fExpose
= fExpose
;
1046 DEALLOCATE_LOCAL(Queue
);
1051 if (!fExpose
|| fastExpose
)
1054 return miHandleExposures(pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
, 0);
1070 return miBankCopy(pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
, 0, FALSE
);
1088 miBankCopy(pSrc
, pDst
, pGC
, srcx
, srcy
, w
, h
, dstx
, dsty
, plane
, TRUE
);
1093 DrawablePtr pDrawable
,
1100 # define GCOP_ARGS GCOP_0D_ARGS
1101 GCOP_COMPLEX(PolyPoint
, xPoint
);
1107 DrawablePtr pDrawable
,
1114 # define GCOP_ARGS GCOP_0D_ARGS
1115 GCOP_COMPLEX(Polylines
, DDXPointRec
);
1121 DrawablePtr pDrawable
,
1127 # define GCOP_ARGS GCOP_1D_ARGS
1128 GCOP_COMPLEX(PolySegment
, xSegment
);
1133 miBankPolyRectangle(
1134 DrawablePtr pDrawable
,
1140 # define GCOP_ARGS GCOP_1D_ARGS
1141 GCOP_COMPLEX(PolyRectangle
, xRectangle
);
1147 DrawablePtr pDrawable
,
1153 # define GCOP_ARGS GCOP_1D_ARGS
1154 GCOP_COMPLEX(PolyArc
, xArc
);
1160 DrawablePtr pDrawable
,
1168 # define GCOP_ARGS GCOP_2D_ARGS
1169 GCOP_COMPLEX(FillPolygon
, DDXPointRec
);
1175 DrawablePtr pDrawable
,
1181 # define GCOP_ARGS GCOP_1D_ARGS
1182 GCOP_COMPLEX(PolyFillRect
, xRectangle
);
1188 DrawablePtr pDrawable
,
1194 # define GCOP_ARGS GCOP_1D_ARGS
1195 GCOP_COMPLEX(PolyFillArc
, xArc
);
1201 DrawablePtr pDrawable
,
1211 GCOP_SIMPLE(retval
=
1212 (*pGC
->ops
->PolyText8
)(pDrawable
, pGC
, x
, y
, nArray
, pchar
));
1219 DrawablePtr pDrawable
,
1224 unsigned short *pchar
1229 GCOP_SIMPLE(retval
=
1230 (*pGC
->ops
->PolyText16
)(pDrawable
, pGC
, x
, y
, nArray
, pchar
));
1237 DrawablePtr pDrawable
,
1245 GCOP_SIMPLE((*pGC
->ops
->ImageText8
)(pDrawable
, pGC
, x
, y
, nArray
, pchar
));
1250 DrawablePtr pDrawable
,
1255 unsigned short *pchar
1258 GCOP_SIMPLE((*pGC
->ops
->ImageText16
)(pDrawable
, pGC
, x
, y
, nArray
, pchar
));
1262 miBankImageGlyphBlt(
1263 DrawablePtr pDrawable
,
1267 unsigned int nArray
,
1272 GCOP_SIMPLE((*pGC
->ops
->ImageGlyphBlt
)(pDrawable
, pGC
,
1273 x
, y
, nArray
, ppci
, pglyphBase
));
1278 DrawablePtr pDrawable
,
1282 unsigned int nArray
,
1287 GCOP_SIMPLE((*pGC
->ops
->PolyGlyphBlt
)(pDrawable
, pGC
,
1288 x
, y
, nArray
, ppci
, pglyphBase
));
1295 DrawablePtr pDrawable
,
1302 if ((w
> 0) && (h
> 0))
1307 if (!IS_BANKED(pDrawable
))
1311 (*pGC
->ops
->PushPixels
)(pGC
, pBitmap
, pDrawable
, w
, h
, x
, y
);
1321 i
= FirstBankOf(x
, y
);
1322 j
= LastBankOf(x
+ w
, y
+ h
);
1325 if (!(pGC
->pCompositeClip
= pGCPriv
->pBankedClips
[i
]))
1330 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, i
);
1332 (*pGC
->ops
->PushPixels
)(pGC
, pBitmap
, pDrawable
, w
, h
, x
, y
);
1344 static GCOps miBankGCOps
=
1354 miBankPolyRectangle
,
1363 miBankImageGlyphBlt
,
1366 {NULL
} /* devPrivate */
1369 /********************
1370 * GCFuncs wrappers *
1371 ********************/
1376 unsigned long changes
,
1377 DrawablePtr pDrawable
1383 (*pGC
->funcs
->ValidateGC
)(pGC
, changes
, pDrawable
);
1385 if ((changes
& (GCClipXOrigin
|GCClipYOrigin
|GCClipMask
|GCSubwindowMode
)) ||
1386 (pDrawable
->serialNumber
!= (pGC
->serialNumber
& DRAWABLE_SERIAL_BITS
)))
1388 ScreenPtr pScreen
= pGC
->pScreen
;
1390 unsigned long planemask
;
1396 if (IS_BANKED(pDrawable
))
1398 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
1400 if (!pScreenPriv
->pBanks
[i
])
1403 if (!(prgnClip
= pGCPriv
->pBankedClips
[i
]))
1404 prgnClip
= REGION_CREATE(pScreen
, NULL
, 1);
1406 REGION_INTERSECT(pScreen
, prgnClip
,
1407 pScreenPriv
->pBanks
[i
], pGC
->pCompositeClip
);
1409 if ((REGION_NUM_RECTS(prgnClip
) <= 1) &&
1410 ((prgnClip
->extents
.x1
== prgnClip
->extents
.x2
) ||
1411 (prgnClip
->extents
.y1
== prgnClip
->extents
.y2
)))
1413 REGION_DESTROY(pScreen
, prgnClip
);
1414 pGCPriv
->pBankedClips
[i
] = NULL
;
1417 pGCPriv
->pBankedClips
[i
] = prgnClip
;
1421 * fastCopy and fastPlane can only be TRUE if we don't need to
1422 * worry about attempts to read partial pixels through the
1425 switch (pScreenPriv
->type
)
1428 pGCPriv
->fastCopy
= pGCPriv
->fastPlane
= FALSE
;
1430 if ((pGC
->alu
!= GXclear
) && (pGC
->alu
!= GXcopy
) &&
1431 (pGC
->alu
!= GXcopyInverted
) && (pGC
->alu
!= GXset
))
1434 if (pScreen
->rootDepth
== 1)
1435 pGCPriv
->fastPlane
= TRUE
;
1437 /* This is probably paranoia */
1438 if ((pDrawable
->depth
!= pScreen
->rootDepth
) ||
1439 (pDrawable
->depth
!= pGC
->depth
))
1442 planemask
= (1 << pGC
->depth
) - 1;
1443 if ((pGC
->planemask
& planemask
) == planemask
)
1444 pGCPriv
->fastCopy
= TRUE
;
1449 pGCPriv
->fastCopy
= pGCPriv
->fastPlane
= TRUE
;
1453 pGCPriv
->fastCopy
= pGCPriv
->fastPlane
= FALSE
;
1460 * Here we are on a pixmap and don't need all that special clipping
1461 * stuff, hence free it.
1463 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
1465 if (!pGCPriv
->pBankedClips
[i
])
1468 REGION_DESTROY(pScreen
, pGCPriv
->pBankedClips
[i
]);
1469 pGCPriv
->pBankedClips
[i
] = NULL
;
1488 (*pGC
->funcs
->ChangeGC
)(pGC
, mask
);
1503 (*pGCDst
->funcs
->CopyGC
)(pGCSrc
, mask
, pGCDst
);
1513 ScreenPtr pScreen
= pGC
->pScreen
;
1520 (*pGC
->funcs
->DestroyGC
)(pGC
);
1522 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
1524 if (!pGCPriv
->pBankedClips
[i
])
1527 REGION_DESTROY(pScreen
, pGCPriv
->pBankedClips
[i
]);
1528 pGCPriv
->pBankedClips
[i
] = NULL
;
1545 (*pGC
->funcs
->ChangeClip
)(pGC
, type
, pvalue
, nrects
);
1558 (*pGC
->funcs
->DestroyClip
)(pGC
);
1572 (*pGCDst
->funcs
->CopyClip
)(pGCDst
, pGCSrc
);
1577 static GCFuncs miBankGCFuncs
=
1588 /*******************
1590 *******************/
1593 miBankCreateScreenResources(
1600 SCREEN_UNWRAP(CreateScreenResources
);
1602 if ((retval
= (*pScreen
->CreateScreenResources
)(pScreen
)))
1604 /* Set screen buffer address to something recognizable */
1605 pScreenPriv
->pScreenPixmap
= (*pScreen
->GetScreenPixmap
)(pScreen
);
1606 pScreenPriv
->pbits
= pScreenPriv
->pScreenPixmap
->devPrivate
.ptr
;
1607 pScreenPriv
->pScreenPixmap
->devPrivate
.ptr
= (pointer
)pScreenPriv
;
1609 /* Get shadow pixmap; width & height of 0 means no pixmap data */
1610 pScreenPriv
->pBankPixmap
= (*pScreen
->CreatePixmap
)(pScreen
, 0, 0,
1611 pScreenPriv
->pScreenPixmap
->drawable
.depth
);
1612 if (!pScreenPriv
->pBankPixmap
)
1616 /* Shadow the screen */
1618 retval
= (*pScreen
->ModifyPixmapHeader
)(pScreenPriv
->pBankPixmap
,
1619 pScreenPriv
->pScreenPixmap
->drawable
.width
,
1620 pScreenPriv
->pScreenPixmap
->drawable
.height
,
1621 pScreenPriv
->pScreenPixmap
->drawable
.depth
,
1622 pScreenPriv
->pScreenPixmap
->drawable
.bitsPerPixel
,
1623 pScreenPriv
->pScreenPixmap
->devKind
, NULL
);
1625 /* Create shadow GC */
1628 pScreenPriv
->pBankGC
= CreateScratchGC(pScreen
,
1629 pScreenPriv
->pBankPixmap
->drawable
.depth
);
1630 if (!pScreenPriv
->pBankGC
)
1634 /* Validate shadow GC */
1637 pScreenPriv
->pBankGC
->graphicsExposures
= FALSE
;
1638 pScreenPriv
->pBankGC
->subWindowMode
= IncludeInferiors
;
1639 ValidateGC((DrawablePtr
)pScreenPriv
->pBankPixmap
,
1640 pScreenPriv
->pBankGC
);
1643 SCREEN_WRAP(CreateScreenResources
, miBankCreateScreenResources
);
1649 miBankModifyPixmapHeader(
1659 Bool retval
= FALSE
;
1663 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
1666 PIXMAP_SAVE(pPixmap
);
1667 SCREEN_UNWRAP(ModifyPixmapHeader
);
1669 retval
= (*pScreen
->ModifyPixmapHeader
)(pPixmap
, width
, height
,
1670 depth
, bitsPerPixel
, devKind
, pPixData
);
1672 SCREEN_WRAP(ModifyPixmapHeader
, miBankModifyPixmapHeader
);
1674 if (pbits
== (pointer
)pScreenPriv
)
1676 pScreenPriv
->pbits
= pPixmap
->devPrivate
.ptr
;
1677 pPixmap
->devPrivate
.ptr
= pbits
;
1694 /* Free shadow GC */
1695 FreeScratchGC(pScreenPriv
->pBankGC
);
1697 /* Free shadow pixmap */
1698 (*pScreen
->DestroyPixmap
)(pScreenPriv
->pBankPixmap
);
1700 /* Restore screen pixmap devPrivate pointer */
1701 pScreenPriv
->pScreenPixmap
->devPrivate
.ptr
= pScreenPriv
->pbits
;
1703 /* Delete bank clips */
1704 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
1705 if (pScreenPriv
->pBanks
[i
])
1706 REGION_DESTROY(pScreen
, pScreenPriv
->pBanks
[i
]);
1708 Xfree(pScreenPriv
->pBanks
);
1710 SCREEN_UNWRAP(CreateScreenResources
);
1711 SCREEN_UNWRAP(ModifyPixmapHeader
);
1712 SCREEN_UNWRAP(CloseScreen
);
1713 SCREEN_UNWRAP(GetImage
);
1714 SCREEN_UNWRAP(GetSpans
);
1715 SCREEN_UNWRAP(CreateGC
);
1716 SCREEN_UNWRAP(PaintWindowBackground
);
1717 SCREEN_UNWRAP(PaintWindowBorder
);
1718 SCREEN_UNWRAP(CopyWindow
);
1719 SCREEN_UNWRAP(BackingStoreFuncs
);
1722 return (*pScreen
->CloseScreen
)(nIndex
, pScreen
);
1727 DrawablePtr pDrawable
,
1732 unsigned int format
,
1733 unsigned long planemask
,
1737 if ((w
> 0) && (h
> 0))
1739 ScreenPtr pScreen
= pDrawable
->pScreen
;
1743 SCREEN_UNWRAP(GetImage
);
1745 if (!IS_BANKED(pDrawable
))
1747 (*pScreen
->GetImage
)(pDrawable
, sx
, sy
, w
, h
,
1748 format
, planemask
, pImage
);
1755 paddedWidth
= PixmapBytePad(w
,
1756 pScreenPriv
->pScreenPixmap
->drawable
.depth
);
1757 pBankImage
= (char *)ALLOCATE_LOCAL(paddedWidth
* h
);
1763 ModifyPixmap(pScreenPriv
->pBankPixmap
, w
, paddedWidth
,
1766 (*pScreenPriv
->pBankGC
->ops
->CopyArea
)(
1767 (DrawablePtr
)WindowTable
[pScreen
->myNum
],
1768 (DrawablePtr
)pScreenPriv
->pBankPixmap
,
1769 pScreenPriv
->pBankGC
,
1770 sx
+ pDrawable
->x
, sy
+ pDrawable
->y
, w
, h
, 0, 0);
1772 (*pScreen
->GetImage
)((DrawablePtr
)pScreenPriv
->pBankPixmap
,
1773 0, 0, w
, h
, format
, planemask
, pImage
);
1777 DEALLOCATE_LOCAL(pBankImage
);
1781 SCREEN_WRAP(GetImage
, miBankGetImage
);
1787 DrawablePtr pDrawable
,
1797 ScreenPtr pScreen
= pDrawable
->pScreen
;
1801 SCREEN_UNWRAP(GetSpans
);
1803 if (!IS_BANKED(pDrawable
))
1805 (*pScreen
->GetSpans
)(pDrawable
, wMax
, ppt
, pwidth
, nspans
, pImage
);
1816 PixmapBytePad(pScreenPriv
->pScreenPixmap
->drawable
.width
,
1817 pScreenPriv
->pScreenPixmap
->drawable
.depth
);
1818 pBankImage
= (char *)ALLOCATE_LOCAL(paddedWidth
);
1824 ModifyPixmap(pScreenPriv
->pBankPixmap
,
1825 pScreenPriv
->pScreenPixmap
->drawable
.width
,
1826 paddedWidth
, pBankImage
);
1828 for (; nspans
--; ppt
++, pwidth
++)
1833 (*pScreenPriv
->pBankGC
->ops
->CopyArea
)(
1834 (DrawablePtr
)WindowTable
[pScreen
->myNum
],
1835 (DrawablePtr
)pScreenPriv
->pBankPixmap
,
1836 pScreenPriv
->pBankGC
,
1837 ppt
->x
, ppt
->y
, *pwidth
, 1, 0, 0);
1839 (*pScreen
->GetSpans
)((DrawablePtr
)pScreenPriv
->pBankPixmap
,
1840 wMax
, &pt
, pwidth
, 1, pImage
);
1842 pImage
= pImage
+ PixmapBytePad(*pwidth
, pDrawable
->depth
);
1847 DEALLOCATE_LOCAL(pBankImage
);
1851 SCREEN_WRAP(GetSpans
, miBankGetSpans
);
1860 ScreenPtr pScreen
= pGC
->pScreen
;
1861 miBankGCPtr pGCPriv
= BANK_GCPRIVATE(pGC
);
1865 SCREEN_UNWRAP(CreateGC
);
1867 if ((ret
= (*pScreen
->CreateGC
)(pGC
)))
1869 pGCPriv
->unwrappedOps
= &miBankGCOps
;
1870 pGCPriv
->unwrappedFuncs
= &miBankGCFuncs
;
1873 memset(&pGCPriv
->pBankedClips
, 0,
1874 pScreenPriv
->nBanks
* sizeof(pGCPriv
->pBankedClips
));
1877 SCREEN_WRAP(CreateGC
, miBankCreateGC
);
1889 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
1892 PaintWindowProcPtr PaintWindow
;
1897 if (what
== PW_BORDER
)
1899 SCREEN_UNWRAP(PaintWindowBorder
);
1900 PaintWindow
= pScreen
->PaintWindowBorder
;
1904 SCREEN_UNWRAP(PaintWindowBackground
);
1905 PaintWindow
= pScreen
->PaintWindowBackground
;
1908 if (!IS_BANKED(pWin
))
1910 (*PaintWindow
)(pWin
, pRegion
, what
);
1914 REGION_NULL(pScreen
, &tmpReg
);
1916 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
1918 if (!pScreenPriv
->pBanks
[i
])
1921 REGION_INTERSECT(pScreen
, &tmpReg
, pRegion
,
1922 pScreenPriv
->pBanks
[i
]);
1924 if (REGION_NIL(&tmpReg
))
1927 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, i
);
1929 (*PaintWindow
)(pWin
, &tmpReg
, what
);
1932 REGION_UNINIT(pScreen
, &tmpReg
);
1935 if (what
== PW_BORDER
)
1937 SCREEN_WRAP(PaintWindowBorder
, miBankPaintWindow
);
1941 SCREEN_WRAP(PaintWindowBackground
, miBankPaintWindow
);
1950 DDXPointRec ptOldOrg
,
1954 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
1957 DrawablePtr pDrawable
= (DrawablePtr
)WindowTable
[pScreen
->myNum
];
1959 BoxPtr pBox
, pBoxTmp
, pBoxNext
, pBoxBase
, pBoxNew1
, pBoxNew2
;
1960 XID subWindowMode
= IncludeInferiors
;
1962 pGC
= GetScratchGC(pDrawable
->depth
, pScreen
);
1964 ChangeGC(pGC
, GCSubwindowMode
, &subWindowMode
);
1965 ValidateGC(pDrawable
, pGC
);
1967 pRgnDst
= REGION_CREATE(pScreen
, NULL
, 1);
1969 dx
= ptOldOrg
.x
- pWindow
->drawable
.x
;
1970 dy
= ptOldOrg
.y
- pWindow
->drawable
.y
;
1971 REGION_TRANSLATE(pScreen
, pRgnSrc
, -dx
, -dy
);
1972 REGION_INTERSECT(pScreen
, pRgnDst
, &pWindow
->borderClip
, pRgnSrc
);
1974 pBox
= REGION_RECTS(pRgnDst
);
1975 nBox
= REGION_NUM_RECTS(pRgnDst
);
1984 /* Sort boxes from bottom to top */
1985 pBoxNew1
= ALLOCATE_LOCAL_ARRAY(BoxRec
, nBox
);
1989 pBoxBase
= pBoxNext
= pBox
+ nBox
- 1;
1991 while (pBoxBase
>= pBox
)
1993 while ((pBoxNext
>= pBox
) &&
1994 (pBoxBase
->y1
== pBoxNext
->y1
))
1997 pBoxTmp
= pBoxNext
+ 1;
1999 while (pBoxTmp
<= pBoxBase
)
2000 *pBoxNew1
++ = *pBoxTmp
++;
2002 pBoxBase
= pBoxNext
;
2012 /* Sort boxes from right to left */
2013 pBoxNew2
= ALLOCATE_LOCAL_ARRAY(BoxRec
, nBox
);
2017 pBoxBase
= pBoxNext
= pBox
;
2019 while (pBoxBase
< pBox
+ nBox
)
2021 while ((pBoxNext
< pBox
+ nBox
) &&
2022 (pBoxNext
->y1
== pBoxBase
->y1
))
2027 while (pBoxTmp
!= pBoxBase
)
2028 *pBoxNew2
++ = *--pBoxTmp
;
2030 pBoxBase
= pBoxNext
;
2041 (*pGC
->ops
->CopyArea
)(pDrawable
, pDrawable
, pGC
,
2042 pBox
->x1
+ dx
, pBox
->y1
+ dy
,
2043 pBox
->x2
- pBox
->x1
, pBox
->y2
- pBox
->y1
,
2044 pBox
->x1
, pBox
->y1
);
2051 REGION_DESTROY(pScreen
, pRgnDst
);
2053 DEALLOCATE_LOCAL(pBoxNew2
);
2054 DEALLOCATE_LOCAL(pBoxNew1
);
2057 /**************************
2058 * Backing store wrappers *
2059 **************************/
2070 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
2071 RegionRec rgnClipped
;
2076 SCREEN_UNWRAP(BackingStoreFuncs
.SaveAreas
);
2078 if (!IS_BANKED(pWin
))
2080 (*pScreen
->BackingStoreFuncs
.SaveAreas
)(pPixmap
, prgnSave
, xorg
, yorg
,
2085 REGION_NULL(pScreen
, &rgnClipped
);
2086 REGION_TRANSLATE(pScreen
, prgnSave
, xorg
, yorg
);
2088 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
2090 if (!pScreenPriv
->pBanks
[i
])
2093 REGION_INTERSECT(pScreen
, &rgnClipped
,
2094 prgnSave
, pScreenPriv
->pBanks
[i
]);
2096 if (REGION_NIL(&rgnClipped
))
2099 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, i
);
2101 REGION_TRANSLATE(pScreen
, &rgnClipped
, -xorg
, -yorg
);
2103 (*pScreen
->BackingStoreFuncs
.SaveAreas
)(pPixmap
, &rgnClipped
,
2107 REGION_TRANSLATE(pScreen
, prgnSave
, -xorg
, -yorg
);
2108 REGION_UNINIT(pScreen
, &rgnClipped
);
2111 SCREEN_WRAP(BackingStoreFuncs
.SaveAreas
, miBankSaveAreas
);
2118 RegionPtr prgnRestore
,
2124 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
2125 RegionRec rgnClipped
;
2130 SCREEN_UNWRAP(BackingStoreFuncs
.RestoreAreas
);
2132 if (!IS_BANKED(pWin
))
2134 (*pScreen
->BackingStoreFuncs
.RestoreAreas
)(pPixmap
, prgnRestore
,
2139 REGION_NULL(pScreen
, &rgnClipped
);
2141 for (i
= 0; i
< pScreenPriv
->nBanks
; i
++)
2143 if (!pScreenPriv
->pBanks
[i
])
2146 REGION_INTERSECT(pScreen
, &rgnClipped
,
2147 prgnRestore
, pScreenPriv
->pBanks
[i
]);
2149 if (REGION_NIL(&rgnClipped
))
2152 SET_SINGLE_BANK(pScreenPriv
->pScreenPixmap
, -1, -1, i
);
2154 (*pScreen
->BackingStoreFuncs
.RestoreAreas
)(pPixmap
, &rgnClipped
,
2158 REGION_UNINIT(pScreen
, &rgnClipped
);
2161 SCREEN_WRAP(BackingStoreFuncs
.RestoreAreas
, miBankRestoreAreas
);
2166 miInitializeBanking(
2171 miBankInfoPtr pBankInfo
2174 miBankScreenPtr pScreenPriv
;
2175 unsigned long nBitsPerBank
, nBitsPerScanline
, nPixelsPerScanlinePadUnit
;
2176 unsigned long BankBase
, ServerPad
;
2177 unsigned int type
, iBank
, nBanks
, maxRects
, we
, nBankBPP
;
2180 if (!pBankInfo
|| !pBankInfo
->BankSize
)
2181 return TRUE
; /* No banking required */
2185 if (!pScreen
|| !xsize
|| !ysize
|| (xsize
> width
) ||
2186 !pBankInfo
->SetSourceBank
|| !pBankInfo
->SetDestinationBank
||
2187 !pBankInfo
->SetSourceAndDestinationBanks
||
2188 !pBankInfo
->pBankA
|| !pBankInfo
->pBankB
||
2189 !pBankInfo
->nBankDepth
)
2193 * DDX *must* have registered a pixmap format whose depth is
2194 * pBankInfo->nBankDepth. This is not necessarily the rootDepth
2198 while (screenInfo
.formats
[i
].depth
!= pBankInfo
->nBankDepth
)
2199 if (++i
>= screenInfo
.numPixmapFormats
)
2201 nBankBPP
= screenInfo
.formats
[i
].bitsPerPixel
;
2204 while (screenInfo
.formats
[i
].depth
!= pScreen
->rootDepth
)
2205 if (++i
>= screenInfo
.numPixmapFormats
)
2208 if (nBankBPP
> screenInfo
.formats
[i
].bitsPerPixel
)
2211 /* Determine banking type */
2212 if ((type
= miBankDeriveType(pScreen
, pBankInfo
)) == BANK_NOBANK
)
2217 nBitsPerBank
= pBankInfo
->BankSize
* 8;
2218 ServerPad
= PixmapBytePad(1, pBankInfo
->nBankDepth
) * 8;
2219 if (nBitsPerBank
% ServerPad
)
2221 nBitsPerScanline
= PixmapBytePad(width
, pBankInfo
->nBankDepth
) * 8;
2222 nBanks
= ((nBitsPerScanline
* (ysize
- 1)) +
2223 (nBankBPP
* xsize
) + nBitsPerBank
- 1) / nBitsPerBank
;
2224 nPixelsPerScanlinePadUnit
= miLCM(ServerPad
, nBankBPP
) / nBankBPP
;
2228 if (miBankGeneration
!= serverGeneration
)
2230 if (((miBankScreenIndex
= AllocateScreenPrivateIndex()) < 0) ||
2231 ((miBankGCIndex
= AllocateGCPrivateIndex()) < 0))
2234 miBankGeneration
= serverGeneration
;
2237 if (!AllocateGCPrivate(pScreen
, miBankGCIndex
,
2238 (nBanks
* sizeof(RegionPtr
)) +
2239 (sizeof(miBankGCRec
) - sizeof(RegionPtr
))))
2242 if (!(pScreenPriv
= (miBankScreenPtr
)Xcalloc(sizeof(miBankScreenRec
))))
2245 if (!(pScreenPriv
->pBanks
= /* Allocate and clear */
2246 (RegionPtr
*)Xcalloc(nBanks
* sizeof(RegionPtr
))))
2253 * Translate banks into clipping regions which are themselves clipped
2254 * against the screen. This also ensures that pixels with imbedded bank
2255 * boundaries are off-screen.
2261 for (iBank
= 0; iBank
< nBanks
; iBank
++)
2263 xRectangle pRects
[3], *pRect
= pRects
;
2264 unsigned int xb
, yb
, xe
, ye
;
2266 xb
= ((BankBase
+ nBankBPP
- 1) % nBitsPerScanline
) / nBankBPP
;
2267 yb
= (BankBase
+ nBankBPP
- 1) / nBitsPerScanline
;
2282 BankBase
+= nBitsPerBank
;
2284 we
= (BankBase
% nBitsPerScanline
) % nBankBPP
;
2285 xe
= (BankBase
% nBitsPerScanline
) / nBankBPP
;
2286 ye
= BankBase
/ nBitsPerScanline
;
2305 pRect
->width
= xe
- xb
;
2316 pRect
->width
= xsize
- xb
;
2326 pRect
->width
= xsize
;
2327 pRect
->height
= ye
- yb
;
2328 maxRects
+= min(pRect
->height
, 3) + 1;
2343 pScreenPriv
->pBanks
[iBank
] =
2344 RECTS_TO_REGION(pScreen
, pRect
- pRects
, pRects
, 0);
2345 if (!pScreenPriv
->pBanks
[iBank
] ||
2346 REGION_NAR(pScreenPriv
->pBanks
[iBank
]))
2353 if (we
&& (iBank
< nBanks
))
2355 for (i
= iBank
; i
>= 0; i
--)
2356 if (pScreenPriv
->pBanks
[i
])
2357 REGION_DESTROY(pScreen
, pScreenPriv
->pBanks
[i
]);
2359 Xfree(pScreenPriv
->pBanks
);
2365 /* Open for business */
2367 pScreenPriv
->type
= type
;
2368 pScreenPriv
->nBanks
= nBanks
;
2369 pScreenPriv
->maxRects
= maxRects
;
2370 pScreenPriv
->nBankBPP
= nBankBPP
;
2371 pScreenPriv
->BankInfo
= *pBankInfo
;
2372 pScreenPriv
->nBitsPerBank
= nBitsPerBank
;
2373 pScreenPriv
->nBitsPerScanline
= nBitsPerScanline
;
2374 pScreenPriv
->nPixelsPerScanlinePadUnit
= nPixelsPerScanlinePadUnit
;
2376 SCREEN_WRAP(CreateScreenResources
, miBankCreateScreenResources
);
2377 SCREEN_WRAP(ModifyPixmapHeader
, miBankModifyPixmapHeader
);
2378 SCREEN_WRAP(CloseScreen
, miBankCloseScreen
);
2379 SCREEN_WRAP(GetImage
, miBankGetImage
);
2380 SCREEN_WRAP(GetSpans
, miBankGetSpans
);
2381 SCREEN_WRAP(CreateGC
, miBankCreateGC
);
2382 SCREEN_WRAP(PaintWindowBackground
, miBankPaintWindow
);
2383 SCREEN_WRAP(PaintWindowBorder
, miBankPaintWindow
);
2384 SCREEN_WRAP(CopyWindow
, miBankCopyWindow
);
2386 pScreenPriv
->BackingStoreFuncs
= pScreen
->BackingStoreFuncs
;
2388 pScreen
->BackingStoreFuncs
.SaveAreas
= miBankSaveAreas
;
2389 pScreen
->BackingStoreFuncs
.RestoreAreas
= miBankRestoreAreas
;
2390 /* ??????????????????????????????????????????????????????????????
2391 pScreen->BackingStoreFuncs.SetClipmaskRgn = miBankSetClipmaskRgn;
2392 ?????????????????????????????????????????????????????????????? */
2394 BANK_SCRPRIVLVAL
= (pointer
)pScreenPriv
;
2399 /* This is used to force GC revalidation when the banking type is changed */
2402 miBankNewSerialNumber(
2407 pWin
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
2408 return WT_WALKCHILDREN
;
2411 /* This entry modifies the banking interface */
2415 miBankInfoPtr pBankInfo
2423 if (miBankGeneration
== serverGeneration
)
2429 if (!pBankInfo
|| !pBankInfo
->BankSize
||
2430 !pBankInfo
->pBankA
|| !pBankInfo
->pBankB
||
2431 !pBankInfo
->SetSourceBank
|| !pBankInfo
->SetDestinationBank
||
2432 !pBankInfo
->SetSourceAndDestinationBanks
)
2435 /* BankSize and nBankDepth cannot, as yet, be changed */
2436 if ((pScreenPriv
->BankInfo
.BankSize
!= pBankInfo
->BankSize
) ||
2437 (pScreenPriv
->BankInfo
.nBankDepth
!= pBankInfo
->nBankDepth
))
2440 if ((type
= miBankDeriveType(pScreen
, pBankInfo
)) == BANK_NOBANK
)
2443 /* Reset banking info */
2444 pScreenPriv
->BankInfo
= *pBankInfo
;
2445 if (type
!= pScreenPriv
->type
)
2448 * Banking type is changing. Revalidate all window GC's.
2450 pScreenPriv
->type
= type
;
2451 WalkTree(pScreen
, miBankNewSerialNumber
, 0);
2458 if (!pBankInfo
|| !pBankInfo
->BankSize
)
2459 return TRUE
; /* No change requested */
2465 * Given various screen attributes, determine the minimum scanline width such
2466 * that each scanline is server and DDX padded and any pixels with imbedded
2467 * bank boundaries are off-screen. This function returns -1 if such a width
2468 * cannot exist. This function exists because the DDX needs to be able to
2469 * determine this width before initializing a frame buffer.
2473 unsigned int xsize
, /* pixels */
2474 unsigned int ysize
, /* pixels */
2475 unsigned int width
, /* pixels */
2476 unsigned long BankSize
, /* char's */
2477 PixmapFormatRec
*pBankFormat
,
2478 unsigned int nWidthUnit
/* bits */
2481 unsigned long nBitsPerBank
, nBitsPerScanline
, nBitsPerScanlinePadUnit
;
2482 unsigned long minBitsPerScanline
, maxBitsPerScanline
;
2486 if (!nWidthUnit
|| !pBankFormat
)
2489 nBitsPerBank
= BankSize
* 8;
2490 if (nBitsPerBank
% pBankFormat
->scanlinePad
)
2495 nBitsPerScanlinePadUnit
= miLCM(pBankFormat
->scanlinePad
, nWidthUnit
);
2497 (((width
* pBankFormat
->bitsPerPixel
) + nBitsPerScanlinePadUnit
- 1) /
2498 nBitsPerScanlinePadUnit
) * nBitsPerScanlinePadUnit
;
2499 width
= nBitsPerScanline
/ pBankFormat
->bitsPerPixel
;
2501 if (!xsize
|| !(nBitsPerBank
% pBankFormat
->bitsPerPixel
))
2505 * Scanlines will be server-pad aligned at this point. They will also be
2506 * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
2507 * bank boundaries are off-screen.
2509 * It seems reasonable to limit total frame buffer size to 1/16 of the
2510 * theoretical maximum address space size. On a machine with 32-bit
2511 * addresses (to 8-bit quantities) this turns out to be 256MB. Not only
2512 * does this provide a simple limiting condition for the loops below, but
2513 * it also prevents unsigned long wraparounds.
2518 minBitsPerScanline
= xsize
* pBankFormat
->bitsPerPixel
;
2519 if (minBitsPerScanline
> nBitsPerBank
)
2525 maxBitsPerScanline
=
2526 (((unsigned long)(-1) >> 1) - minBitsPerScanline
) / (ysize
- 1);
2527 while (nBitsPerScanline
<= maxBitsPerScanline
)
2529 unsigned long BankBase
, BankUnit
;
2531 BankUnit
= ((nBitsPerBank
+ nBitsPerScanline
- 1) / nBitsPerBank
) *
2533 if (!(BankUnit
% nBitsPerScanline
))
2536 for (BankBase
= BankUnit
; ; BankBase
+= nBitsPerBank
)
2540 y
= BankBase
/ nBitsPerScanline
;
2544 x
= BankBase
% nBitsPerScanline
;
2545 if (!(x
% pBankFormat
->bitsPerPixel
))
2548 if (x
< minBitsPerScanline
)
2551 * Skip ahead certain widths by dividing the excess scanline
2554 y
*= nBitsPerScanlinePadUnit
;
2556 ((x
+ y
- 1) / y
) * nBitsPerScanlinePadUnit
;
2557 width
= nBitsPerScanline
/ pBankFormat
->bitsPerPixel
;
2561 if (BankBase
!= BankUnit
)
2564 if (!(nBitsPerScanline
% x
))
2567 BankBase
= ((nBitsPerScanline
- minBitsPerScanline
) /
2568 (nBitsPerScanline
- x
)) * BankUnit
;