1706f2543Smrg/*
2706f2543Smrg * Copyright © 1998 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
24706f2543Smrg#include <dix-config.h>
25706f2543Smrg#endif
26706f2543Smrg
27706f2543Smrg#include "fb.h"
28706f2543Smrg
29706f2543Smrg#ifndef FBNOPIXADDR
30706f2543Smrg/*
31706f2543Smrg * This is a slight abuse of the preprocessor to generate repetitive
32706f2543Smrg * code, the idea is to generate code for each case of a copy-mode
33706f2543Smrg * transparent stipple
34706f2543Smrg */
35706f2543Smrg#define LaneCases1(c,a)	    case c: \
36706f2543Smrg				while (n--) { FbLaneCase(c,a); a++; } \
37706f2543Smrg				break
38706f2543Smrg#define LaneCases2(c,a)	    LaneCases1(c,a); LaneCases1(c+1,a)
39706f2543Smrg#define LaneCases4(c,a)	    LaneCases2(c,a); LaneCases2(c+2,a)
40706f2543Smrg#define LaneCases8(c,a)	    LaneCases4(c,a); LaneCases4(c+4,a)
41706f2543Smrg#define LaneCases16(c,a)    LaneCases8(c,a); LaneCases8(c+8,a)
42706f2543Smrg#define LaneCases32(c,a)    LaneCases16(c,a); LaneCases16(c+16,a)
43706f2543Smrg#define LaneCases64(c,a)    LaneCases32(c,a); LaneCases32(c+32,a)
44706f2543Smrg#define LaneCases128(c,a)   LaneCases64(c,a); LaneCases64(c+64,a)
45706f2543Smrg#define LaneCases256(c,a)   LaneCases128(c,a); LaneCases128(c+128,a)
46706f2543Smrg
47706f2543Smrg#if FB_SHIFT == 6
48706f2543Smrg#define LaneCases(a)	    LaneCases256(0,a)
49706f2543Smrg#endif
50706f2543Smrg
51706f2543Smrg#if FB_SHIFT == 5
52706f2543Smrg#define LaneCases(a)	    LaneCases16(0,a)
53706f2543Smrg#endif
54706f2543Smrg
55706f2543Smrg/*
56706f2543Smrg * Repeat a transparent stipple across a scanline n times
57706f2543Smrg */
58706f2543Smrg
59706f2543Smrgvoid
60706f2543SmrgfbTransparentSpan (FbBits   *dst,
61706f2543Smrg		   FbBits   stip,
62706f2543Smrg		   FbBits   fgxor,
63706f2543Smrg		   int	    n)
64706f2543Smrg{
65706f2543Smrg    FbStip  s;
66706f2543Smrg
67706f2543Smrg    s  = ((FbStip) (stip      ) & 0x01);
68706f2543Smrg    s |= ((FbStip) (stip >>  8) & 0x02);
69706f2543Smrg    s |= ((FbStip) (stip >> 16) & 0x04);
70706f2543Smrg    s |= ((FbStip) (stip >> 24) & 0x08);
71706f2543Smrg#if FB_SHIFT > 5
72706f2543Smrg    s |= ((FbStip) (stip >> 32) & 0x10);
73706f2543Smrg    s |= ((FbStip) (stip >> 40) & 0x20);
74706f2543Smrg    s |= ((FbStip) (stip >> 48) & 0x40);
75706f2543Smrg    s |= ((FbStip) (stip >> 56) & 0x80);
76706f2543Smrg#endif
77706f2543Smrg    switch (s) {
78706f2543Smrg	LaneCases(dst);
79706f2543Smrg    }
80706f2543Smrg}
81706f2543Smrg#endif
82706f2543Smrg
83706f2543Smrgvoid
84706f2543SmrgfbEvenStipple (FbBits	*dst,
85706f2543Smrg	       FbStride	dstStride,
86706f2543Smrg	       int	dstX,
87706f2543Smrg	       int	dstBpp,
88706f2543Smrg
89706f2543Smrg	       int	width,
90706f2543Smrg	       int	height,
91706f2543Smrg
92706f2543Smrg	       FbStip	*stip,
93706f2543Smrg	       FbStride	stipStride,
94706f2543Smrg	       int	stipHeight,
95706f2543Smrg
96706f2543Smrg	       FbBits	fgand,
97706f2543Smrg	       FbBits	fgxor,
98706f2543Smrg	       FbBits	bgand,
99706f2543Smrg	       FbBits	bgxor,
100706f2543Smrg
101706f2543Smrg	       int	xRot,
102706f2543Smrg	       int	yRot)
103706f2543Smrg{
104706f2543Smrg    FbBits	startmask, endmask;
105706f2543Smrg    FbBits	mask, and, xor;
106706f2543Smrg    int		nmiddle, n;
107706f2543Smrg    FbStip	*s, *stipEnd, bits;
108706f2543Smrg    int		rot, stipX, stipY;
109706f2543Smrg    int		pixelsPerDst;
110706f2543Smrg    const FbBits    *fbBits;
111706f2543Smrg    Bool	transparent;
112706f2543Smrg    int		startbyte, endbyte;
113706f2543Smrg
114706f2543Smrg    /*
115706f2543Smrg     * Check for a transparent stipple (stencil)
116706f2543Smrg     */
117706f2543Smrg    transparent = FALSE;
118706f2543Smrg    if (dstBpp >= 8 &&
119706f2543Smrg	fgand == 0 && bgand == FB_ALLONES && bgxor == 0)
120706f2543Smrg	transparent = TRUE;
121706f2543Smrg
122706f2543Smrg    pixelsPerDst = FB_UNIT / dstBpp;
123706f2543Smrg    /*
124706f2543Smrg     * Adjust dest pointers
125706f2543Smrg     */
126706f2543Smrg    dst += dstX >> FB_SHIFT;
127706f2543Smrg    dstX &= FB_MASK;
128706f2543Smrg    FbMaskBitsBytes (dstX, width, fgand == 0 && bgand == 0,
129706f2543Smrg		     startmask, startbyte, nmiddle, endmask, endbyte);
130706f2543Smrg
131706f2543Smrg    if (startmask)
132706f2543Smrg	dstStride--;
133706f2543Smrg    dstStride -= nmiddle;
134706f2543Smrg
135706f2543Smrg    xRot *= dstBpp;
136706f2543Smrg    /*
137706f2543Smrg     * Compute stip start scanline and rotation parameters
138706f2543Smrg     */
139706f2543Smrg    stipEnd = stip + stipStride * stipHeight;
140706f2543Smrg    modulus (- yRot, stipHeight, stipY);
141706f2543Smrg    s = stip + stipStride * stipY;
142706f2543Smrg    modulus (- xRot, FB_UNIT, stipX);
143706f2543Smrg    rot = stipX;
144706f2543Smrg
145706f2543Smrg    /*
146706f2543Smrg     * Get pointer to stipple mask array for this depth
147706f2543Smrg     */
148706f2543Smrg    /* fbStippleTable covers all valid bpp (4,8,16,32) */
149706f2543Smrg    fbBits = fbStippleTable[pixelsPerDst];
150706f2543Smrg
151706f2543Smrg    while (height--)
152706f2543Smrg    {
153706f2543Smrg	/*
154706f2543Smrg	 * Extract stipple bits for this scanline;
155706f2543Smrg	 */
156706f2543Smrg	bits = READ(s);
157706f2543Smrg	s += stipStride;
158706f2543Smrg	if (s == stipEnd)
159706f2543Smrg	    s = stip;
160706f2543Smrg#if FB_UNIT > 32
161706f2543Smrg	if (pixelsPerDst == 16)
162706f2543Smrg	    mask = FbStipple16Bits(FbLeftStipBits(bits,16));
163706f2543Smrg	else
164706f2543Smrg#endif
165706f2543Smrg	    mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
166706f2543Smrg	/*
167706f2543Smrg	 * Rotate into position and compute reduced rop values
168706f2543Smrg	 */
169706f2543Smrg	mask = FbRotLeft(mask, rot);
170706f2543Smrg	and = (fgand & mask) | (bgand & ~mask);
171706f2543Smrg	xor = (fgxor & mask) | (bgxor & ~mask);
172706f2543Smrg
173706f2543Smrg#ifndef FBNOPIXADDR
174706f2543Smrg	if (transparent)
175706f2543Smrg	{
176706f2543Smrg	    if (startmask)
177706f2543Smrg	    {
178706f2543Smrg		fbTransparentSpan(dst, mask&startmask, fgxor, 1);
179706f2543Smrg		dst++;
180706f2543Smrg	    }
181706f2543Smrg	    fbTransparentSpan (dst, mask, fgxor, nmiddle);
182706f2543Smrg	    dst += nmiddle;
183706f2543Smrg	    if (endmask)
184706f2543Smrg		fbTransparentSpan(dst, mask&endmask, fgxor, 1);
185706f2543Smrg	}
186706f2543Smrg	else
187706f2543Smrg#endif
188706f2543Smrg	{
189706f2543Smrg	    /*
190706f2543Smrg	     * Fill scanline
191706f2543Smrg	     */
192706f2543Smrg	    if (startmask)
193706f2543Smrg	    {
194706f2543Smrg		FbDoLeftMaskByteRRop (dst, startbyte, startmask, and, xor);
195706f2543Smrg		dst++;
196706f2543Smrg	    }
197706f2543Smrg	    n = nmiddle;
198706f2543Smrg	    if (!and)
199706f2543Smrg		while (n--)
200706f2543Smrg		    WRITE(dst++, xor);
201706f2543Smrg	    else
202706f2543Smrg	    {
203706f2543Smrg		while (n--)
204706f2543Smrg		{
205706f2543Smrg		    WRITE(dst, FbDoRRop (READ(dst), and, xor));
206706f2543Smrg		    dst++;
207706f2543Smrg		}
208706f2543Smrg	    }
209706f2543Smrg	    if (endmask)
210706f2543Smrg		FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
211706f2543Smrg	}
212706f2543Smrg	dst += dstStride;
213706f2543Smrg    }
214706f2543Smrg}
215706f2543Smrg
216706f2543Smrgvoid
217706f2543SmrgfbOddStipple (FbBits	*dst,
218706f2543Smrg	      FbStride	dstStride,
219706f2543Smrg	      int	dstX,
220706f2543Smrg	      int	dstBpp,
221706f2543Smrg
222706f2543Smrg	      int	width,
223706f2543Smrg	      int	height,
224706f2543Smrg
225706f2543Smrg	      FbStip	*stip,
226706f2543Smrg	      FbStride	stipStride,
227706f2543Smrg	      int	stipWidth,
228706f2543Smrg	      int	stipHeight,
229706f2543Smrg
230706f2543Smrg	      FbBits	fgand,
231706f2543Smrg	      FbBits	fgxor,
232706f2543Smrg	      FbBits	bgand,
233706f2543Smrg	      FbBits	bgxor,
234706f2543Smrg
235706f2543Smrg	      int	xRot,
236706f2543Smrg	      int	yRot)
237706f2543Smrg{
238706f2543Smrg    int		stipX, stipY, sx;
239706f2543Smrg    int		widthTmp;
240706f2543Smrg    int		h, w;
241706f2543Smrg    int		x, y;
242706f2543Smrg
243706f2543Smrg    modulus (- yRot, stipHeight, stipY);
244706f2543Smrg    modulus (dstX / dstBpp - xRot, stipWidth, stipX);
245706f2543Smrg    y = 0;
246706f2543Smrg    while (height)
247706f2543Smrg    {
248706f2543Smrg	h = stipHeight - stipY;
249706f2543Smrg	if (h > height)
250706f2543Smrg	    h = height;
251706f2543Smrg	height -= h;
252706f2543Smrg	widthTmp = width;
253706f2543Smrg	x = dstX;
254706f2543Smrg	sx = stipX;
255706f2543Smrg	while (widthTmp)
256706f2543Smrg	{
257706f2543Smrg	    w = (stipWidth - sx) * dstBpp;
258706f2543Smrg	    if (w > widthTmp)
259706f2543Smrg		w = widthTmp;
260706f2543Smrg	    widthTmp -= w;
261706f2543Smrg	    fbBltOne (stip + stipY * stipStride,
262706f2543Smrg		      stipStride,
263706f2543Smrg		      sx,
264706f2543Smrg
265706f2543Smrg		      dst + y * dstStride,
266706f2543Smrg		      dstStride,
267706f2543Smrg		      x,
268706f2543Smrg		      dstBpp,
269706f2543Smrg
270706f2543Smrg		      w, h,
271706f2543Smrg
272706f2543Smrg		      fgand, fgxor, bgand, bgxor);
273706f2543Smrg	    x += w;
274706f2543Smrg	    sx = 0;
275706f2543Smrg	}
276706f2543Smrg	y += h;
277706f2543Smrg	stipY = 0;
278706f2543Smrg    }
279706f2543Smrg}
280706f2543Smrg
281706f2543Smrgvoid
282706f2543SmrgfbStipple (FbBits	*dst,
283706f2543Smrg	   FbStride	dstStride,
284706f2543Smrg	   int		dstX,
285706f2543Smrg	   int		dstBpp,
286706f2543Smrg
287706f2543Smrg	   int		width,
288706f2543Smrg	   int		height,
289706f2543Smrg
290706f2543Smrg	   FbStip	*stip,
291706f2543Smrg	   FbStride	stipStride,
292706f2543Smrg	   int		stipWidth,
293706f2543Smrg	   int		stipHeight,
294706f2543Smrg	   Bool		even,
295706f2543Smrg
296706f2543Smrg	   FbBits	fgand,
297706f2543Smrg	   FbBits	fgxor,
298706f2543Smrg	   FbBits	bgand,
299706f2543Smrg	   FbBits	bgxor,
300706f2543Smrg
301706f2543Smrg	   int		xRot,
302706f2543Smrg	   int		yRot)
303706f2543Smrg{
304706f2543Smrg    if (even)
305706f2543Smrg	fbEvenStipple (dst, dstStride, dstX, dstBpp, width, height,
306706f2543Smrg		       stip, stipStride, stipHeight,
307706f2543Smrg		       fgand, fgxor, bgand, bgxor, xRot, yRot);
308706f2543Smrg    else
309706f2543Smrg	fbOddStipple (dst, dstStride, dstX, dstBpp, width, height,
310706f2543Smrg		      stip, stipStride, stipWidth, stipHeight,
311706f2543Smrg		      fgand, fgxor, bgand, bgxor, xRot, yRot);
312706f2543Smrg}
313