xref: /OK3568_Linux_fs/external/xserver/fb/fbbltone.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 1998 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that
7*4882a593Smuzhiyun  * copyright notice and this permission notice appear in supporting
8*4882a593Smuzhiyun  * documentation, and that the name of Keith Packard not be used in
9*4882a593Smuzhiyun  * advertising or publicity pertaining to distribution of the software without
10*4882a593Smuzhiyun  * specific, written prior permission.  Keith Packard makes no
11*4882a593Smuzhiyun  * representations about the suitability of this software for any purpose.  It
12*4882a593Smuzhiyun  * is provided "as is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20*4882a593Smuzhiyun  * PERFORMANCE OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
24*4882a593Smuzhiyun #include <dix-config.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include "fb.h"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  * Stipple masks are independent of bit/byte order as long
31*4882a593Smuzhiyun  * as bitorder == byteorder.  FB doesn't handle the case
32*4882a593Smuzhiyun  * where these differ
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun #define BitsMask(x,w)	((FB_ALLONES << ((x) & FB_MASK)) & \
35*4882a593Smuzhiyun 			 (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK)))
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define Mask(x,w)	BitsMask((x)*(w),(w))
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define SelMask(b,n,w)	((((b) >> n) & 1) * Mask(n,w))
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define C1(b,w) \
42*4882a593Smuzhiyun     (SelMask(b,0,w))
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define C2(b,w) \
45*4882a593Smuzhiyun     (SelMask(b,0,w) | \
46*4882a593Smuzhiyun      SelMask(b,1,w))
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define C4(b,w) \
49*4882a593Smuzhiyun     (SelMask(b,0,w) | \
50*4882a593Smuzhiyun      SelMask(b,1,w) | \
51*4882a593Smuzhiyun      SelMask(b,2,w) | \
52*4882a593Smuzhiyun      SelMask(b,3,w))
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define C8(b,w) \
55*4882a593Smuzhiyun     (SelMask(b,0,w) | \
56*4882a593Smuzhiyun      SelMask(b,1,w) | \
57*4882a593Smuzhiyun      SelMask(b,2,w) | \
58*4882a593Smuzhiyun      SelMask(b,3,w) | \
59*4882a593Smuzhiyun      SelMask(b,4,w) | \
60*4882a593Smuzhiyun      SelMask(b,5,w) | \
61*4882a593Smuzhiyun      SelMask(b,6,w) | \
62*4882a593Smuzhiyun      SelMask(b,7,w))
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun static const FbBits fbStipple8Bits[256] = {
65*4882a593Smuzhiyun     C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4),
66*4882a593Smuzhiyun     C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4),
67*4882a593Smuzhiyun     C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4),
68*4882a593Smuzhiyun     C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4),
69*4882a593Smuzhiyun     C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4),
70*4882a593Smuzhiyun     C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4),
71*4882a593Smuzhiyun     C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4),
72*4882a593Smuzhiyun     C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4),
73*4882a593Smuzhiyun     C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4),
74*4882a593Smuzhiyun     C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4),
75*4882a593Smuzhiyun     C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4),
76*4882a593Smuzhiyun     C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4),
77*4882a593Smuzhiyun     C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4),
78*4882a593Smuzhiyun     C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4),
79*4882a593Smuzhiyun     C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4),
80*4882a593Smuzhiyun     C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4),
81*4882a593Smuzhiyun     C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4),
82*4882a593Smuzhiyun     C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4),
83*4882a593Smuzhiyun     C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4),
84*4882a593Smuzhiyun     C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4),
85*4882a593Smuzhiyun     C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4),
86*4882a593Smuzhiyun     C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4),
87*4882a593Smuzhiyun     C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4),
88*4882a593Smuzhiyun     C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4),
89*4882a593Smuzhiyun     C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4),
90*4882a593Smuzhiyun     C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4),
91*4882a593Smuzhiyun     C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4),
92*4882a593Smuzhiyun     C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4),
93*4882a593Smuzhiyun     C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4),
94*4882a593Smuzhiyun     C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4),
95*4882a593Smuzhiyun     C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4),
96*4882a593Smuzhiyun     C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4),
97*4882a593Smuzhiyun     C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4),
98*4882a593Smuzhiyun     C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4),
99*4882a593Smuzhiyun     C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4),
100*4882a593Smuzhiyun     C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4),
101*4882a593Smuzhiyun     C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4),
102*4882a593Smuzhiyun     C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4),
103*4882a593Smuzhiyun     C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4),
104*4882a593Smuzhiyun     C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4),
105*4882a593Smuzhiyun     C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4),
106*4882a593Smuzhiyun     C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4),
107*4882a593Smuzhiyun     C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4),
108*4882a593Smuzhiyun };
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun static const FbBits fbStipple4Bits[16] = {
111*4882a593Smuzhiyun     C4(0, 8), C4(1, 8), C4(2, 8), C4(3, 8), C4(4, 8), C4(5, 8),
112*4882a593Smuzhiyun     C4(6, 8), C4(7, 8), C4(8, 8), C4(9, 8), C4(10, 8), C4(11, 8),
113*4882a593Smuzhiyun     C4(12, 8), C4(13, 8), C4(14, 8), C4(15, 8),
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun static const FbBits fbStipple2Bits[4] = {
117*4882a593Smuzhiyun     C2(0, 16), C2(1, 16), C2(2, 16), C2(3, 16),
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun static const FbBits fbStipple1Bits[2] = {
121*4882a593Smuzhiyun     C1(0, 32), C1(1, 32),
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun #ifdef __clang__
125*4882a593Smuzhiyun /* shift overflow is intentional */
126*4882a593Smuzhiyun #pragma clang diagnostic ignored "-Wshift-overflow"
127*4882a593Smuzhiyun #endif
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun /*
130*4882a593Smuzhiyun  *  Example: srcX = 13 dstX = 8	(FB unit 32 dstBpp 8)
131*4882a593Smuzhiyun  *
132*4882a593Smuzhiyun  *	**** **** **** **** **** **** **** ****
133*4882a593Smuzhiyun  *			^
134*4882a593Smuzhiyun  *	********  ********  ********  ********
135*4882a593Smuzhiyun  *		  ^
136*4882a593Smuzhiyun  *  leftShift = 12
137*4882a593Smuzhiyun  *  rightShift = 20
138*4882a593Smuzhiyun  *
139*4882a593Smuzhiyun  *  Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8)
140*4882a593Smuzhiyun  *
141*4882a593Smuzhiyun  *	**** **** **** **** **** **** **** ****
142*4882a593Smuzhiyun  *	^
143*4882a593Smuzhiyun  *	********  ********  ********  ********
144*4882a593Smuzhiyun  *		  ^
145*4882a593Smuzhiyun  *
146*4882a593Smuzhiyun  *  leftShift = 24
147*4882a593Smuzhiyun  *  rightShift = 8
148*4882a593Smuzhiyun  */
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun #define LoadBits {\
151*4882a593Smuzhiyun     if (leftShift) { \
152*4882a593Smuzhiyun 	bitsRight = (src < srcEnd ? READ(src++) : 0); \
153*4882a593Smuzhiyun 	bits = (FbStipLeft (bitsLeft, leftShift) | \
154*4882a593Smuzhiyun 		FbStipRight(bitsRight, rightShift)); \
155*4882a593Smuzhiyun 	bitsLeft = bitsRight; \
156*4882a593Smuzhiyun     } else \
157*4882a593Smuzhiyun 	bits = (src < srcEnd ? READ(src++) : 0); \
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun void
fbBltOne(FbStip * src,FbStride srcStride,int srcX,FbBits * dst,FbStride dstStride,int dstX,int dstBpp,int width,int height,FbBits fgand,FbBits fgxor,FbBits bgand,FbBits bgxor)161*4882a593Smuzhiyun fbBltOne(FbStip * src, FbStride srcStride,      /* FbStip units per scanline */
162*4882a593Smuzhiyun          int srcX,              /* bit position of source */
163*4882a593Smuzhiyun          FbBits * dst, FbStride dstStride,      /* FbBits units per scanline */
164*4882a593Smuzhiyun          int dstX,              /* bit position of dest */
165*4882a593Smuzhiyun          int dstBpp,            /* bits per destination unit */
166*4882a593Smuzhiyun          int width,             /* width in bits of destination */
167*4882a593Smuzhiyun          int height,            /* height in scanlines */
168*4882a593Smuzhiyun          FbBits fgand,          /* rrop values */
169*4882a593Smuzhiyun          FbBits fgxor, FbBits bgand, FbBits bgxor)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun     const FbBits *fbBits;
172*4882a593Smuzhiyun     FbBits *srcEnd;
173*4882a593Smuzhiyun     int pixelsPerDst;           /* dst pixels per FbBits */
174*4882a593Smuzhiyun     int unitsPerSrc;            /* src patterns per FbStip */
175*4882a593Smuzhiyun     int leftShift, rightShift;  /* align source with dest */
176*4882a593Smuzhiyun     FbBits startmask, endmask;  /* dest scanline masks */
177*4882a593Smuzhiyun     FbStip bits = 0, bitsLeft, bitsRight;       /* source bits */
178*4882a593Smuzhiyun     FbStip left;
179*4882a593Smuzhiyun     FbBits mask;
180*4882a593Smuzhiyun     int nDst;                   /* dest longwords (w.o. end) */
181*4882a593Smuzhiyun     int w;
182*4882a593Smuzhiyun     int n, nmiddle;
183*4882a593Smuzhiyun     int dstS;                   /* stipple-relative dst X coordinate */
184*4882a593Smuzhiyun     Bool copy;                  /* accelerate dest-invariant */
185*4882a593Smuzhiyun     Bool transparent;           /* accelerate 0 nop */
186*4882a593Smuzhiyun     int srcinc;                 /* source units consumed */
187*4882a593Smuzhiyun     Bool endNeedsLoad = FALSE;  /* need load for endmask */
188*4882a593Smuzhiyun     int startbyte, endbyte;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     /*
191*4882a593Smuzhiyun      * Do not read past the end of the buffer!
192*4882a593Smuzhiyun      */
193*4882a593Smuzhiyun     srcEnd = src + height * srcStride;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun     /*
196*4882a593Smuzhiyun      * Number of destination units in FbBits == number of stipple pixels
197*4882a593Smuzhiyun      * used each time
198*4882a593Smuzhiyun      */
199*4882a593Smuzhiyun     pixelsPerDst = FB_UNIT / dstBpp;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun     /*
202*4882a593Smuzhiyun      * Number of source stipple patterns in FbStip
203*4882a593Smuzhiyun      */
204*4882a593Smuzhiyun     unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun     copy = FALSE;
207*4882a593Smuzhiyun     transparent = FALSE;
208*4882a593Smuzhiyun     if (bgand == 0 && fgand == 0)
209*4882a593Smuzhiyun         copy = TRUE;
210*4882a593Smuzhiyun     else if (bgand == FB_ALLONES && bgxor == 0)
211*4882a593Smuzhiyun         transparent = TRUE;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun     /*
214*4882a593Smuzhiyun      * Adjust source and dest to nearest FbBits boundary
215*4882a593Smuzhiyun      */
216*4882a593Smuzhiyun     src += srcX >> FB_STIP_SHIFT;
217*4882a593Smuzhiyun     dst += dstX >> FB_SHIFT;
218*4882a593Smuzhiyun     srcX &= FB_STIP_MASK;
219*4882a593Smuzhiyun     dstX &= FB_MASK;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     FbMaskBitsBytes(dstX, width, copy,
222*4882a593Smuzhiyun                     startmask, startbyte, nmiddle, endmask, endbyte);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun     /*
225*4882a593Smuzhiyun      * Compute effective dest alignment requirement for
226*4882a593Smuzhiyun      * source -- must align source to dest unit boundary
227*4882a593Smuzhiyun      */
228*4882a593Smuzhiyun     dstS = dstX / dstBpp;
229*4882a593Smuzhiyun     /*
230*4882a593Smuzhiyun      * Compute shift constants for effective alignement
231*4882a593Smuzhiyun      */
232*4882a593Smuzhiyun     if (srcX >= dstS) {
233*4882a593Smuzhiyun         leftShift = srcX - dstS;
234*4882a593Smuzhiyun         rightShift = FB_STIP_UNIT - leftShift;
235*4882a593Smuzhiyun     }
236*4882a593Smuzhiyun     else {
237*4882a593Smuzhiyun         rightShift = dstS - srcX;
238*4882a593Smuzhiyun         leftShift = FB_STIP_UNIT - rightShift;
239*4882a593Smuzhiyun     }
240*4882a593Smuzhiyun     /*
241*4882a593Smuzhiyun      * Get pointer to stipple mask array for this depth
242*4882a593Smuzhiyun      */
243*4882a593Smuzhiyun     fbBits = 0;                 /* unused */
244*4882a593Smuzhiyun     switch (pixelsPerDst) {
245*4882a593Smuzhiyun     case 8:
246*4882a593Smuzhiyun         fbBits = fbStipple8Bits;
247*4882a593Smuzhiyun         break;
248*4882a593Smuzhiyun     case 4:
249*4882a593Smuzhiyun         fbBits = fbStipple4Bits;
250*4882a593Smuzhiyun         break;
251*4882a593Smuzhiyun     case 2:
252*4882a593Smuzhiyun         fbBits = fbStipple2Bits;
253*4882a593Smuzhiyun         break;
254*4882a593Smuzhiyun     case 1:
255*4882a593Smuzhiyun         fbBits = fbStipple1Bits;
256*4882a593Smuzhiyun         break;
257*4882a593Smuzhiyun     default:
258*4882a593Smuzhiyun         return;
259*4882a593Smuzhiyun     }
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun     /*
262*4882a593Smuzhiyun      * Compute total number of destination words written, but
263*4882a593Smuzhiyun      * don't count endmask
264*4882a593Smuzhiyun      */
265*4882a593Smuzhiyun     nDst = nmiddle;
266*4882a593Smuzhiyun     if (startmask)
267*4882a593Smuzhiyun         nDst++;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun     dstStride -= nDst;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     /*
272*4882a593Smuzhiyun      * Compute total number of source words consumed
273*4882a593Smuzhiyun      */
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun     srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun     if (srcX > dstS)
278*4882a593Smuzhiyun         srcinc++;
279*4882a593Smuzhiyun     if (endmask) {
280*4882a593Smuzhiyun         endNeedsLoad = nDst % unitsPerSrc == 0;
281*4882a593Smuzhiyun         if (endNeedsLoad)
282*4882a593Smuzhiyun             srcinc++;
283*4882a593Smuzhiyun     }
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun     srcStride -= srcinc;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun     /*
288*4882a593Smuzhiyun      * Copy rectangle
289*4882a593Smuzhiyun      */
290*4882a593Smuzhiyun     while (height--) {
291*4882a593Smuzhiyun         w = nDst;               /* total units across scanline */
292*4882a593Smuzhiyun         n = unitsPerSrc;        /* units avail in single stipple */
293*4882a593Smuzhiyun         if (n > w)
294*4882a593Smuzhiyun             n = w;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun         bitsLeft = 0;
297*4882a593Smuzhiyun         if (srcX > dstS)
298*4882a593Smuzhiyun             bitsLeft = READ(src++);
299*4882a593Smuzhiyun         if (n) {
300*4882a593Smuzhiyun             /*
301*4882a593Smuzhiyun              * Load first set of stipple bits
302*4882a593Smuzhiyun              */
303*4882a593Smuzhiyun             LoadBits;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun             /*
306*4882a593Smuzhiyun              * Consume stipple bits for startmask
307*4882a593Smuzhiyun              */
308*4882a593Smuzhiyun             if (startmask) {
309*4882a593Smuzhiyun                 mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
310*4882a593Smuzhiyun                 if (mask || !transparent)
311*4882a593Smuzhiyun                     FbDoLeftMaskByteStippleRRop(dst, mask,
312*4882a593Smuzhiyun                                                 fgand, fgxor, bgand, bgxor,
313*4882a593Smuzhiyun                                                 startbyte, startmask);
314*4882a593Smuzhiyun                 bits = FbStipLeft(bits, pixelsPerDst);
315*4882a593Smuzhiyun                 dst++;
316*4882a593Smuzhiyun                 n--;
317*4882a593Smuzhiyun                 w--;
318*4882a593Smuzhiyun             }
319*4882a593Smuzhiyun             /*
320*4882a593Smuzhiyun              * Consume stipple bits across scanline
321*4882a593Smuzhiyun              */
322*4882a593Smuzhiyun             for (;;) {
323*4882a593Smuzhiyun                 w -= n;
324*4882a593Smuzhiyun                 if (copy) {
325*4882a593Smuzhiyun                     while (n--) {
326*4882a593Smuzhiyun                         mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
327*4882a593Smuzhiyun                         WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor));
328*4882a593Smuzhiyun                         dst++;
329*4882a593Smuzhiyun                         bits = FbStipLeft(bits, pixelsPerDst);
330*4882a593Smuzhiyun                     }
331*4882a593Smuzhiyun                 }
332*4882a593Smuzhiyun                 else {
333*4882a593Smuzhiyun                     while (n--) {
334*4882a593Smuzhiyun                         left = FbLeftStipBits(bits, pixelsPerDst);
335*4882a593Smuzhiyun                         if (left || !transparent) {
336*4882a593Smuzhiyun                             mask = fbBits[left];
337*4882a593Smuzhiyun                             WRITE(dst, FbStippleRRop(READ(dst), mask, fgand,
338*4882a593Smuzhiyun                                                      fgxor, bgand, bgxor));
339*4882a593Smuzhiyun                         }
340*4882a593Smuzhiyun                         dst++;
341*4882a593Smuzhiyun                         bits = FbStipLeft(bits, pixelsPerDst);
342*4882a593Smuzhiyun                     }
343*4882a593Smuzhiyun                 }
344*4882a593Smuzhiyun                 if (!w)
345*4882a593Smuzhiyun                     break;
346*4882a593Smuzhiyun                 /*
347*4882a593Smuzhiyun                  * Load another set and reset number of available units
348*4882a593Smuzhiyun                  */
349*4882a593Smuzhiyun                 LoadBits;
350*4882a593Smuzhiyun                 n = unitsPerSrc;
351*4882a593Smuzhiyun                 if (n > w)
352*4882a593Smuzhiyun                     n = w;
353*4882a593Smuzhiyun             }
354*4882a593Smuzhiyun         }
355*4882a593Smuzhiyun         /*
356*4882a593Smuzhiyun          * Consume stipple bits for endmask
357*4882a593Smuzhiyun          */
358*4882a593Smuzhiyun         if (endmask) {
359*4882a593Smuzhiyun             if (endNeedsLoad) {
360*4882a593Smuzhiyun                 LoadBits;
361*4882a593Smuzhiyun             }
362*4882a593Smuzhiyun             mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)];
363*4882a593Smuzhiyun             if (mask || !transparent)
364*4882a593Smuzhiyun                 FbDoRightMaskByteStippleRRop(dst, mask, fgand, fgxor,
365*4882a593Smuzhiyun                                              bgand, bgxor, endbyte, endmask);
366*4882a593Smuzhiyun         }
367*4882a593Smuzhiyun         dst += dstStride;
368*4882a593Smuzhiyun         src += srcStride;
369*4882a593Smuzhiyun     }
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun /*
373*4882a593Smuzhiyun  * Not very efficient, but simple -- copy a single plane
374*4882a593Smuzhiyun  * from an N bit image to a 1 bit image
375*4882a593Smuzhiyun  */
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun void
fbBltPlane(FbBits * src,FbStride srcStride,int srcX,int srcBpp,FbStip * dst,FbStride dstStride,int dstX,int width,int height,FbStip fgand,FbStip fgxor,FbStip bgand,FbStip bgxor,Pixel planeMask)378*4882a593Smuzhiyun fbBltPlane(FbBits * src,
379*4882a593Smuzhiyun            FbStride srcStride,
380*4882a593Smuzhiyun            int srcX,
381*4882a593Smuzhiyun            int srcBpp,
382*4882a593Smuzhiyun            FbStip * dst,
383*4882a593Smuzhiyun            FbStride dstStride,
384*4882a593Smuzhiyun            int dstX,
385*4882a593Smuzhiyun            int width,
386*4882a593Smuzhiyun            int height,
387*4882a593Smuzhiyun            FbStip fgand,
388*4882a593Smuzhiyun            FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask)
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun     FbBits *s;
391*4882a593Smuzhiyun     FbBits pm;
392*4882a593Smuzhiyun     FbBits srcMask;
393*4882a593Smuzhiyun     FbBits srcMaskFirst;
394*4882a593Smuzhiyun     FbBits srcMask0 = 0;
395*4882a593Smuzhiyun     FbBits srcBits;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun     FbStip dstBits;
398*4882a593Smuzhiyun     FbStip *d;
399*4882a593Smuzhiyun     FbStip dstMask;
400*4882a593Smuzhiyun     FbStip dstMaskFirst;
401*4882a593Smuzhiyun     FbStip dstUnion;
402*4882a593Smuzhiyun     int w;
403*4882a593Smuzhiyun     int wt;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun     if (!width)
406*4882a593Smuzhiyun         return;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun     src += srcX >> FB_SHIFT;
409*4882a593Smuzhiyun     srcX &= FB_MASK;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun     dst += dstX >> FB_STIP_SHIFT;
412*4882a593Smuzhiyun     dstX &= FB_STIP_MASK;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun     w = width / srcBpp;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun     pm = fbReplicatePixel(planeMask, srcBpp);
417*4882a593Smuzhiyun     srcMaskFirst = pm & FbBitsMask(srcX, srcBpp);
418*4882a593Smuzhiyun     srcMask0 = pm & FbBitsMask(0, srcBpp);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     dstMaskFirst = FbStipMask(dstX, 1);
421*4882a593Smuzhiyun     while (height--) {
422*4882a593Smuzhiyun         d = dst;
423*4882a593Smuzhiyun         dst += dstStride;
424*4882a593Smuzhiyun         s = src;
425*4882a593Smuzhiyun         src += srcStride;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun         srcMask = srcMaskFirst;
428*4882a593Smuzhiyun         srcBits = READ(s++);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun         dstMask = dstMaskFirst;
431*4882a593Smuzhiyun         dstUnion = 0;
432*4882a593Smuzhiyun         dstBits = 0;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun         wt = w;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun         while (wt--) {
437*4882a593Smuzhiyun             if (!srcMask) {
438*4882a593Smuzhiyun                 srcBits = READ(s++);
439*4882a593Smuzhiyun                 srcMask = srcMask0;
440*4882a593Smuzhiyun             }
441*4882a593Smuzhiyun             if (!dstMask) {
442*4882a593Smuzhiyun                 WRITE(d, FbStippleRRopMask(READ(d), dstBits,
443*4882a593Smuzhiyun                                            fgand, fgxor, bgand, bgxor,
444*4882a593Smuzhiyun                                            dstUnion));
445*4882a593Smuzhiyun                 d++;
446*4882a593Smuzhiyun                 dstMask = FbStipMask(0, 1);
447*4882a593Smuzhiyun                 dstUnion = 0;
448*4882a593Smuzhiyun                 dstBits = 0;
449*4882a593Smuzhiyun             }
450*4882a593Smuzhiyun             if (srcBits & srcMask)
451*4882a593Smuzhiyun                 dstBits |= dstMask;
452*4882a593Smuzhiyun             dstUnion |= dstMask;
453*4882a593Smuzhiyun             if (srcBpp == FB_UNIT)
454*4882a593Smuzhiyun                 srcMask = 0;
455*4882a593Smuzhiyun             else
456*4882a593Smuzhiyun                 srcMask = FbScrRight(srcMask, srcBpp);
457*4882a593Smuzhiyun             dstMask = FbStipRight(dstMask, 1);
458*4882a593Smuzhiyun         }
459*4882a593Smuzhiyun         if (dstUnion)
460*4882a593Smuzhiyun             WRITE(d, FbStippleRRopMask(READ(d), dstBits,
461*4882a593Smuzhiyun                                        fgand, fgxor, bgand, bgxor, dstUnion));
462*4882a593Smuzhiyun     }
463*4882a593Smuzhiyun }
464