8
Copyright (c) 1989 X Consortium
10
Permission is hereby granted, free of charge, to any person obtaining a copy
11
of this software and associated documentation files (the "Software"), to deal
12
in the Software without restriction, including without limitation the rights
13
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
copies of the Software, and to permit persons to whom the Software is
15
furnished to do so, subject to the following conditions:
17
The above copyright notice and this permission notice shall be included in
18
all copies or substantial portions of the Software.
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
Except as contained in this notice, the name of the X Consortium shall not be
28
used in advertising or otherwise to promote the sale, use or other dealings
29
in this Software without prior written authorization from the X Consortium.
34
/* $XConsortium: ilbmblt.c,v 1.11 94/04/17 20:28:16 dpw Exp $ */
36
/* Modified jun 95 by Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
37
to use interleaved bitplanes instead of normal bitplanes */
39
#ifdef HAVE_DIX_CONFIG_H
40
#include <dix-config.h>
45
#include <X11/Xproto.h>
48
#include "windowstr.h"
49
#include "scrnintstr.h"
50
#include "pixmapstr.h"
51
#include "regionstr.h"
57
MROP_NAME(ilbmDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
58
DrawablePtr pSrc, pDst;
62
unsigned long planemask;
64
PixelType *psrcBase, *pdstBase; /* start of src and dst bitmaps */
65
int widthSrc, widthDst; /* add to get to same position in next line */
66
int heightSrc, heightDst;
72
BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
73
/* temporaries for shuffling rectangles */
74
DDXPointPtr pptTmp, pptNew1, pptNew2;
75
/* shuffling boxes entails shuffling the
78
int xdir; /* 1 = left right, -1 = right left/ */
79
int ydir; /* 1 = top down, -1 = bottom up */
81
PixelType *psrcLine, *pdstLine;
82
/* pointers to line with current src and dst */
83
register PixelType *psrc; /* pointer to current src longword */
84
register PixelType *pdst; /* pointer to current dst longword */
88
/* following used for looping through a line */
89
PixelType startmask, endmask; /* masks for writing ends of dst */
90
int nlMiddle; /* whole longwords in dst */
92
register int leftShift, rightShift;
93
register PixelType bits;
94
register PixelType bits1;
95
register int nl; /* temp copy of nlMiddle */
97
/* place to store full source word */
98
int nstart; /* number of ragged bits at start of dst */
99
int nend; /* number of ragged bits at end of dst */
100
int srcStartOver; /* pulling nstart bits from src
101
overflows into the next word? */
107
MROP_INITIALIZE(alu,0);
109
ilbmGetPixelWidthAuxDepthAndPointer(pSrc, widthSrc, auxSrc, depthSrc,
111
ilbmGetPixelWidthAuxDepthAndPointer(pDst, widthDst, auxDst, depthDst,
114
/* Special case where depth of dest pixmap is 1 but source pixmap isn't
115
* Used for GetImage to copy a plane from a source pixmap to a particular
117
* Note: planemask should have only one bit set or several planes from
118
* the source will be copied to the same dest plane.
120
if (depthDst == 1 && depthDst != depthSrc)
123
/* XXX we have to err on the side of safety when both are windows,
124
* because we don't know if IncludeInferiors is being used.
126
careful = ((pSrc == pDst) ||
127
((pSrc->type == DRAWABLE_WINDOW) &&
128
(pDst->type == DRAWABLE_WINDOW)));
130
pbox = REGION_RECTS(prgnDst);
131
nbox = REGION_NUM_RECTS(prgnDst);
137
if (careful && (pptSrc->y < pbox->y1)) {
138
/* walk source botttom to top */
144
/* keep ordering in each band, reverse order of bands */
145
pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
148
pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
150
DEALLOCATE_LOCAL(pboxNew1);
153
pboxBase = pboxNext = pbox+nbox-1;
154
while (pboxBase >= pbox) {
155
while ((pboxNext >= pbox) &&
156
(pboxBase->y1 == pboxNext->y1))
158
pboxTmp = pboxNext+1;
159
pptTmp = pptSrc + (pboxTmp - pbox);
160
while (pboxTmp <= pboxBase) {
161
*pboxNew1++ = *pboxTmp++;
162
*pptNew1++ = *pptTmp++;
172
/* walk source top to bottom */
176
if (careful && (pptSrc->x < pbox->x1)) {
177
/* walk source right to left */
181
/* reverse order of rects in each band */
182
pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
183
pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
184
if (!pboxNew2 || !pptNew2) {
186
DEALLOCATE_LOCAL(pptNew2);
188
DEALLOCATE_LOCAL(pboxNew2);
190
DEALLOCATE_LOCAL(pptNew1);
191
DEALLOCATE_LOCAL(pboxNew1);
195
pboxBase = pboxNext = pbox;
196
while (pboxBase < pbox+nbox) {
197
while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1))
200
pptTmp = pptSrc + (pboxTmp - pbox);
201
while (pboxTmp != pboxBase) {
202
*pboxNew2++ = *--pboxTmp;
203
*pptNew2++ = *--pptTmp;
213
/* walk source left to right */
219
for (d = 0; d < depthSrc; d++) {
223
if (!(planemask & (1 << d)))
226
psrcB = psrcBase + widthSrc * d; /* @@@ NEXT PLANE @@@ */
227
pdstB = pdstBase + widthDst * d; /* @@@ NEXT PLANE @@@ */
229
w = pbox->x2 - pbox->x1;
230
h = pbox->y2 - pbox->y1;
232
if (ydir == -1) { /* start at last scanline of rectangle */
233
psrcLine = ilbmScanlineDeltaSrc(psrcB, -(pptSrc->y+h-1), auxSrc);
234
pdstLine = ilbmScanlineDeltaDst(pdstB, -(pbox->y2-1), auxDst);
235
} else { /* start at first scanline */
236
psrcLine = ilbmScanlineDeltaSrc(psrcB, pptSrc->y, auxSrc);
237
pdstLine = ilbmScanlineDeltaDst(pdstB, pbox->y1, auxDst);
239
if ((pbox->x1 & PIM) + w <= PPW) {
240
maskpartialbits (pbox->x1, w, startmask);
244
maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
247
xoffSrc = pptSrc->x & PIM;
248
xoffDst = pbox->x1 & PIM;
249
pdstLine += (pbox->x1 >> PWSH);
250
psrcLine += (pptSrc->x >> PWSH);
251
#ifdef DO_UNALIGNED_BITBLT
252
nl = xoffSrc - xoffDst;
253
psrcLine = (PixelType *)(((unsigned char *) psrcLine) + nl);
255
if (xoffSrc == xoffDst)
262
*pdst = MROP_MASK(*psrc, *pdst, startmask);
268
#ifdef LARGE_INSTRUCTION_CACHE
269
#ifdef FAST_CONSTANT_OFFSET_MODE
271
psrc += nl & (UNROLL-1);
272
pdst += nl & (UNROLL-1);
274
#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
275
#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
283
#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
284
#define BodyEven(n) BodyOdd(n)
297
/* you'd think this would be faster --
298
* a single instruction instead of 6
299
* but measurements show it to be ~15% slower
301
while ((nl -= 6) >= 0) {
302
asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
303
: "=m" (*(char *)pdst)
304
: "m" (*(char *)psrc)
305
: "d0", "d1", "d2", "d3",
314
*pdst = MROP_SOLID (*psrc, *pdst);
319
*pdst = MROP_MASK(*psrc, *pdst, endmask);
320
ilbmScanlineIncDst(pdstLine, auxDst);
321
ilbmScanlineIncSrc(psrcLine, auxSrc);
324
#ifndef DO_UNALIGNED_BITBLT
326
if (xoffSrc > xoffDst) {
327
leftShift = (xoffSrc - xoffDst);
328
rightShift = PPW - leftShift;
330
rightShift = (xoffDst - xoffSrc);
331
leftShift = PPW - rightShift;
337
if (xoffSrc > xoffDst)
340
bits1 = BitLeft(bits,leftShift);
342
bits1 |= BitRight(bits,rightShift);
343
*pdst = MROP_MASK(bits1, *pdst, startmask);
348
#ifdef LARGE_INSTRUCTION_CACHE
351
#ifdef FAST_CONSTANT_OFFSET_MODE
353
psrc += nl & (UNROLL-1);
354
pdst += nl & (UNROLL-1);
358
pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
360
#define BodyEven(n) \
362
pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
372
*pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
375
#define BodyEven(n) \
377
*pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
382
#endif /* !FAST_CONSTANT_OFFSET_MODE */
392
bits1 = BitLeft(bits, leftShift);
394
*pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
400
bits1 = BitLeft(bits, leftShift);
401
if (BitLeft(endmask, rightShift)) {
403
bits1 |= BitRight(bits, rightShift);
405
*pdst = MROP_MASK (bits1, *pdst, endmask);
407
ilbmScanlineIncDst(pdstLine, auxDst);
408
ilbmScanlineIncSrc(psrcLine, auxSrc);
411
#endif /* DO_UNALIGNED_BITBLT */
412
} else { /* xdir == -1 */
413
xoffSrc = (pptSrc->x + w - 1) & PIM;
414
xoffDst = (pbox->x2 - 1) & PIM;
415
pdstLine += ((pbox->x2-1) >> PWSH) + 1;
416
psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
417
#ifdef DO_UNALIGNED_BITBLT
418
nl = xoffSrc - xoffDst;
419
psrcLine = (PixelType *)
420
(((unsigned char *) psrcLine) + nl);
422
if (xoffSrc == xoffDst)
431
*pdst = MROP_MASK (*psrc, *pdst, endmask);
435
#ifdef LARGE_INSTRUCTION_CACHE
436
#ifdef FAST_CONSTANT_OFFSET_MODE
437
psrc -= nl & (UNROLL - 1);
438
pdst -= nl & (UNROLL - 1);
440
#define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
442
#define BodyEven(n) BodyOdd(n)
450
#define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
451
#define BodyEven(n) BodyOdd(n)
463
--pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
469
*pdst = MROP_MASK(*psrc, *pdst, startmask);
471
ilbmScanlineIncDst(pdstLine, auxDst);
472
ilbmScanlineIncSrc(psrcLine, auxSrc);
475
#ifndef DO_UNALIGNED_BITBLT
477
if (xoffDst > xoffSrc) {
478
rightShift = (xoffDst - xoffSrc);
479
leftShift = PPW - rightShift;
481
leftShift = (xoffSrc - xoffDst);
482
rightShift = PPW - leftShift;
488
if (xoffDst > xoffSrc)
491
bits1 = BitRight(bits, rightShift);
493
bits1 |= BitLeft(bits, leftShift);
495
*pdst = MROP_MASK(bits1, *pdst, endmask);
499
#ifdef LARGE_INSTRUCTION_CACHE
501
#ifdef FAST_CONSTANT_OFFSET_MODE
502
psrc -= nl & (UNROLL - 1);
503
pdst -= nl & (UNROLL - 1);
507
pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
509
#define BodyEven(n) \
511
pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
520
bits = *--psrc; --pdst; \
521
*pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
523
#define BodyEven(n) \
524
bits1 = *--psrc; --pdst; \
525
*pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
539
bits1 = BitRight(bits, rightShift);
542
*pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
547
bits1 = BitRight(bits, rightShift);
548
if (BitRight (startmask, leftShift)) {
550
bits1 |= BitLeft(bits, leftShift);
553
*pdst = MROP_MASK(bits1, *pdst, startmask);
555
ilbmScanlineIncDst(pdstLine, auxDst);
556
ilbmScanlineIncSrc(psrcLine, auxSrc);
566
DEALLOCATE_LOCAL(pptNew2);
567
DEALLOCATE_LOCAL(pboxNew2);
570
DEALLOCATE_LOCAL(pptNew1);
571
DEALLOCATE_LOCAL(pboxNew1);