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