1/* 	$NetBSD: rasops_bitops.h,v 1.25 2019/08/10 01:24:17 rin Exp $	*/
2
3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#ifndef _RASOPS_BITOPS_H_
33#define _RASOPS_BITOPS_H_ 1
34
35#if   RASOPS_DEPTH == 1
36#define	PIXEL_SHIFT	0
37#elif RASOPS_DEPTH == 2
38#define	PIXEL_SHIFT	1
39#elif RASOPS_DEPTH == 4
40#define	PIXEL_SHIFT	2
41#else
42#error "Depth not supported"
43#endif
44
45#define	NAME(name)		NAME1(RASOPS_DEPTH, name)
46#define	NAME1(depth, name)	NAME2(depth, name)
47#define	NAME2(depth, name)	rasops ## depth ## _ ## name
48
49/*
50 * Erase columns.
51 */
52static void
53NAME(erasecols)(void *cookie, int row, int col, int num, long attr)
54{
55	struct rasops_info *ri = (struct rasops_info *)cookie;
56	int height, cnt;
57	uint32_t bg, lbg, rbg, lmask, rmask, tmp;
58	uint32_t *dp, *rp, *hp;
59
60	hp = NULL;	/* XXX GCC */
61
62#ifdef RASOPS_CLIPPING
63	if ((unsigned)row >= (unsigned)ri->ri_rows)
64		return;
65
66	if (col < 0) {
67		num += col;
68		col = 0;
69	}
70
71	if (col + num > ri->ri_cols)
72		num = ri->ri_cols - col;
73
74	if (num <= 0)
75		return;
76#endif
77
78	height = ri->ri_font->fontheight;
79	col *= ri->ri_font->fontwidth << PIXEL_SHIFT;
80	num *= ri->ri_font->fontwidth << PIXEL_SHIFT;
81
82	rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
83	if (ri->ri_hwbits)
84		hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
85		    ((col >> 3) & ~3));
86
87	col &= 31;
88
89	bg = ATTR_BG(ri, attr);
90
91	if (col + num <= 32) {
92		lmask = ~rasops_pmask[col][num & 31];
93		bg &= ~lmask;
94
95		while (height--) {
96			tmp = (*rp & lmask) | bg;
97			*rp = tmp;
98
99			if (ri->ri_hwbits) {
100				*hp = tmp;
101				DELTA(hp, ri->ri_stride, uint32_t *);
102			}
103
104			DELTA(rp, ri->ri_stride, uint32_t *);
105		}
106	} else {
107		lmask = rasops_rmask[col];
108		rmask = rasops_lmask[(col + num) & 31];
109
110		if (lmask)
111			num = (num - (32 - col)) >> 5;
112		else
113			num = num >> 5;
114
115		lbg = bg & ~lmask;
116		rbg = bg & ~rmask;
117
118		while (height--) {
119			dp = rp;
120
121			if (lmask) {
122				*dp = (*dp & lmask) | lbg;
123				dp++;
124			}
125
126			for (cnt = num; cnt > 0; cnt--)
127				*dp++ = bg;
128
129			if (rmask)
130				*dp = (*dp & rmask) | rbg;
131
132			if (ri->ri_hwbits) {
133				memcpy(hp, rp, ((lmask != 0) + num +
134				    (rmask != 0)) << 2);
135				DELTA(hp, ri->ri_stride, uint32_t *);
136			}
137
138			DELTA(rp, ri->ri_stride, uint32_t *);
139		}
140	}
141}
142
143/*
144 * Actually paint the cursor.
145 */
146static void
147NAME(do_cursor)(struct rasops_info *ri)
148{
149	int row, col, height, width, cnt;
150	uint32_t lmask, rmask, tmp;
151	uint32_t *dp, *rp, *hp;
152
153	hp = NULL;	/* XXX GCC */
154
155	row = ri->ri_crow;
156	col = ri->ri_ccol * ri->ri_font->fontwidth << PIXEL_SHIFT;
157
158	height = ri->ri_font->fontheight;
159	width = ri->ri_font->fontwidth << PIXEL_SHIFT;
160
161	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
162	    ((col >> 3) & ~3));
163	if (ri->ri_hwbits)
164		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
165		    ((col >> 3) & ~3));
166
167	col &= 31;
168
169	if (col + width <= 32) {
170		lmask = rasops_pmask[col][width & 31];
171
172		while (height--) {
173			tmp = *rp ^ lmask;
174			*rp = tmp;
175			if (ri->ri_hwbits) {
176				*hp = tmp;
177				DELTA(hp, ri->ri_stride, uint32_t *);
178			}
179			DELTA(rp, ri->ri_stride, uint32_t *);
180		}
181	} else {
182		lmask = ~rasops_rmask[col];
183		rmask = ~rasops_lmask[(col + width) & 31];
184
185		if (lmask != -1)
186			width = (width - (32 - col)) >> 5;
187		else
188			width = width >> 5;
189
190		while (height--) {
191			dp = rp;
192
193			if (lmask != -1)
194				*dp++ ^= lmask;
195
196			for (cnt = width; cnt; cnt--) {
197				*dp = ~*dp;
198				dp++;
199			}
200
201			if (rmask != -1)
202				*dp ^= rmask;
203
204			if (ri->ri_hwbits) {
205				memcpy(hp, rp, ((lmask != -1) + width +
206				    (rmask != -1)) << 2);
207				DELTA(hp, ri->ri_stride, uint32_t *);
208			}
209
210			DELTA(rp, ri->ri_stride, uint32_t *);
211		}
212	}
213}
214
215/*
216 * Copy columns. Ick!
217 */
218static void
219NAME(copycols)(void *cookie, int row, int src, int dst, int num)
220{
221	struct rasops_info *ri = (struct rasops_info *)cookie;
222	int height, width, lnum, rnum, sb, db, full, cnt, sboff;
223	uint32_t lmask, rmask, tmp;
224	uint32_t *sp, *dp, *srp, *drp, *hp;
225	bool sbover;
226
227	hp = NULL;	/* XXX GCC */
228
229	if (__predict_false(dst == src))
230		return;
231
232#ifdef RASOPS_CLIPPING
233	/* Catches < 0 case too */
234	if ((unsigned)row >= (unsigned)ri->ri_rows)
235		return;
236
237	if (src < 0) {
238		num += src;
239		src = 0;
240	}
241
242	if (src + num > ri->ri_cols)
243		num = ri->ri_cols - src;
244
245	if (dst < 0) {
246		num += dst;
247		dst = 0;
248	}
249
250	if (dst + num > ri->ri_cols)
251		num = ri->ri_cols - dst;
252
253	if (num <= 0)
254		return;
255#endif
256
257	height = ri->ri_font->fontheight;
258	width = ri->ri_font->fontwidth << PIXEL_SHIFT;
259
260	row *= ri->ri_yscale;
261
262	src *= width;
263	dst *= width;
264	num *= width;
265
266	sb = src & 31;
267	db = dst & 31;
268
269	if (db + num <= 32) {
270		/* Destination is contained within a single word */
271		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
272		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
273		if (ri->ri_hwbits)
274			hp = (uint32_t *)(ri->ri_hwbits + row +
275			    ((dst >> 3) & ~3));
276
277		while (height--) {
278			GETBITS(srp, sb, num, tmp);
279			PUTBITS(tmp, db, num, drp);
280			if (ri->ri_hwbits) {
281				*hp = *drp;
282				DELTA(hp, ri->ri_stride, uint32_t *);
283			}
284			DELTA(srp, ri->ri_stride, uint32_t *);
285			DELTA(drp, ri->ri_stride, uint32_t *);
286		}
287
288		return;
289	}
290
291	lmask = rasops_rmask[db];
292	rmask = rasops_lmask[(dst + num) & 31];
293	lnum = (32 - db) & 31;
294	rnum = (dst + num) & 31;
295
296	if (lmask != 0)
297		full = (num - lnum) >> 5;
298	else
299		full = num >> 5;
300
301	if (src < dst && src + num > dst) {
302		/* Copy right-to-left */
303		srp = (uint32_t *)(ri->ri_bits + row +
304		    (((src + num) >> 3) & ~3));
305		drp = (uint32_t *)(ri->ri_bits + row +
306		    (((dst + num) >> 3) & ~3));
307		if (ri->ri_hwbits) {
308			hp = (uint32_t *)(ri->ri_hwbits + row +
309			    (((dst + num) >> 3) & ~3));
310			hp -= (lmask != 0) + full;
311		}
312
313		sboff = (src + num) & 31;
314		sbover = sb + lnum >= 32;
315		if ((sboff -= rnum) < 0) {
316			srp--;
317			sboff += 32;
318		}
319
320		while (height--) {
321			sp = srp;
322			dp = drp;
323
324			if (rmask != 0) {
325				GETBITS(sp, sboff, rnum, tmp);
326				PUTBITS(tmp, 0, rnum, dp);
327			}
328
329			/* Now aligned to 32-bits wrt dp */
330			for (cnt = full; cnt; cnt--) {
331				--dp;
332				--sp;
333				GETBITS(sp, sboff, 32, tmp);
334				*dp = tmp;
335			}
336
337			if (lmask != 0) {
338				if (sbover)
339					--sp;
340				--dp;
341				GETBITS(sp, sb, lnum, tmp);
342				PUTBITS(tmp, db, lnum, dp);
343 			}
344
345			if (ri->ri_hwbits) {
346				memcpy(hp, dp, ((lmask != 0) + full +
347				    (rmask != 0)) << 2);
348				DELTA(hp, ri->ri_stride, uint32_t *);
349			}
350
351			DELTA(srp, ri->ri_stride, uint32_t *);
352			DELTA(drp, ri->ri_stride, uint32_t *);
353 		}
354	} else {
355		/* Copy left-to-right */
356		srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
357		drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
358		if (ri->ri_hwbits)
359			hp = (uint32_t *)(ri->ri_hwbits + row +
360			    ((dst >> 3) & ~3));
361
362		while (height--) {
363			sp = srp;
364			dp = drp;
365
366			sboff = sb;
367
368			if (lmask != 0) {
369				GETBITS(sp, sboff, lnum, tmp);
370				PUTBITS(tmp, db, lnum, dp);
371				dp++;
372
373				if ((sboff += lnum) > 31) {
374					sp++;
375					sboff -= 32;
376				}
377			}
378
379			/* Now aligned to 32-bits wrt dp */
380			for (cnt = full; cnt; cnt--, sp++) {
381				GETBITS(sp, sboff, 32, tmp);
382				*dp++ = tmp;
383			}
384
385			if (rmask != 0) {
386				GETBITS(sp, sboff, rnum, tmp);
387				PUTBITS(tmp, 0, rnum, dp);
388 			}
389
390			if (ri->ri_hwbits) {
391				memcpy(hp, drp, ((lmask != 0) + full +
392				    (rmask != 0)) << 2);
393				DELTA(hp, ri->ri_stride, uint32_t *);
394			}
395
396			DELTA(srp, ri->ri_stride, uint32_t *);
397			DELTA(drp, ri->ri_stride, uint32_t *);
398 		}
399 	}
400}
401
402#undef	PIXEL_SHIFT
403
404#undef	NAME
405#undef	NAME1
406#undef	NAME2
407
408#endif /* _RASOPS_BITOPS_H_ */
409