7 Copyright (c) 1989 X Consortium
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall not be
27 used in advertising or otherwise to promote the sale, use or other dealings
28 in this Software without prior written authorization from the X Consortium.
33 /* $XConsortium: mfbblt.c,v 1.11 94/04/17 20:28:16 dpw Exp $ */
34 /* $XFree86: xc/programs/Xserver/mfb/mfbblt.c,v 3.0 1994/08/12 14:03:38 dawes Exp $ */
41 #include "windowstr.h"
42 #include "scrnintstr.h"
43 #include "pixmapstr.h"
44 #include "regionstr.h"
50 MROP_NAME(mfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc)
51 DrawablePtr pSrc, pDst;
56 PixelType *psrcBase, *pdstBase;
57 /* start of src and dst bitmaps */
58 int widthSrc, widthDst; /* add to get to same position in next line */
63 BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2;
64 /* temporaries for shuffling rectangles */
65 DDXPointPtr pptTmp, pptNew1, pptNew2;
66 /* shuffling boxes entails shuffling the
69 int xdir; /* 1 = left right, -1 = right left/ */
70 int ydir; /* 1 = top down, -1 = bottom up */
72 PixelType *psrcLine, *pdstLine;
73 /* pointers to line with current src and dst */
74 register PixelType *psrc;/* pointer to current src longword */
75 register PixelType *pdst;/* pointer to current dst longword */
79 /* following used for looping through a line */
80 PixelType startmask, endmask; /* masks for writing ends of dst */
81 int nlMiddle; /* whole longwords in dst */
83 register int leftShift, rightShift;
84 register PixelType bits;
85 register PixelType bits1;
86 register int nl; /* temp copy of nlMiddle */
88 /* place to store full source word */
89 int nstart; /* number of ragged bits at start of dst */
90 int nend; /* number of ragged bits at end of dst */
91 int srcStartOver; /* pulling nstart bits from src
92 overflows into the next word? */
96 MROP_INITIALIZE(alu,0);
98 mfbGetPixelWidthAndPointer(pSrc, widthSrc, psrcBase);
100 mfbGetPixelWidthAndPointer(pDst, widthDst, pdstBase);
102 /* XXX we have to err on the side of safety when both are windows,
103 * because we don't know if IncludeInferiors is being used.
105 careful = ((pSrc == pDst) ||
106 ((pSrc->type == DRAWABLE_WINDOW) &&
107 (pDst->type == DRAWABLE_WINDOW)));
109 pbox = REGION_RECTS(prgnDst);
110 nbox = REGION_NUM_RECTS(prgnDst);
116 if (careful && (pptSrc->y < pbox->y1))
118 /* walk source botttom to top */
120 widthSrc = -widthSrc;
121 widthDst = -widthDst;
125 /* keep ordering in each band, reverse order of bands */
126 pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
129 pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
132 DEALLOCATE_LOCAL(pboxNew1);
135 pboxBase = pboxNext = pbox+nbox-1;
136 while (pboxBase >= pbox)
138 while ((pboxNext >= pbox) &&
139 (pboxBase->y1 == pboxNext->y1))
141 pboxTmp = pboxNext+1;
142 pptTmp = pptSrc + (pboxTmp - pbox);
143 while (pboxTmp <= pboxBase)
145 *pboxNew1++ = *pboxTmp++;
146 *pptNew1++ = *pptTmp++;
158 /* walk source top to bottom */
162 if (careful && (pptSrc->x < pbox->x1))
164 /* walk source right to left */
169 /* reverse order of rects in each band */
170 pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox);
171 pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
172 if(!pboxNew2 || !pptNew2)
174 if (pptNew2) DEALLOCATE_LOCAL(pptNew2);
175 if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2);
178 DEALLOCATE_LOCAL(pptNew1);
179 DEALLOCATE_LOCAL(pboxNew1);
183 pboxBase = pboxNext = pbox;
184 while (pboxBase < pbox+nbox)
186 while ((pboxNext < pbox+nbox) &&
187 (pboxNext->y1 == pboxBase->y1))
190 pptTmp = pptSrc + (pboxTmp - pbox);
191 while (pboxTmp != pboxBase)
193 *pboxNew2++ = *--pboxTmp;
194 *pptNew2++ = *--pptTmp;
206 /* walk source left to right */
212 w = pbox->x2 - pbox->x1;
213 h = pbox->y2 - pbox->y1;
215 if (ydir == -1) /* start at last scanline of rectangle */
217 psrcLine = mfbScanlineDeltaSrc(psrcBase, -(pptSrc->y+h-1), widthSrc);
218 pdstLine = mfbScanlineDeltaDst(pdstBase, -(pbox->y2-1), widthDst);
220 else /* start at first scanline */
222 psrcLine = mfbScanlineDeltaSrc(psrcBase, pptSrc->y, widthSrc);
223 pdstLine = mfbScanlineDeltaDst(pdstBase, pbox->y1, widthDst);
225 if ((pbox->x1 & PIM) + w <= PPW)
227 maskpartialbits (pbox->x1, w, startmask);
233 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 *)
244 (((unsigned char *) psrcLine) + nl);
246 if (xoffSrc == xoffDst)
255 *pdst = MROP_MASK(*psrc, *pdst, startmask);
261 #ifdef LARGE_INSTRUCTION_CACHE
262 #ifdef FAST_CONSTANT_OFFSET_MODE
264 psrc += nl & (UNROLL-1);
265 pdst += nl & (UNROLL-1);
267 #define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
268 #define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]);
276 #define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;
277 #define BodyEven(n) BodyOdd(n)
290 /* you'd think this would be faster --
291 * a single instruction instead of 6
292 * but measurements show it to be ~15% slower
294 while ((nl -= 6) >= 0)
296 asm ("moveml %1+,#0x0c0f;moveml#0x0c0f,%0"
297 : "=m" (*(char *)pdst)
298 : "m" (*(char *)psrc)
299 : "d0", "d1", "d2", "d3",
308 *pdst = MROP_SOLID (*psrc, *pdst);
313 *pdst = MROP_MASK(*psrc, *pdst, endmask);
314 mfbScanlineIncDst(pdstLine, widthDst);
315 mfbScanlineIncSrc(psrcLine, widthSrc);
318 #ifndef DO_UNALIGNED_BITBLT
321 if (xoffSrc > xoffDst)
323 leftShift = (xoffSrc - xoffDst);
324 rightShift = PPW - leftShift;
328 rightShift = (xoffDst - xoffSrc);
329 leftShift = PPW - rightShift;
336 if (xoffSrc > xoffDst)
340 bits1 = BitLeft(bits,leftShift);
341 if (BitLeft(startmask, rightShift)) {
343 bits1 |= BitRight(bits,rightShift);
345 *pdst = MROP_MASK(bits1, *pdst, startmask);
350 #ifdef LARGE_INSTRUCTION_CACHE
353 #ifdef FAST_CONSTANT_OFFSET_MODE
355 psrc += nl & (UNROLL-1);
356 pdst += nl & (UNROLL-1);
360 pdst[-n] = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), pdst[-n]);
362 #define BodyEven(n) \
364 pdst[-n] = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), pdst[-n]);
374 *pdst = MROP_SOLID(BitLeft(bits1, leftShift) | BitRight(bits, rightShift), *pdst); \
377 #define BodyEven(n) \
379 *pdst = MROP_SOLID(BitLeft(bits, leftShift) | BitRight(bits1, rightShift), *pdst); \
384 #endif /* !FAST_CONSTANT_OFFSET_MODE */
394 bits1 = BitLeft(bits, leftShift);
396 *pdst = MROP_SOLID (bits1 | BitRight(bits, rightShift), *pdst);
403 bits1 = BitLeft(bits, leftShift);
404 if (BitLeft(endmask, rightShift))
407 bits1 |= BitRight(bits, rightShift);
409 *pdst = MROP_MASK (bits1, *pdst, endmask);
411 mfbScanlineIncDst(pdstLine, widthDst);
412 mfbScanlineIncSrc(psrcLine, widthSrc);
415 #endif /* DO_UNALIGNED_BITBLT */
417 else /* xdir == -1 */
419 xoffSrc = (pptSrc->x + w - 1) & PIM;
420 xoffDst = (pbox->x2 - 1) & PIM;
421 pdstLine += ((pbox->x2-1) >> PWSH) + 1;
422 psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1;
423 #ifdef DO_UNALIGNED_BITBLT
424 nl = xoffSrc - xoffDst;
425 psrcLine = (PixelType *)
426 (((unsigned char *) psrcLine) + nl);
428 if (xoffSrc == xoffDst)
439 *pdst = MROP_MASK (*psrc, *pdst, endmask);
443 #ifdef LARGE_INSTRUCTION_CACHE
444 #ifdef FAST_CONSTANT_OFFSET_MODE
445 psrc -= nl & (UNROLL - 1);
446 pdst -= nl & (UNROLL - 1);
448 #define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]);
450 #define BodyEven(n) BodyOdd(n)
458 #define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst);
459 #define BodyEven(n) BodyOdd(n)
471 --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);)
478 *pdst = MROP_MASK(*psrc, *pdst, startmask);
480 mfbScanlineIncDst(pdstLine, widthDst);
481 mfbScanlineIncSrc(psrcLine, widthSrc);
484 #ifndef DO_UNALIGNED_BITBLT
487 if (xoffDst > xoffSrc)
489 rightShift = (xoffDst - xoffSrc);
490 leftShift = PPW - rightShift;
494 leftShift = (xoffSrc - xoffDst);
495 rightShift = PPW - leftShift;
502 if (xoffDst > xoffSrc)
506 bits1 = BitRight(bits, rightShift);
507 if (BitRight(endmask, leftShift)) {
509 bits1 |= BitLeft(bits, leftShift);
512 *pdst = MROP_MASK(bits1, *pdst, endmask);
516 #ifdef LARGE_INSTRUCTION_CACHE
518 #ifdef FAST_CONSTANT_OFFSET_MODE
519 psrc -= nl & (UNROLL - 1);
520 pdst -= nl & (UNROLL - 1);
524 pdst[n-1] = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),pdst[n-1]);
526 #define BodyEven(n) \
528 pdst[n-1] = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),pdst[n-1]);
537 bits = *--psrc; --pdst; \
538 *pdst = MROP_SOLID(BitRight(bits1, rightShift) | BitLeft(bits, leftShift),*pdst);
540 #define BodyEven(n) \
541 bits1 = *--psrc; --pdst; \
542 *pdst = MROP_SOLID(BitRight(bits, rightShift) | BitLeft(bits1, leftShift),*pdst);
556 bits1 = BitRight(bits, rightShift);
559 *pdst = MROP_SOLID(bits1 | BitLeft(bits, leftShift),*pdst);
565 bits1 = BitRight(bits, rightShift);
566 if (BitRight (startmask, leftShift))
569 bits1 |= BitLeft(bits, leftShift);
572 *pdst = MROP_MASK(bits1, *pdst, startmask);
574 mfbScanlineIncDst(pdstLine, widthDst);
575 mfbScanlineIncSrc(psrcLine, widthSrc);
585 DEALLOCATE_LOCAL(pptNew2);
586 DEALLOCATE_LOCAL(pboxNew2);
590 DEALLOCATE_LOCAL(pptNew1);
591 DEALLOCATE_LOCAL(pboxNew1);