1
/* $XFree86: xc/programs/Xserver/afb/afbblt.c,v 3.0 1996/08/18 01:45:24 dawes Exp $ */
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: afbblt.c,v 1.11 94/04/17 20:28:16 dpw Exp $ */
36
#ifdef HAVE_DIX_CONFIG_H
37
#include <dix-config.h>
42
#include <X11/Xproto.h>
45
#include "windowstr.h"
46
#include "scrnintstr.h"
47
#include "pixmapstr.h"
48
#include "regionstr.h"
54
MROP_NAME(afbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
55
DrawablePtr pSrc, pDst;
59
unsigned long planemask;
61
PixelType *psrcBase, *pdstBase; /* start of src and dst bitmaps */
62
int widthSrc, widthDst; /* add to get to same position in next line */
68
BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
69
/* temporaries for shuffling rectangles */
70
DDXPointPtr pptTmp, pptNew1, pptNew2;
71
/* shuffling boxes entails shuffling the
74
int xdir; /* 1 = left right, -1 = right left/ */
75
int ydir; /* 1 = top down, -1 = bottom up */
77
PixelType *psrcLine, *pdstLine;
78
/* pointers to line with current src and dst */
79
register PixelType *psrc; /* pointer to current src longword */
80
register PixelType *pdst; /* pointer to current dst longword */
84
/* following used for looping through a line */
85
PixelType startmask, endmask; /* masks for writing ends of dst */
86
int nlMiddle; /* whole longwords in dst */
88
register int leftShift, rightShift;
89
register PixelType bits;
90
register PixelType bits1;
91
register int nl; /* temp copy of nlMiddle */
97
MROP_INITIALIZE(alu,0);
99
afbGetPixelWidthSizeDepthAndPointer(pSrc, widthSrc, sizeSrc, depthSrc,
101
afbGetPixelWidthSizeDepthAndPointer(pDst, widthDst, sizeDst, depthDst,
104
/* Special case where depth of dest pixmap is 1 but source pixmap isn't
105
* Used for GetImage to copy a plane from a source pixmap to a particular
107
* Note: planemask should have only one bit set or several planes from
108
* the source will be copied to the same dest plane.
110
if (depthDst == 1 && depthDst != depthSrc)
113
/* XXX we have to err on the side of safety when both are windows,
114
* because we don't know if IncludeInferiors is being used.
116
careful = ((pSrc == pDst) ||
117
((pSrc->type == DRAWABLE_WINDOW) &&
118
(pDst->type == DRAWABLE_WINDOW)));
120
pbox = REGION_RECTS(prgnDst);
121
nbox = REGION_NUM_RECTS(prgnDst);
127
if (careful && (pptSrc->y < pbox->y1)) {
128
/* walk source botttom to top */
130
widthSrc = -widthSrc;
131
widthDst = -widthDst;
134
/* keep ordering in each band, reverse order of bands */
135
pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
138
pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
140
DEALLOCATE_LOCAL(pboxNew1);
143
pboxBase = pboxNext = pbox+nbox-1;
144
while (pboxBase >= pbox) {
145
while ((pboxNext >= pbox) &&
146
(pboxBase->y1 == pboxNext->y1))
148
pboxTmp = pboxNext+1;
149
pptTmp = pptSrc + (pboxTmp - pbox);
150
while (pboxTmp <= pboxBase) {
151
*pboxNew1++ = *pboxTmp++;
152
*pptNew1++ = *pptTmp++;
162
/* walk source top to bottom */
166
if (careful && (pptSrc->x < pbox->x1)) {
167
/* walk source right to left */
171
/* reverse order of rects in each band */
172
pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
173
pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
174
if(!pboxNew2 || !pptNew2) {
176
DEALLOCATE_LOCAL(pptNew2);
178
DEALLOCATE_LOCAL(pboxNew2);
180
DEALLOCATE_LOCAL(pptNew1);
181
DEALLOCATE_LOCAL(pboxNew1);
185
pboxBase = pboxNext = pbox;
186
while (pboxBase < pbox+nbox) {
187
while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1))
190
pptTmp = pptSrc + (pboxTmp - pbox);
191
while (pboxTmp != pboxBase) {
192
*pboxNew2++ = *--pboxTmp;
193
*pptNew2++ = *--pptTmp;
203
/* walk source left to right */
209
for (d = 0; d < depthSrc; d++) {
213
if (!(planemask & (1 << d)))
216
psrcB = psrcBase + sizeSrc * d; /* @@@ NEXT PLANE @@@ */
217
pdstB = pdstBase + sizeDst * d; /* @@@ NEXT PLANE @@@ */
219
w = pbox->x2 - pbox->x1;
220
h = pbox->y2 - pbox->y1;
222
if (ydir == -1) { /* start at last scanline of rectangle */
223
psrcLine = afbScanlineDeltaSrc(psrcB, -(pptSrc->y+h-1), widthSrc);
224
pdstLine = afbScanlineDeltaDst(pdstB, -(pbox->y2-1), widthDst);
225
} else { /* start at first scanline */
226
psrcLine = afbScanlineDeltaSrc(psrcB, pptSrc->y, widthSrc);
227
pdstLine = afbScanlineDeltaDst(pdstB, pbox->y1, widthDst);
229
if ((pbox->x1 & PIM) + w <= PPW) {
230
maskpartialbits (pbox->x1, w, startmask);
234
maskbits(pbox->x1, w, startmask, endmask, nlMiddle);
237
xoffSrc = pptSrc->x & PIM;
238
xoffDst = pbox->x1 & PIM;
239
pdstLine += (pbox->x1 >> PWSH);
240
psrcLine += (pptSrc->x >> PWSH);
241
#ifdef DO_UNALIGNED_BITBLT
242
nl = xoffSrc - xoffDst;
243
psrcLine = (PixelType *)(((unsigned char *) psrcLine) + nl);
245
if (xoffSrc == xoffDst)
252
*pdst = MROP_MASK(*psrc, *pdst, startmask);
258
#ifdef LARGE_INSTRUCTION_CACHE
259
#ifdef FAST_CONSTANT_OFFSET_MODE
261
psrc += nl & (UNROLL-1);
262
pdst += nl & (UNROLL-1);
264
#define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
265
#define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
273
#define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
274
#define BodyEven(n) BodyOdd(n)
287
/* you'd think this would be faster --
288
* a single instruction instead of 6
289
* but measurements show it to be ~15% slower
291
while ((nl -= 6) >= 0) {
292
asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
293
: "=m" (*(char *)pdst)
294
: "m" (*(char *)psrc)
295
: "d0", "d1", "d2", "d3",
304
*pdst = MROP_SOLID (*psrc, *pdst);
309
*pdst = MROP_MASK(*psrc, *pdst, endmask);
310
afbScanlineIncDst(pdstLine, widthDst);
311
afbScanlineIncSrc(psrcLine, widthSrc);
314
#ifndef DO_UNALIGNED_BITBLT
316
if (xoffSrc > xoffDst) {
317
leftShift = (xoffSrc - xoffDst);
318
rightShift = PPW - leftShift;
320
rightShift = (xoffDst - xoffSrc);
321
leftShift = PPW - rightShift;
327
if (xoffSrc > xoffDst)
330
bits1 = BitLeft(bits,leftShift);
332
bits1 |= BitRight(bits,rightShift);
333
*pdst = MROP_MASK(bits1, *pdst, startmask);
338
#ifdef LARGE_INSTRUCTION_CACHE
341
#ifdef FAST_CONSTANT_OFFSET_MODE
343
psrc += nl & (UNROLL-1);
344
pdst += nl & (UNROLL-1);
348
pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
350
#define BodyEven(n) \
352
pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
362
*pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
365
#define BodyEven(n) \
367
*pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
372
#endif /* !FAST_CONSTANT_OFFSET_MODE */
382
bits1 = BitLeft(bits, leftShift);
384
*pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
390
bits1 = BitLeft(bits, leftShift);
391
if (BitLeft(endmask, rightShift)) {
393
bits1 |= BitRight(bits, rightShift);
395
*pdst = MROP_MASK (bits1, *pdst, endmask);
397
afbScanlineIncDst(pdstLine, widthDst);
398
afbScanlineIncSrc(psrcLine, widthSrc);
401
#endif /* DO_UNALIGNED_BITBLT */
402
} else { /* xdir == -1 */
403
xoffSrc = (pptSrc->x + w - 1) & PIM;
404
xoffDst = (pbox->x2 - 1) & PIM;
405
pdstLine += ((pbox->x2-1) >> PWSH) + 1;
406
psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
407
#ifdef DO_UNALIGNED_BITBLT
408
nl = xoffSrc - xoffDst;
409
psrcLine = (PixelType *)
410
(((unsigned char *) psrcLine) + nl);
412
if (xoffSrc == xoffDst)
421
*pdst = MROP_MASK (*psrc, *pdst, endmask);
425
#ifdef LARGE_INSTRUCTION_CACHE
426
#ifdef FAST_CONSTANT_OFFSET_MODE
427
psrc -= nl & (UNROLL - 1);
428
pdst -= nl & (UNROLL - 1);
430
#define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
432
#define BodyEven(n) BodyOdd(n)
440
#define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
441
#define BodyEven(n) BodyOdd(n)
453
--pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
459
*pdst = MROP_MASK(*psrc, *pdst, startmask);
461
afbScanlineIncDst(pdstLine, widthDst);
462
afbScanlineIncSrc(psrcLine, widthSrc);
465
#ifndef DO_UNALIGNED_BITBLT
467
if (xoffDst > xoffSrc) {
468
rightShift = (xoffDst - xoffSrc);
469
leftShift = PPW - rightShift;
471
leftShift = (xoffSrc - xoffDst);
472
rightShift = PPW - leftShift;
478
if (xoffDst > xoffSrc)
481
bits1 = BitRight(bits, rightShift);
483
bits1 |= BitLeft(bits, leftShift);
485
*pdst = MROP_MASK(bits1, *pdst, endmask);
489
#ifdef LARGE_INSTRUCTION_CACHE
491
#ifdef FAST_CONSTANT_OFFSET_MODE
492
psrc -= nl & (UNROLL - 1);
493
pdst -= nl & (UNROLL - 1);
497
pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
499
#define BodyEven(n) \
501
pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
510
bits = *--psrc; --pdst; \
511
*pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
513
#define BodyEven(n) \
514
bits1 = *--psrc; --pdst; \
515
*pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
529
bits1 = BitRight(bits, rightShift);
532
*pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
537
bits1 = BitRight(bits, rightShift);
538
if (BitRight (startmask, leftShift)) {
540
bits1 |= BitLeft(bits, leftShift);
543
*pdst = MROP_MASK(bits1, *pdst, startmask);
545
afbScanlineIncDst(pdstLine, widthDst);
546
afbScanlineIncSrc(psrcLine, widthSrc);
556
DEALLOCATE_LOCAL(pptNew2);
557
DEALLOCATE_LOCAL(pboxNew2);
560
DEALLOCATE_LOCAL(pptNew1);
561
DEALLOCATE_LOCAL(pboxNew1);