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.
34 #ifdef HAVE_DIX_CONFIG_H
35 #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
);