xref: /openbsd/sys/dev/rasops/rasops1.c (revision 8529ddd3)
1 /*	$OpenBSD: rasops1.c,v 1.9 2014/12/19 22:44:58 guenther Exp $	*/
2 /*	$NetBSD: rasops1.c,v 1.11 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 #include <dev/rasops/rasops_masks.h>
42 
43 int	rasops1_copycols(void *, int, int, int, int);
44 int	rasops1_erasecols(void *, int, int, int, long);
45 int	rasops1_do_cursor(struct rasops_info *);
46 int	rasops1_putchar(void *, int, int col, u_int, long);
47 #ifndef RASOPS_SMALL
48 int	rasops1_putchar8(void *, int, int col, u_int, long);
49 int	rasops1_putchar16(void *, int, int col, u_int, long);
50 #endif
51 
52 /*
53  * Initialize rasops_info struct for this colordepth.
54  */
55 void
56 rasops1_init(struct rasops_info *ri)
57 {
58 	rasops_masks_init();
59 
60 	switch (ri->ri_font->fontwidth) {
61 #ifndef RASOPS_SMALL
62 	case 8:
63 		ri->ri_ops.putchar = rasops1_putchar8;
64 		break;
65 	case 16:
66 		ri->ri_ops.putchar = rasops1_putchar16;
67 		break;
68 #endif
69 	default:
70 		ri->ri_ops.putchar = rasops1_putchar;
71 		break;
72 	}
73 
74 	if ((ri->ri_font->fontwidth & 7) != 0) {
75 		ri->ri_ops.erasecols = rasops1_erasecols;
76 		ri->ri_ops.copycols = rasops1_copycols;
77 		ri->ri_do_cursor = rasops1_do_cursor;
78 	}
79 }
80 
81 /*
82  * Paint a single character. This is the generic version, this is ugly.
83  */
84 int
85 rasops1_putchar(void *cookie, int row, int col, u_int uc, long attr)
86 {
87 	u_int fs, rs, fb, bg, fg, lmask, rmask;
88 	u_int32_t height, width;
89 	struct rasops_info *ri;
90 	int32_t *rp;
91 	u_char *fr;
92 
93 	ri = (struct rasops_info *)cookie;
94 
95 #ifdef RASOPS_CLIPPING
96 	/* Catches 'row < 0' case too */
97 	if ((unsigned)row >= (unsigned)ri->ri_rows)
98 		return 0;
99 
100 	if ((unsigned)col >= (unsigned)ri->ri_cols)
101 		return 0;
102 #endif
103 
104 	col *= ri->ri_font->fontwidth;
105 	rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
106 	height = ri->ri_font->fontheight;
107 	width = ri->ri_font->fontwidth;
108 	col = col & 31;
109 	rs = ri->ri_stride;
110 
111 	bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
112 	fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
113 
114 	/* If fg and bg match this becomes a space character */
115 	if (fg == bg || uc == ' ') {
116 		uc = (u_int)-1;
117 		fr = 0;		/* shutup gcc */
118 		fs = 0;		/* shutup gcc */
119 	} else {
120 		uc -= ri->ri_font->firstchar;
121 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
122 		fs = ri->ri_font->stride;
123 	}
124 
125 	/* Single word, one mask */
126 	if ((col + width) <= 32) {
127 		rmask = rasops_pmask[col][width];
128 		lmask = ~rmask;
129 
130 		if (uc == (u_int)-1) {
131 			bg &= rmask;
132 
133 			while (height--) {
134 				*rp = (*rp & lmask) | bg;
135 				DELTA(rp, rs, int32_t *);
136 			}
137 		} else {
138 			/* NOT fontbits if bg is white */
139 			if (bg) {
140 				while (height--) {
141 					fb = ~(fr[3] | (fr[2] << 8) |
142 					    (fr[1] << 16) | (fr[0] << 24));
143 					*rp = (*rp & lmask)
144 					    | (MBE(fb >> col) & rmask);
145 
146 					fr += fs;
147 					DELTA(rp, rs, int32_t *);
148 				}
149 			} else {
150 				while (height--) {
151 					fb = (fr[3] | (fr[2] << 8) |
152 					    (fr[1] << 16) | (fr[0] << 24));
153 					*rp = (*rp & lmask)
154 					    | (MBE(fb >> col) & rmask);
155 
156 					fr += fs;
157 					DELTA(rp, rs, int32_t *);
158 				}
159 			}
160 		}
161 
162 		/* Do underline */
163 		if ((attr & 1) != 0) {
164 			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
165 			*rp = (*rp & lmask) | (fg & rmask);
166 		}
167 	} else {
168 		lmask = ~rasops_lmask[col];
169 		rmask = ~rasops_rmask[(col + width) & 31];
170 
171 		if (uc == (u_int)-1) {
172 			width = bg & ~rmask;
173 			bg = bg & ~lmask;
174 
175 			while (height--) {
176 				rp[0] = (rp[0] & lmask) | bg;
177 				rp[1] = (rp[1] & rmask) | width;
178 				DELTA(rp, rs, int32_t *);
179 			}
180 		} else {
181 			width = 32 - col;
182 
183 			/* NOT fontbits if bg is white */
184 			if (bg) {
185 				while (height--) {
186 					fb = ~(fr[3] | (fr[2] << 8) |
187 					    (fr[1] << 16) | (fr[0] << 24));
188 
189 					rp[0] = (rp[0] & lmask)
190 					    | MBE((u_int)fb >> col);
191 
192 					rp[1] = (rp[1] & rmask)
193 					    | (MBE((u_int)fb << width) & ~rmask);
194 
195 					fr += fs;
196 					DELTA(rp, rs, int32_t *);
197 				}
198 			} else {
199 				while (height--) {
200 					fb = (fr[3] | (fr[2] << 8) |
201 					    (fr[1] << 16) | (fr[0] << 24));
202 
203 					rp[0] = (rp[0] & lmask)
204 					    | MBE(fb >> col);
205 
206 					rp[1] = (rp[1] & rmask)
207 					    | (MBE(fb << width) & ~rmask);
208 
209 					fr += fs;
210 					DELTA(rp, rs, int32_t *);
211 				}
212 			}
213 		}
214 
215 		/* Do underline */
216 		if ((attr & 1) != 0) {
217 			DELTA(rp, -(ri->ri_stride << 1), int32_t *);
218 			rp[0] = (rp[0] & lmask) | (fg & ~lmask);
219 			rp[1] = (rp[1] & rmask) | (fg & ~rmask);
220 		}
221 	}
222 
223 	return 0;
224 }
225 
226 #ifndef RASOPS_SMALL
227 /*
228  * Paint a single character. This is for 8-pixel wide fonts.
229  */
230 int
231 rasops1_putchar8(void *cookie, int row, int col, u_int uc, long attr)
232 {
233 	int height, fs, rs, bg, fg;
234 	struct rasops_info *ri;
235 	u_char *fr, *rp;
236 
237 	ri = (struct rasops_info *)cookie;
238 
239 #ifdef RASOPS_CLIPPING
240 	/* Catches 'row < 0' case too */
241 	if ((unsigned)row >= (unsigned)ri->ri_rows)
242 		return 0;
243 
244 	if ((unsigned)col >= (unsigned)ri->ri_cols)
245 		return 0;
246 #endif
247 
248 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
249 	height = ri->ri_font->fontheight;
250 	rs = ri->ri_stride;
251 
252 	bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
253 	fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
254 
255 	/* If fg and bg match this becomes a space character */
256 	if (fg == bg || uc == ' ') {
257 		while (height--) {
258 			*rp = bg;
259 			rp += rs;
260 		}
261 	} else {
262 		uc -= ri->ri_font->firstchar;
263 		fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
264 		fs = ri->ri_font->stride;
265 
266 		/* NOT fontbits if bg is white */
267 		if (bg) {
268 			while (height--) {
269 				*rp = ~*fr;
270 				fr += fs;
271 				rp += rs;
272 			}
273 		} else {
274 			while (height--) {
275 				*rp = *fr;
276 				fr += fs;
277 				rp += rs;
278 			}
279 		}
280 
281 	}
282 
283 	/* Do underline */
284 	if ((attr & 1) != 0)
285 		rp[-(ri->ri_stride << 1)] = fg;
286 
287 	return 0;
288 }
289 
290 /*
291  * Paint a single character. This is for 16-pixel wide fonts.
292  */
293 int
294 rasops1_putchar16(void *cookie, int row, int col, u_int uc, long attr)
295 {
296 	int height, fs, rs, bg, fg;
297 	struct rasops_info *ri;
298 	u_char *fr, *rp;
299 
300 	ri = (struct rasops_info *)cookie;
301 
302 #ifdef RASOPS_CLIPPING
303 	/* Catches 'row < 0' case too */
304 	if ((unsigned)row >= (unsigned)ri->ri_rows)
305 		return 0;
306 
307 	if ((unsigned)col >= (unsigned)ri->ri_cols)
308 		return 0;
309 #endif
310 
311 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
312 	height = ri->ri_font->fontheight;
313 	rs = ri->ri_stride;
314 
315 	bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
316 	fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
317 
318 	/* If fg and bg match this becomes a space character */
319 	if (fg == bg || uc == ' ') {
320 		while (height--) {
321 			*(int16_t *)rp = bg;
322 			rp += rs;
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 		/* NOT fontbits if bg is white */
330 		if (bg) {
331 			while (height--) {
332 				rp[0] = ~fr[0];
333 				rp[1] = ~fr[1];
334 				fr += fs;
335 				rp += rs;
336 			}
337 		} else {
338 			while (height--) {
339 				rp[0] = fr[0];
340 				rp[1] = fr[1];
341 				fr += fs;
342 				rp += rs;
343 			}
344 		}
345 	}
346 
347 	/* Do underline */
348 	if ((attr & 1) != 0)
349 		*(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
350 
351 	return 0;
352 }
353 #endif	/* !RASOPS_SMALL */
354 
355 /*
356  * Grab routines common to depths where (bpp < 8)
357  */
358 #define NAME(ident)	rasops1_##ident
359 #define PIXEL_SHIFT	0
360 
361 #include <dev/rasops/rasops_bitops.h>
362