1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright © 1998 Keith Packard
3428d7b3dSmrg * Copyright © 2012 Intel Corporation
4428d7b3dSmrg *
5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that
7428d7b3dSmrg * the above copyright notice appear in all copies and that both that
8428d7b3dSmrg * copyright notice and this permission notice appear in supporting
9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in
10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without
11428d7b3dSmrg * specific, written prior permission.  Keith Packard makes no
12428d7b3dSmrg * representations about the suitability of this software for any purpose.  It
13428d7b3dSmrg * is provided "as is" without express or implied warranty.
14428d7b3dSmrg *
15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE.
22428d7b3dSmrg */
23428d7b3dSmrg
24428d7b3dSmrg#define isClipped(c,ul,lr)  (((c) | ((c) - (ul)) | ((lr) - (c))) & 0x80008000)
25428d7b3dSmrg#define RROP(b,a,x)	WRITE((b), FbDoRRop (READ(b), (a), (x)))
26428d7b3dSmrg
27428d7b3dSmrgstatic void
28428d7b3dSmrgPOLYLINE(DrawablePtr drawable, GCPtr gc, int mode, int n_0, DDXPointPtr pt_0)
29428d7b3dSmrg{
30428d7b3dSmrg	int xoff = drawable->x;
31428d7b3dSmrg	int yoff = drawable->y;
32428d7b3dSmrg	unsigned int bias = miGetZeroLineBias(drawable->pScreen);
33428d7b3dSmrg	const BoxRec *clip = region_rects(gc->pCompositeClip);
34428d7b3dSmrg	const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip);
35428d7b3dSmrg
36428d7b3dSmrg	FbBits *dst;
37428d7b3dSmrg	int dstStride;
38428d7b3dSmrg	int dstBpp;
39428d7b3dSmrg	int dstXoff, dstYoff;
40428d7b3dSmrg
41428d7b3dSmrg	BITS *bits, *bitsBase;
42428d7b3dSmrg	FbStride bitsStride;
43428d7b3dSmrg	BITS xor = fb_gc(gc)->xor;
44428d7b3dSmrg	BITS and = fb_gc(gc)->and;
45428d7b3dSmrg
46428d7b3dSmrg
47428d7b3dSmrg	int e, e1, e3, len;
48428d7b3dSmrg	int stepmajor, stepminor;
49428d7b3dSmrg	int octant;
50428d7b3dSmrg
51428d7b3dSmrg	if (mode == CoordModePrevious)
52428d7b3dSmrg		fbFixCoordModePrevious(n_0, pt_0);
53428d7b3dSmrg
54428d7b3dSmrg	fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
55428d7b3dSmrg	bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
56428d7b3dSmrg	bitsBase = ((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
57428d7b3dSmrg
58428d7b3dSmrg	DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip)));
59428d7b3dSmrg	do {
60428d7b3dSmrg		INT32 *pt = (INT32 *)pt_0;
61428d7b3dSmrg		int n = n_0;
62428d7b3dSmrg		INT32 pt1, pt2;
63428d7b3dSmrg
64428d7b3dSmrg		INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff);
65428d7b3dSmrg		INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1);
66428d7b3dSmrg
67428d7b3dSmrg		DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2));
68428d7b3dSmrg
69428d7b3dSmrg		pt1 = *pt++; n--;
70428d7b3dSmrg		pt2 = *pt++; n--;
71428d7b3dSmrg		for (;;) {
72428d7b3dSmrg			if (isClipped(pt1, ul, lr) | isClipped(pt2, ul, lr)) {
73428d7b3dSmrg				int dashoffset = 0;
74428d7b3dSmrg				fbSegment1(drawable, gc, clip,
75428d7b3dSmrg					  intToX(pt1) + xoff, intToY(pt1) + yoff,
76428d7b3dSmrg					  intToX(pt2) + xoff, intToY(pt2) + yoff,
77428d7b3dSmrg					  n == 0 && gc->capStyle != CapNotLast, &dashoffset);
78428d7b3dSmrg				if (!n)
79428d7b3dSmrg					goto next_clip;
80428d7b3dSmrg
81428d7b3dSmrg				pt1 = pt2;
82428d7b3dSmrg				pt2 = *pt++;
83428d7b3dSmrg				n--;
84428d7b3dSmrg			} else {
85428d7b3dSmrg				bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1);
86428d7b3dSmrg				for (;;) {
87428d7b3dSmrg					CalcLineDeltas(intToX(pt1), intToY(pt1),
88428d7b3dSmrg						       intToX(pt2), intToY(pt2),
89428d7b3dSmrg						       len, e1, stepmajor, stepminor, 1, bitsStride,
90428d7b3dSmrg						       octant);
91428d7b3dSmrg					if (len < e1) {
92428d7b3dSmrg						e3 = len;
93428d7b3dSmrg						len = e1;
94428d7b3dSmrg						e1 = e3;
95428d7b3dSmrg
96428d7b3dSmrg						e3 = stepminor;
97428d7b3dSmrg						stepminor = stepmajor;
98428d7b3dSmrg						stepmajor = e3;
99428d7b3dSmrg						SetYMajorOctant(octant);
100428d7b3dSmrg					}
101428d7b3dSmrg					e = -len;
102428d7b3dSmrg					e1 <<= 1;
103428d7b3dSmrg					e3 = e << 1;
104428d7b3dSmrg					FIXUP_ERROR(e, octant, bias);
105428d7b3dSmrg					if (and == 0) {
106428d7b3dSmrg						while (len--) {
107428d7b3dSmrg							WRITE(bits, xor);
108428d7b3dSmrg							bits += stepmajor;
109428d7b3dSmrg							e += e1;
110428d7b3dSmrg							if (e >= 0) {
111428d7b3dSmrg								bits += stepminor;
112428d7b3dSmrg								e += e3;
113428d7b3dSmrg							}
114428d7b3dSmrg						}
115428d7b3dSmrg					} else {
116428d7b3dSmrg						while (len--) {
117428d7b3dSmrg							RROP(bits, and, xor);
118428d7b3dSmrg							bits += stepmajor;
119428d7b3dSmrg							e += e1;
120428d7b3dSmrg							if (e >= 0) {
121428d7b3dSmrg								bits += stepminor;
122428d7b3dSmrg								e += e3;
123428d7b3dSmrg							}
124428d7b3dSmrg						}
125428d7b3dSmrg					}
126428d7b3dSmrg					if (!n) {
127428d7b3dSmrg						if (gc->capStyle != CapNotLast &&
128428d7b3dSmrg						    pt2 != *((INT32 *)pt_0)) {
129428d7b3dSmrg							RROP(bits, and, xor);
130428d7b3dSmrg						}
131428d7b3dSmrg						goto next_clip;
132428d7b3dSmrg					}
133428d7b3dSmrg					pt1 = pt2;
134428d7b3dSmrg					pt2 = *pt++;
135428d7b3dSmrg					--n;
136428d7b3dSmrg					if (isClipped(pt2, ul, lr))
137428d7b3dSmrg						break;
138428d7b3dSmrg				}
139428d7b3dSmrg			}
140428d7b3dSmrg		}
141428d7b3dSmrgnext_clip: (void)clip;
142428d7b3dSmrg	} while (++clip != last_clip);
143428d7b3dSmrg}
144428d7b3dSmrg
145428d7b3dSmrgstatic void
146428d7b3dSmrgPOLYSEGMENT(DrawablePtr drawable, GCPtr gc, int n_0, xSegment *seg_0)
147428d7b3dSmrg{
148428d7b3dSmrg	int xoff = drawable->x;
149428d7b3dSmrg	int yoff = drawable->y;
150428d7b3dSmrg	unsigned int bias = miGetZeroLineBias(drawable->pScreen);
151428d7b3dSmrg	const BoxRec *clip = region_rects(gc->pCompositeClip);
152428d7b3dSmrg	const BoxRec *const last_clip = clip + region_num_rects(gc->pCompositeClip);
153428d7b3dSmrg
154428d7b3dSmrg	FbBits *dst;
155428d7b3dSmrg	int dstStride;
156428d7b3dSmrg	int dstBpp;
157428d7b3dSmrg	int dstXoff, dstYoff;
158428d7b3dSmrg
159428d7b3dSmrg	BITS *bits, *bitsBase;
160428d7b3dSmrg	FbStride bitsStride;
161428d7b3dSmrg	FbBits xor = fb_gc(gc)->xor;
162428d7b3dSmrg	FbBits and = fb_gc(gc)->and;
163428d7b3dSmrg
164428d7b3dSmrg	int e, e1, e3, len;
165428d7b3dSmrg	int stepmajor, stepminor;
166428d7b3dSmrg	int octant;
167428d7b3dSmrg	bool capNotLast = gc->capStyle == CapNotLast;
168428d7b3dSmrg
169428d7b3dSmrg	fbGetDrawable(drawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
170428d7b3dSmrg	bitsStride = dstStride * (sizeof(FbBits) / sizeof(BITS));
171428d7b3dSmrg	bitsBase =
172428d7b3dSmrg		((BITS *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff);
173428d7b3dSmrg
174428d7b3dSmrg	DBG(("%s: processing %ld clip boxes\n", __FUNCTION__, (long)(last_clip - clip)));
175428d7b3dSmrg	do {
176428d7b3dSmrg		INT32 ul = coordToInt(clip->x1 - xoff, clip->y1 - yoff);
177428d7b3dSmrg		INT32 lr = coordToInt(clip->x2 - xoff - 1, clip->y2 - yoff - 1);
178428d7b3dSmrg		uint64_t *pt = (uint64_t *)seg_0;
179428d7b3dSmrg		int n = n_0;
180428d7b3dSmrg
181428d7b3dSmrg		DBG(("%s: clip box=(%d, %d), (%d, %d)\n", __FUNCTION__, clip->x1, clip->y1, clip->x2, clip->y2));
182428d7b3dSmrg
183428d7b3dSmrg		while (n--) {
184428d7b3dSmrg			union {
185428d7b3dSmrg				int32_t pt32[2];
186428d7b3dSmrg				uint64_t pt64;
187428d7b3dSmrg			} u;
188428d7b3dSmrg
189428d7b3dSmrg			u.pt64 = *pt++;
190428d7b3dSmrg			if (isClipped(u.pt32[0], ul, lr) | isClipped(u.pt32[1], ul, lr)) {
191428d7b3dSmrg				int dashoffset = 0;
192428d7b3dSmrg				fbSegment1(drawable, gc, clip,
193428d7b3dSmrg					  intToX(u.pt32[0]) + xoff, intToY(u.pt32[0]) + yoff,
194428d7b3dSmrg					  intToX(u.pt32[1]) + xoff, intToY(u.pt32[1]) + yoff,
195428d7b3dSmrg					  !capNotLast, &dashoffset);
196428d7b3dSmrg			} else {
197428d7b3dSmrg				CalcLineDeltas(intToX(u.pt32[0]), intToY(u.pt32[0]),
198428d7b3dSmrg					       intToX(u.pt32[1]), intToY(u.pt32[1]),
199428d7b3dSmrg					       len, e1, stepmajor, stepminor, 1, bitsStride,
200428d7b3dSmrg					       octant);
201428d7b3dSmrg				if (e1 == 0 && len > 3) {
202428d7b3dSmrg					int x1, x2;
203428d7b3dSmrg					FbBits *dstLine;
204428d7b3dSmrg					int dstX, width;
205428d7b3dSmrg					FbBits startmask, endmask;
206428d7b3dSmrg					int nmiddle;
207428d7b3dSmrg
208428d7b3dSmrg					if (stepmajor < 0) {
209428d7b3dSmrg						x1 = intToX(u.pt32[1]);
210428d7b3dSmrg						x2 = intToX(u.pt32[0]) + 1;
211428d7b3dSmrg						if (capNotLast)
212428d7b3dSmrg							x1++;
213428d7b3dSmrg					} else {
214428d7b3dSmrg						x1 = intToX(u.pt32[0]);
215428d7b3dSmrg						x2 = intToX(u.pt32[1]);
216428d7b3dSmrg						if (!capNotLast)
217428d7b3dSmrg							x2++;
218428d7b3dSmrg					}
219428d7b3dSmrg					dstX = (x1 + xoff + dstXoff) * (sizeof(BITS) * 8);
220428d7b3dSmrg					width = (x2 - x1) * (sizeof(BITS) * 8);
221428d7b3dSmrg
222428d7b3dSmrg					dstLine = dst + (intToY(u.pt32[0]) + yoff + dstYoff) * dstStride;
223428d7b3dSmrg					dstLine += dstX >> FB_SHIFT;
224428d7b3dSmrg					dstX &= FB_MASK;
225428d7b3dSmrg					FbMaskBits(dstX, width, startmask, nmiddle, endmask);
226428d7b3dSmrg					if (startmask) {
227428d7b3dSmrg						WRITE(dstLine,
228428d7b3dSmrg						      FbDoMaskRRop(READ(dstLine), and, xor,
229428d7b3dSmrg								   startmask));
230428d7b3dSmrg						dstLine++;
231428d7b3dSmrg					}
232428d7b3dSmrg					if (!and)
233428d7b3dSmrg						while (nmiddle--)
234428d7b3dSmrg							WRITE(dstLine++, xor);
235428d7b3dSmrg					else
236428d7b3dSmrg						while (nmiddle--) {
237428d7b3dSmrg							WRITE(dstLine,
238428d7b3dSmrg							      FbDoRRop(READ(dstLine), and, xor));
239428d7b3dSmrg							dstLine++;
240428d7b3dSmrg						}
241428d7b3dSmrg					if (endmask)
242428d7b3dSmrg						WRITE(dstLine,
243428d7b3dSmrg						      FbDoMaskRRop(READ(dstLine), and, xor,
244428d7b3dSmrg								   endmask));
245428d7b3dSmrg				} else {
246428d7b3dSmrg					bits = bitsBase + intToY(u.pt32[0]) * bitsStride + intToX(u.pt32[0]);
247428d7b3dSmrg					if (len < e1) {
248428d7b3dSmrg						e3 = len;
249428d7b3dSmrg						len = e1;
250428d7b3dSmrg						e1 = e3;
251428d7b3dSmrg
252428d7b3dSmrg						e3 = stepminor;
253428d7b3dSmrg						stepminor = stepmajor;
254428d7b3dSmrg						stepmajor = e3;
255428d7b3dSmrg						SetYMajorOctant(octant);
256428d7b3dSmrg					}
257428d7b3dSmrg					e = -len;
258428d7b3dSmrg					e1 <<= 1;
259428d7b3dSmrg					e3 = e << 1;
260428d7b3dSmrg					FIXUP_ERROR(e, octant, bias);
261428d7b3dSmrg					if (!capNotLast)
262428d7b3dSmrg						len++;
263428d7b3dSmrg					if (and == 0) {
264428d7b3dSmrg						while (len--) {
265428d7b3dSmrg							WRITE(bits, xor);
266428d7b3dSmrg							bits += stepmajor;
267428d7b3dSmrg							e += e1;
268428d7b3dSmrg							if (e >= 0) {
269428d7b3dSmrg								bits += stepminor;
270428d7b3dSmrg								e += e3;
271428d7b3dSmrg							}
272428d7b3dSmrg						}
273428d7b3dSmrg					} else {
274428d7b3dSmrg						while (len--) {
275428d7b3dSmrg							RROP(bits, and, xor);
276428d7b3dSmrg							bits += stepmajor;
277428d7b3dSmrg							e += e1;
278428d7b3dSmrg							if (e >= 0) {
279428d7b3dSmrg								bits += stepminor;
280428d7b3dSmrg								e += e3;
281428d7b3dSmrg							}
282428d7b3dSmrg						}
283428d7b3dSmrg					}
284428d7b3dSmrg				}
285428d7b3dSmrg			}
286428d7b3dSmrg		}
287428d7b3dSmrg	} while (++clip != last_clip);
288428d7b3dSmrg}
289428d7b3dSmrg
290428d7b3dSmrg#undef RROP
291428d7b3dSmrg#undef isClipped
292