~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to mi/mibank.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
 
3
 *
 
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.
 
13
 *
 
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.
 
21
 */
 
22
 
 
23
/*
 
24
 * Copyright 1990,91,92,93 by Thomas Roell, Germany.
 
25
 * Copyright 1991,92,93    by SGCS (Snitily Graphics Consulting Services), USA.
 
26
 *
 
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.
 
37
 *
 
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.
 
45
 */
 
46
 
 
47
/* $XFree86: xc/programs/Xserver/mi/mibank.c,v 1.15 2003/11/10 18:39:16 tsi Exp $ */
 
48
 
 
49
/*
 
50
 * This thing originated from an idea of Edwin Goei and his bank switching
 
51
 * code for the DEC TX board.
 
52
 */
 
53
 
 
54
/*
 
55
 * Heavily modified for the XFree86 Project to turn this into an mi wrapper.
 
56
 * ---  Marc Aurele La France (tsi@xfree86.org)
 
57
 */
 
58
 
 
59
/*
 
60
 * "Heavily modified", indeed!  By the time this is finalized, there probably
 
61
 * won't be much left of Roell's code...
 
62
 *
 
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
 
66
 *   partial pixels.
 
67
 * - Plans to generalise this to do (hardware) colour plane switching have been
 
68
 *   dropped due to colour flashing concerns.
 
69
 *
 
70
 * TODO:
 
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.
 
76
 */
 
77
 
 
78
/* #define NO_ALLOCA 1 */
 
79
 
 
80
#ifdef HAVE_DIX_CONFIG_H
 
81
#include <dix-config.h>
 
82
#endif
 
83
 
 
84
#include "servermd.h"
 
85
#include "gcstruct.h"
 
86
#include "pixmapstr.h"
 
87
#include "scrnintstr.h"
 
88
#include "windowstr.h"
 
89
#include "mi.h"
 
90
#include "mibank.h"
 
91
 
 
92
#define BANK_SINGLE 0
 
93
#define BANK_SHARED 1
 
94
#define BANK_DOUBLE 2
 
95
#define BANK_NOBANK 3
 
96
 
 
97
typedef struct _miBankScreen
 
98
{
 
99
    miBankInfoRec BankInfo;
 
100
    unsigned int  nBankBPP;
 
101
    unsigned int  type;
 
102
 
 
103
    unsigned long nBitsPerBank;
 
104
    unsigned long nBitsPerScanline;
 
105
    unsigned long nPixelsPerScanlinePadUnit;
 
106
 
 
107
    PixmapPtr     pScreenPixmap;
 
108
    PixmapPtr     pBankPixmap;
 
109
    GCPtr         pBankGC;
 
110
 
 
111
    int           nBanks, maxRects;
 
112
    RegionPtr     *pBanks;
 
113
 
 
114
    pointer       pbits;
 
115
 
 
116
    /*
 
117
     * Screen Wrappers
 
118
     */
 
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;
 
130
 
 
131
typedef struct _miBankGC
 
132
{
 
133
    GCOps     *wrappedOps,   *unwrappedOps;
 
134
    GCFuncs   *wrappedFuncs, *unwrappedFuncs;
 
135
 
 
136
    Bool      fastCopy, fastPlane;
 
137
 
 
138
    RegionPtr pBankedClips[1];
 
139
} miBankGCRec, *miBankGCPtr;
 
140
 
 
141
typedef struct _miBankQueue
 
142
{
 
143
    Bool           fastBlit;
 
144
    unsigned short srcBankNo;
 
145
    unsigned short dstBankNo;
 
146
    short          x;
 
147
    short          y;
 
148
    short          w;
 
149
    short          h;
 
150
} miBankQueue;
 
151
 
 
152
/*
 
153
 * CAVEAT:  This banking scheme requires that the DDX store Pixmap data in the
 
154
 *          server's address space.
 
155
 */
 
156
 
 
157
#define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
 
158
    (*pScreen->ModifyPixmapHeader)((_pPix), \
 
159
        (_width), -1, -1, -1, (_devKind), (_pbits))
 
160
 
 
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)))
 
166
 
 
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)))
 
172
 
 
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)))
 
178
 
 
179
#define ALLOCATE_LOCAL_ARRAY(atype, ntype) \
 
180
    (atype *)ALLOCATE_LOCAL((ntype) * sizeof(atype))
 
181
 
 
182
static int           miBankScreenIndex;
 
183
static int           miBankGCIndex;
 
184
static unsigned long miBankGeneration = 0;
 
185
 
 
186
#define BANK_SCRPRIVLVAL pScreen->devPrivates[miBankScreenIndex].ptr
 
187
 
 
188
#define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
 
189
 
 
190
#define BANK_GCPRIVLVAL(pGC) (pGC)->devPrivates[miBankGCIndex].ptr
 
191
 
 
192
#define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
 
193
 
 
194
#define PIXMAP_STATUS(_pPix) \
 
195
    pointer pbits = (_pPix)->devPrivate.ptr
 
196
 
 
197
#define PIXMAP_SAVE(_pPix) \
 
198
    PIXMAP_STATUS(_pPix); \
 
199
    if (pbits == (pointer)pScreenPriv) \
 
200
        (_pPix)->devPrivate.ptr = pScreenPriv->pbits
 
201
 
 
202
#define PIXMAP_RESTORE(_pPix) \
 
203
    (_pPix)->devPrivate.ptr = pbits
 
204
 
 
205
#define BANK_SAVE \
 
206
    int width   = pScreenPriv->pBankPixmap->drawable.width; \
 
207
    int devKind = pScreenPriv->pBankPixmap->devKind; \
 
208
    PIXMAP_SAVE(pScreenPriv->pBankPixmap)
 
209
 
 
210
#define BANK_RESTORE \
 
211
    pScreenPriv->pBankPixmap->drawable.width = width; \
 
212
    pScreenPriv->pBankPixmap->devKind = devKind; \
 
213
    PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
 
214
 
 
215
#define SCREEN_STATUS \
 
216
    PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
 
217
 
 
218
#define SCREEN_SAVE \
 
219
    PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
 
220
 
 
221
#define SCREEN_RESTORE \
 
222
    PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
 
223
 
 
224
#define SCREEN_INIT \
 
225
    miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
 
226
 
 
227
#define SCREEN_UNWRAP(field) \
 
228
    pScreen->field = pScreenPriv->field
 
229
 
 
230
#define SCREEN_WRAP(field, wrapper) \
 
231
    pScreenPriv->field = pScreen->field; \
 
232
    pScreen->field     = wrapper
 
233
 
 
234
#define GC_INIT(pGC) \
 
235
    miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
 
236
 
 
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
 
242
 
 
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
 
248
 
 
249
#define IS_BANKED(pDrawable) \
 
250
    ((pbits == (pointer)pScreenPriv) && \
 
251
     (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
 
252
 
 
253
#define CLIP_SAVE \
 
254
    RegionPtr pOrigCompositeClip = pGC->pCompositeClip
 
255
 
 
256
#define CLIP_RESTORE \
 
257
    pGC->pCompositeClip = pOrigCompositeClip
 
258
 
 
259
#define GCOP_INIT \
 
260
    ScreenPtr pScreen = pGC->pScreen; \
 
261
    SCREEN_INIT; \
 
262
    GC_INIT(pGC)
 
263
 
 
264
#define GCOP_UNWRAP \
 
265
    GC_UNWRAP(pGC)
 
266
 
 
267
#define GCOP_WRAP \
 
268
    GC_WRAP(pGC)
 
269
 
 
270
#define GCOP_TOP_PART \
 
271
    for (i = 0;  i < pScreenPriv->nBanks;  i++) \
 
272
    { \
 
273
        if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
 
274
            continue; \
 
275
        GCOP_UNWRAP; \
 
276
        SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
 
277
 
 
278
#define GCOP_BOTTOM_PART \
 
279
        GCOP_WRAP; \
 
280
    }
 
281
 
 
282
#define GCOP_SIMPLE(statement) \
 
283
    if (nArray > 0) \
 
284
    { \
 
285
        GCOP_INIT; \
 
286
        SCREEN_SAVE; \
 
287
        if (!IS_BANKED(pDrawable)) \
 
288
        { \
 
289
            GCOP_UNWRAP; \
 
290
            statement; \
 
291
            GCOP_WRAP; \
 
292
        } \
 
293
        else \
 
294
        { \
 
295
            int i; \
 
296
            CLIP_SAVE; \
 
297
            GCOP_TOP_PART; \
 
298
            statement; \
 
299
            GCOP_BOTTOM_PART; \
 
300
            CLIP_RESTORE; \
 
301
        } \
 
302
        SCREEN_RESTORE; \
 
303
    }
 
304
 
 
305
#define GCOP_0D_ARGS mode,
 
306
#define GCOP_1D_ARGS
 
307
#define GCOP_2D_ARGS shape, mode,
 
308
 
 
309
#define GCOP_COMPLEX(aop, atype) \
 
310
    if (nArray > 0) \
 
311
    { \
 
312
        GCOP_INIT; \
 
313
        SCREEN_SAVE; \
 
314
        if (!IS_BANKED(pDrawable)) \
 
315
        { \
 
316
            GCOP_UNWRAP; \
 
317
            (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
 
318
            GCOP_WRAP; \
 
319
        } \
 
320
        else \
 
321
        { \
 
322
            atype *aarg = pArray, *acopy; \
 
323
            int   i; \
 
324
            CLIP_SAVE; \
 
325
            if ((acopy = ALLOCATE_LOCAL_ARRAY(atype, nArray))) \
 
326
                aarg = acopy; \
 
327
            GCOP_TOP_PART; \
 
328
            if (acopy) \
 
329
                memcpy(acopy, pArray, nArray * sizeof(atype)); \
 
330
            (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
 
331
            GCOP_BOTTOM_PART; \
 
332
            DEALLOCATE_LOCAL(acopy); \
 
333
            CLIP_RESTORE; \
 
334
        } \
 
335
        SCREEN_RESTORE; \
 
336
    }
 
337
 
 
338
/*********************
 
339
 * Utility functions *
 
340
 *********************/
 
341
 
 
342
static int
 
343
miBankOf(
 
344
    miBankScreenPtr pScreenPriv,
 
345
    int             x,
 
346
    int             y
 
347
)
 
348
{
 
349
    int iBank = ((x * (int)pScreenPriv->nBankBPP) +
 
350
                 (y * (long)pScreenPriv->nBitsPerScanline)) /
 
351
                (long)pScreenPriv->nBitsPerBank;
 
352
 
 
353
    if (iBank < 0)
 
354
        iBank = 0;
 
355
    else if (iBank >= pScreenPriv->nBanks)
 
356
        iBank = pScreenPriv->nBanks - 1;
 
357
 
 
358
    return iBank;
 
359
}
 
360
 
 
361
#define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
 
362
#define  LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
 
363
 
 
364
/* Determine banking type from the BankInfoRec */
 
365
static unsigned int
 
366
miBankDeriveType(
 
367
    ScreenPtr     pScreen,
 
368
    miBankInfoPtr pBankInfo
 
369
)
 
370
{
 
371
    unsigned int type;
 
372
 
 
373
    if (pBankInfo->pBankA == pBankInfo->pBankB)
 
374
    {
 
375
        if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
 
376
        {
 
377
            if (pBankInfo->SetSourceAndDestinationBanks !=
 
378
                pBankInfo->SetSourceBank)
 
379
                return BANK_NOBANK;
 
380
 
 
381
            type = BANK_SINGLE;
 
382
        }
 
383
        else
 
384
        {
 
385
            if (pBankInfo->SetSourceAndDestinationBanks ==
 
386
                pBankInfo->SetDestinationBank)
 
387
                return BANK_NOBANK;
 
388
            if (pBankInfo->SetSourceAndDestinationBanks ==
 
389
                pBankInfo->SetSourceBank)
 
390
                return BANK_NOBANK;
 
391
 
 
392
            type = BANK_SHARED;
 
393
        }
 
394
    }
 
395
    else
 
396
    {
 
397
        if ((unsigned long)abs((char *)pBankInfo->pBankA -
 
398
                               (char *)pBankInfo->pBankB) < pBankInfo->BankSize)
 
399
            return BANK_NOBANK;
 
400
 
 
401
        if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
 
402
        {
 
403
            if (pBankInfo->SetSourceAndDestinationBanks !=
 
404
                pBankInfo->SetSourceBank)
 
405
                return BANK_NOBANK;
 
406
        }
 
407
        else
 
408
        {
 
409
            if (pBankInfo->SetSourceAndDestinationBanks ==
 
410
                pBankInfo->SetDestinationBank)
 
411
                return BANK_NOBANK;
 
412
        }
 
413
 
 
414
        type = BANK_DOUBLE;
 
415
    }
 
416
 
 
417
    /*
 
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.
 
421
     */
 
422
    if (pBankInfo->nBankDepth != pScreen->rootDepth)
 
423
        type = BANK_SINGLE;
 
424
 
 
425
    return type;
 
426
}
 
427
 
 
428
/* Least common multiple */
 
429
static unsigned int
 
430
miLCM(
 
431
    unsigned int x,
 
432
    unsigned int y
 
433
)
 
434
{
 
435
    unsigned int m = x, n = y, o;
 
436
 
 
437
    while ((o = m % n))
 
438
    {
 
439
        m = n;
 
440
        n = o;
 
441
    }
 
442
 
 
443
    return (x / n) * y;
 
444
}
 
445
 
 
446
/******************
 
447
 * GCOps wrappers *
 
448
 ******************/
 
449
 
 
450
static void
 
451
miBankFillSpans(
 
452
    DrawablePtr pDrawable,
 
453
    GCPtr       pGC,
 
454
    int         nArray,
 
455
    DDXPointPtr pptInit,
 
456
    int         *pwidthInit,
 
457
    int         fSorted
 
458
)
 
459
{
 
460
    GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC,
 
461
        nArray, pptInit, pwidthInit, fSorted));
 
462
}
 
463
 
 
464
static void
 
465
miBankSetSpans(
 
466
    DrawablePtr pDrawable,
 
467
    GCPtr       pGC,
 
468
    char        *psrc,
 
469
    DDXPointPtr ppt,
 
470
    int         *pwidth,
 
471
    int         nArray,
 
472
    int         fSorted
 
473
)
 
474
{
 
475
    GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc,
 
476
        ppt, pwidth, nArray, fSorted));
 
477
}
 
478
 
 
479
static void
 
480
miBankPutImage(
 
481
    DrawablePtr pDrawable,
 
482
    GCPtr       pGC,
 
483
    int         depth,
 
484
    int         x,
 
485
    int         y,
 
486
    int         w,
 
487
    int         h,
 
488
    int         leftPad,
 
489
    int         format,
 
490
    char        *pImage
 
491
)
 
492
{
 
493
    if ((w > 0) && (h > 0))
 
494
    {
 
495
        GCOP_INIT;
 
496
        SCREEN_SAVE;
 
497
 
 
498
        if (!IS_BANKED(pDrawable))
 
499
        {
 
500
            GCOP_UNWRAP;
 
501
 
 
502
            (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
 
503
                leftPad, format, pImage);
 
504
 
 
505
            GCOP_WRAP;
 
506
        }
 
507
        else
 
508
        {
 
509
            int i, j;
 
510
 
 
511
            CLIP_SAVE;
 
512
 
 
513
            i = FirstBankOf(x + pDrawable->x,     y + pDrawable->y);
 
514
            j =  LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h);
 
515
            for (;  i <= j;  i++)
 
516
            {
 
517
                if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
 
518
                    continue;
 
519
 
 
520
                GCOP_UNWRAP;
 
521
 
 
522
                SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
 
523
 
 
524
                (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
 
525
                    leftPad, format, pImage);
 
526
 
 
527
                GCOP_WRAP;
 
528
            }
 
529
 
 
530
            CLIP_RESTORE;
 
531
        }
 
532
 
 
533
        SCREEN_RESTORE;
 
534
    }
 
535
}
 
536
 
 
537
/*
 
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.
 
545
 */
 
546
static RegionPtr
 
547
miBankCopy(
 
548
    DrawablePtr   pSrc,
 
549
    DrawablePtr   pDst,
 
550
    GCPtr         pGC,
 
551
    int           srcx,
 
552
    int           srcy,
 
553
    int           w,
 
554
    int           h,
 
555
    int           dstx,
 
556
    int           dsty,
 
557
    unsigned long plane,
 
558
    Bool          SinglePlane
 
559
)
 
560
{
 
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;
 
568
    RegionRec   rgnDst;
 
569
    char        *pImage = NULL;
 
570
    miBankQueue *pQueue, *pQueueNew, *Queue;
 
571
    miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase;
 
572
    Bool        fastBlit, freeSrcClip, fastClip;
 
573
    Bool        fExpose = FALSE, fastExpose = FALSE;
 
574
 
 
575
    GCOP_INIT;
 
576
    SCREEN_SAVE;
 
577
 
 
578
    if (!IS_BANKED(pSrc) && !IS_BANKED(pDst))
 
579
    {
 
580
        GCOP_UNWRAP;
 
581
 
 
582
        if (SinglePlane)
 
583
            ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
 
584
                srcx, srcy, w, h, dstx, dsty, plane);
 
585
        else
 
586
            ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
 
587
                srcx, srcy, w, h, dstx, dsty);
 
588
 
 
589
        GCOP_WRAP;
 
590
    }
 
591
    else if (!IS_BANKED(pDst))
 
592
    {
 
593
        fExpose = pGC->fExpose;
 
594
        pGC->fExpose = FALSE;
 
595
 
 
596
        xorg = pSrc->x;
 
597
        yorg = pSrc->y;
 
598
        dx   = dstx - srcx;
 
599
        dy   = dsty - srcy;
 
600
        srcx += xorg;
 
601
        srcy += yorg;
 
602
 
 
603
        ns = FirstBankOf(srcx,     srcy);
 
604
        nse = LastBankOf(srcx + w, srcy + h);
 
605
        for (;  ns <= nse;  ns++)
 
606
        {
 
607
            if (!pScreenPriv->pBanks[ns])
 
608
                continue;
 
609
 
 
610
            nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
 
611
            pBox = REGION_RECTS(pScreenPriv->pBanks[ns]);
 
612
 
 
613
            for (;  nBox--;  pBox++)
 
614
            {
 
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);
 
619
 
 
620
                if ((cx1 >= cx2) || (cy1 >= cy2))
 
621
                    continue;
 
622
 
 
623
                GCOP_UNWRAP;
 
624
 
 
625
                SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns);
 
626
 
 
627
                if (SinglePlane)
 
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);
 
632
                else
 
633
                    (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
 
634
                        cx1 - xorg, cy1 - yorg,
 
635
                        cx2 - cx1, cy2 - cy1,
 
636
                        cx1 + dx - xorg, cy1 + dy - yorg);
 
637
 
 
638
                GCOP_WRAP;
 
639
            }
 
640
        }
 
641
 
 
642
        pGC->fExpose = fExpose;
 
643
        srcx -= xorg;
 
644
        srcy -= yorg;
 
645
    }
 
646
    else if (!IS_BANKED(pSrc))
 
647
    {
 
648
        CLIP_SAVE;
 
649
 
 
650
        if (pGC->miTranslate)
 
651
        {
 
652
            xorg = pDst->x;
 
653
            yorg = pDst->y;
 
654
        }
 
655
        dx = srcx - dstx;
 
656
        dy = srcy - dsty;
 
657
        dstx += xorg;
 
658
        dsty += yorg;
 
659
 
 
660
        nd = FirstBankOf(dstx,     dsty);
 
661
        nde = LastBankOf(dstx + w, dsty + h);
 
662
        for (;  nd <= nde;  nd++)
 
663
        {
 
664
            if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd]))
 
665
                continue;
 
666
 
 
667
            /*
 
668
             * It's faster to let the lower-level CopyArea do the clipping
 
669
             * within each bank.
 
670
             */
 
671
            nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
 
672
            pBox = REGION_RECTS(pScreenPriv->pBanks[nd]);
 
673
 
 
674
            for (;  nBox--;  pBox++)
 
675
            {
 
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);
 
680
 
 
681
                if ((cx1 >= cx2) || (cy1 >= cy2))
 
682
                    continue;
 
683
 
 
684
                GCOP_UNWRAP;
 
685
 
 
686
                SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd);
 
687
 
 
688
                if (SinglePlane)
 
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);
 
693
                else
 
694
                    (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
 
695
                        cx1 + dx - xorg, cy1 + dy - yorg,
 
696
                        cx2 - cx1, cy2 - cy1,
 
697
                        cx1 - xorg, cy1 - yorg);
 
698
 
 
699
                GCOP_WRAP;
 
700
            }
 
701
        }
 
702
 
 
703
        CLIP_RESTORE;
 
704
    }
 
705
    else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
 
706
    {
 
707
        CLIP_SAVE;
 
708
 
 
709
        fExpose = pGC->fExpose;
 
710
 
 
711
        fastBox.x1 = srcx + pSrc->x;
 
712
        fastBox.y1 = srcy + pSrc->y;
 
713
        fastBox.x2 = fastBox.x1 + w;
 
714
        fastBox.y2 = fastBox.y1 + h;
 
715
 
 
716
        dx = dstx - fastBox.x1;
 
717
        dy = dsty - fastBox.y1;
 
718
        if (pGC->miTranslate)
 
719
        {
 
720
            xorg = pDst->x;
 
721
            yorg = pDst->y;
 
722
        }
 
723
 
 
724
        /*
 
725
         * Clip against the source.  Otherwise we will blit too much for SINGLE
 
726
         * and SHARED banked systems.
 
727
         */
 
728
        freeSrcClip = FALSE;
 
729
        fastClip    = FALSE;
 
730
        fastExpose  = FALSE;
 
731
 
 
732
        if (pGC->subWindowMode != IncludeInferiors)
 
733
            prgnSrcClip = &((WindowPtr)pSrc)->clipList;
 
734
        else if (!((WindowPtr)pSrc)->parent)
 
735
            fastClip = TRUE;
 
736
        else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE))
 
737
            prgnSrcClip = pGC->pCompositeClip;
 
738
        else
 
739
        {
 
740
            prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc);
 
741
            freeSrcClip = TRUE;
 
742
        }
 
743
 
 
744
        if (fastClip)
 
745
        {
 
746
            fastExpose = TRUE;
 
747
 
 
748
            /*
 
749
             * Clip the source.  If regions extend beyond the source size, make
 
750
             * sure exposure events get sent.
 
751
             */
 
752
            if (fastBox.x1 < pSrc->x)
 
753
            {
 
754
                fastBox.x1 = pSrc->x;
 
755
                fastExpose = FALSE;
 
756
            }
 
757
            if (fastBox.y1 < pSrc->y)
 
758
            {
 
759
                fastBox.y1 = pSrc->y;
 
760
                fastExpose = FALSE;
 
761
            }
 
762
            if (fastBox.x2 > pSrc->x + (int) pSrc->width)
 
763
            {
 
764
                fastBox.x2 = pSrc->x + (int) pSrc->width;
 
765
                fastExpose = FALSE;
 
766
            }
 
767
            if (fastBox.y2 > pSrc->y + (int) pSrc->height)
 
768
            {
 
769
                fastBox.y2 = pSrc->y + (int) pSrc->height;
 
770
                fastExpose = FALSE;
 
771
            }
 
772
 
 
773
            nBox = 1;
 
774
            pBox = &fastBox;
 
775
        }
 
776
        else
 
777
        {
 
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);
 
782
        }
 
783
 
 
784
        /*
 
785
         * fastBlit can only be TRUE if we don't need to worry about attempts
 
786
         * to read partial pixels through the destination bank.
 
787
         */
 
788
        if (SinglePlane)
 
789
            fastBlit = pGCPriv->fastPlane;
 
790
        else
 
791
            fastBlit = pGCPriv->fastCopy;
 
792
 
 
793
        nQueue = nBox * pScreenPriv->maxRects * 2;
 
794
        pQueue = Queue = ALLOCATE_LOCAL_ARRAY(miBankQueue, nQueue);
 
795
 
 
796
        if (Queue)
 
797
        {
 
798
            for (;  nBox--;  pBox++)
 
799
            {
 
800
                ns = FirstBankOf(pBox->x1, pBox->y1);
 
801
                nse = LastBankOf(pBox->x2, pBox->y2);
 
802
                for (;  ns <= nse;  ns++)
 
803
                {
 
804
                    if (!pScreenPriv->pBanks[ns])
 
805
                        continue;
 
806
 
 
807
                    nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
 
808
                    pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]);
 
809
 
 
810
                    for (;  nBoxClipSrc--;  pBoxClipSrc++)
 
811
                    {
 
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);
 
816
 
 
817
                        /* Check to see if the region is empty */
 
818
                        if ((cx1 >= cx2) || (cy1 >= cy2))
 
819
                            continue;
 
820
 
 
821
                        /* Translate c[xy]* to destination coordinates */
 
822
                        cx1 += dx + xorg;
 
823
                        cy1 += dy + yorg;
 
824
                        cx2 += dx + xorg;
 
825
                        cy2 += dy + yorg;
 
826
 
 
827
                        nd = FirstBankOf(cx1, cy1);
 
828
                        nde = LastBankOf(cx2, cy2);
 
829
                        for (;  nd <= nde;  nd++)
 
830
                        {
 
831
                            if (!pGCPriv->pBankedClips[nd])
 
832
                                continue;
 
833
 
 
834
                            /*
 
835
                             * Clients can send quite large clip descriptions,
 
836
                             * so use the bank clips here instead.
 
837
                             */
 
838
                            nBoxClipDst =
 
839
                                REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
 
840
                            pBoxClipDst =
 
841
                                REGION_RECTS(pScreenPriv->pBanks[nd]);
 
842
 
 
843
                            for (;  nBoxClipDst--;  pBoxClipDst++)
 
844
                            {
 
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);
 
849
 
 
850
                                /* Check to see if the region is empty */
 
851
                                if ((ccBox.x1 >= ccBox.x2) ||
 
852
                                    (ccBox.y1 >= ccBox.y2))
 
853
                                    continue;
 
854
 
 
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;
 
861
 
 
862
                                if (maxWidth < pQueue->w)
 
863
                                    maxWidth = pQueue->w;
 
864
                                if (maxHeight < pQueue->h)
 
865
                                    maxHeight = pQueue->h;
 
866
 
 
867
                                /*
 
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.
 
872
                                 */
 
873
                                pQueue->fastBlit = fastBlit;
 
874
                                if (fastBlit &&
 
875
                                    (pScreenPriv->type == BANK_SHARED) &&
 
876
                                    (ns != nd) &&
 
877
                                    ((ccBox.x1 %
 
878
                                      pScreenPriv->nPixelsPerScanlinePadUnit) ||
 
879
                                     (ccBox.x2 %
 
880
                                      pScreenPriv->nPixelsPerScanlinePadUnit) ||
 
881
                                     (RECT_IN_REGION(pScreen,
 
882
                                       pGCPriv->pBankedClips[nd], &ccBox) !=
 
883
                                      rgnIN)))
 
884
                                    pQueue->fastBlit = FALSE;
 
885
                                pQueue++;
 
886
                            }
 
887
                        }
 
888
                    }
 
889
                }
 
890
            }
 
891
        }
 
892
 
 
893
        if (!fastClip)
 
894
        {
 
895
            REGION_UNINIT(pScreen, &rgnDst);
 
896
            if (freeSrcClip)
 
897
                REGION_DESTROY(pScreen, prgnSrcClip);
 
898
        }
 
899
 
 
900
        pQueueNew = pQueue;
 
901
        nQueue = pQueue - Queue;
 
902
 
 
903
        if (nQueue > 0)
 
904
        {
 
905
            BANK_SAVE;
 
906
 
 
907
            pQueue = Queue;
 
908
 
 
909
            if ((nQueue > 1) &&
 
910
                ((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors)))
 
911
            {
 
912
                if ((srcy + pSrc->y) < (dsty + yorg))
 
913
                {
 
914
                    /* Sort from bottom to top */
 
915
                    pQueueBase = pQueueNext = pQueue + nQueue - 1;
 
916
 
 
917
                    while (pQueueBase >= pQueue)
 
918
                    {
 
919
                        while ((pQueueNext >= pQueue) &&
 
920
                               (pQueueBase->y == pQueueNext->y))
 
921
                            pQueueNext--;
 
922
 
 
923
                        pQueueTmp = pQueueNext + 1;
 
924
                        while (pQueueTmp <= pQueueBase)
 
925
                            *pQueueNew++ = *pQueueTmp++;
 
926
 
 
927
                        pQueueBase = pQueueNext;
 
928
                    }
 
929
 
 
930
                    pQueueNew -= nQueue;
 
931
                    pQueue = pQueueNew;
 
932
                    pQueueNew = Queue;
 
933
                }
 
934
 
 
935
                if ((srcx + pSrc->x) < (dstx + xorg))
 
936
                {
 
937
                    /* Sort from right to left */
 
938
                    pQueueBase = pQueueNext = pQueue;
 
939
 
 
940
                    while (pQueueBase < pQueue + nQueue)
 
941
                    {
 
942
                        while ((pQueueNext < pQueue + nQueue) &&
 
943
                               (pQueueNext->y == pQueueBase->y))
 
944
                            pQueueNext++;
 
945
 
 
946
                        pQueueTmp = pQueueNext;
 
947
                        while (pQueueTmp != pQueueBase)
 
948
                            *pQueueNew++ = *--pQueueTmp;
 
949
 
 
950
                        pQueueBase = pQueueNext;
 
951
                    }
 
952
 
 
953
                    pQueueNew -= nQueue;
 
954
                    pQueue = pQueueNew;
 
955
                }
 
956
            }
 
957
 
 
958
            paddedWidth = PixmapBytePad(maxWidth,
 
959
                pScreenPriv->pScreenPixmap->drawable.depth);
 
960
            pImage = (char *)ALLOCATE_LOCAL(paddedWidth * maxHeight);
 
961
 
 
962
            pGC->fExpose = FALSE;
 
963
 
 
964
            while (nQueue--)
 
965
            {
 
966
                pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo];
 
967
 
 
968
                GCOP_UNWRAP;
 
969
 
 
970
                if (pQueue->srcBankNo == pQueue->dstBankNo)
 
971
                {
 
972
                    SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
 
973
                        -1, -1, pQueue->srcBankNo);
 
974
 
 
975
                    if (SinglePlane)
 
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);
 
979
                    else
 
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);
 
983
                }
 
984
                else if (pQueue->fastBlit)
 
985
                {
 
986
                    SET_SOURCE_BANK     (pScreenPriv->pBankPixmap,
 
987
                        pScreenPriv->pScreenPixmap->drawable.width,
 
988
                        pScreenPriv->pScreenPixmap->devKind,
 
989
                        pQueue->srcBankNo);
 
990
                    SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap,
 
991
                        -1, -1, pQueue->dstBankNo);
 
992
 
 
993
                    if (SinglePlane)
 
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);
 
998
                    else
 
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);
 
1003
                }
 
1004
                else if (pImage)
 
1005
                {
 
1006
                    ModifyPixmap(pScreenPriv->pBankPixmap,
 
1007
                        maxWidth, paddedWidth, pImage);
 
1008
 
 
1009
                    SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
 
1010
                        -1, -1, pQueue->srcBankNo);
 
1011
 
 
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);
 
1017
 
 
1018
                    SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
 
1019
                        -1, -1, pQueue->dstBankNo);
 
1020
 
 
1021
                    if (SinglePlane)
 
1022
                        (*pGC->ops->CopyPlane)(
 
1023
                            (DrawablePtr)pScreenPriv->pBankPixmap,
 
1024
                            pDst, pGC, 0, 0, pQueue->w, pQueue->h,
 
1025
                            pQueue->x, pQueue->y, plane);
 
1026
                    else
 
1027
                        (*pGC->ops->CopyArea)(
 
1028
                            (DrawablePtr)pScreenPriv->pBankPixmap,
 
1029
                            pDst, pGC, 0, 0, pQueue->w, pQueue->h,
 
1030
                            pQueue->x, pQueue->y);
 
1031
                }
 
1032
 
 
1033
                GCOP_WRAP;
 
1034
 
 
1035
                pQueue++;
 
1036
            }
 
1037
 
 
1038
            DEALLOCATE_LOCAL(pImage);
 
1039
 
 
1040
            BANK_RESTORE;
 
1041
        }
 
1042
 
 
1043
        CLIP_RESTORE;
 
1044
 
 
1045
        pGC->fExpose = fExpose;
 
1046
 
 
1047
        DEALLOCATE_LOCAL(Queue);
 
1048
    }
 
1049
 
 
1050
    SCREEN_RESTORE;
 
1051
 
 
1052
    if (!fExpose || fastExpose)
 
1053
        return ret;
 
1054
 
 
1055
    return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0);
 
1056
}
 
1057
 
 
1058
static RegionPtr
 
1059
miBankCopyArea(
 
1060
    DrawablePtr pSrc,
 
1061
    DrawablePtr pDst,
 
1062
    GCPtr       pGC,
 
1063
    int         srcx,
 
1064
    int         srcy,
 
1065
    int         w,
 
1066
    int         h,
 
1067
    int         dstx,
 
1068
    int         dsty
 
1069
)
 
1070
{
 
1071
    return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE);
 
1072
}
 
1073
 
 
1074
static RegionPtr
 
1075
miBankCopyPlane(
 
1076
    DrawablePtr   pSrc,
 
1077
    DrawablePtr   pDst,
 
1078
    GCPtr         pGC,
 
1079
    int           srcx,
 
1080
    int           srcy,
 
1081
    int           w,
 
1082
    int           h,
 
1083
    int           dstx,
 
1084
    int           dsty,
 
1085
    unsigned long plane
 
1086
)
 
1087
{
 
1088
    return
 
1089
        miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE);
 
1090
}
 
1091
 
 
1092
static void
 
1093
miBankPolyPoint(
 
1094
    DrawablePtr pDrawable,
 
1095
    GCPtr       pGC,
 
1096
    int         mode,
 
1097
    int         nArray,
 
1098
    xPoint      *pArray
 
1099
)
 
1100
{
 
1101
#   define GCOP_ARGS GCOP_0D_ARGS
 
1102
    GCOP_COMPLEX(PolyPoint, xPoint);
 
1103
#   undef GCOP_ARGS
 
1104
}
 
1105
 
 
1106
static void
 
1107
miBankPolylines(
 
1108
    DrawablePtr pDrawable,
 
1109
    GCPtr       pGC,
 
1110
    int         mode,
 
1111
    int         nArray,
 
1112
    DDXPointPtr pArray
 
1113
)
 
1114
{
 
1115
#   define GCOP_ARGS GCOP_0D_ARGS
 
1116
    GCOP_COMPLEX(Polylines, DDXPointRec);
 
1117
#   undef GCOP_ARGS
 
1118
}
 
1119
 
 
1120
static void
 
1121
miBankPolySegment(
 
1122
    DrawablePtr pDrawable,
 
1123
    GCPtr       pGC,
 
1124
    int         nArray,
 
1125
    xSegment    *pArray
 
1126
)
 
1127
{
 
1128
#   define GCOP_ARGS GCOP_1D_ARGS
 
1129
    GCOP_COMPLEX(PolySegment, xSegment);
 
1130
#   undef GCOP_ARGS
 
1131
}
 
1132
 
 
1133
static void
 
1134
miBankPolyRectangle(
 
1135
    DrawablePtr pDrawable,
 
1136
    GCPtr       pGC,
 
1137
    int         nArray,
 
1138
    xRectangle  *pArray
 
1139
)
 
1140
{
 
1141
#   define GCOP_ARGS GCOP_1D_ARGS
 
1142
    GCOP_COMPLEX(PolyRectangle, xRectangle);
 
1143
#   undef GCOP_ARGS
 
1144
}
 
1145
 
 
1146
static void
 
1147
miBankPolyArc(
 
1148
    DrawablePtr pDrawable,
 
1149
    GCPtr       pGC,
 
1150
    int         nArray,
 
1151
    xArc        *pArray
 
1152
)
 
1153
{
 
1154
#   define GCOP_ARGS GCOP_1D_ARGS
 
1155
    GCOP_COMPLEX(PolyArc, xArc);
 
1156
#   undef GCOP_ARGS
 
1157
}
 
1158
 
 
1159
static void
 
1160
miBankFillPolygon(
 
1161
    DrawablePtr pDrawable,
 
1162
    GCPtr       pGC,
 
1163
    int         shape,
 
1164
    int         mode,
 
1165
    int         nArray,
 
1166
    DDXPointRec *pArray
 
1167
)
 
1168
{
 
1169
#   define GCOP_ARGS GCOP_2D_ARGS
 
1170
    GCOP_COMPLEX(FillPolygon, DDXPointRec);
 
1171
#   undef GCOP_ARGS
 
1172
}
 
1173
 
 
1174
static void
 
1175
miBankPolyFillRect(
 
1176
    DrawablePtr pDrawable,
 
1177
    GCPtr       pGC,
 
1178
    int         nArray,
 
1179
    xRectangle  *pArray
 
1180
)
 
1181
{
 
1182
#   define GCOP_ARGS GCOP_1D_ARGS
 
1183
    GCOP_COMPLEX(PolyFillRect, xRectangle);
 
1184
#   undef GCOP_ARGS
 
1185
}
 
1186
 
 
1187
static void
 
1188
miBankPolyFillArc(
 
1189
    DrawablePtr pDrawable,
 
1190
    GCPtr       pGC,
 
1191
    int         nArray,
 
1192
    xArc        *pArray
 
1193
)
 
1194
{
 
1195
#   define GCOP_ARGS GCOP_1D_ARGS
 
1196
    GCOP_COMPLEX(PolyFillArc, xArc);
 
1197
#   undef GCOP_ARGS
 
1198
}
 
1199
 
 
1200
static int
 
1201
miBankPolyText8(
 
1202
    DrawablePtr pDrawable,
 
1203
    GCPtr       pGC,
 
1204
    int         x,
 
1205
    int         y,
 
1206
    int         nArray,
 
1207
    char        *pchar
 
1208
)
 
1209
{
 
1210
    int retval = x;
 
1211
 
 
1212
    GCOP_SIMPLE(retval =
 
1213
        (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar));
 
1214
 
 
1215
    return retval;
 
1216
}
 
1217
 
 
1218
static int
 
1219
miBankPolyText16(
 
1220
    DrawablePtr    pDrawable,
 
1221
    GCPtr          pGC,
 
1222
    int            x,
 
1223
    int            y,
 
1224
    int            nArray,
 
1225
    unsigned short *pchar
 
1226
)
 
1227
{
 
1228
    int retval = x;
 
1229
 
 
1230
    GCOP_SIMPLE(retval =
 
1231
        (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar));
 
1232
 
 
1233
    return retval;
 
1234
}
 
1235
 
 
1236
static void
 
1237
miBankImageText8(
 
1238
    DrawablePtr pDrawable,
 
1239
    GCPtr       pGC,
 
1240
    int         x,
 
1241
    int         y,
 
1242
    int         nArray,
 
1243
    char        *pchar
 
1244
)
 
1245
{
 
1246
    GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar));
 
1247
}
 
1248
 
 
1249
static void
 
1250
miBankImageText16(
 
1251
    DrawablePtr    pDrawable,
 
1252
    GCPtr          pGC,
 
1253
    int            x,
 
1254
    int            y,
 
1255
    int            nArray,
 
1256
    unsigned short *pchar
 
1257
)
 
1258
{
 
1259
    GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar));
 
1260
}
 
1261
 
 
1262
static void
 
1263
miBankImageGlyphBlt(
 
1264
    DrawablePtr  pDrawable,
 
1265
    GCPtr        pGC,
 
1266
    int          x,
 
1267
    int          y,
 
1268
    unsigned int nArray,
 
1269
    CharInfoPtr  *ppci,
 
1270
    pointer      pglyphBase
 
1271
)
 
1272
{
 
1273
    GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC,
 
1274
        x, y, nArray, ppci, pglyphBase));
 
1275
}
 
1276
 
 
1277
static void
 
1278
miBankPolyGlyphBlt(
 
1279
    DrawablePtr  pDrawable,
 
1280
    GCPtr        pGC,
 
1281
    int          x,
 
1282
    int          y,
 
1283
    unsigned int nArray,
 
1284
    CharInfoPtr  *ppci,
 
1285
    pointer      pglyphBase
 
1286
)
 
1287
{
 
1288
    GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC,
 
1289
        x, y, nArray, ppci, pglyphBase));
 
1290
}
 
1291
 
 
1292
static void
 
1293
miBankPushPixels(
 
1294
    GCPtr       pGC,
 
1295
    PixmapPtr   pBitmap,
 
1296
    DrawablePtr pDrawable,
 
1297
    int         w,
 
1298
    int         h,
 
1299
    int         x,
 
1300
    int         y
 
1301
)
 
1302
{
 
1303
    if ((w > 0) && (h > 0))
 
1304
    {
 
1305
        GCOP_INIT;
 
1306
        SCREEN_SAVE;
 
1307
 
 
1308
        if (!IS_BANKED(pDrawable))
 
1309
        {
 
1310
            GCOP_UNWRAP;
 
1311
 
 
1312
            (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
 
1313
 
 
1314
            GCOP_WRAP;
 
1315
        }
 
1316
        else
 
1317
        {
 
1318
            int i, j;
 
1319
 
 
1320
            CLIP_SAVE;
 
1321
 
 
1322
            i = FirstBankOf(x,     y);
 
1323
            j =  LastBankOf(x + w, y + h);
 
1324
            for (;  i <= j;  i++)
 
1325
            {
 
1326
                if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
 
1327
                    continue;
 
1328
 
 
1329
                GCOP_UNWRAP;
 
1330
 
 
1331
                SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
 
1332
 
 
1333
                (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
 
1334
 
 
1335
                GCOP_WRAP;
 
1336
            }
 
1337
 
 
1338
            CLIP_RESTORE;
 
1339
        }
 
1340
 
 
1341
        SCREEN_RESTORE;
 
1342
    }
 
1343
}
 
1344
 
 
1345
static GCOps miBankGCOps =
 
1346
{
 
1347
    miBankFillSpans,
 
1348
    miBankSetSpans,
 
1349
    miBankPutImage,
 
1350
    miBankCopyArea,
 
1351
    miBankCopyPlane,
 
1352
    miBankPolyPoint,
 
1353
    miBankPolylines,
 
1354
    miBankPolySegment,
 
1355
    miBankPolyRectangle,
 
1356
    miBankPolyArc,
 
1357
    miBankFillPolygon,
 
1358
    miBankPolyFillRect,
 
1359
    miBankPolyFillArc,
 
1360
    miBankPolyText8,
 
1361
    miBankPolyText16,
 
1362
    miBankImageText8,
 
1363
    miBankImageText16,
 
1364
    miBankImageGlyphBlt,
 
1365
    miBankPolyGlyphBlt,
 
1366
    miBankPushPixels,
 
1367
#ifdef NEED_LINEHELPER
 
1368
    NULL,               /* LineHelper */
 
1369
#endif
 
1370
    {NULL}              /* devPrivate */
 
1371
};
 
1372
 
 
1373
/********************
 
1374
 * GCFuncs wrappers *
 
1375
 ********************/
 
1376
 
 
1377
static void
 
1378
miBankValidateGC(
 
1379
    GCPtr         pGC,
 
1380
    unsigned long changes,
 
1381
    DrawablePtr   pDrawable
 
1382
)
 
1383
{
 
1384
    GC_INIT(pGC);
 
1385
    GC_UNWRAP(pGC);
 
1386
 
 
1387
    (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
 
1388
 
 
1389
    if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
 
1390
        (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
 
1391
    {
 
1392
        ScreenPtr     pScreen = pGC->pScreen;
 
1393
        RegionPtr     prgnClip;
 
1394
        unsigned long planemask;
 
1395
        int           i;
 
1396
 
 
1397
        SCREEN_INIT;
 
1398
        SCREEN_SAVE;
 
1399
 
 
1400
        if (IS_BANKED(pDrawable))
 
1401
        {
 
1402
            for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
1403
            {
 
1404
                if (!pScreenPriv->pBanks[i])
 
1405
                    continue;
 
1406
 
 
1407
                if (!(prgnClip = pGCPriv->pBankedClips[i]))
 
1408
                    prgnClip = REGION_CREATE(pScreen, NULL, 1);
 
1409
 
 
1410
                REGION_INTERSECT(pScreen, prgnClip,
 
1411
                    pScreenPriv->pBanks[i], pGC->pCompositeClip);
 
1412
 
 
1413
                if ((REGION_NUM_RECTS(prgnClip) <= 1) &&
 
1414
                    ((prgnClip->extents.x1 == prgnClip->extents.x2) ||
 
1415
                     (prgnClip->extents.y1 == prgnClip->extents.y2)))
 
1416
                {
 
1417
                    REGION_DESTROY(pScreen, prgnClip);
 
1418
                    pGCPriv->pBankedClips[i] = NULL;
 
1419
                }
 
1420
                else
 
1421
                    pGCPriv->pBankedClips[i] = prgnClip;
 
1422
            }
 
1423
 
 
1424
            /*
 
1425
             * fastCopy and fastPlane can only be TRUE if we don't need to
 
1426
             * worry about attempts to read partial pixels through the
 
1427
             * destination bank.
 
1428
             */
 
1429
            switch (pScreenPriv->type)
 
1430
            {
 
1431
                case BANK_SHARED:
 
1432
                    pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
 
1433
 
 
1434
                    if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) &&
 
1435
                        (pGC->alu != GXcopyInverted) && (pGC->alu != GXset))
 
1436
                        break;
 
1437
 
 
1438
                    if (pScreen->rootDepth == 1)
 
1439
                        pGCPriv->fastPlane = TRUE;
 
1440
 
 
1441
                    /* This is probably paranoia */
 
1442
                    if ((pDrawable->depth != pScreen->rootDepth) ||
 
1443
                        (pDrawable->depth != pGC->depth))
 
1444
                        break;
 
1445
 
 
1446
                    planemask = (1 << pGC->depth) - 1;
 
1447
                    if ((pGC->planemask & planemask) == planemask)
 
1448
                        pGCPriv->fastCopy = TRUE;
 
1449
 
 
1450
                    break;
 
1451
 
 
1452
                case BANK_DOUBLE:
 
1453
                    pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE;
 
1454
                    break;
 
1455
 
 
1456
                default:
 
1457
                    pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
 
1458
                    break;
 
1459
            }
 
1460
        }
 
1461
        else
 
1462
        {
 
1463
            /*
 
1464
             * Here we are on a pixmap and don't need all that special clipping
 
1465
             * stuff, hence free it.
 
1466
             */
 
1467
            for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
1468
            {
 
1469
                if (!pGCPriv->pBankedClips[i])
 
1470
                    continue;
 
1471
 
 
1472
                REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
 
1473
                pGCPriv->pBankedClips[i] = NULL;
 
1474
            }
 
1475
        }
 
1476
 
 
1477
        SCREEN_RESTORE;
 
1478
    }
 
1479
 
 
1480
    GC_WRAP(pGC);
 
1481
}
 
1482
 
 
1483
static void
 
1484
miBankChangeGC(
 
1485
    GCPtr         pGC,
 
1486
    unsigned long mask
 
1487
)
 
1488
{
 
1489
    GC_INIT(pGC);
 
1490
    GC_UNWRAP(pGC);
 
1491
 
 
1492
    (*pGC->funcs->ChangeGC)(pGC, mask);
 
1493
 
 
1494
    GC_WRAP(pGC);
 
1495
}
 
1496
 
 
1497
static void
 
1498
miBankCopyGC(
 
1499
    GCPtr         pGCSrc,
 
1500
    unsigned long mask,
 
1501
    GCPtr         pGCDst
 
1502
)
 
1503
{
 
1504
    GC_INIT(pGCDst);
 
1505
    GC_UNWRAP(pGCDst);
 
1506
 
 
1507
    (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
 
1508
 
 
1509
    GC_WRAP(pGCDst);
 
1510
}
 
1511
 
 
1512
static void
 
1513
miBankDestroyGC(
 
1514
    GCPtr pGC
 
1515
)
 
1516
{
 
1517
    ScreenPtr pScreen = pGC->pScreen;
 
1518
    int       i;
 
1519
 
 
1520
    SCREEN_INIT;
 
1521
    GC_INIT(pGC);
 
1522
    GC_UNWRAP(pGC);
 
1523
 
 
1524
    (*pGC->funcs->DestroyGC)(pGC);
 
1525
 
 
1526
    for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
1527
    {
 
1528
        if (!pGCPriv->pBankedClips[i])
 
1529
            continue;
 
1530
 
 
1531
        REGION_DESTROY(pScreen, pGCPriv->pBankedClips[i]);
 
1532
        pGCPriv->pBankedClips[i] = NULL;
 
1533
    }
 
1534
 
 
1535
    GC_WRAP(pGC);
 
1536
}
 
1537
 
 
1538
static void
 
1539
miBankChangeClip(
 
1540
    GCPtr   pGC,
 
1541
    int     type,
 
1542
    pointer pvalue,
 
1543
    int     nrects
 
1544
)
 
1545
{
 
1546
    GC_INIT(pGC);
 
1547
    GC_UNWRAP(pGC);
 
1548
 
 
1549
    (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
 
1550
 
 
1551
    GC_WRAP(pGC);
 
1552
}
 
1553
 
 
1554
static void
 
1555
miBankDestroyClip(
 
1556
    GCPtr pGC
 
1557
)
 
1558
{
 
1559
    GC_INIT(pGC);
 
1560
    GC_UNWRAP(pGC);
 
1561
 
 
1562
    (*pGC->funcs->DestroyClip)(pGC);
 
1563
 
 
1564
    GC_WRAP(pGC);
 
1565
}
 
1566
 
 
1567
static void
 
1568
miBankCopyClip(
 
1569
    GCPtr pGCDst,
 
1570
    GCPtr pGCSrc
 
1571
)
 
1572
{
 
1573
    GC_INIT(pGCDst);
 
1574
    GC_UNWRAP(pGCDst);
 
1575
 
 
1576
    (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
 
1577
 
 
1578
    GC_WRAP(pGCDst);
 
1579
}
 
1580
 
 
1581
static GCFuncs miBankGCFuncs =
 
1582
{
 
1583
    miBankValidateGC,
 
1584
    miBankChangeGC,
 
1585
    miBankCopyGC,
 
1586
    miBankDestroyGC,
 
1587
    miBankChangeClip,
 
1588
    miBankDestroyClip,
 
1589
    miBankCopyClip
 
1590
};
 
1591
 
 
1592
/*******************
 
1593
 * Screen Wrappers *
 
1594
 *******************/
 
1595
 
 
1596
static Bool
 
1597
miBankCreateScreenResources(
 
1598
    ScreenPtr pScreen
 
1599
)
 
1600
{
 
1601
    Bool retval;
 
1602
 
 
1603
    SCREEN_INIT;
 
1604
    SCREEN_UNWRAP(CreateScreenResources);
 
1605
 
 
1606
    if ((retval = (*pScreen->CreateScreenResources)(pScreen)))
 
1607
    {
 
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;
 
1612
 
 
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)
 
1617
            retval = FALSE;
 
1618
    }
 
1619
 
 
1620
    /* Shadow the screen */
 
1621
    if (retval)
 
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);
 
1628
 
 
1629
    /* Create shadow GC */
 
1630
    if (retval)
 
1631
    {
 
1632
        pScreenPriv->pBankGC = CreateScratchGC(pScreen,
 
1633
            pScreenPriv->pBankPixmap->drawable.depth);
 
1634
        if (!pScreenPriv->pBankGC)
 
1635
            retval = FALSE;
 
1636
    }
 
1637
 
 
1638
    /* Validate shadow GC */
 
1639
    if (retval)
 
1640
    {
 
1641
        pScreenPriv->pBankGC->graphicsExposures = FALSE;
 
1642
        pScreenPriv->pBankGC->subWindowMode = IncludeInferiors;
 
1643
        ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap,
 
1644
            pScreenPriv->pBankGC);
 
1645
    }
 
1646
 
 
1647
    SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
 
1648
 
 
1649
    return retval;
 
1650
}
 
1651
 
 
1652
static Bool
 
1653
miBankModifyPixmapHeader(
 
1654
    PixmapPtr pPixmap,
 
1655
    int       width,
 
1656
    int       height,
 
1657
    int       depth,
 
1658
    int       bitsPerPixel,
 
1659
    int       devKind,
 
1660
    pointer   pPixData
 
1661
)
 
1662
{
 
1663
    Bool retval = FALSE;
 
1664
 
 
1665
    if (pPixmap)
 
1666
    {
 
1667
        ScreenPtr pScreen = pPixmap->drawable.pScreen;
 
1668
 
 
1669
        SCREEN_INIT;
 
1670
        PIXMAP_SAVE(pPixmap);
 
1671
        SCREEN_UNWRAP(ModifyPixmapHeader);
 
1672
 
 
1673
        retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height,
 
1674
            depth, bitsPerPixel, devKind, pPixData);
 
1675
 
 
1676
        SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
 
1677
 
 
1678
        if (pbits == (pointer)pScreenPriv)
 
1679
        {
 
1680
            pScreenPriv->pbits = pPixmap->devPrivate.ptr;
 
1681
            pPixmap->devPrivate.ptr = pbits;
 
1682
        }
 
1683
    }
 
1684
 
 
1685
    return retval;
 
1686
}
 
1687
 
 
1688
static Bool
 
1689
miBankCloseScreen(
 
1690
    int       nIndex,
 
1691
    ScreenPtr pScreen
 
1692
)
 
1693
{
 
1694
    int i;
 
1695
 
 
1696
    SCREEN_INIT;
 
1697
 
 
1698
    /* Free shadow GC */
 
1699
    FreeScratchGC(pScreenPriv->pBankGC);
 
1700
 
 
1701
    /* Free shadow pixmap */
 
1702
    (*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap);
 
1703
 
 
1704
    /* Restore screen pixmap devPrivate pointer */
 
1705
    pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits;
 
1706
 
 
1707
    /* Delete bank clips */
 
1708
    for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
1709
        if (pScreenPriv->pBanks[i])
 
1710
            REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
 
1711
 
 
1712
    Xfree(pScreenPriv->pBanks);
 
1713
 
 
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);
 
1724
 
 
1725
    Xfree(pScreenPriv);
 
1726
    return (*pScreen->CloseScreen)(nIndex, pScreen);
 
1727
}
 
1728
 
 
1729
static void
 
1730
miBankGetImage(
 
1731
    DrawablePtr   pDrawable,
 
1732
    int           sx,
 
1733
    int           sy,
 
1734
    int           w,
 
1735
    int           h,
 
1736
    unsigned int  format,
 
1737
    unsigned long planemask,
 
1738
    char          *pImage
 
1739
)
 
1740
{
 
1741
    if ((w > 0) && (h > 0))
 
1742
    {
 
1743
        ScreenPtr pScreen = pDrawable->pScreen;
 
1744
 
 
1745
        SCREEN_INIT;
 
1746
        SCREEN_STATUS;
 
1747
        SCREEN_UNWRAP(GetImage);
 
1748
 
 
1749
        if (!IS_BANKED(pDrawable))
 
1750
        {
 
1751
            (*pScreen->GetImage)(pDrawable, sx, sy, w, h,
 
1752
                format, planemask, pImage);
 
1753
        }
 
1754
        else
 
1755
        {
 
1756
            int  paddedWidth;
 
1757
            char *pBankImage;
 
1758
 
 
1759
            paddedWidth = PixmapBytePad(w,
 
1760
                pScreenPriv->pScreenPixmap->drawable.depth);
 
1761
            pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth * h);
 
1762
 
 
1763
            if (pBankImage)
 
1764
            {
 
1765
                BANK_SAVE;
 
1766
 
 
1767
                ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth,
 
1768
                    pBankImage);
 
1769
 
 
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);
 
1775
 
 
1776
                (*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap,
 
1777
                    0, 0, w, h, format, planemask, pImage);
 
1778
 
 
1779
                BANK_RESTORE;
 
1780
 
 
1781
                DEALLOCATE_LOCAL(pBankImage);
 
1782
            }
 
1783
        }
 
1784
 
 
1785
        SCREEN_WRAP(GetImage, miBankGetImage);
 
1786
    }
 
1787
}
 
1788
 
 
1789
static void
 
1790
miBankGetSpans(
 
1791
    DrawablePtr pDrawable,
 
1792
    int         wMax,
 
1793
    DDXPointPtr ppt,
 
1794
    int         *pwidth,
 
1795
    int         nspans,
 
1796
    char        *pImage
 
1797
)
 
1798
{
 
1799
    if (nspans > 0)
 
1800
    {
 
1801
        ScreenPtr pScreen = pDrawable->pScreen;
 
1802
 
 
1803
        SCREEN_INIT;
 
1804
        SCREEN_STATUS;
 
1805
        SCREEN_UNWRAP(GetSpans);
 
1806
 
 
1807
        if (!IS_BANKED(pDrawable))
 
1808
        {
 
1809
            (*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage);
 
1810
        }
 
1811
        else
 
1812
        {
 
1813
            char        *pBankImage;
 
1814
            int         paddedWidth;
 
1815
            DDXPointRec pt;
 
1816
 
 
1817
            pt.x = pt.y = 0;
 
1818
 
 
1819
            paddedWidth =
 
1820
                PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width,
 
1821
                    pScreenPriv->pScreenPixmap->drawable.depth);
 
1822
            pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth);
 
1823
 
 
1824
            if (pBankImage)
 
1825
            {
 
1826
                BANK_SAVE;
 
1827
 
 
1828
                ModifyPixmap(pScreenPriv->pBankPixmap,
 
1829
                    pScreenPriv->pScreenPixmap->drawable.width,
 
1830
                    paddedWidth, pBankImage);
 
1831
 
 
1832
                for (;  nspans--;  ppt++, pwidth++)
 
1833
                {
 
1834
                    if (*pwidth <= 0)
 
1835
                        continue;
 
1836
 
 
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);
 
1842
 
 
1843
                    (*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap,
 
1844
                        wMax, &pt, pwidth, 1, pImage);
 
1845
 
 
1846
                    pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth);
 
1847
                }
 
1848
 
 
1849
                BANK_RESTORE;
 
1850
 
 
1851
                DEALLOCATE_LOCAL(pBankImage);
 
1852
            }
 
1853
        }
 
1854
 
 
1855
        SCREEN_WRAP(GetSpans, miBankGetSpans);
 
1856
    }
 
1857
}
 
1858
 
 
1859
static Bool
 
1860
miBankCreateGC(
 
1861
    GCPtr pGC
 
1862
)
 
1863
{
 
1864
    ScreenPtr   pScreen = pGC->pScreen;
 
1865
    miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC);
 
1866
    Bool        ret;
 
1867
 
 
1868
    SCREEN_INIT;
 
1869
    SCREEN_UNWRAP(CreateGC);
 
1870
 
 
1871
    if ((ret = (*pScreen->CreateGC)(pGC)))
 
1872
    {
 
1873
        pGCPriv->unwrappedOps = &miBankGCOps;
 
1874
        pGCPriv->unwrappedFuncs = &miBankGCFuncs;
 
1875
        GC_WRAP(pGC);
 
1876
 
 
1877
        memset(&pGCPriv->pBankedClips, 0,
 
1878
            pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips));
 
1879
    }
 
1880
 
 
1881
    SCREEN_WRAP(CreateGC, miBankCreateGC);
 
1882
 
 
1883
    return ret;
 
1884
}
 
1885
 
 
1886
static void
 
1887
miBankPaintWindow(
 
1888
    WindowPtr pWin,
 
1889
    RegionPtr pRegion,
 
1890
    int       what
 
1891
)
 
1892
{
 
1893
    ScreenPtr          pScreen = pWin->drawable.pScreen;
 
1894
    RegionRec          tmpReg;
 
1895
    int                i;
 
1896
    PaintWindowProcPtr PaintWindow;
 
1897
 
 
1898
    SCREEN_INIT;
 
1899
    SCREEN_SAVE;
 
1900
 
 
1901
    if (what == PW_BORDER)
 
1902
    {
 
1903
        SCREEN_UNWRAP(PaintWindowBorder);
 
1904
        PaintWindow = pScreen->PaintWindowBorder;
 
1905
    }
 
1906
    else
 
1907
    {
 
1908
        SCREEN_UNWRAP(PaintWindowBackground);
 
1909
        PaintWindow = pScreen->PaintWindowBackground;
 
1910
    }
 
1911
 
 
1912
    if (!IS_BANKED(pWin))
 
1913
    {
 
1914
        (*PaintWindow)(pWin, pRegion, what);
 
1915
    }
 
1916
    else
 
1917
    {
 
1918
        REGION_NULL(pScreen, &tmpReg);
 
1919
 
 
1920
        for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
1921
        {
 
1922
            if (!pScreenPriv->pBanks[i])
 
1923
                continue;
 
1924
 
 
1925
            REGION_INTERSECT(pScreen, &tmpReg, pRegion,
 
1926
                pScreenPriv->pBanks[i]);
 
1927
 
 
1928
            if (REGION_NIL(&tmpReg))
 
1929
                continue;
 
1930
 
 
1931
            SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
 
1932
 
 
1933
            (*PaintWindow)(pWin, &tmpReg, what);
 
1934
        }
 
1935
 
 
1936
        REGION_UNINIT(pScreen, &tmpReg);
 
1937
    }
 
1938
 
 
1939
    if (what == PW_BORDER)
 
1940
    {
 
1941
        SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
 
1942
    }
 
1943
    else
 
1944
    {
 
1945
        SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
 
1946
    }
 
1947
 
 
1948
    SCREEN_RESTORE;
 
1949
}
 
1950
 
 
1951
static void
 
1952
miBankCopyWindow(
 
1953
    WindowPtr   pWindow,
 
1954
    DDXPointRec ptOldOrg,
 
1955
    RegionPtr   pRgnSrc
 
1956
)
 
1957
{
 
1958
    ScreenPtr   pScreen = pWindow->drawable.pScreen;
 
1959
    GCPtr       pGC;
 
1960
    int         dx, dy, nBox;
 
1961
    DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum];
 
1962
    RegionPtr   pRgnDst;
 
1963
    BoxPtr      pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2;
 
1964
    XID         subWindowMode = IncludeInferiors;
 
1965
 
 
1966
    pGC = GetScratchGC(pDrawable->depth, pScreen);
 
1967
 
 
1968
    ChangeGC(pGC, GCSubwindowMode, &subWindowMode);
 
1969
    ValidateGC(pDrawable, pGC);
 
1970
 
 
1971
    pRgnDst = REGION_CREATE(pScreen, NULL, 1);
 
1972
 
 
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);
 
1977
 
 
1978
    pBox = REGION_RECTS(pRgnDst);
 
1979
    nBox = REGION_NUM_RECTS(pRgnDst);
 
1980
 
 
1981
    pBoxNew1 = NULL;
 
1982
    pBoxNew2 = NULL;
 
1983
 
 
1984
    if (nBox > 1)
 
1985
    {
 
1986
        if (dy < 0)
 
1987
        {
 
1988
            /* Sort boxes from bottom to top */
 
1989
            pBoxNew1 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
 
1990
 
 
1991
            if (pBoxNew1)
 
1992
            {
 
1993
                pBoxBase = pBoxNext = pBox + nBox - 1;
 
1994
 
 
1995
                while (pBoxBase >= pBox)
 
1996
                {
 
1997
                    while ((pBoxNext >= pBox) &&
 
1998
                           (pBoxBase->y1 == pBoxNext->y1))
 
1999
                        pBoxNext--;
 
2000
 
 
2001
                    pBoxTmp = pBoxNext + 1;
 
2002
 
 
2003
                    while (pBoxTmp <= pBoxBase)
 
2004
                        *pBoxNew1++ = *pBoxTmp++;
 
2005
 
 
2006
                    pBoxBase = pBoxNext;
 
2007
                }
 
2008
 
 
2009
                pBoxNew1 -= nBox;
 
2010
                pBox = pBoxNew1;
 
2011
            }
 
2012
        }
 
2013
 
 
2014
        if (dx < 0)
 
2015
        {
 
2016
            /* Sort boxes from right to left */
 
2017
            pBoxNew2 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
 
2018
 
 
2019
            if (pBoxNew2)
 
2020
            {
 
2021
                pBoxBase = pBoxNext = pBox;
 
2022
 
 
2023
                while (pBoxBase < pBox + nBox)
 
2024
                {
 
2025
                    while ((pBoxNext < pBox + nBox) &&
 
2026
                           (pBoxNext->y1 == pBoxBase->y1))
 
2027
                        pBoxNext++;
 
2028
 
 
2029
                    pBoxTmp = pBoxNext;
 
2030
 
 
2031
                    while (pBoxTmp != pBoxBase)
 
2032
                        *pBoxNew2++ = *--pBoxTmp;
 
2033
 
 
2034
                    pBoxBase = pBoxNext;
 
2035
                }
 
2036
 
 
2037
                pBoxNew2 -= nBox;
 
2038
                pBox = pBoxNew2;
 
2039
            }
 
2040
        }
 
2041
    }
 
2042
 
 
2043
    while (nBox--)
 
2044
    {
 
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);
 
2049
 
 
2050
        pBox++;
 
2051
    }
 
2052
 
 
2053
    FreeScratchGC(pGC);
 
2054
 
 
2055
    REGION_DESTROY(pScreen, pRgnDst);
 
2056
 
 
2057
    DEALLOCATE_LOCAL(pBoxNew2);
 
2058
    DEALLOCATE_LOCAL(pBoxNew1);
 
2059
}
 
2060
 
 
2061
/**************************
 
2062
 * Backing store wrappers *
 
2063
 **************************/
 
2064
 
 
2065
static void
 
2066
miBankSaveAreas(
 
2067
    PixmapPtr pPixmap,
 
2068
    RegionPtr prgnSave,
 
2069
    int       xorg,
 
2070
    int       yorg,
 
2071
    WindowPtr pWin
 
2072
)
 
2073
{
 
2074
    ScreenPtr   pScreen   = pPixmap->drawable.pScreen;
 
2075
    RegionRec   rgnClipped;
 
2076
    int         i;
 
2077
 
 
2078
    SCREEN_INIT;
 
2079
    SCREEN_SAVE;
 
2080
    SCREEN_UNWRAP(BackingStoreFuncs.SaveAreas);
 
2081
 
 
2082
    if (!IS_BANKED(pWin))
 
2083
    {
 
2084
        (*pScreen->BackingStoreFuncs.SaveAreas)(pPixmap, prgnSave, xorg, yorg,
 
2085
            pWin);
 
2086
    }
 
2087
    else
 
2088
    {
 
2089
        REGION_NULL(pScreen, &rgnClipped);
 
2090
        REGION_TRANSLATE(pScreen, prgnSave, xorg, yorg);
 
2091
 
 
2092
        for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
2093
        {
 
2094
            if (!pScreenPriv->pBanks[i])
 
2095
                continue;
 
2096
 
 
2097
            REGION_INTERSECT(pScreen, &rgnClipped,
 
2098
                prgnSave, pScreenPriv->pBanks[i]);
 
2099
 
 
2100
            if (REGION_NIL(&rgnClipped))
 
2101
                continue;
 
2102
 
 
2103
            SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
 
2104
 
 
2105
            REGION_TRANSLATE(pScreen, &rgnClipped, -xorg, -yorg);
 
2106
 
 
2107
            (*pScreen->BackingStoreFuncs.SaveAreas)(pPixmap, &rgnClipped,
 
2108
                xorg, yorg, pWin);
 
2109
        }
 
2110
 
 
2111
        REGION_TRANSLATE(pScreen, prgnSave, -xorg, -yorg);
 
2112
        REGION_UNINIT(pScreen, &rgnClipped);
 
2113
    }
 
2114
 
 
2115
    SCREEN_WRAP(BackingStoreFuncs.SaveAreas, miBankSaveAreas);
 
2116
    SCREEN_RESTORE;
 
2117
}
 
2118
 
 
2119
static void
 
2120
miBankRestoreAreas(
 
2121
    PixmapPtr pPixmap,
 
2122
    RegionPtr prgnRestore,
 
2123
    int       xorg,
 
2124
    int       yorg,
 
2125
    WindowPtr pWin
 
2126
)
 
2127
{
 
2128
    ScreenPtr   pScreen   = pPixmap->drawable.pScreen;
 
2129
    RegionRec   rgnClipped;
 
2130
    int         i;
 
2131
 
 
2132
    SCREEN_INIT;
 
2133
    SCREEN_SAVE;
 
2134
    SCREEN_UNWRAP(BackingStoreFuncs.RestoreAreas);
 
2135
 
 
2136
    if (!IS_BANKED(pWin))
 
2137
    {
 
2138
        (*pScreen->BackingStoreFuncs.RestoreAreas)(pPixmap, prgnRestore,
 
2139
            xorg, yorg, pWin);
 
2140
    }
 
2141
    else
 
2142
    {
 
2143
        REGION_NULL(pScreen, &rgnClipped);
 
2144
 
 
2145
        for (i = 0;  i < pScreenPriv->nBanks;  i++)
 
2146
        {
 
2147
            if (!pScreenPriv->pBanks[i])
 
2148
                continue;
 
2149
 
 
2150
            REGION_INTERSECT(pScreen, &rgnClipped,
 
2151
                prgnRestore, pScreenPriv->pBanks[i]);
 
2152
 
 
2153
            if (REGION_NIL(&rgnClipped))
 
2154
                continue;
 
2155
 
 
2156
            SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
 
2157
 
 
2158
            (*pScreen->BackingStoreFuncs.RestoreAreas)(pPixmap, &rgnClipped,
 
2159
                xorg, yorg, pWin);
 
2160
        }
 
2161
 
 
2162
        REGION_UNINIT(pScreen, &rgnClipped);
 
2163
    }
 
2164
 
 
2165
    SCREEN_WRAP(BackingStoreFuncs.RestoreAreas, miBankRestoreAreas);
 
2166
    SCREEN_RESTORE;
 
2167
}
 
2168
 
 
2169
Bool
 
2170
miInitializeBanking(
 
2171
    ScreenPtr     pScreen,
 
2172
    unsigned int  xsize,
 
2173
    unsigned int  ysize,
 
2174
    unsigned int  width,
 
2175
    miBankInfoPtr pBankInfo
 
2176
)
 
2177
{
 
2178
    miBankScreenPtr pScreenPriv;
 
2179
    unsigned long   nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit;
 
2180
    unsigned long   BankBase, ServerPad;
 
2181
    unsigned int    type, iBank, nBanks, maxRects, we, nBankBPP;
 
2182
    int             i;
 
2183
 
 
2184
    if (!pBankInfo || !pBankInfo->BankSize)
 
2185
        return TRUE;            /* No banking required */
 
2186
 
 
2187
    /* Sanity checks */
 
2188
 
 
2189
    if (!pScreen || !xsize || !ysize || (xsize > width) ||
 
2190
        !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
 
2191
        !pBankInfo->SetSourceAndDestinationBanks ||
 
2192
        !pBankInfo->pBankA || !pBankInfo->pBankB ||
 
2193
        !pBankInfo->nBankDepth)
 
2194
        return FALSE;
 
2195
 
 
2196
    /*
 
2197
     * DDX *must* have registered a pixmap format whose depth is
 
2198
     * pBankInfo->nBankDepth.  This is not necessarily the rootDepth
 
2199
     * pixmap format.
 
2200
     */
 
2201
    i = 0;
 
2202
    while (screenInfo.formats[i].depth != pBankInfo->nBankDepth)
 
2203
        if (++i >= screenInfo.numPixmapFormats)
 
2204
            return FALSE;
 
2205
    nBankBPP = screenInfo.formats[i].bitsPerPixel;
 
2206
 
 
2207
    i = 0;
 
2208
    while (screenInfo.formats[i].depth != pScreen->rootDepth)
 
2209
        if (++i >= screenInfo.numPixmapFormats)
 
2210
            return FALSE;
 
2211
 
 
2212
    if (nBankBPP > screenInfo.formats[i].bitsPerPixel)
 
2213
        return FALSE;
 
2214
 
 
2215
    /* Determine banking type */
 
2216
    if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
 
2217
        return FALSE;
 
2218
 
 
2219
    /* Internal data */
 
2220
 
 
2221
    nBitsPerBank = pBankInfo->BankSize * 8;
 
2222
    ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8;
 
2223
    if (nBitsPerBank % ServerPad)
 
2224
        return FALSE;
 
2225
    nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8;
 
2226
    nBanks = ((nBitsPerScanline * (ysize - 1)) +
 
2227
              (nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank;
 
2228
    nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP;
 
2229
 
 
2230
    /* Private areas */
 
2231
 
 
2232
    if (miBankGeneration != serverGeneration)
 
2233
    {
 
2234
        if (((miBankScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
 
2235
            ((miBankGCIndex = AllocateGCPrivateIndex()) < 0))
 
2236
            return FALSE;
 
2237
 
 
2238
        miBankGeneration = serverGeneration;
 
2239
    }
 
2240
 
 
2241
    if (!AllocateGCPrivate(pScreen, miBankGCIndex,
 
2242
        (nBanks * sizeof(RegionPtr)) +
 
2243
            (sizeof(miBankGCRec) - sizeof(RegionPtr))))
 
2244
        return FALSE;
 
2245
 
 
2246
    if (!(pScreenPriv = (miBankScreenPtr)Xcalloc(sizeof(miBankScreenRec))))
 
2247
        return FALSE;
 
2248
 
 
2249
    if (!(pScreenPriv->pBanks =                 /* Allocate and clear */
 
2250
        (RegionPtr *)Xcalloc(nBanks * sizeof(RegionPtr))))
 
2251
    {
 
2252
        Xfree(pScreenPriv);
 
2253
        return FALSE;
 
2254
    }
 
2255
 
 
2256
    /*
 
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.
 
2260
     */
 
2261
 
 
2262
    BankBase = 0;
 
2263
    maxRects = 0;
 
2264
    we = 0;
 
2265
    for (iBank = 0;  iBank < nBanks;  iBank++)
 
2266
    {
 
2267
        xRectangle   pRects[3], *pRect = pRects;
 
2268
        unsigned int xb, yb, xe, ye;
 
2269
 
 
2270
        xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP;
 
2271
        yb =  (BankBase + nBankBPP - 1) / nBitsPerScanline;
 
2272
        if (xb >= xsize)
 
2273
        {
 
2274
            xb = we = 0;
 
2275
            yb++;
 
2276
        }
 
2277
        if (yb >= ysize)
 
2278
        {
 
2279
            we = 0;
 
2280
            break;
 
2281
        }
 
2282
 
 
2283
        if (we)
 
2284
            break;
 
2285
 
 
2286
        BankBase += nBitsPerBank;
 
2287
 
 
2288
        we = (BankBase % nBitsPerScanline) % nBankBPP;
 
2289
        xe = (BankBase % nBitsPerScanline) / nBankBPP;
 
2290
        ye =  BankBase / nBitsPerScanline;
 
2291
        if (xe >= xsize)
 
2292
        {
 
2293
            we = xe = 0;
 
2294
            ye++;
 
2295
        }
 
2296
        if (ye >= ysize)
 
2297
        {
 
2298
            we = xe = 0;
 
2299
            ye = ysize;
 
2300
        }
 
2301
 
 
2302
        if (yb == ye)
 
2303
        {
 
2304
            if (xb >= xe)
 
2305
                continue;
 
2306
 
 
2307
            pRect->x      = xb;
 
2308
            pRect->y      = yb;
 
2309
            pRect->width  = xe - xb;
 
2310
            pRect->height = 1;
 
2311
            maxRects += 2;
 
2312
            pRect++;
 
2313
        }
 
2314
        else
 
2315
        {
 
2316
            if (xb)
 
2317
            {
 
2318
                pRect->x      = xb;
 
2319
                pRect->y      = yb++;
 
2320
                pRect->width  = xsize - xb;
 
2321
                pRect->height = 1;
 
2322
                maxRects += 2;
 
2323
                pRect++;
 
2324
            }
 
2325
 
 
2326
            if (yb < ye)
 
2327
            {
 
2328
                pRect->x      = 0;
 
2329
                pRect->y      = yb;
 
2330
                pRect->width  = xsize;
 
2331
                pRect->height = ye - yb;
 
2332
                maxRects += min(pRect->height, 3) + 1;
 
2333
                pRect++;
 
2334
            }
 
2335
 
 
2336
            if (xe)
 
2337
            {
 
2338
                pRect->x      = 0;
 
2339
                pRect->y      = ye;
 
2340
                pRect->width  = xe;
 
2341
                pRect->height = 1;
 
2342
                maxRects += 2;
 
2343
                pRect++;
 
2344
            }
 
2345
        }
 
2346
 
 
2347
        pScreenPriv->pBanks[iBank] =
 
2348
            RECTS_TO_REGION(pScreen, pRect - pRects, pRects, 0);
 
2349
        if (!pScreenPriv->pBanks[iBank] ||
 
2350
            REGION_NAR(pScreenPriv->pBanks[iBank]))
 
2351
        {
 
2352
            we = 1;
 
2353
            break;
 
2354
        }
 
2355
    }
 
2356
 
 
2357
    if (we && (iBank < nBanks))
 
2358
    {
 
2359
        for (i = iBank;  i >= 0;  i--)
 
2360
            if (pScreenPriv->pBanks[i])
 
2361
                REGION_DESTROY(pScreen, pScreenPriv->pBanks[i]);
 
2362
 
 
2363
        Xfree(pScreenPriv->pBanks);
 
2364
        Xfree(pScreenPriv);
 
2365
 
 
2366
        return FALSE;
 
2367
    }
 
2368
 
 
2369
    /* Open for business */
 
2370
 
 
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;
 
2379
 
 
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);
 
2389
 
 
2390
    pScreenPriv->BackingStoreFuncs     = pScreen->BackingStoreFuncs;
 
2391
 
 
2392
    pScreen->BackingStoreFuncs.SaveAreas      = miBankSaveAreas;
 
2393
    pScreen->BackingStoreFuncs.RestoreAreas   = miBankRestoreAreas;
 
2394
    /* ??????????????????????????????????????????????????????????????
 
2395
    pScreen->BackingStoreFuncs.SetClipmaskRgn = miBankSetClipmaskRgn;
 
2396
    ?????????????????????????????????????????????????????????????? */
 
2397
 
 
2398
    BANK_SCRPRIVLVAL = (pointer)pScreenPriv;
 
2399
 
 
2400
    return TRUE;
 
2401
}
 
2402
 
 
2403
/* This is used to force GC revalidation when the banking type is changed */
 
2404
/*ARGSUSED*/
 
2405
static int
 
2406
miBankNewSerialNumber(
 
2407
    WindowPtr pWin,
 
2408
    pointer   unused
 
2409
)
 
2410
{
 
2411
    pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 
2412
    return WT_WALKCHILDREN;
 
2413
}
 
2414
 
 
2415
/* This entry modifies the banking interface */
 
2416
Bool
 
2417
miModifyBanking(
 
2418
    ScreenPtr     pScreen,
 
2419
    miBankInfoPtr pBankInfo
 
2420
)
 
2421
{
 
2422
    unsigned int type;
 
2423
 
 
2424
    if (!pScreen)
 
2425
        return FALSE;
 
2426
 
 
2427
    if (miBankGeneration == serverGeneration)
 
2428
    {
 
2429
        SCREEN_INIT;
 
2430
 
 
2431
        if (pScreenPriv)
 
2432
        {
 
2433
            if (!pBankInfo || !pBankInfo->BankSize ||
 
2434
                !pBankInfo->pBankA || !pBankInfo->pBankB ||
 
2435
                !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
 
2436
                !pBankInfo->SetSourceAndDestinationBanks)
 
2437
                return FALSE;
 
2438
 
 
2439
            /* BankSize and nBankDepth cannot, as yet, be changed */
 
2440
            if ((pScreenPriv->BankInfo.BankSize != pBankInfo->BankSize) ||
 
2441
                (pScreenPriv->BankInfo.nBankDepth != pBankInfo->nBankDepth))
 
2442
                return FALSE;
 
2443
 
 
2444
            if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
 
2445
                return FALSE;
 
2446
 
 
2447
            /* Reset banking info */
 
2448
            pScreenPriv->BankInfo = *pBankInfo;
 
2449
            if (type != pScreenPriv->type)
 
2450
            {
 
2451
                /*
 
2452
                 * Banking type is changing.  Revalidate all window GC's.
 
2453
                 */
 
2454
                pScreenPriv->type = type;
 
2455
                WalkTree(pScreen, miBankNewSerialNumber, 0);
 
2456
            }
 
2457
 
 
2458
            return TRUE;
 
2459
        }
 
2460
    }
 
2461
 
 
2462
    if (!pBankInfo || !pBankInfo->BankSize)
 
2463
        return TRUE;                            /* No change requested */
 
2464
 
 
2465
    return FALSE;
 
2466
}
 
2467
 
 
2468
/*
 
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.
 
2474
 */
 
2475
int
 
2476
miScanLineWidth(
 
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 */
 
2483
)
 
2484
{
 
2485
    unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
 
2486
    unsigned long minBitsPerScanline, maxBitsPerScanline;
 
2487
 
 
2488
    /* Sanity checks */
 
2489
 
 
2490
    if (!nWidthUnit || !pBankFormat)
 
2491
        return -1;
 
2492
 
 
2493
    nBitsPerBank = BankSize * 8;
 
2494
    if (nBitsPerBank % pBankFormat->scanlinePad)
 
2495
        return -1;
 
2496
 
 
2497
    if (xsize > width)
 
2498
        width = xsize;
 
2499
    nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit);
 
2500
    nBitsPerScanline =
 
2501
        (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
 
2502
         nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
 
2503
    width = nBitsPerScanline / pBankFormat->bitsPerPixel;
 
2504
 
 
2505
    if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
 
2506
        return (int)width;
 
2507
 
 
2508
    /*
 
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.
 
2512
     *
 
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.
 
2518
     */
 
2519
    if (!ysize)
 
2520
        return -1;
 
2521
 
 
2522
    minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
 
2523
    if (minBitsPerScanline > nBitsPerBank)
 
2524
        return -1;
 
2525
 
 
2526
    if (ysize == 1)
 
2527
        return (int)width;
 
2528
 
 
2529
    maxBitsPerScanline =
 
2530
        (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
 
2531
    while (nBitsPerScanline <= maxBitsPerScanline)
 
2532
    {
 
2533
        unsigned long BankBase, BankUnit;
 
2534
 
 
2535
        BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
 
2536
            nBitsPerBank;
 
2537
        if (!(BankUnit % nBitsPerScanline))
 
2538
            return (int)width;
 
2539
 
 
2540
        for (BankBase = BankUnit;  ;  BankBase += nBitsPerBank)
 
2541
        {
 
2542
            unsigned long x, y;
 
2543
 
 
2544
            y = BankBase / nBitsPerScanline;
 
2545
            if (y >= ysize)
 
2546
                return (int)width;
 
2547
 
 
2548
            x = BankBase % nBitsPerScanline;
 
2549
            if (!(x % pBankFormat->bitsPerPixel))
 
2550
                continue;
 
2551
 
 
2552
            if (x < minBitsPerScanline)
 
2553
            {
 
2554
                /*
 
2555
                 * Skip ahead certain widths by dividing the excess scanline
 
2556
                 * amongst the y's.
 
2557
                 */
 
2558
                y *= nBitsPerScanlinePadUnit;
 
2559
                nBitsPerScanline +=
 
2560
                    ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
 
2561
                width = nBitsPerScanline / pBankFormat->bitsPerPixel;
 
2562
                break;
 
2563
            }
 
2564
 
 
2565
            if (BankBase != BankUnit)
 
2566
                continue;
 
2567
 
 
2568
            if (!(nBitsPerScanline % x))
 
2569
                return (int)width;
 
2570
 
 
2571
            BankBase = ((nBitsPerScanline - minBitsPerScanline) /
 
2572
                (nBitsPerScanline - x)) * BankUnit;
 
2573
        }
 
2574
    }
 
2575
 
 
2576
    return -1;
 
2577
}