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
,
50 int height
, int alu
, FbBits pm
, int bpp
, Bool reverse
, Bool upsidedown
)
53 int leftShift
, rightShift
;
54 FbBits startmask
, endmask
;
58 int startbyte
, endbyte
;
63 if (bpp
== 24 && !FbCheck24Pix(pm
)) {
64 fbBlt24(srcLine
, srcStride
, srcX
, dstLine
, dstStride
, dstX
,
65 width
, height
, alu
, pm
, reverse
, upsidedown
);
69 careful
= !((srcLine
< dstLine
&& srcLine
+ width
* (bpp
>> 3) > dstLine
) ||
70 (dstLine
< srcLine
&& dstLine
+ width
* (bpp
>> 3) > srcLine
))
73 if (alu
== GXcopy
&& pm
== FB_ALLONES
&& !careful
&&
74 !(srcX
& 7) && !(dstX
& 7) && !(width
& 7)) {
76 CARD8
*tmpsrc
= (CARD8
*) srcLine
;
77 CARD8
*tmpdst
= (CARD8
*) dstLine
;
79 srcStride
*= sizeof(FbBits
);
80 dstStride
*= sizeof(FbBits
);
82 tmpsrc
+= (srcX
>> 3);
83 tmpdst
+= (dstX
>> 3);
86 for (i
= 0; i
< height
; i
++)
87 MEMCPY_WRAPPED(tmpdst
+ i
* dstStride
, tmpsrc
+ i
* srcStride
, width
);
89 for (i
= height
- 1; i
>= 0; i
--)
90 MEMCPY_WRAPPED(tmpdst
+ i
* dstStride
, tmpsrc
+ i
* srcStride
, width
);
95 FbInitializeMergeRop(alu
, pm
);
96 destInvarient
= FbDestInvarientMergeRop();
98 srcLine
+= (height
- 1) * (srcStride
);
99 dstLine
+= (height
- 1) * (dstStride
);
100 srcStride
= -srcStride
;
101 dstStride
= -dstStride
;
103 FbMaskBitsBytes(dstX
, width
, destInvarient
, startmask
, startbyte
,
104 nmiddle
, endmask
, endbyte
);
106 srcLine
+= ((srcX
+ width
- 1) >> FB_SHIFT
) + 1;
107 dstLine
+= ((dstX
+ width
- 1) >> FB_SHIFT
) + 1;
108 srcX
= (srcX
+ width
- 1) & FB_MASK
;
109 dstX
= (dstX
+ width
- 1) & FB_MASK
;
112 srcLine
+= srcX
>> FB_SHIFT
;
113 dstLine
+= dstX
>> FB_SHIFT
;
120 srcLine
+= srcStride
;
122 dstLine
+= dstStride
;
127 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
132 WRITE(--dst
, FbDoDestInvarientMergeRop(READ(--src
)));
138 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
144 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
150 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
157 * This provides some speedup on screen->screen blts
158 * over the PCI bus, usually about 10%. But fb
159 * isn't usually used for this operation...
161 if (_ca2
+ 1 == 0 && _cx2
== 0) {
162 FbBits t1
, t2
, t3
, t4
;
178 WRITE(dst
++, FbDoDestInvarientMergeRop(READ(src
++)));
183 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
189 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
196 leftShift
= srcX
- dstX
;
197 rightShift
= FB_UNIT
- leftShift
;
200 rightShift
= dstX
- srcX
;
201 leftShift
= FB_UNIT
- rightShift
;
205 srcLine
+= srcStride
;
207 dstLine
+= dstStride
;
214 bits
= FbScrRight(bits1
, rightShift
);
215 if (FbScrRight(endmask
, leftShift
)) {
217 bits
|= FbScrLeft(bits1
, leftShift
);
220 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
225 bits
= FbScrRight(bits1
, rightShift
);
227 bits
|= FbScrLeft(bits1
, leftShift
);
229 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
234 bits
= FbScrRight(bits1
, rightShift
);
236 bits
|= FbScrLeft(bits1
, leftShift
);
238 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
242 bits
= FbScrRight(bits1
, rightShift
);
243 if (FbScrRight(startmask
, leftShift
)) {
245 bits
|= FbScrLeft(bits1
, leftShift
);
248 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
255 bits
= FbScrLeft(bits1
, leftShift
);
256 if (FbScrLeft(startmask
, rightShift
)) {
258 bits
|= FbScrRight(bits1
, rightShift
);
260 FbDoLeftMaskByteMergeRop(dst
, bits
, startbyte
, startmask
);
266 bits
= FbScrLeft(bits1
, leftShift
);
268 bits
|= FbScrRight(bits1
, rightShift
);
269 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
275 bits
= FbScrLeft(bits1
, leftShift
);
277 bits
|= FbScrRight(bits1
, rightShift
);
278 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
283 bits
= FbScrLeft(bits1
, leftShift
);
284 if (FbScrLeft(endmask
, rightShift
)) {
286 bits
|= FbScrRight(bits1
, rightShift
);
288 FbDoRightMaskByteMergeRop(dst
, bits
, endbyte
, endmask
);
299 getPixel(char *src
, int x
)
304 memcpy(&l
, src
+ x
* 3, 3);
310 fbBlt24Line(FbBits
* src
,
312 FbBits
* dst
, int dstX
, int width
, int alu
, FbBits pm
, Bool reverse
)
315 char *origDst
= (char *) dst
;
316 FbBits
*origLine
= dst
+ ((dstX
>> FB_SHIFT
) - 1);
317 int origNlw
= ((width
+ FB_MASK
) >> FB_SHIFT
) + 3;
318 int origX
= dstX
/ 24;
321 int leftShift
, rightShift
;
322 FbBits startmask
, endmask
;
332 FbInitializeMergeRop(alu
, FB_ALLONES
);
333 FbMaskBits(dstX
, width
, startmask
, n
, endmask
);
335 ErrorF("dstX %d width %d reverse %d\n", dstX
, width
, reverse
);
338 src
+= ((srcX
+ width
- 1) >> FB_SHIFT
) + 1;
339 dst
+= ((dstX
+ width
- 1) >> FB_SHIFT
) + 1;
340 rot
= FbFirst24Rot(((dstX
+ width
- 8) & FB_MASK
));
341 rot
= FbPrev24Rot(rot
);
343 ErrorF("dstX + width - 8: %d rot: %d\n", (dstX
+ width
- 8) & FB_MASK
,
346 srcX
= (srcX
+ width
- 1) & FB_MASK
;
347 dstX
= (dstX
+ width
- 1) & FB_MASK
;
350 src
+= srcX
>> FB_SHIFT
;
351 dst
+= dstX
>> FB_SHIFT
;
354 rot
= FbFirst24Rot(dstX
);
356 ErrorF("dstX: %d rot: %d\n", dstX
, rot
);
359 mask
= FbRot24(pm
, rot
);
361 ErrorF("pm 0x%x mask 0x%x\n", pm
, mask
);
368 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& endmask
));
369 mask
= FbPrev24Pix(mask
);
374 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
375 mask
= FbPrev24Pix(mask
);
380 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& startmask
));
386 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& startmask
));
388 mask
= FbNext24Pix(mask
);
392 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
394 mask
= FbNext24Pix(mask
);
398 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& endmask
));
404 leftShift
= srcX
- dstX
;
405 rightShift
= FB_UNIT
- leftShift
;
408 rightShift
= dstX
- srcX
;
409 leftShift
= FB_UNIT
- rightShift
;
417 bits
= FbScrRight(bits1
, rightShift
);
418 if (FbScrRight(endmask
, leftShift
)) {
420 bits
|= FbScrLeft(bits1
, leftShift
);
423 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& endmask
));
424 mask
= FbPrev24Pix(mask
);
427 bits
= FbScrRight(bits1
, rightShift
);
429 bits
|= FbScrLeft(bits1
, leftShift
);
431 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
432 mask
= FbPrev24Pix(mask
);
435 bits
= FbScrRight(bits1
, rightShift
);
436 if (FbScrRight(startmask
, leftShift
)) {
438 bits
|= FbScrLeft(bits1
, leftShift
);
441 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& startmask
));
448 bits
= FbScrLeft(bits1
, leftShift
);
450 bits
|= FbScrRight(bits1
, rightShift
);
451 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& startmask
));
453 mask
= FbNext24Pix(mask
);
456 bits
= FbScrLeft(bits1
, leftShift
);
458 bits
|= FbScrRight(bits1
, rightShift
);
459 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
));
461 mask
= FbNext24Pix(mask
);
464 bits
= FbScrLeft(bits1
, leftShift
);
465 if (FbScrLeft(endmask
, rightShift
)) {
467 bits
|= FbScrRight(bits1
, rightShift
);
469 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), mask
& endmask
));
475 int firstx
, lastx
, x
;
480 lastx
= origX
+ width
/ 24 + 1;
481 for (x
= firstx
; x
<= lastx
; x
++)
482 ErrorF("%06x ", getPixel(origDst
, x
));
485 ErrorF("%08x ", *origLine
++);
492 fbBlt24(FbBits
* srcLine
,
499 int height
, int alu
, FbBits pm
, Bool reverse
, Bool upsidedown
)
502 srcLine
+= (height
- 1) * srcStride
;
503 dstLine
+= (height
- 1) * dstStride
;
504 srcStride
= -srcStride
;
505 dstStride
= -dstStride
;
508 fbBlt24Line(srcLine
, srcX
, dstLine
, dstX
, width
, alu
, pm
, reverse
);
509 srcLine
+= srcStride
;
510 dstLine
+= dstStride
;
517 #if FB_SHIFT == FB_STIP_SHIFT + 1
520 * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by
521 * creating an ring of values stepped through for each line
525 fbBltOdd(FbBits
* srcLine
,
526 FbStride srcStrideEven
,
527 FbStride srcStrideOdd
,
531 FbStride dstStrideEven
,
532 FbStride dstStrideOdd
,
534 int dstXOdd
, int width
, int height
, int alu
, FbBits pm
, int bpp
)
537 int leftShiftEven
, rightShiftEven
;
538 FbBits startmaskEven
, endmaskEven
;
542 int leftShiftOdd
, rightShiftOdd
;
543 FbBits startmaskOdd
, endmaskOdd
;
546 int leftShift
, rightShift
;
547 FbBits startmask
, endmask
;
560 FbInitializeMergeRop(alu
, pm
);
561 destInvarient
= FbDestInvarientMergeRop();
563 srcLine
+= srcXEven
>> FB_SHIFT
;
564 dstLine
+= dstXEven
>> FB_SHIFT
;
570 FbMaskBits(dstXEven
, width
, startmaskEven
, nmiddleEven
, endmaskEven
);
571 FbMaskBits(dstXOdd
, width
, startmaskOdd
, nmiddleOdd
, endmaskOdd
);
574 InitializeShifts(srcXEven
, dstXEven
, leftShiftEven
, rightShiftEven
);
575 InitializeShifts(srcXOdd
, dstXOdd
, leftShiftOdd
, rightShiftOdd
);
582 startmask
= startmaskEven
;
583 endmask
= endmaskEven
;
584 nmiddle
= nmiddleEven
;
585 leftShift
= leftShiftEven
;
586 rightShift
= rightShiftEven
;
587 srcLine
+= srcStrideEven
;
588 dstLine
+= dstStrideEven
;
594 startmask
= startmaskOdd
;
595 endmask
= endmaskOdd
;
596 nmiddle
= nmiddleOdd
;
597 leftShift
= leftShiftOdd
;
598 rightShift
= rightShiftOdd
;
599 srcLine
+= srcStrideOdd
;
600 dstLine
+= dstStrideOdd
;
606 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), startmask
));
613 WRITE(dst
, FbDoDestInvarientMergeRop(bits
));
620 WRITE(dst
, FbDoMergeRop(bits
, READ(dst
)));
626 WRITE(dst
, FbDoMaskMergeRop(bits
, READ(dst
), endmask
));
634 bits1
= FbScrLeft(bits
, leftShift
);
636 bits1
|= FbScrRight(bits
, rightShift
);
637 WRITE(dst
, FbDoMaskMergeRop(bits1
, READ(dst
), startmask
));
643 bits1
= FbScrLeft(bits
, leftShift
);
645 bits1
|= FbScrRight(bits
, rightShift
);
646 WRITE(dst
, FbDoDestInvarientMergeRop(bits1
));
652 bits1
= FbScrLeft(bits
, leftShift
);
654 bits1
|= FbScrRight(bits
, rightShift
);
655 WRITE(dst
, FbDoMergeRop(bits1
, READ(dst
)));
660 bits1
= FbScrLeft(bits
, leftShift
);
661 if (FbScrLeft(endmask
, rightShift
)) {
663 bits1
|= FbScrRight(bits
, rightShift
);
665 WRITE(dst
, FbDoMaskMergeRop(bits1
, READ(dst
), endmask
));
672 fbBltOdd24(FbBits
* srcLine
,
673 FbStride srcStrideEven
,
674 FbStride srcStrideOdd
,
678 FbStride dstStrideEven
,
679 FbStride dstStrideOdd
,
680 int dstXEven
, int dstXOdd
, int width
, int height
, int alu
, FbBits pm
)
686 fbBlt24Line(srcLine
, srcXEven
, dstLine
, dstXEven
,
687 width
, alu
, pm
, FALSE
);
688 srcLine
+= srcStrideEven
;
689 dstLine
+= dstStrideEven
;
693 fbBlt24Line(srcLine
, srcXOdd
, dstLine
, dstXOdd
,
694 width
, alu
, pm
, FALSE
);
695 srcLine
+= srcStrideOdd
;
696 dstLine
+= dstStrideOdd
;
704 #if FB_STIP_SHIFT != FB_SHIFT
706 fbSetBltOdd(FbStip
* stip
,
710 FbStride
* strideEven
,
711 FbStride
* strideOdd
, int *srcXEven
, int *srcXOdd
)
717 * bytes needed to align source
719 srcAdjust
= (((int) stip
) & (FB_MASK
>> 3));
721 * FbStip units needed to align stride
723 strideAdjust
= stipStride
& (FB_MASK
>> FB_STIP_SHIFT
);
725 *bits
= (FbBits
*) ((char *) stip
- srcAdjust
);
727 *strideEven
= FbStipStrideToBitsStride(stipStride
+ 1);
728 *strideOdd
= FbStipStrideToBitsStride(stipStride
);
730 *srcXEven
= srcX
+ (srcAdjust
<< 3);
731 *srcXOdd
= srcX
+ (srcAdjust
<< 3) - (strideAdjust
<< FB_STIP_SHIFT
);
734 *strideEven
= FbStipStrideToBitsStride(stipStride
);
735 *strideOdd
= FbStipStrideToBitsStride(stipStride
+ 1);
738 *srcXOdd
= srcX
+ (strideAdjust
<< FB_STIP_SHIFT
);
744 fbBltStip(FbStip
* src
, FbStride srcStride
, /* in FbStip units, not FbBits units */
745 int srcX
, FbStip
* dst
, FbStride dstStride
, /* in FbStip units, not FbBits units */
746 int dstX
, int width
, int height
, int alu
, FbBits pm
, int bpp
)
748 #if FB_STIP_SHIFT != FB_SHIFT
749 if (FB_STIP_ODDSTRIDE(srcStride
) || FB_STIP_ODDPTR(src
) ||
750 FB_STIP_ODDSTRIDE(dstStride
) || FB_STIP_ODDPTR(dst
)) {
751 FbStride srcStrideEven
, srcStrideOdd
;
752 FbStride dstStrideEven
, dstStrideOdd
;
753 int srcXEven
, srcXOdd
;
754 int dstXEven
, dstXOdd
;
758 src
+= srcX
>> FB_STIP_SHIFT
;
759 srcX
&= FB_STIP_MASK
;
760 dst
+= dstX
>> FB_STIP_SHIFT
;
761 dstX
&= FB_STIP_MASK
;
763 fbSetBltOdd(src
, srcStride
, srcX
,
764 &s
, &srcStrideEven
, &srcStrideOdd
, &srcXEven
, &srcXOdd
);
766 fbSetBltOdd(dst
, dstStride
, dstX
,
767 &d
, &dstStrideEven
, &dstStrideOdd
, &dstXEven
, &dstXOdd
);
769 if (bpp
== 24 && !FbCheck24Pix(pm
)) {
770 fbBltOdd24(s
, srcStrideEven
, srcStrideOdd
,
772 d
, dstStrideEven
, dstStrideOdd
,
773 dstXEven
, dstXOdd
, width
, height
, alu
, pm
);
776 fbBltOdd(s
, srcStrideEven
, srcStrideOdd
,
778 d
, dstStrideEven
, dstStrideOdd
,
779 dstXEven
, dstXOdd
, width
, height
, alu
, pm
, bpp
);
785 fbBlt((FbBits
*) src
, FbStipStrideToBitsStride(srcStride
),
787 (FbBits
*) dst
, FbStipStrideToBitsStride(dstStride
),
788 dstX
, width
, height
, alu
, pm
, bpp
, FALSE
, FALSE
);