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 */
52 static void
NAME(erasecols)53 NAME(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 */
146 static void
NAME(do_cursor)147 NAME(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 */
218 static void
NAME(copycols)219 NAME(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