xref: /openbsd/sys/dev/rasops/rasops24.c (revision 32c728c5)
1 /*	$OpenBSD: rasops24.c,v 1.13 2023/01/18 11:08:49 nicm Exp $	*/
2 /*	$NetBSD: rasops24.c,v 1.12 2000/04/12 14:22:29 pk Exp $	*/
3 
4 /*-
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Andrew Doran.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/time.h>
36 #include <sys/endian.h>
37 
38 #include <dev/wscons/wsdisplayvar.h>
39 #include <dev/wscons/wsconsio.h>
40 #include <dev/rasops/rasops.h>
41 
42 int 	rasops24_putchar(void *, int, int, u_int, uint32_t attr);
43 #ifndef RASOPS_SMALL
44 int 	rasops24_putchar8(void *, int, int, u_int, uint32_t attr);
45 int 	rasops24_putchar12(void *, int, int, u_int, uint32_t attr);
46 int 	rasops24_putchar16(void *, int, int, u_int, uint32_t attr);
47 void	rasops24_makestamp(struct rasops_info *, uint32_t);
48 
49 /*
50  * 4x1 stamp for optimized character blitting
51  */
52 static int32_t	stamp[64];
53 static uint32_t	stamp_attr;
54 static int	stamp_mutex;	/* XXX see note in readme */
55 #endif
56 
57 /*
58  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
59  * that the shift count is negative.
60  *
61  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
62  * destination int32_t[0] = STAMP_READ(offset)
63  * destination int32_t[1] = STAMP_READ(offset + 4)
64  * destination int32_t[2] = STAMP_READ(offset + 8)
65  */
66 #define STAMP_SHIFT(fb,n)	((n*4-4) >= 0 ? (fb)>>(n*4-4):(fb)<<-(n*4-4))
67 #define STAMP_MASK		(0xf << 4)
68 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
69 
70 /*
71  * Initialize rasops_info struct for this colordepth.
72  */
73 void
rasops24_init(struct rasops_info * ri)74 rasops24_init(struct rasops_info *ri)
75 {
76 
77 	switch (ri->ri_font->fontwidth) {
78 #ifndef RASOPS_SMALL
79 	case 8:
80 		ri->ri_ops.putchar = rasops24_putchar8;
81 		break;
82 	case 12:
83 		ri->ri_ops.putchar = rasops24_putchar12;
84 		break;
85 	case 16:
86 		ri->ri_ops.putchar = rasops24_putchar16;
87 		break;
88 #endif
89 	default:
90 		ri->ri_ops.putchar = rasops24_putchar;
91 		break;
92 	}
93 
94 	if (ri->ri_rnum == 0) {
95 		ri->ri_rnum = 8;
96 		ri->ri_rpos = 0;
97 		ri->ri_gnum = 8;
98 		ri->ri_gpos = 8;
99 		ri->ri_bnum = 8;
100 		ri->ri_bpos = 16;
101 	}
102 }
103 
104 /*
105  * Put a single character. This is the generic version.
106  * XXX this bites - we should use masks.
107  */
108 int
rasops24_putchar(void * cookie,int row,int col,u_int uc,uint32_t attr)109 rasops24_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr)
110 {
111 	int fb, width, height, cnt, clr[2];
112 	struct rasops_info *ri;
113 	u_char *dp, *rp, *fr;
114 
115 	ri = (struct rasops_info *)cookie;
116 
117 #ifdef RASOPS_CLIPPING
118 	/* Catches 'row < 0' case too */
119 	if ((unsigned)row >= (unsigned)ri->ri_rows)
120 		return 0;
121 
122 	if ((unsigned)col >= (unsigned)ri->ri_cols)
123 		return 0;
124 #endif
125 
126 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
127 	height = ri->ri_font->fontheight;
128 	width = ri->ri_font->fontwidth;
129 
130 	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
131 	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
132 
133 	if (uc == ' ') {
134 		while (height--) {
135 			dp = rp;
136 			rp += ri->ri_stride;
137 
138 			for (cnt = width; cnt; cnt--) {
139 				*dp++ = clr[0] >> 16;
140 				*dp++ = clr[0] >> 8;
141 				*dp++ = clr[0];
142 			}
143 		}
144 	} else {
145 		uc -= ri->ri_font->firstchar;
146 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
147 
148 		while (height--) {
149 			dp = rp;
150 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) |
151 			    (fr[0] << 24);
152 			fr += ri->ri_font->stride;
153 			rp += ri->ri_stride;
154 
155 			for (cnt = width; cnt; cnt--, fb <<= 1) {
156 				if ((fb >> 31) & 1) {
157 					*dp++ = clr[1] >> 16;
158 					*dp++ = clr[1] >> 8;
159 					*dp++ = clr[1];
160 				} else {
161 					*dp++ = clr[0] >> 16;
162 					*dp++ = clr[0] >> 8;
163 					*dp++ = clr[0];
164 				}
165 			}
166 		}
167 	}
168 
169 	/* Do underline */
170 	if ((attr & WSATTR_UNDERLINE) != 0) {
171 		rp -= ri->ri_stride << 1;
172 
173 		while (width--) {
174 			*rp++ = clr[1] >> 16;
175 			*rp++ = clr[1] >> 8;
176 			*rp++ = clr[1];
177 		}
178 	}
179 
180 	return 0;
181 }
182 
183 #ifndef RASOPS_SMALL
184 /*
185  * Recompute the blitting stamp.
186  */
187 void
rasops24_makestamp(struct rasops_info * ri,uint32_t attr)188 rasops24_makestamp(struct rasops_info *ri, uint32_t attr)
189 {
190 	u_int fg, bg, c1, c2, c3, c4;
191 	int i;
192 
193 	fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffffff;
194 	bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffffff;
195 	stamp_attr = attr;
196 
197 	for (i = 0; i < 64; i += 4) {
198 #if BYTE_ORDER == LITTLE_ENDIAN
199 		c1 = (i & 32 ? fg : bg);
200 		c2 = (i & 16 ? fg : bg);
201 		c3 = (i & 8 ? fg : bg);
202 		c4 = (i & 4 ? fg : bg);
203 #else
204 		c1 = (i & 8 ? fg : bg);
205 		c2 = (i & 4 ? fg : bg);
206 		c3 = (i & 16 ? fg : bg);
207 		c4 = (i & 32 ? fg : bg);
208 #endif
209 		stamp[i+0] = (c1 <<  8) | (c2 >> 16);
210 		stamp[i+1] = (c2 << 16) | (c3 >>  8);
211 		stamp[i+2] = (c3 << 24) | c4;
212 
213 #if BYTE_ORDER == LITTLE_ENDIAN
214 		if ((ri->ri_flg & RI_BSWAP) == 0) {
215 #else
216 		if ((ri->ri_flg & RI_BSWAP) != 0) {
217 #endif
218 			stamp[i+0] = swap32(stamp[i+0]);
219 			stamp[i+1] = swap32(stamp[i+1]);
220 			stamp[i+2] = swap32(stamp[i+2]);
221 		}
222 	}
223 }
224 
225 /*
226  * Put a single character. This is for 8-pixel wide fonts.
227  */
228 int
229 rasops24_putchar8(void *cookie, int row, int col, u_int uc, uint32_t attr)
230 {
231 	struct rasops_info *ri;
232 	int height, so, fs;
233 	int32_t *rp;
234 	u_char *fr;
235 
236 	/* Can't risk remaking the stamp if it's already in use */
237 	if (stamp_mutex++) {
238 		stamp_mutex--;
239 		return rasops24_putchar(cookie, row, col, uc, attr);
240 	}
241 
242 	ri = (struct rasops_info *)cookie;
243 
244 #ifdef RASOPS_CLIPPING
245 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
246 		stamp_mutex--;
247 		return 0;
248 	}
249 
250 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
251 		stamp_mutex--;
252 		return 0;
253 	}
254 #endif
255 
256 	/* Recompute stamp? */
257 	if (attr != stamp_attr)
258 		rasops24_makestamp(ri, attr);
259 
260 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
261 	height = ri->ri_font->fontheight;
262 
263 	if (uc == (u_int)-1) {
264 		int32_t c = stamp[0];
265 		while (height--) {
266 			rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
267 			DELTA(rp, ri->ri_stride, int32_t *);
268 		}
269 	} else {
270 		uc -= ri->ri_font->firstchar;
271 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
272 		fs = ri->ri_font->stride;
273 
274 		while (height--) {
275 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
276 			rp[0] = STAMP_READ(so);
277 			rp[1] = STAMP_READ(so + 4);
278 			rp[2] = STAMP_READ(so + 8);
279 
280 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
281 			rp[3] = STAMP_READ(so);
282 			rp[4] = STAMP_READ(so + 4);
283 			rp[5] = STAMP_READ(so + 8);
284 
285 			fr += fs;
286 			DELTA(rp, ri->ri_stride, int32_t *);
287 		}
288 	}
289 
290 	/* Do underline */
291 	if ((attr & WSATTR_UNDERLINE) != 0) {
292 		int32_t c = STAMP_READ(52);
293 
294 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
295 		rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
296 	}
297 
298 	stamp_mutex--;
299 
300 	return 0;
301 }
302 
303 /*
304  * Put a single character. This is for 12-pixel wide fonts.
305  */
306 int
307 rasops24_putchar12(void *cookie, int row, int col, u_int uc, uint32_t attr)
308 {
309 	struct rasops_info *ri;
310 	int height, so, fs;
311 	int32_t *rp;
312 	u_char *fr;
313 
314 	/* Can't risk remaking the stamp if it's already in use */
315 	if (stamp_mutex++) {
316 		stamp_mutex--;
317 		return rasops24_putchar(cookie, row, col, uc, attr);
318 	}
319 
320 	ri = (struct rasops_info *)cookie;
321 
322 #ifdef RASOPS_CLIPPING
323 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
324 		stamp_mutex--;
325 		return 0;
326 	}
327 
328 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
329 		stamp_mutex--;
330 		return 0;
331 	}
332 #endif
333 
334 	/* Recompute stamp? */
335 	if (attr != stamp_attr)
336 		rasops24_makestamp(ri, attr);
337 
338 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
339 	height = ri->ri_font->fontheight;
340 
341 	if (uc == (u_int)-1) {
342 		int32_t c = stamp[0];
343 		while (height--) {
344 			rp[0] = rp[1] = rp[2] = rp[3] =
345 			rp[4] = rp[5] = rp[6] = rp[7] = rp[8] = c;
346 			DELTA(rp, ri->ri_stride, int32_t *);
347 		}
348 	} else {
349 		uc -= ri->ri_font->firstchar;
350 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
351 		fs = ri->ri_font->stride;
352 
353 		while (height--) {
354 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
355 			rp[0] = STAMP_READ(so);
356 			rp[1] = STAMP_READ(so + 4);
357 			rp[2] = STAMP_READ(so + 8);
358 
359 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
360 			rp[3] = STAMP_READ(so);
361 			rp[4] = STAMP_READ(so + 4);
362 			rp[5] = STAMP_READ(so + 8);
363 
364 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
365 			rp[6] = STAMP_READ(so);
366 			rp[7] = STAMP_READ(so + 4);
367 			rp[8] = STAMP_READ(so + 8);
368 
369 			fr += fs;
370 			DELTA(rp, ri->ri_stride, int32_t *);
371 		}
372 	}
373 
374 	/* Do underline */
375 	if ((attr & WSATTR_UNDERLINE) != 0) {
376 		int32_t c = STAMP_READ(52);
377 
378 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
379 		rp[0] = rp[1] = rp[2] = rp[3] =
380 		rp[4] = rp[5] = rp[6] = rp[7] = rp[8] = c;
381 	}
382 
383 	stamp_mutex--;
384 
385 	return 0;
386 }
387 
388 /*
389  * Put a single character. This is for 16-pixel wide fonts.
390  */
391 int
392 rasops24_putchar16(void *cookie, int row, int col, u_int uc, uint32_t attr)
393 {
394 	struct rasops_info *ri;
395 	int height, so, fs;
396 	int32_t *rp;
397 	u_char *fr;
398 
399 	/* Can't risk remaking the stamp if it's already in use */
400 	if (stamp_mutex++) {
401 		stamp_mutex--;
402 		return rasops24_putchar(cookie, row, col, uc, attr);
403 	}
404 
405 	ri = (struct rasops_info *)cookie;
406 
407 #ifdef RASOPS_CLIPPING
408 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
409 		stamp_mutex--;
410 		return 0;
411 	}
412 
413 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
414 		stamp_mutex--;
415 		return 0;
416 	}
417 #endif
418 
419 	/* Recompute stamp? */
420 	if (attr != stamp_attr)
421 		rasops24_makestamp(ri, attr);
422 
423 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
424 	height = ri->ri_font->fontheight;
425 
426 	if (uc == (u_int)-1) {
427 		int32_t c = stamp[0];
428 		while (height--) {
429 			rp[0] = rp[1] = rp[2] = rp[3] =
430 			rp[4] = rp[5] = rp[6] = rp[7] =
431 			rp[8] = rp[9] = rp[10] = rp[11] = c;
432 			DELTA(rp, ri->ri_stride, int32_t *);
433 		}
434 	} else {
435 		uc -= ri->ri_font->firstchar;
436 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
437 		fs = ri->ri_font->stride;
438 
439 		while (height--) {
440 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
441 			rp[0] = STAMP_READ(so);
442 			rp[1] = STAMP_READ(so + 4);
443 			rp[2] = STAMP_READ(so + 8);
444 
445 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
446 			rp[3] = STAMP_READ(so);
447 			rp[4] = STAMP_READ(so + 4);
448 			rp[5] = STAMP_READ(so + 8);
449 
450 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
451 			rp[6] = STAMP_READ(so);
452 			rp[7] = STAMP_READ(so + 4);
453 			rp[8] = STAMP_READ(so + 8);
454 
455 			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
456 			rp[9] = STAMP_READ(so);
457 			rp[10] = STAMP_READ(so + 4);
458 			rp[11] = STAMP_READ(so + 8);
459 
460 			DELTA(rp, ri->ri_stride, int32_t *);
461 			fr += fs;
462 		}
463 	}
464 
465 	/* Do underline */
466 	if ((attr & WSATTR_UNDERLINE) != 0) {
467 		int32_t c = STAMP_READ(52);
468 
469 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
470 		rp[0] = rp[1] = rp[2] = rp[3] =
471 		rp[4] = rp[5] = rp[6] = rp[7] =
472 		rp[8] = rp[9] = rp[10] = rp[11] = c;
473 	}
474 
475 	stamp_mutex--;
476 
477 	return 0;
478 }
479 #endif	/* !RASOPS_SMALL */
480