2 * Copyright © 1998 Keith Packard
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
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD 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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
30 #define InitializeShifts(sx,dx,ls,rs) { \
43 fbBlt (FbBits
*srcLine
,
62 int leftShift
, rightShift
;
63 FbBits startmask
, endmask
;
67 int startbyte
, endbyte
;
71 if (bpp
== 24 && !FbCheck24Pix (pm
))
73 fbBlt24 (srcLine
, srcStride
, srcX
, dstLine
, dstStride
, dstX
,
74 width
, height
, alu
, pm
, reverse
, upsidedown
);
79 if (alu
== GXcopy
&& pm
== FB_ALLONES
&& !reverse
&&
80 !(srcX
& 7) && !(dstX
& 7) && !(width
& 7)) {
82 CARD8
*src
= (CARD8
*) srcLine
;
83 CARD8
*dst
= (CARD8
*) dstLine
;
85 srcStride
*= sizeof(FbBits
);
86 dstStride
*= sizeof(FbBits
);
92 for (i
= 0; i
< height
; i
++)
93 MEMCPY_WRAPPED(dst
+ i
* dstStride
, src
+ i
* srcStride
, width
);
95 for (i
= height
- 1; i
>= 0; i
--)
96 MEMCPY_WRAPPED(dst
+ i
* dstStride
, src
+ i
* srcStride
, width
);
101 FbInitializeMergeRop(alu
, pm
);
102 destInvarient
= FbDestInvarientMergeRop();
105 srcLine
+= (height
- 1) * (srcStride
);
106 dstLine
+= (height
- 1) * (dstStride
);
107 srcStride
= -srcStride
;
108 dstStride
= -dstStride
;
110 FbMaskBitsBytes (dstX
, width
, destInvarient
, startmask
, startbyte
,
111 nmiddle
, endmask
, endbyte
);
114 srcLine
+= ((srcX
+ width
- 1) >> FB_SHIFT
) + 1;
115 dstLine
+= ((dstX
+ width
- 1) >> FB_SHIFT
) + 1;
116 srcX
= (srcX
+ width
- 1) & FB_MASK
;
117 dstX
= (dstX
+ width
- 1) & FB_MASK
;
121 srcLine
+= srcX
>> FB_SHIFT
;
122 dstLine
+= dstX
>> FB_SHIFT
;
131 srcLine
+= srcStride
;
133 dstLine
+= dstStride
;
140 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
146 WRITE(--dst
, FbDoDestInvarientMergeRop(READ(--src
)));
154 WRITE(dst
, FbDoMergeRop (bits
, READ(dst
)));
161 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
169 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
177 * This provides some speedup on screen->screen blts
178 * over the PCI bus, usually about 10%. But fb
179 * isn't usually used for this operation...
181 if (_ca2
+ 1 == 0 && _cx2
== 0)
183 FbBits t1
, t2
, t3
, t4
;
199 WRITE(dst
++, FbDoDestInvarientMergeRop(READ(src
++)));
206 WRITE(dst
, FbDoMergeRop (bits
, READ(dst
)));
213 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
222 leftShift
= srcX
- dstX
;
223 rightShift
= FB_UNIT
- leftShift
;
227 rightShift
= dstX
- srcX
;
228 leftShift
= FB_UNIT
- rightShift
;
233 srcLine
+= srcStride
;
235 dstLine
+= dstStride
;
244 bits
= FbScrRight(bits1
, rightShift
);
245 if (FbScrRight(endmask
, leftShift
))
248 bits
|= FbScrLeft(bits1
, leftShift
);
251 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
258 bits
= FbScrRight(bits1
, rightShift
);
260 bits
|= FbScrLeft(bits1
, leftShift
);
262 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
269 bits
= FbScrRight(bits1
, rightShift
);
271 bits
|= FbScrLeft(bits1
, leftShift
);
273 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
278 bits
= FbScrRight(bits1
, rightShift
);
279 if (FbScrRight(startmask
, leftShift
))
282 bits
|= FbScrLeft(bits1
, leftShift
);
285 FbDoLeftMaskByteMergeRop (dst
, bits
, startbyte
, startmask
);
294 bits
= FbScrLeft(bits1
, leftShift
);
295 if (FbScrLeft(startmask
, rightShift
))
298 bits
|= FbScrRight(bits1
, rightShift
);
300 FbDoLeftMaskByteMergeRop (dst
, bits
, startbyte
, startmask
);
308 bits
= FbScrLeft(bits1
, leftShift
);
310 bits
|= FbScrRight(bits1
, rightShift
);
311 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
319 bits
= FbScrLeft(bits1
, leftShift
);
321 bits
|= FbScrRight(bits1
, rightShift
);
322 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
328 bits
= FbScrLeft(bits1
, leftShift
);
329 if (FbScrLeft(endmask
, rightShift
))
332 bits
|= FbScrRight(bits1
, rightShift
);
334 FbDoRightMaskByteMergeRop (dst
, bits
, endbyte
, endmask
);
347 getPixel (char *src
, int x
)
352 memcpy (&l
, src
+ x
* 3, 3);
358 fbBlt24Line (FbBits
*src
,
372 char *origDst
= (char *) dst
;
373 FbBits
*origLine
= dst
+ ((dstX
>> FB_SHIFT
) - 1);
374 int origNlw
= ((width
+ FB_MASK
) >> FB_SHIFT
) + 3;
375 int origX
= dstX
/ 24;
378 int leftShift
, rightShift
;
379 FbBits startmask
, endmask
;
386 FbDeclareMergeRop ();
388 FbInitializeMergeRop (alu
, FB_ALLONES
);
389 FbMaskBits(dstX
, width
, startmask
, n
, endmask
);
391 ErrorF ("dstX %d width %d reverse %d\n", dstX
, width
, reverse
);
395 src
+= ((srcX
+ width
- 1) >> FB_SHIFT
) + 1;
396 dst
+= ((dstX
+ width
- 1) >> FB_SHIFT
) + 1;
397 rot
= FbFirst24Rot (((dstX
+ width
- 8) & FB_MASK
));
398 rot
= FbPrev24Rot(rot
);
400 ErrorF ("dstX + width - 8: %d rot: %d\n", (dstX
+ width
- 8) & FB_MASK
, rot
);
402 srcX
= (srcX
+ width
- 1) & FB_MASK
;
403 dstX
= (dstX
+ width
- 1) & FB_MASK
;
407 src
+= srcX
>> FB_SHIFT
;
408 dst
+= dstX
>> FB_SHIFT
;
411 rot
= FbFirst24Rot (dstX
);
413 ErrorF ("dstX: %d rot: %d\n", dstX
, rot
);
416 mask
= FbRot24(pm
,rot
);
418 ErrorF ("pm 0x%x mask 0x%x\n", pm
, mask
);
428 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& endmask
));
429 mask
= FbPrev24Pix (mask
);
435 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
));
436 mask
= FbPrev24Pix (mask
);
442 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& startmask
));
450 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& startmask
));
452 mask
= FbNext24Pix(mask
);
457 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
));
459 mask
= FbNext24Pix(mask
);
464 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& endmask
));
472 leftShift
= srcX
- dstX
;
473 rightShift
= FB_UNIT
- leftShift
;
477 rightShift
= dstX
- srcX
;
478 leftShift
= FB_UNIT
- rightShift
;
488 bits
= FbScrRight(bits1
, rightShift
);
489 if (FbScrRight(endmask
, leftShift
))
492 bits
|= FbScrLeft(bits1
, leftShift
);
495 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& endmask
));
496 mask
= FbPrev24Pix(mask
);
500 bits
= FbScrRight(bits1
, rightShift
);
502 bits
|= FbScrLeft(bits1
, leftShift
);
504 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
505 mask
= FbPrev24Pix(mask
);
509 bits
= FbScrRight(bits1
, rightShift
);
510 if (FbScrRight(startmask
, leftShift
))
513 bits
|= FbScrLeft(bits1
, leftShift
);
516 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& startmask
));
525 bits
= FbScrLeft(bits1
, leftShift
);
527 bits
|= FbScrRight(bits1
, rightShift
);
528 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& startmask
));
530 mask
= FbNext24Pix(mask
);
534 bits
= FbScrLeft(bits1
, leftShift
);
536 bits
|= FbScrRight(bits1
, rightShift
);
537 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
539 mask
= FbNext24Pix(mask
);
543 bits
= FbScrLeft(bits1
, leftShift
);
544 if (FbScrLeft(endmask
, rightShift
))
547 bits
|= FbScrRight(bits1
, rightShift
);
549 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), mask
& endmask
));
555 int firstx
, lastx
, x
;
560 lastx
= origX
+ width
/24 + 1;
561 for (x
= firstx
; x
<= lastx
; x
++)
562 ErrorF ("%06x ", getPixel (origDst
, x
));
565 ErrorF ("%08x ", *origLine
++);
572 fbBlt24 (FbBits
*srcLine
,
591 srcLine
+= (height
-1) * srcStride
;
592 dstLine
+= (height
-1) * dstStride
;
593 srcStride
= -srcStride
;
594 dstStride
= -dstStride
;
598 fbBlt24Line (srcLine
, srcX
, dstLine
, dstX
, width
, alu
, pm
, reverse
);
599 srcLine
+= srcStride
;
600 dstLine
+= dstStride
;
606 #endif /* FB_24BIT */
608 #if FB_SHIFT == FB_STIP_SHIFT + 1
611 * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by
612 * creating an ring of values stepped through for each line
616 fbBltOdd (FbBits
*srcLine
,
617 FbStride srcStrideEven
,
618 FbStride srcStrideOdd
,
623 FbStride dstStrideEven
,
624 FbStride dstStrideOdd
,
636 int leftShiftEven
, rightShiftEven
;
637 FbBits startmaskEven
, endmaskEven
;
641 int leftShiftOdd
, rightShiftOdd
;
642 FbBits startmaskOdd
, endmaskOdd
;
645 int leftShift
, rightShift
;
646 FbBits startmask
, endmask
;
656 FbDeclareMergeRop ();
658 FbInitializeMergeRop (alu
, pm
);
659 destInvarient
= FbDestInvarientMergeRop();
661 srcLine
+= srcXEven
>> FB_SHIFT
;
662 dstLine
+= dstXEven
>> FB_SHIFT
;
668 FbMaskBits(dstXEven
, width
, startmaskEven
, nmiddleEven
, endmaskEven
);
669 FbMaskBits(dstXOdd
, width
, startmaskOdd
, nmiddleOdd
, endmaskOdd
);
672 InitializeShifts(srcXEven
, dstXEven
, leftShiftEven
, rightShiftEven
);
673 InitializeShifts(srcXOdd
, dstXOdd
, leftShiftOdd
, rightShiftOdd
);
682 startmask
= startmaskEven
;
683 endmask
= endmaskEven
;
684 nmiddle
= nmiddleEven
;
685 leftShift
= leftShiftEven
;
686 rightShift
= rightShiftEven
;
687 srcLine
+= srcStrideEven
;
688 dstLine
+= dstStrideEven
;
695 startmask
= startmaskOdd
;
696 endmask
= endmaskOdd
;
697 nmiddle
= nmiddleOdd
;
698 leftShift
= leftShiftOdd
;
699 rightShift
= rightShiftOdd
;
700 srcLine
+= srcStrideOdd
;
701 dstLine
+= dstStrideOdd
;
709 WRITE(dst
, FbDoMaskMergeRop (bits
, READ(dst
), startmask
));
718 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
727 WRITE(dst
, FbDoMergeRop (bits
, READ(dst
)));
734 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), endmask
));
744 bits1
= FbScrLeft(bits
, leftShift
);
746 bits1
|= FbScrRight(bits
, rightShift
);
747 WRITE(dst
, FbDoMaskMergeRop (bits1
, READ(dst
), startmask
));
755 bits1
= FbScrLeft(bits
, leftShift
);
757 bits1
|= FbScrRight(bits
, rightShift
);
758 WRITE(dst
, FbDoDestInvarientMergeRop(bits1
));
766 bits1
= FbScrLeft(bits
, leftShift
);
768 bits1
|= FbScrRight(bits
, rightShift
);
769 WRITE(dst
, FbDoMergeRop(bits1
, READ(dst
)));
775 bits1
= FbScrLeft(bits
, leftShift
);
776 if (FbScrLeft(endmask
, rightShift
))
779 bits1
|= FbScrRight(bits
, rightShift
);
781 WRITE(dst
, FbDoMaskMergeRop (bits1
, READ(dst
), endmask
));
789 fbBltOdd24 (FbBits
*srcLine
,
790 FbStride srcStrideEven
,
791 FbStride srcStrideOdd
,
796 FbStride dstStrideEven
,
797 FbStride dstStrideOdd
,
813 fbBlt24Line (srcLine
, srcXEven
, dstLine
, dstXEven
,
814 width
, alu
, pm
, FALSE
);
815 srcLine
+= srcStrideEven
;
816 dstLine
+= dstStrideEven
;
821 fbBlt24Line (srcLine
, srcXOdd
, dstLine
, dstXOdd
,
822 width
, alu
, pm
, FALSE
);
823 srcLine
+= srcStrideOdd
;
824 dstLine
+= dstStrideOdd
;
829 fprintf (stderr
, "\n");
836 #if FB_STIP_SHIFT != FB_SHIFT
838 fbSetBltOdd (FbStip
*stip
,
842 FbStride
*strideEven
,
851 * bytes needed to align source
853 srcAdjust
= (((int) stip
) & (FB_MASK
>> 3));
855 * FbStip units needed to align stride
857 strideAdjust
= stipStride
& (FB_MASK
>> FB_STIP_SHIFT
);
859 *bits
= (FbBits
*) ((char *) stip
- srcAdjust
);
862 *strideEven
= FbStipStrideToBitsStride (stipStride
+ 1);
863 *strideOdd
= FbStipStrideToBitsStride (stipStride
);
865 *srcXEven
= srcX
+ (srcAdjust
<< 3);
866 *srcXOdd
= srcX
+ (srcAdjust
<< 3) - (strideAdjust
<< FB_STIP_SHIFT
);
870 *strideEven
= FbStipStrideToBitsStride (stipStride
);
871 *strideOdd
= FbStipStrideToBitsStride (stipStride
+ 1);
874 *srcXOdd
= srcX
+ (strideAdjust
<< FB_STIP_SHIFT
);
880 fbBltStip (FbStip
*src
,
881 FbStride srcStride
, /* in FbStip units, not FbBits units */
885 FbStride dstStride
, /* in FbStip units, not FbBits units */
895 #if FB_STIP_SHIFT != FB_SHIFT
896 if (FB_STIP_ODDSTRIDE(srcStride
) || FB_STIP_ODDPTR(src
) ||
897 FB_STIP_ODDSTRIDE(dstStride
) || FB_STIP_ODDPTR(dst
))
899 FbStride srcStrideEven
, srcStrideOdd
;
900 FbStride dstStrideEven
, dstStrideOdd
;
901 int srcXEven
, srcXOdd
;
902 int dstXEven
, dstXOdd
;
906 src
+= srcX
>> FB_STIP_SHIFT
;
907 srcX
&= FB_STIP_MASK
;
908 dst
+= dstX
>> FB_STIP_SHIFT
;
909 dstX
&= FB_STIP_MASK
;
911 fbSetBltOdd (src
, srcStride
, srcX
,
913 &srcStrideEven
, &srcStrideOdd
,
914 &srcXEven
, &srcXOdd
);
916 fbSetBltOdd (dst
, dstStride
, dstX
,
918 &dstStrideEven
, &dstStrideOdd
,
919 &dstXEven
, &dstXOdd
);
922 if (bpp
== 24 && !FbCheck24Pix (pm
))
924 fbBltOdd24 (s
, srcStrideEven
, srcStrideOdd
,
927 d
, dstStrideEven
, dstStrideOdd
,
930 width
, height
, alu
, pm
);
935 fbBltOdd (s
, srcStrideEven
, srcStrideOdd
,
938 d
, dstStrideEven
, dstStrideOdd
,
941 width
, height
, alu
, pm
, bpp
);
947 fbBlt ((FbBits
*) src
, FbStipStrideToBitsStride (srcStride
),
949 (FbBits
*) dst
, FbStipStrideToBitsStride (dstStride
),
952 alu
, pm
, bpp
, FALSE
, FALSE
);