1 /*	$OpenBSD: rasops4.c,v 1.7 2006/08/03 18:42:06 miod Exp $	*/
2 /*	$NetBSD: rasops4.c,v 1.4 2001/11/15 09:48:15 lukem 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  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/time.h>
43 #include <machine/endian.h>
44 
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/rasops/rasops.h>
48 #include <dev/rasops/rasops_masks.h>
49 
50 void	rasops4_copycols(void *, int, int, int, int);
51 void	rasops4_erasecols(void *, int, int, int, long);
52 void	rasops4_do_cursor(struct rasops_info *);
53 void	rasops4_putchar(void *, int, int col, u_int, long);
54 #ifndef RASOPS_SMALL
55 void	rasops4_putchar8(void *, int, int col, u_int, long);
56 void	rasops4_putchar12(void *, int, int col, u_int, long);
57 void	rasops4_putchar16(void *, int, int col, u_int, long);
58 void	rasops4_makestamp(struct rasops_info *, long);
59 
60 /*
61  * 4x1 stamp for optimized character blitting
62  */
63 static u_int16_t	stamp[16];
64 static long	stamp_attr;
65 static int	stamp_mutex;	/* XXX see note in README */
66 #endif
67 
68 /*
69  * Initialize rasops_info struct for this colordepth.
70  */
71 void
rasops4_init(ri)72 rasops4_init(ri)
73 	struct rasops_info *ri;
74 {
75 	rasops_masks_init();
76 
77 	switch (ri->ri_font->fontwidth) {
78 #ifndef RASOPS_SMALL
79 	case 8:
80 		ri->ri_ops.putchar = rasops4_putchar8;
81 		break;
82 	case 12:
83 		ri->ri_ops.putchar = rasops4_putchar12;
84 		break;
85 	case 16:
86 		ri->ri_ops.putchar = rasops4_putchar16;
87 		break;
88 #endif	/* !RASOPS_SMALL */
89 	default:
90 		panic("fontwidth not 8/12/16 or RASOPS_SMALL - fixme!");
91 		ri->ri_ops.putchar = rasops4_putchar;
92 		break;
93 	}
94 
95 	if ((ri->ri_font->fontwidth & 1) != 0) {
96 		ri->ri_ops.erasecols = rasops4_erasecols;
97 		ri->ri_ops.copycols = rasops4_copycols;
98 		ri->ri_do_cursor = rasops4_do_cursor;
99 	}
100 }
101 
102 #ifdef notyet
103 /*
104  * Paint a single character. This is the generic version, this is ugly.
105  */
106 void
rasops4_putchar(cookie,row,col,uc,attr)107 rasops4_putchar(cookie, row, col, uc, attr)
108 	void *cookie;
109 	int row, col;
110 	u_int uc;
111 	long attr;
112 {
113 	int height, width, fs, rs, fb, bg, fg, lmask, rmask;
114 	struct rasops_info *ri;
115 	int32_t *rp;
116 	u_char *fr;
117 
118 	ri = (struct rasops_info *)cookie;
119 
120 #ifdef RASOPS_CLIPPING
121 	/* Catches 'row < 0' case too */
122 	if ((unsigned)row >= (unsigned)ri->ri_rows)
123 		return;
124 
125 	if ((unsigned)col >= (unsigned)ri->ri_cols)
126 		return;
127 #endif
128 
129 	width = ri->ri_font->fontwidth << 1;
130 	height = ri->ri_font->fontheight;
131 	col *= width;
132 	rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
133 	col = col & 31;
134 	rs = ri->ri_stride;
135 
136 	bg = ri->ri_devcmap[(attr >> 16) & 0xf];
137 	fg = ri->ri_devcmap[(attr >> 24) & 0xf];
138 
139 	/* If fg and bg match this becomes a space character */
140 	if (fg == bg || uc == ' ') {
141 		uc = (u_int)-1;
142 		fr = 0;		/* shutup gcc */
143 		fs = 0;		/* shutup gcc */
144 	} else {
145 		uc -= ri->ri_font->firstchar;
146 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
147 		fs = ri->ri_font->stride;
148 	}
149 
150 	/* Single word, one mask */
151 	if ((col + width) <= 32) {
152 		rmask = rasops_pmask[col][width];
153 		lmask = ~rmask;
154 
155 		if (uc == (u_int)-1) {
156 			bg &= rmask;
157 
158 			while (height--) {
159 				*rp = (*rp & lmask) | bg;
160 				DELTA(rp, rs, int32_t *);
161 			}
162 		} else {
163 			while (height--) {
164 				/* get bits, mask */
165 				/* compose sl */
166 				/* mask sl */
167 				/* put word */
168 			}
169 		}
170 
171 		/* Do underline */
172 		if (attr & 1) {
173 			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
174 			*rp = (*rp & lmask) | (fg & rmask);
175 		}
176 	} else {
177 		lmask = ~rasops_lmask[col];
178 		rmask = ~rasops_rmask[(col + width) & 31];
179 
180 		if (uc == (u_int)-1) {
181 			bg = bg & ~lmask;
182 			width = bg & ~rmask;
183 
184 			while (height--) {
185 				rp[0] = (rp[0] & lmask) | bg;
186 				rp[1] = (rp[1] & rmask) | width;
187 				DELTA(rp, rs, int32_t *);
188 			}
189 		} else {
190 			width = 32 - col;
191 
192 			/* NOT fontbits if bg is white */
193 			while (height--) {
194 				fb = ~(fr[3] | (fr[2] << 8) |
195 				    (fr[1] << 16) | (fr[0] << 24));
196 
197 				rp[0] = (rp[0] & lmask)
198 				    | MBE((u_int)fb >> col);
199 
200 				rp[1] = (rp[1] & rmask)
201 				   | (MBE((u_int)fb << width) & ~rmask);
202 
203 				fr += fs;
204 				DELTA(rp, rs, int32_t *);
205 			}
206 		}
207 
208 		/* Do underline */
209 		if (attr & 1) {
210 			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
211 			rp[0] = (rp[0] & lmask) | (fg & ~lmask);
212 			rp[1] = (rp[1] & rmask) | (fg & ~rmask);
213 		}
214 	}
215 }
216 #endif
217 
218 /*
219  * Put a single character. This is the generic version.
220  */
221 void
rasops4_putchar(cookie,row,col,uc,attr)222 rasops4_putchar(cookie, row, col, uc, attr)
223 	void *cookie;
224 	int row, col;
225 	u_int uc;
226 	long attr;
227 {
228 
229 	/* XXX punt */
230 }
231 
232 #ifndef RASOPS_SMALL
233 /*
234  * Recompute the blitting stamp.
235  */
236 void
rasops4_makestamp(ri,attr)237 rasops4_makestamp(ri, attr)
238 	struct rasops_info *ri;
239 	long attr;
240 {
241 	int i, fg, bg;
242 
243 	fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xf;
244 	bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xf;
245 	stamp_attr = attr;
246 
247 	for (i = 0; i < 16; i++) {
248 #if BYTE_ORDER == LITTLE_ENDIAN
249 		stamp[i] =  (i & 1 ? fg : bg) << 8;
250 		stamp[i] |= (i & 2 ? fg : bg) << 12;
251 		stamp[i] |= (i & 4 ? fg : bg) << 0;
252 		stamp[i] |= (i & 8 ? fg : bg) << 4;
253 #else
254 		stamp[i] =  (i & 1 ? fg : bg) << 0;
255 		stamp[i] |= (i & 2 ? fg : bg) << 4;
256 		stamp[i] |= (i & 4 ? fg : bg) << 8;
257 		stamp[i] |= (i & 8 ? fg : bg) << 12;
258 #endif
259 	}
260 }
261 
262 /*
263  * Put a single character. This is for 8-pixel wide fonts.
264  */
265 void
rasops4_putchar8(cookie,row,col,uc,attr)266 rasops4_putchar8(cookie, row, col, uc, attr)
267 	void *cookie;
268 	int row, col;
269 	u_int uc;
270 	long attr;
271 {
272 	struct rasops_info *ri;
273 	int height, fs, rs;
274 	u_char *fr;
275 	u_int16_t *rp;
276 
277 	/* Can't risk remaking the stamp if it's already in use */
278 	if (stamp_mutex++) {
279 		stamp_mutex--;
280 		rasops4_putchar(cookie, row, col, uc, attr);
281 		return;
282 	}
283 
284 	ri = (struct rasops_info *)cookie;
285 
286 #ifdef RASOPS_CLIPPING
287 	/* Catches 'row < 0' case too */
288 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
289 		stamp_mutex--;
290 		return;
291 	}
292 
293 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
294 		stamp_mutex--;
295 		return;
296 	}
297 #endif
298 
299 	rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale);
300 	height = ri->ri_font->fontheight;
301 	rs = ri->ri_stride / sizeof(*rp);
302 
303 	/* Recompute stamp? */
304 	if (attr != stamp_attr)
305 		rasops4_makestamp(ri, attr);
306 
307 	if (uc == ' ') {
308 		u_int16_t c = stamp[0];
309 		while (height--) {
310 			rp[0] = c;
311 			rp[1] = c;
312 			rp += rs;
313 		}
314 	} else {
315 		uc -= ri->ri_font->firstchar;
316 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
317 		fs = ri->ri_font->stride;
318 
319 		while (height--) {
320 			rp[0] = stamp[(*fr >> 4) & 0xf];
321 			rp[1] = stamp[*fr & 0xf];
322 			fr += fs;
323 			rp += rs;
324 		}
325 	}
326 
327 	/* Do underline */
328 	if ((attr & 1) != 0) {
329 		rp -= (rs << 1);
330 		rp[0] = stamp[15];
331 		rp[1] = stamp[15];
332 	}
333 
334 	stamp_mutex--;
335 }
336 
337 /*
338  * Put a single character. This is for 12-pixel wide fonts.
339  */
340 void
rasops4_putchar12(cookie,row,col,uc,attr)341 rasops4_putchar12(cookie, row, col, uc, attr)
342 	void *cookie;
343 	int row, col;
344 	u_int uc;
345 	long attr;
346 {
347 	struct rasops_info *ri;
348 	int height, fs, rs;
349 	u_char *fr;
350 	u_int16_t *rp;
351 
352 	/* Can't risk remaking the stamp if it's already in use */
353 	if (stamp_mutex++) {
354 		stamp_mutex--;
355 		rasops4_putchar(cookie, row, col, uc, attr);
356 		return;
357 	}
358 
359 	ri = (struct rasops_info *)cookie;
360 
361 #ifdef RASOPS_CLIPPING
362 	/* Catches 'row < 0' case too */
363 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
364 		stamp_mutex--;
365 		return;
366 	}
367 
368 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
369 		stamp_mutex--;
370 		return;
371 	}
372 #endif
373 
374 	rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale);
375 	height = ri->ri_font->fontheight;
376 	rs = ri->ri_stride / sizeof(*rp);
377 
378 	/* Recompute stamp? */
379 	if (attr != stamp_attr)
380 		rasops4_makestamp(ri, attr);
381 
382 	if (uc == ' ') {
383 		u_int16_t c = stamp[0];
384 		while (height--) {
385 			rp[0] = c;
386 			rp[1] = c;
387 			rp[2] = c;
388 			rp += rs;
389 		}
390 	} else {
391 		uc -= ri->ri_font->firstchar;
392 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
393 		fs = ri->ri_font->stride;
394 
395 		while (height--) {
396 			rp[0] = stamp[(fr[0] >> 4) & 0xf];
397 			rp[1] = stamp[fr[0] & 0xf];
398 			rp[2] = stamp[(fr[1] >> 4) & 0xf];
399 			fr += fs;
400 			rp += rs;
401 		}
402 	}
403 
404 	/* Do underline */
405 	if ((attr & 1) != 0) {
406 		rp -= (rs << 1);
407 		rp[0] = stamp[15];
408 		rp[1] = stamp[15];
409 		rp[2] = stamp[15];
410 	}
411 
412 	stamp_mutex--;
413 }
414 
415 /*
416  * Put a single character. This is for 16-pixel wide fonts.
417  */
418 void
rasops4_putchar16(cookie,row,col,uc,attr)419 rasops4_putchar16(cookie, row, col, uc, attr)
420 	void *cookie;
421 	int row, col;
422 	u_int uc;
423 	long attr;
424 {
425 	struct rasops_info *ri;
426 	int height, fs, rs;
427 	u_char *fr;
428 	u_int16_t *rp;
429 
430 	/* Can't risk remaking the stamp if it's already in use */
431 	if (stamp_mutex++) {
432 		stamp_mutex--;
433 		rasops4_putchar(cookie, row, col, uc, attr);
434 		return;
435 	}
436 
437 	ri = (struct rasops_info *)cookie;
438 
439 #ifdef RASOPS_CLIPPING
440 	/* Catches 'row < 0' case too */
441 	if ((unsigned)row >= (unsigned)ri->ri_rows) {
442 		stamp_mutex--;
443 		return;
444 	}
445 
446 	if ((unsigned)col >= (unsigned)ri->ri_cols) {
447 		stamp_mutex--;
448 		return;
449 	}
450 #endif
451 
452 	rp = (u_int16_t *)(ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale);
453 	height = ri->ri_font->fontheight;
454 	rs = ri->ri_stride / sizeof(*rp);
455 
456 	/* Recompute stamp? */
457 	if (attr != stamp_attr)
458 		rasops4_makestamp(ri, attr);
459 
460 	if (uc == ' ') {
461 		u_int16_t c = stamp[0];
462 		while (height--) {
463 			rp[0] = c;
464 			rp[1] = c;
465 			rp[2] = c;
466 			rp[3] = c;
467 			rp += rs;
468 		}
469 	} else {
470 		uc -= ri->ri_font->firstchar;
471 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
472 		fs = ri->ri_font->stride;
473 
474 		while (height--) {
475 			rp[0] = stamp[(fr[0] >> 4) & 0xf];
476 			rp[1] = stamp[fr[0] & 0xf];
477 			rp[2] = stamp[(fr[1] >> 4) & 0xf];
478 			rp[3] = stamp[fr[1] & 0xf];
479 			fr += fs;
480 			rp += rs;
481 		}
482 	}
483 
484 	/* Do underline */
485 	if ((attr & 1) != 0) {
486 		rp -= (rs << 1);
487 		rp[0] = stamp[15];
488 		rp[1] = stamp[15];
489 		rp[2] = stamp[15];
490 		rp[3] = stamp[15];
491 	}
492 
493 	stamp_mutex--;
494 }
495 #endif	/* !RASOPS_SMALL */
496 
497 /*
498  * Grab routines common to depths where (bpp < 8)
499  */
500 #define NAME(ident)	rasops4_##ident
501 #define PIXEL_SHIFT	2
502 
503 #include <dev/rasops/rasops_bitops.h>
504