xref: /openbsd/sys/dev/rasops/rasops8.c (revision 32c728c5)
1 /*	$OpenBSD: rasops8.c,v 1.12 2023/01/18 11:08:49 nicm Exp $	*/
2 /*	$NetBSD: rasops8.c,v 1.8 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 	rasops8_putchar(void *, int, int, u_int, uint32_t attr);
42 #ifndef RASOPS_SMALL
43 int 	rasops8_putchar8(void *, int, int, u_int, uint32_t attr);
44 int 	rasops8_putchar12(void *, int, int, u_int, uint32_t attr);
45 int 	rasops8_putchar16(void *, int, int, u_int, uint32_t attr);
46 void	rasops8_makestamp(struct rasops_info *ri, uint32_t);
47 
48 /*
49  * 4x1 stamp for optimized character blitting
50  */
51 static int32_t	stamp[16];
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 = STAMP_READ(offset)
62  */
63 #define STAMP_SHIFT(fb,n)	((n*4-2) >= 0 ? (fb)>>(n*4-2):(fb)<<-(n*4-2))
64 #define STAMP_MASK		(0xf << 2)
65 #define STAMP_READ(o)		(*(int32_t *)((caddr_t)stamp + (o)))
66 
67 /*
68  * Initialize a 'rasops_info' descriptor for this depth.
69  */
70 void
rasops8_init(struct rasops_info * ri)71 rasops8_init(struct rasops_info *ri)
72 {
73 
74 	switch (ri->ri_font->fontwidth) {
75 #ifndef RASOPS_SMALL
76 	case 8:
77 		ri->ri_ops.putchar = rasops8_putchar8;
78 		break;
79 	case 12:
80 		ri->ri_ops.putchar = rasops8_putchar12;
81 		break;
82 	case 16:
83 		ri->ri_ops.putchar = rasops8_putchar16;
84 		break;
85 #endif /* !RASOPS_SMALL */
86 	default:
87 		ri->ri_ops.putchar = rasops8_putchar;
88 		break;
89 	}
90 }
91 
92 /*
93  * Put a single character.
94  */
95 int
rasops8_putchar(void * cookie,int row,int col,u_int uc,uint32_t attr)96 rasops8_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr)
97 {
98 	int width, height, cnt, fs, fb;
99 	u_char *dp, *rp, *fr, clr[2];
100 	struct rasops_info *ri;
101 
102 	ri = (struct rasops_info *)cookie;
103 
104 #ifdef RASOPS_CLIPPING
105 	/* Catches 'row < 0' case too */
106 	if ((unsigned)row >= (unsigned)ri->ri_rows)
107 		return 0;
108 
109 	if ((unsigned)col >= (unsigned)ri->ri_cols)
110 		return 0;
111 #endif
112 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
113 
114 	height = ri->ri_font->fontheight;
115 	width = ri->ri_font->fontwidth;
116 	clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
117 	clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
118 
119 	if (uc == ' ') {
120 		u_char c = clr[0];
121 
122 		while (height--) {
123 			dp = rp;
124 			rp += ri->ri_stride;
125 
126 			for (cnt = width; cnt; cnt--)
127 				*dp++ = c;
128 		}
129 	} else {
130 		uc -= ri->ri_font->firstchar;
131 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
132 		fs = ri->ri_font->stride;
133 
134 		while (height--) {
135 			dp = rp;
136 			fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
137 			fr += fs;
138 			rp += ri->ri_stride;
139 
140 			for (cnt = width; cnt; cnt--) {
141 				*dp++ = clr[(fb >> 31) & 1];
142 				fb <<= 1;
143 			}
144 		}
145 	}
146 
147 	/* Do underline */
148 	if ((attr & WSATTR_UNDERLINE) != 0) {
149 		u_char c = clr[1];
150 
151 		rp -= (ri->ri_stride << 1);
152 
153 		while (width--)
154 			*rp++ = c;
155 	}
156 
157 	return 0;
158 }
159 
160 #ifndef RASOPS_SMALL
161 /*
162  * Recompute the 4x1 blitting stamp.
163  */
164 void
rasops8_makestamp(struct rasops_info * ri,uint32_t attr)165 rasops8_makestamp(struct rasops_info *ri, uint32_t attr)
166 {
167 	int32_t fg, bg;
168 	int i;
169 
170 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
171 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
172 	stamp_attr = attr;
173 
174 	for (i = 0; i < 16; i++) {
175 #if BYTE_ORDER == LITTLE_ENDIAN
176 		stamp[i] = (i & 8 ? fg : bg);
177 		stamp[i] |= ((i & 4 ? fg : bg) << 8);
178 		stamp[i] |= ((i & 2 ? fg : bg) << 16);
179 		stamp[i] |= ((i & 1 ? fg : bg) << 24);
180 #else
181 		stamp[i] = (i & 1 ? fg : bg);
182 		stamp[i] |= ((i & 2 ? fg : bg) << 8);
183 		stamp[i] |= ((i & 4 ? fg : bg) << 16);
184 		stamp[i] |= ((i & 8 ? fg : bg) << 24);
185 #endif
186 #if NRASOPS_BSWAP > 0
187 		if (ri->ri_flg & RI_BSWAP)
188 			stamp[i] = swap32(stamp[i]);
189 #endif
190 	}
191 }
192 
193 /*
194  * Put a single character. This is for 8-pixel wide fonts.
195  */
196 int
rasops8_putchar8(void * cookie,int row,int col,u_int uc,uint32_t attr)197 rasops8_putchar8(void *cookie, int row, int col, u_int uc, uint32_t attr)
198 {
199 	struct rasops_info *ri;
200 	int height, fs;
201 	int32_t *rp;
202 	u_char *fr;
203 
204 	/* Can't risk remaking the stamp if it's already in use */
205 	if (stamp_mutex++) {
206 		stamp_mutex--;
207 		return rasops8_putchar(cookie, row, col, uc, attr);
208 	}
209 
210 	ri = (struct rasops_info *)cookie;
211 
212 #ifdef RASOPS_CLIPPING
213 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
214 		stamp_mutex--;
215 		return 0;
216 	}
217 
218 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
219 		stamp_mutex--;
220 		return 0;
221 	}
222 #endif
223 
224 	/* Recompute stamp? */
225 	if (attr != stamp_attr)
226 		rasops8_makestamp(ri, attr);
227 
228 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
229 	height = ri->ri_font->fontheight;
230 
231 	if (uc == ' ') {
232 		while (height--) {
233 			rp[0] = rp[1] = stamp[0];
234 			DELTA(rp, ri->ri_stride, int32_t *);
235 		}
236 	} else {
237 		uc -= ri->ri_font->firstchar;
238 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
239 		fs = ri->ri_font->stride;
240 
241 		while (height--) {
242 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
243 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
244 
245 			fr += fs;
246 			DELTA(rp, ri->ri_stride, int32_t *);
247 		}
248 	}
249 
250 	/* Do underline */
251 	if ((attr & WSATTR_UNDERLINE) != 0) {
252 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
253 		rp[0] = rp[1] = stamp[15];
254 	}
255 
256 	stamp_mutex--;
257 
258 	return 0;
259 }
260 
261 /*
262  * Put a single character. This is for 12-pixel wide fonts.
263  */
264 int
rasops8_putchar12(void * cookie,int row,int col,u_int uc,uint32_t attr)265 rasops8_putchar12(void *cookie, int row, int col, u_int uc, uint32_t attr)
266 {
267 	struct rasops_info *ri;
268 	int height, fs;
269 	int32_t *rp;
270 	u_char *fr;
271 
272 	/* Can't risk remaking the stamp if it's already in use */
273 	if (stamp_mutex++) {
274 		stamp_mutex--;
275 		return rasops8_putchar(cookie, row, col, uc, attr);
276 	}
277 
278 	ri = (struct rasops_info *)cookie;
279 
280 #ifdef RASOPS_CLIPPING
281 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
282 		stamp_mutex--;
283 		return 0;
284 	}
285 
286 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
287 		stamp_mutex--;
288 		return 0;
289 	}
290 #endif
291 
292 	/* Recompute stamp? */
293 	if (attr != stamp_attr)
294 		rasops8_makestamp(ri, attr);
295 
296 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
297 	height = ri->ri_font->fontheight;
298 
299 	if (uc == ' ') {
300 		while (height--) {
301 			int32_t c = stamp[0];
302 
303 			rp[0] = rp[1] = rp[2] = c;
304 			DELTA(rp, ri->ri_stride, int32_t *);
305 		}
306 	} else {
307 		uc -= ri->ri_font->firstchar;
308 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
309 		fs = ri->ri_font->stride;
310 
311 		while (height--) {
312 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
313 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
314 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
315 
316 			fr += fs;
317 			DELTA(rp, ri->ri_stride, int32_t *);
318 		}
319 	}
320 
321 	/* Do underline */
322 	if ((attr & WSATTR_UNDERLINE) != 0) {
323 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
324 		rp[0] = rp[1] = rp[2] = stamp[15];
325 	}
326 
327 	stamp_mutex--;
328 
329 	return 0;
330 }
331 
332 /*
333  * Put a single character. This is for 16-pixel wide fonts.
334  */
335 int
rasops8_putchar16(void * cookie,int row,int col,u_int uc,uint32_t attr)336 rasops8_putchar16(void *cookie, int row, int col, u_int uc, uint32_t attr)
337 {
338 	struct rasops_info *ri;
339 	int height, fs;
340 	int32_t *rp;
341 	u_char *fr;
342 
343 	/* Can't risk remaking the stamp if it's already in use */
344 	if (stamp_mutex++) {
345 		stamp_mutex--;
346 		return rasops8_putchar(cookie, row, col, uc, attr);
347 	}
348 
349 	ri = (struct rasops_info *)cookie;
350 
351 #ifdef RASOPS_CLIPPING
352 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
353 		stamp_mutex--;
354 		return 0;
355 	}
356 
357 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
358 		stamp_mutex--;
359 		return 0;
360 	}
361 #endif
362 
363 	/* Recompute stamp? */
364 	if (attr != stamp_attr)
365 		rasops8_makestamp(ri, attr);
366 
367 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
368 	height = ri->ri_font->fontheight;
369 
370 	if (uc == ' ') {
371 		while (height--)
372 			rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
373 	} else {
374 		uc -= ri->ri_font->firstchar;
375 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
376 		fs = ri->ri_font->stride;
377 
378 		while (height--) {
379 			rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
380 			rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
381 			rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
382 			rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
383 
384 			fr += fs;
385 			DELTA(rp, ri->ri_stride, int32_t *);
386 		}
387 	}
388 
389 	/* Do underline */
390 	if ((attr & WSATTR_UNDERLINE) != 0) {
391 		DELTA(rp, -(ri->ri_stride << 1), int32_t *);
392 		rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
393 	}
394 
395 	stamp_mutex--;
396 
397 	return 0;
398 }
399 #endif /* !RASOPS_SMALL */
400