rasops_bitops.h revision 1.23 1 /* $NetBSD: rasops_bitops.h,v 1.23 2019/08/02 04:39:09 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 #define NAME(name) NAME1(RASOPS_DEPTH, name)
36 #define NAME1(depth, name) NAME2(depth, name)
37 #define NAME2(depth, name) rasops ## depth ## _ ## name
38
39 #if RASOPS_DEPTH == 1
40 #define PIXEL_SHIFT 0
41 #elif RASOPS_DEPTH == 2
42 #define PIXEL_SHIFT 1
43 #elif RASOPS_DEPTH == 4
44 #define PIXEL_SHIFT 2
45 #else
46 #error "Depth not supported"
47 #endif
48
49 #define PIXEL_BITS RASOPS_DEPTH
50 #define COLOR_MASK __BITS(32 - PIXEL_BITS, 31)
51
52 #if RASOPS_DEPTH != 1
53 /*
54 * Paint a single character. This function is also applicable to
55 * monochrome, but that in rasops1.c is much simpler and faster.
56 */
57 static void
58 NAME(putchar)(void *cookie, int row, int col, u_int uc, long attr)
59 {
60 struct rasops_info *ri = (struct rasops_info *)cookie;
61 struct wsdisplay_font *font = PICK_FONT(ri, uc);
62 int full, cnt, bit;
63 uint32_t fs, rs, fb, bg, fg, lmask, rmask, lbg, rbg, clr[2];
64 uint32_t height, width;
65 uint32_t *rp, *bp, *hp, tmp;
66 uint8_t *fr;
67 bool space;
68
69 hp = NULL; /* XXX GCC */
70
71 #ifdef RASOPS_CLIPPING
72 /* Catches 'row < 0' case too */
73 if ((unsigned)row >= (unsigned)ri->ri_rows)
74 return;
75
76 if ((unsigned)col >= (unsigned)ri->ri_cols)
77 return;
78 #endif
79
80 width = font->fontwidth << PIXEL_SHIFT;
81 col *= width;
82 height = font->fontheight;
83 rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
84 ((col >> 3) & ~3));
85 if (ri->ri_hwbits)
86 hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
87 ((col >> 3) & ~3));
88 col &= 31;
89 rs = ri->ri_stride;
90
91 bg = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
92 fg = ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
93
94 /* If fg and bg match this becomes a space character */
95 if (uc == ' ' || __predict_false(fg == bg)) {
96 space = true;
97 fr = NULL; /* XXX GCC */
98 fs = 0; /* XXX GCC */
99 } else {
100 space = false;
101 fr = FONT_GLYPH(uc, font, ri);
102 fs = font->stride;
103 }
104
105 if (col + width <= 32) {
106 /* Single word, only one mask */
107
108 rmask = rasops_pmask[col][width & 31];
109 lmask = ~rmask;
110
111 if (space) {
112 bg &= rmask;
113 while (height--) {
114 tmp = (*rp & lmask) | bg;
115 *rp = tmp;
116 DELTA(rp, rs, uint32_t *);
117 if (ri->ri_hwbits) {
118 *hp = tmp;
119 DELTA(hp, rs, uint32_t *);
120 }
121 }
122 } else {
123 clr[0] = bg & COLOR_MASK;
124 clr[1] = fg & COLOR_MASK;
125 while (height--) {
126 fb = be32uatoh(fr);
127 fr += fs;
128 tmp = 0;
129 for (bit = col; bit < col + width;
130 bit += PIXEL_BITS) {
131 tmp |= clr[(fb >> 31) & 1] >> bit;
132 fb <<= 1;
133 }
134 tmp = (*rp & lmask) | MBE(tmp);
135 *rp = tmp;
136 DELTA(rp, rs, uint32_t *);
137 if (ri->ri_hwbits) {
138 *hp = tmp;
139 DELTA(hp, rs, uint32_t *);
140 }
141 }
142 }
143
144 /* Do underline */
145 if ((attr & WSATTR_UNDERLINE) != 0) {
146 DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
147 tmp = (*rp & lmask) | (fg & rmask);
148 *rp = tmp;
149 if (ri->ri_hwbits) {
150 DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
151 *hp = tmp;
152 }
153 }
154
155 return;
156 }
157
158 /* Word boundary, two masks needed */
159
160 lmask = ~rasops_lmask[col];
161 rmask = ~rasops_rmask[(col + width) & 31];
162
163 if (lmask != -1)
164 width -= 32 - col;
165 full = width / 32;
166 width -= full * 32;
167
168 if (space) {
169 lbg = bg & ~lmask;
170 rbg = bg & ~rmask;
171
172 while (height--) {
173 bp = rp;
174
175 if (lmask != -1) {
176 *bp = (*bp & lmask) | lbg;
177 bp++;
178 }
179
180 for (cnt = full; cnt; cnt--)
181 *bp++ = bg;
182
183 if (rmask != -1)
184 *bp = (*bp & rmask) | rbg;
185
186 if (ri->ri_hwbits) {
187 memcpy(hp, rp, ((lmask != -1) + full +
188 (rmask != -1)) << 2);
189 DELTA(hp, rs, uint32_t *);
190 }
191 DELTA(rp, rs, uint32_t *);
192 }
193 } else {
194 clr[0] = bg & COLOR_MASK;
195 clr[1] = fg & COLOR_MASK;
196
197 while (height--) {
198 bp = rp;
199
200 fb = be32uatoh(fr);
201 fr += fs;
202
203 if (lmask != -1) {
204 tmp = 0;
205 for (bit = col; bit < 32; bit += PIXEL_BITS) {
206 tmp |= clr[(fb >> 31) & 1] >> bit;
207 fb <<= 1;
208 }
209 *bp = (*bp & lmask) | MBE(tmp);
210 bp++;
211 }
212
213 for (cnt = full; cnt; cnt--) {
214 tmp = 0;
215 for (bit = 0; bit < 32; bit += PIXEL_BITS) {
216 tmp |= clr[(fb >> 31) & 1] >> bit;
217 fb <<= 1;
218 }
219 *bp++ = MBE(tmp);
220 }
221
222 if (rmask != -1) {
223 tmp = 0;
224 for (bit = 0; bit < width; bit += PIXEL_BITS) {
225 tmp |= clr[(fb >> 31) & 1] >> bit;
226 fb <<= 1;
227 }
228 *bp = (*bp & rmask) | MBE(tmp);
229 }
230
231 if (ri->ri_hwbits) {
232 memcpy(hp, rp, ((lmask != -1) + full +
233 (rmask != -1)) << 2);
234 DELTA(hp, rs, uint32_t *);
235 }
236
237 DELTA(rp, rs, uint32_t *);
238 }
239 }
240
241 /* Do underline */
242 if ((attr & WSATTR_UNDERLINE) != 0) {
243 DELTA(rp, -(ri->ri_stride << 1), uint32_t *);
244 bp = rp;
245 if (lmask != -1) {
246 *bp = (*bp & lmask) | (fg & ~lmask);
247 bp++;
248 }
249 for (cnt = full; cnt; cnt--)
250 *bp++ = fg;
251 if (rmask != -1)
252 *bp = (*bp & rmask) | (fg & ~rmask);
253 if (ri->ri_hwbits) {
254 DELTA(hp, -(ri->ri_stride << 1), uint32_t *);
255 memcpy(hp, rp, ((lmask != -1) + full +
256 (rmask != -1)) << 2);
257 }
258 }
259 }
260 #endif /* RASOPS_DEPTH != 1 */
261
262 /*
263 * Erase columns.
264 */
265 static void
266 NAME(erasecols)(void *cookie, int row, int col, int num, long attr)
267 {
268 struct rasops_info *ri = (struct rasops_info *)cookie;
269 uint32_t lclr, rclr, clr;
270 uint32_t *dp, *rp, *hp, tmp, lmask, rmask;
271 int height, cnt;
272
273 hp = NULL; /* XXX GCC */
274
275 #ifdef RASOPS_CLIPPING
276 if ((unsigned)row >= (unsigned)ri->ri_rows)
277 return;
278
279 if (col < 0) {
280 num += col;
281 col = 0;
282 }
283
284 if (col + num > ri->ri_cols)
285 num = ri->ri_cols - col;
286
287 if (num <= 0)
288 return;
289 #endif
290
291 col *= ri->ri_font->fontwidth << PIXEL_SHIFT;
292 num *= ri->ri_font->fontwidth << PIXEL_SHIFT;
293 height = ri->ri_font->fontheight;
294 clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
295 rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
296 if (ri->ri_hwbits)
297 hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
298 ((col >> 3) & ~3));
299 col &= 31;
300
301 if (col + num <= 32) {
302 lmask = ~rasops_pmask[col][num & 31];
303 lclr = clr & ~lmask;
304
305 while (height--) {
306 dp = rp;
307 DELTA(rp, ri->ri_stride, uint32_t *);
308
309 tmp = (*dp & lmask) | lclr;
310 *dp = tmp;
311 if (ri->ri_hwbits) {
312 *hp = tmp;
313 DELTA(hp, ri->ri_stride, uint32_t *);
314 }
315 }
316 } else {
317 lmask = rasops_rmask[col];
318 rmask = rasops_lmask[(col + num) & 31];
319
320 if (lmask)
321 num = (num - (32 - col)) >> 5;
322 else
323 num = num >> 5;
324
325 lclr = clr & ~lmask;
326 rclr = clr & ~rmask;
327
328 while (height--) {
329 dp = rp;
330
331 if (lmask) {
332 *dp = (*dp & lmask) | lclr;
333 dp++;
334 }
335
336 for (cnt = num; cnt > 0; cnt--)
337 *dp++ = clr;
338
339 if (rmask)
340 *dp = (*dp & rmask) | rclr;
341
342 if (ri->ri_hwbits) {
343 memcpy(hp, rp, ((lmask != 0) + num +
344 (rmask != 0)) << 2);
345 DELTA(hp, ri->ri_stride, uint32_t *);
346 }
347 DELTA(rp, ri->ri_stride, uint32_t *);
348 }
349 }
350 }
351
352 /*
353 * Actually paint the cursor.
354 */
355 static void
356 NAME(do_cursor)(struct rasops_info *ri)
357 {
358 int height, row, col, num, cnt;
359 uint32_t *dp, *rp, *hp, tmp, lmask, rmask;
360
361 hp = NULL; /* XXX GCC */
362
363 row = ri->ri_crow;
364 col = ri->ri_ccol * ri->ri_font->fontwidth << PIXEL_SHIFT;
365 height = ri->ri_font->fontheight;
366 num = ri->ri_font->fontwidth << PIXEL_SHIFT;
367 rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
368 ((col >> 3) & ~3));
369 if (ri->ri_hwbits)
370 hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
371 ((col >> 3) & ~3));
372 col &= 31;
373
374 if (col + num <= 32) {
375 lmask = rasops_pmask[col][num & 31];
376
377 while (height--) {
378 tmp = *rp ^ lmask;
379 *rp = tmp;
380 if (ri->ri_hwbits) {
381 *hp = tmp;
382 DELTA(hp, ri->ri_stride, uint32_t *);
383 }
384 DELTA(rp, ri->ri_stride, uint32_t *);
385 }
386 } else {
387 lmask = ~rasops_rmask[col];
388 rmask = ~rasops_lmask[(col + num) & 31];
389
390 if (lmask != -1)
391 num = (num - (32 - col)) >> 5;
392 else
393 num = num >> 5;
394
395 while (height--) {
396 dp = rp;
397
398 if (lmask != -1) {
399 *dp = *dp ^ lmask;
400 dp++;
401 }
402
403 for (cnt = num; cnt; cnt--) {
404 *dp = ~*dp;
405 dp++;
406 }
407
408 if (rmask != -1)
409 *dp = *dp ^ rmask;
410
411 if (ri->ri_hwbits) {
412 memcpy(hp, rp, ((lmask != -1) + num +
413 (rmask != -1)) << 2);
414 DELTA(hp, ri->ri_stride, uint32_t *);
415 }
416
417 DELTA(rp, ri->ri_stride, uint32_t *);
418 }
419 }
420 }
421
422 /*
423 * Copy columns. Ick!
424 */
425 static void
426 NAME(copycols)(void *cookie, int row, int src, int dst, int num)
427 {
428 struct rasops_info *ri = (struct rasops_info *)cookie;
429 int height, lnum, rnum, sb, db, cnt, full;
430 uint32_t tmp, lmask, rmask;
431 uint32_t *sp, *dp, *srp, *drp, *dhp, *hp;
432
433 dhp = hp = NULL; /* XXX GCC */
434
435 #ifdef RASOPS_CLIPPING
436 if (dst == src)
437 return;
438
439 /* Catches < 0 case too */
440 if ((unsigned)row >= (unsigned)ri->ri_rows)
441 return;
442
443 if (src < 0) {
444 num += src;
445 src = 0;
446 }
447
448 if (src + num > ri->ri_cols)
449 num = ri->ri_cols - src;
450
451 if (dst < 0) {
452 num += dst;
453 dst = 0;
454 }
455
456 if (dst + num > ri->ri_cols)
457 num = ri->ri_cols - dst;
458
459 if (num <= 0)
460 return;
461 #endif
462
463 cnt = ri->ri_font->fontwidth << PIXEL_SHIFT;
464 src *= cnt;
465 dst *= cnt;
466 num *= cnt;
467 row *= ri->ri_yscale;
468 height = ri->ri_font->fontheight;
469 db = dst & 31;
470
471 if (db + num <= 32) {
472 /* Destination is contained within a single word */
473 srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
474 drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
475 if (ri->ri_hwbits)
476 dhp = (uint32_t *)(ri->ri_hwbits + row +
477 ((dst >> 3) & ~3));
478 sb = src & 31;
479
480 while (height--) {
481 GETBITS(srp, sb, num, tmp);
482 PUTBITS(tmp, db, num, drp);
483 if (ri->ri_hwbits) {
484 PUTBITS(tmp, db, num, dhp);
485 DELTA(dhp, ri->ri_stride, uint32_t *);
486 }
487 DELTA(srp, ri->ri_stride, uint32_t *);
488 DELTA(drp, ri->ri_stride, uint32_t *);
489 }
490
491 return;
492 }
493
494 lmask = rasops_rmask[db];
495 rmask = rasops_lmask[(dst + num) & 31];
496 lnum = (32 - db) & 31;
497 rnum = (dst + num) & 31;
498
499 if (lmask)
500 full = (num - lnum) >> 5;
501 else
502 full = num >> 5;
503
504 if (src < dst && src + num > dst) {
505 /* Copy right-to-left */
506 bool sbover;
507 int sboff;
508
509 srp = (uint32_t *)(ri->ri_bits + row +
510 (((src + num) >> 3) & ~3));
511 drp = (uint32_t *)(ri->ri_bits + row +
512 (((dst + num) >> 3) & ~3));
513 if (ri->ri_hwbits)
514 dhp = (uint32_t *)(ri->ri_hwbits + row +
515 (((dst + num) >> 3) & ~3));
516
517 sb = src & 31;
518 sbover = (sb + lnum) >= 32;
519 sboff = (src + num) & 31;
520 if ((sboff -= rnum) < 0) {
521 srp--;
522 sboff += 32;
523 }
524
525 while (height--) {
526 sp = srp;
527 dp = drp;
528
529 if (rnum) {
530 GETBITS(sp, sboff, rnum, tmp);
531 PUTBITS(tmp, 0, rnum, dp);
532 }
533
534 /* Now aligned to 32-bits wrt dp */
535 for (cnt = full; cnt; cnt--) {
536 --dp;
537 --sp;
538 GETBITS(sp, sboff, 32, tmp);
539 *dp = tmp;
540 }
541
542 if (lmask) {
543 if (sbover)
544 --sp;
545 --dp;
546 GETBITS(sp, sb, lnum, tmp);
547 PUTBITS(tmp, db, lnum, dp);
548 }
549
550 if (ri->ri_hwbits) {
551 hp = dhp;
552 hp -= (lmask != 0) + full;
553 memcpy(hp, dp, ((lmask != 0) + full +
554 (rnum != 0)) << 2);
555 DELTA(dhp, ri->ri_stride, uint32_t *);
556 }
557
558 DELTA(srp, ri->ri_stride, uint32_t *);
559 DELTA(drp, ri->ri_stride, uint32_t *);
560 }
561 } else {
562 /* Copy left-to-right */
563 srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
564 drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
565 if (ri->ri_hwbits)
566 dhp = (uint32_t *)(ri->ri_hwbits + row +
567 ((dst >> 3) & ~3));
568
569 while (height--) {
570 sb = src & 31;
571 sp = srp;
572 dp = drp;
573
574 if (lmask) {
575 GETBITS(sp, sb, lnum, tmp);
576 PUTBITS(tmp, db, lnum, dp);
577 dp++;
578
579 sb += lnum;
580 if (sb > 31) {
581 sp++;
582 sb -= 32;
583 }
584 }
585
586 /* Now aligned to 32-bits wrt dp */
587 for (cnt = full; cnt; cnt--, sp++) {
588 GETBITS(sp, sb, 32, tmp);
589 *dp++ = tmp;
590 }
591
592 if (rmask) {
593 GETBITS(sp, sb, rnum, tmp);
594 PUTBITS(tmp, 0, rnum, dp);
595 }
596
597 if (ri->ri_hwbits) {
598 memcpy(dhp, drp, ((lmask != 0) + full +
599 (rmask != 0)) << 2);
600 DELTA(dhp, ri->ri_stride, uint32_t *);
601 }
602
603 DELTA(srp, ri->ri_stride, uint32_t *);
604 DELTA(drp, ri->ri_stride, uint32_t *);
605 }
606 }
607 }
608
609 #undef PIXEL_SHIFT
610 #undef PIXEL_BITS
611 #undef COLOR_MASK
612
613 #endif /* _RASOPS_BITOPS_H_ */
614