xref: /openbsd/sys/dev/rasops/rasops15.c (revision 32c728c5)
1 /*	$OpenBSD: rasops15.c,v 1.10 2023/01/18 11:08:49 nicm Exp $	*/
2 /*	$NetBSD: rasops15.c,v 1.7 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 
37 #include <dev/wscons/wsdisplayvar.h>
38 #include <dev/wscons/wsconsio.h>
39 #include <dev/rasops/rasops.h>
40 
41 int 	rasops15_putchar(void *, int, int, u_int, uint32_t attr);
42 #ifndef RASOPS_SMALL
43 int 	rasops15_putchar8(void *, int, int, u_int, uint32_t attr);
44 int 	rasops15_putchar12(void *, int, int, u_int, uint32_t attr);
45 int 	rasops15_putchar16(void *, int, int, u_int, uint32_t attr);
46 void	rasops15_makestamp(struct rasops_info *, uint32_t);
47 
48 /*
49  * (2x2)x1 stamp for optimized character blitting
50  */
51 static int32_t	stamp[32];
52 static uint32_t	stamp_attr;
53 static int	stamp_mutex;	/* XXX see note in readme */
54 #endif
55 
56 /*
57  * XXX this confuses the hell out of gcc2 (not egcs) which always insists
58  * that the shift count is negative.
59  *
60  * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
61  * destination int32_t[0] = STAMP_READ(offset)
62  * destination int32_t[1] = STAMP_READ(offset + 4)
63  */
64 #define STAMP_SHIFT(fb,n)	((n*4-3) >= 0 ? (fb)>>(n*4-3):(fb)<<-(n*4-3))
65 #define STAMP_MASK		(15 << 3)
66 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
67 
68 /*
69  * Initialize rasops_info struct for this colordepth.
70  */
71 void
rasops15_init(struct rasops_info * ri)72 rasops15_init(struct rasops_info *ri)
73 {
74 
75 	switch (ri->ri_font->fontwidth) {
76 #ifndef RASOPS_SMALL
77 	case 8:
78 		ri->ri_ops.putchar = rasops15_putchar8;
79 		break;
80 
81 	case 12:
82 		ri->ri_ops.putchar = rasops15_putchar12;
83 		break;
84 
85 	case 16:
86 		ri->ri_ops.putchar = rasops15_putchar16;
87 		break;
88 #endif	/* !RASOPS_SMALL */
89 	default:
90 		ri->ri_ops.putchar = rasops15_putchar;
91 		break;
92 	}
93 
94 	if (ri->ri_rnum == 0) {
95 		ri->ri_rnum = 5;
96 		ri->ri_rpos = 0;
97 		ri->ri_gnum = 5 + (ri->ri_depth == 16);
98 		ri->ri_gpos = 5;
99 		ri->ri_bnum = 5;
100 		ri->ri_bpos = 10 + (ri->ri_depth == 16);
101 	}
102 }
103 
104 /*
105  * Paint a single character.
106  */
107 int
rasops15_putchar(void * cookie,int row,int col,u_int uc,uint32_t attr)108 rasops15_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr)
109 {
110 	int fb, width, height, cnt, clr[2];
111 	struct rasops_info *ri;
112 	u_char *dp, *rp, *fr;
113 
114 	ri = (struct rasops_info *)cookie;
115 
116 #ifdef RASOPS_CLIPPING
117 	/* Catches 'row < 0' case too */
118 	if ((unsigned)row >= (unsigned)ri->ri_rows)
119 		return 0;
120 
121 	if ((unsigned)col >= (unsigned)ri->ri_cols)
122 		return 0;
123 #endif
124 
125 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
126 	height = ri->ri_font->fontheight;
127 	width = ri->ri_font->fontwidth;
128 
129 	clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
130 	clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
131 
132 	if (uc == ' ') {
133 		int16_t c = (int16_t)clr[0];
134 		while (height--) {
135 			dp = rp;
136 			rp += ri->ri_stride;
137 
138 			for (cnt = width; cnt; cnt--) {
139 				*(int16_t *)dp = c;
140 				dp += 2;
141 			}
142 		}
143 	} else {
144 		uc -= ri->ri_font->firstchar;
145 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
146 
147 		while (height--) {
148 			dp = rp;
149 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
150 			fr += ri->ri_font->stride;
151 			rp += ri->ri_stride;
152 
153 			for (cnt = width; cnt; cnt--) {
154 				*(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
155 				fb <<= 1;
156 				dp += 2;
157 			}
158 		}
159 	}
160 
161 	/* Do underline */
162 	if ((attr & WSATTR_UNDERLINE) != 0) {
163 		int16_t c = (int16_t)clr[1];
164 		rp -= ri->ri_stride << 1;
165 
166 		while (width--) {
167 			*(int16_t *)rp = c;
168 			rp += 2;
169 		}
170 	}
171 
172 	return 0;
173 }
174 
175 #ifndef RASOPS_SMALL
176 /*
177  * Recompute the (2x2)x1 blitting stamp.
178  */
179 void
rasops15_makestamp(struct rasops_info * ri,uint32_t attr)180 rasops15_makestamp(struct rasops_info *ri, uint32_t attr)
181 {
182 	int32_t fg, bg;
183 	int i;
184 
185 	fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff;
186 	bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff;
187 	stamp_attr = attr;
188 
189 	for (i = 0; i < 32; i += 2) {
190 #if BYTE_ORDER == LITTLE_ENDIAN
191 		stamp[i] = (i & 16 ? fg : bg);
192 		stamp[i] |= ((i & 8 ? fg : bg) << 16);
193 		stamp[i + 1] = (i & 4 ? fg : bg);
194 		stamp[i + 1] |= ((i & 2 ? fg : bg) << 16);
195 #else
196 		stamp[i + 1] = (i & 2 ? fg : bg);
197 		stamp[i + 1] |= ((i & 4 ? fg : bg) << 16);
198 		stamp[i] = (i & 8 ? fg : bg);
199 		stamp[i] |= ((i & 16 ? fg : bg) << 16);
200 #endif
201 	}
202 }
203 
204 /*
205  * Paint a single character. This is for 8-pixel wide fonts.
206  */
207 int
rasops15_putchar8(void * cookie,int row,int col,u_int uc,uint32_t attr)208 rasops15_putchar8(void *cookie, int row, int col, u_int uc, uint32_t attr)
209 {
210 	struct rasops_info *ri;
211 	int height, so, fs;
212 	int32_t *rp;
213 	u_char *fr;
214 
215 	/* Can't risk remaking the stamp if it's already in use */
216 	if (stamp_mutex++) {
217 		stamp_mutex--;
218 		return rasops15_putchar(cookie, row, col, uc, attr);
219 	}
220 
221 	ri = (struct rasops_info *)cookie;
222 
223 #ifdef RASOPS_CLIPPING
224 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
225 		stamp_mutex--;
226 		return 0;
227 	}
228 
229 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
230 		stamp_mutex--;
231 		return 0;
232 	}
233 #endif
234 
235 	/* Recompute stamp? */
236 	if (attr != stamp_attr)
237 		rasops15_makestamp(ri, attr);
238 
239 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
240 	height = ri->ri_font->fontheight;
241 
242 	if (uc == (u_int)-1) {
243 		int32_t c = stamp[0];
244 		while (height--) {
245 			rp[0] = rp[1] = rp[2] = rp[3] = c;
246 			DELTA(rp, ri->ri_stride, int32_t *);
247 		}
248 	} else {
249 		uc -= ri->ri_font->firstchar;
250 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
251 		fs = ri->ri_font->stride;
252 
253 		while (height--) {
254 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
255 			rp[0] = STAMP_READ(so);
256 			rp[1] = STAMP_READ(so + 4);
257 
258 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
259 			rp[2] = STAMP_READ(so);
260 			rp[3] = STAMP_READ(so + 4);
261 
262 			fr += fs;
263 			DELTA(rp, ri->ri_stride, int32_t *);
264 		}
265 	}
266 
267 	/* Do underline */
268 	if ((attr & WSATTR_UNDERLINE) != 0) {
269 		int32_t c = STAMP_READ(28);
270 
271 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
272 		rp[0] = rp[1] = rp[2] = rp[3] = c;
273 	}
274 
275 	stamp_mutex--;
276 
277 	return 0;
278 }
279 
280 /*
281  * Paint a single character. This is for 12-pixel wide fonts.
282  */
283 int
rasops15_putchar12(void * cookie,int row,int col,u_int uc,uint32_t attr)284 rasops15_putchar12(void *cookie, int row, int col, u_int uc, uint32_t attr)
285 {
286 	struct rasops_info *ri;
287 	int height, so, fs;
288 	int32_t *rp;
289 	u_char *fr;
290 
291 	/* Can't risk remaking the stamp if it's already in use */
292 	if (stamp_mutex++) {
293 		stamp_mutex--;
294 		return rasops15_putchar(cookie, row, col, uc, attr);
295 	}
296 
297 	ri = (struct rasops_info *)cookie;
298 
299 #ifdef RASOPS_CLIPPING
300 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
301 		stamp_mutex--;
302 		return 0;
303 	}
304 
305 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
306 		stamp_mutex--;
307 		return 0;
308 	}
309 #endif
310 
311 	/* Recompute stamp? */
312 	if (attr != stamp_attr)
313 		rasops15_makestamp(ri, attr);
314 
315 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
316 	height = ri->ri_font->fontheight;
317 
318 	if (uc == (u_int)-1) {
319 		int32_t c = stamp[0];
320 		while (height--) {
321 			rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
322 			DELTA(rp, ri->ri_stride, int32_t *);
323 		}
324 	} else {
325 		uc -= ri->ri_font->firstchar;
326 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
327 		fs = ri->ri_font->stride;
328 
329 		while (height--) {
330 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
331 			rp[0] = STAMP_READ(so);
332 			rp[1] = STAMP_READ(so + 4);
333 
334 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
335 			rp[2] = STAMP_READ(so);
336 			rp[3] = STAMP_READ(so + 4);
337 
338 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
339 			rp[4] = STAMP_READ(so);
340 			rp[5] = STAMP_READ(so + 4);
341 
342 			fr += fs;
343 			DELTA(rp, ri->ri_stride, int32_t *);
344 		}
345 	}
346 
347 	/* Do underline */
348 	if (attr & WSATTR_UNDERLINE) {
349 		int32_t c = STAMP_READ(28);
350 
351 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
352 		rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
353 	}
354 
355 	stamp_mutex--;
356 
357 	return 0;
358 }
359 
360 /*
361  * Paint a single character. This is for 16-pixel wide fonts.
362  */
363 int
rasops15_putchar16(void * cookie,int row,int col,u_int uc,uint32_t attr)364 rasops15_putchar16(void *cookie, int row, int col, u_int uc, uint32_t attr)
365 {
366 	struct rasops_info *ri;
367 	int height, so, fs;
368 	int32_t *rp;
369 	u_char *fr;
370 
371 	/* Can't risk remaking the stamp if it's already in use */
372 	if (stamp_mutex++) {
373 		stamp_mutex--;
374 		return rasops15_putchar(cookie, row, col, uc, attr);
375 	}
376 
377 	ri = (struct rasops_info *)cookie;
378 
379 #ifdef RASOPS_CLIPPING
380 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
381 		stamp_mutex--;
382 		return 0;
383 	}
384 
385 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
386 		stamp_mutex--;
387 		return 0;
388 	}
389 #endif
390 
391 	/* Recompute stamp? */
392 	if (attr != stamp_attr)
393 		rasops15_makestamp(ri, attr);
394 
395 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
396 	height = ri->ri_font->fontheight;
397 
398 	if (uc == (u_int)-1) {
399 		int32_t c = stamp[0];
400 		while (height--) {
401 			rp[0] = rp[1] = rp[2] = rp[3] =
402 			rp[4] = rp[5] = rp[6] = rp[7] = c;
403 			DELTA(rp, ri->ri_stride, int32_t *);
404 		}
405 	} else {
406 		uc -= ri->ri_font->firstchar;
407 		fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
408 		fs = ri->ri_font->stride;
409 
410 		while (height--) {
411 			so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
412 			rp[0] = STAMP_READ(so);
413 			rp[1] = STAMP_READ(so + 4);
414 
415 			so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
416 			rp[2] = STAMP_READ(so);
417 			rp[3] = STAMP_READ(so + 4);
418 
419 			so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
420 			rp[4] = STAMP_READ(so);
421 			rp[5] = STAMP_READ(so + 4);
422 
423 			so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
424 			rp[6] = STAMP_READ(so);
425 			rp[7] = STAMP_READ(so + 4);
426 
427 			DELTA(rp, ri->ri_stride, int32_t *);
428 			fr += fs;
429 		}
430 	}
431 
432 	/* Do underline */
433 	if (attr & WSATTR_UNDERLINE) {
434 		int32_t c = STAMP_READ(28);
435 
436 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
437 		rp[0] = rp[1] = rp[2] = rp[3] =
438 		rp[4] = rp[5] = rp[6] = rp[7] = c;
439 	}
440 
441 	stamp_mutex--;
442 
443 	return 0;
444 }
445 #endif	/* !RASOPS_SMALL */
446