1/* $NetBSD: rasops1.c,v 1.23 2010/05/04 04:57:34 macallan Exp $ */
2
3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.23 2010/05/04 04:57:34 macallan Exp $");
34
35#include "opt_rasops.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/time.h>
40#include <machine/endian.h>
41
42#include <dev/wscons/wsdisplayvar.h>
43#include <dev/wscons/wsconsio.h>
44#include <dev/rasops/rasops.h>
45#include <dev/rasops/rasops_masks.h>
46
47static void rasops1_copycols(void *, int, int, int, int);
48static void rasops1_erasecols(void *, int, int, int, long);
49static void rasops1_do_cursor(struct rasops_info *);
50static void rasops1_putchar(void *, int, int col, u_int, long);
51#ifndef RASOPS_SMALL
52static void rasops1_putchar8(void *, int, int col, u_int, long);
53static void rasops1_putchar16(void *, int, int col, u_int, long);
54#endif
55
56/*
57 * Initialize rasops_info struct for this colordepth.
58 */
59void
60rasops1_init(struct rasops_info *ri)
61{
62
63 switch (ri->ri_font->fontwidth) {
64#ifndef RASOPS_SMALL
65 case 8:
66 ri->ri_ops.putchar = rasops1_putchar8;
67 break;
68 case 16:
69 ri->ri_ops.putchar = rasops1_putchar16;
70 break;
71#endif
72 default:
73 ri->ri_ops.putchar = rasops1_putchar;
74 break;
75 }
76
77 if ((ri->ri_font->fontwidth & 7) != 0) {
78 ri->ri_ops.erasecols = rasops1_erasecols;
79 ri->ri_ops.copycols = rasops1_copycols;
80 ri->ri_do_cursor = rasops1_do_cursor;
81 }
82}
83
84/*
85 * Paint a single character. This is the generic version, this is ugly.
86 */
87static void
88rasops1_putchar(void *cookie, int row, int col, u_int uc, long attr)
89{
90 u_int fs, rs, fb, bg, fg, lmask, rmask;
91 u_int32_t height, width;
92 struct rasops_info *ri = (struct rasops_info *)cookie;
93 struct wsdisplay_font *font = PICK_FONT(ri, uc);
94 int32_t *rp, *hrp = NULL, tmp, tmp2;
95 u_char *fr;
96
97#ifdef RASOPS_CLIPPING
98 /* Catches 'row < 0' case too */
99 if ((unsigned)row >= (unsigned)ri->ri_rows)
100 return;
101
102 if ((unsigned)col >= (unsigned)ri->ri_cols)
103 return;
104#endif
105
106 col *= ri->ri_font->fontwidth;
107 rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
108 if (ri->ri_hwbits)
109 hrp = (int32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
110 ((col >> 3) & ~3));
111 height = font->fontheight;
112 width = font->fontwidth;
113 col = col & 31;
114 rs = ri->ri_stride;
115
116 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
117 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
118
119 /* If fg and bg match this becomes a space character */
120 if (fg == bg || uc == ' ') {
121 uc = (u_int)-1;
122 fr = 0; /* shutup gcc */
123 fs = 0; /* shutup gcc */
124 } else {
125 uc -= font->firstchar;
126 fr = (u_char *)font->data + uc * ri->ri_fontscale;
127 fs = font->stride;
128 }
129
130 /* Single word, one mask */
131 if ((col + width) <= 32) {
132 rmask = rasops_pmask[col][width];
133 lmask = ~rmask;
134
135 if (uc == (u_int)-1) {
136 bg &= rmask;
137
138 while (height--) {
139 tmp = (*rp & lmask) | bg;
140 *rp = tmp;
141 DELTA(rp, rs, int32_t *);
142 if (ri->ri_hwbits) {
143 *hrp = tmp;
144 DELTA(hrp, rs, int32_t *);
145 }
146 }
147 } else {
148 /* NOT fontbits if bg is white */
149 if (bg) {
150 while (height--) {
151 fb = ~(fr[3] | (fr[2] << 8) |
152 (fr[1] << 16) | (fr[0] << 24));
153 tmp = (*rp & lmask)
154 | (MBE(fb >> col) & rmask);
155 *rp = tmp;
156
157 fr += fs;
158 DELTA(rp, rs, int32_t *);
159 if (ri->ri_hwbits) {
160 *hrp = tmp;
161 DELTA(hrp, rs, int32_t *);
162 }
163 }
164 } else {
165 while (height--) {
166 fb = (fr[3] | (fr[2] << 8) |
167 (fr[1] << 16) | (fr[0] << 24));
168 tmp = (*rp & lmask)
169 | (MBE(fb >> col) & rmask);
170 *rp = tmp;
171
172 fr += fs;
173 DELTA(rp, rs, int32_t *);
174 if (ri->ri_hwbits) {
175 *hrp = tmp;
176 DELTA(hrp, rs, int32_t *);
177 }
178 }
179 }
180 }
181
182 /* Do underline */
183 if ((attr & 1) != 0) {
184 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
185 tmp = (*rp & lmask) | (fg & rmask);
186 *rp = tmp;
187 if (ri->ri_hwbits) {
188 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
189 *hrp = tmp;
190 }
191 }
192 } else {
193 lmask = ~rasops_lmask[col];
194 rmask = ~rasops_rmask[(col + width) & 31];
195
196 if (uc == (u_int)-1) {
197 width = bg & ~rmask;
198 bg = bg & ~lmask;
199
200 while (height--) {
201 tmp = (rp[0] & lmask) | bg;
202 tmp2 = (rp[1] & rmask) | width;
203 rp[0] = tmp;
204 rp[1] = tmp2;
205 DELTA(rp, rs, int32_t *);
206 if (ri->ri_hwbits) {
207 hrp[0] = tmp;
208 hrp[1] = tmp2;
209 DELTA(hrp, rs, int32_t *);
210 }
211 }
212 } else {
213 width = 32 - col;
214
215 /* NOT fontbits if bg is white */
216 if (bg) {
217 while (height--) {
218 fb = ~(fr[3] | (fr[2] << 8) |
219 (fr[1] << 16) | (fr[0] << 24));
220
221 tmp = (rp[0] & lmask)
222 | MBE((u_int)fb >> col);
223
224 tmp2 = (rp[1] & rmask)
225 | (MBE((u_int)fb << width) & ~rmask);
226 rp[0] = tmp;
227 rp[1] = tmp2;
228 fr += fs;
229 DELTA(rp, rs, int32_t *);
230 if (ri->ri_hwbits) {
231 hrp[0] = tmp;
232 hrp[1] = tmp2;
233 DELTA(hrp, rs, int32_t *);
234 }
235 }
236 } else {
237 while (height--) {
238 fb = (fr[3] | (fr[2] << 8) |
239 (fr[1] << 16) | (fr[0] << 24));
240
241 tmp = (rp[0] & lmask)
242 | MBE(fb >> col);
243
244 tmp2 = (rp[1] & rmask)
245 | (MBE(fb << width) & ~rmask);
246 rp[0] = tmp;
247 rp[1] = tmp2;
248 fr += fs;
249 DELTA(rp, rs, int32_t *);
250 if (ri->ri_hwbits) {
251 hrp[0] = tmp;
252 hrp[1] = tmp2;
253 DELTA(hrp, rs, int32_t *);
254 }
255 }
256 }
257 }
258
259 /* Do underline */
260 if ((attr & 1) != 0) {
261 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
262 tmp = (rp[0] & lmask) | (fg & ~lmask);
263 tmp2 = (rp[1] & rmask) | (fg & ~rmask);
264 rp[0] = tmp;
265 rp[1] = tmp2;
266 if (ri->ri_hwbits) {
267 DELTA(hrp, -(ri->ri_stride << 1), int32_t *);
268 hrp[0] = tmp;
269 hrp[1] = tmp2;
270 }
271 }
272 }
273}
274
275#ifndef RASOPS_SMALL
276/*
277 * Paint a single character. This is for 8-pixel wide fonts.
278 */
279static void
280rasops1_putchar8(void *cookie, int row, int col, u_int uc, long attr)
281{
282 int height, fs, rs, bg, fg;
283 struct rasops_info *ri = (struct rasops_info *)cookie;
284 struct wsdisplay_font *font = PICK_FONT(ri, uc);
285 u_char *fr, *rp, *hrp = NULL;
286
287#ifdef RASOPS_CLIPPING
288 /* Catches 'row < 0' case too */
289 if ((unsigned)row >= (unsigned)ri->ri_rows)
290 return;
291
292 if ((unsigned)col >= (unsigned)ri->ri_cols)
293 return;
294#endif
295
296 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
297 if (ri->ri_hwbits)
298 hrp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
299 height = font->fontheight;
300 rs = ri->ri_stride;
301
302 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
303 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
304
305 /* If fg and bg match this becomes a space character */
306 if (fg == bg || uc == ' ') {
307 while (height--) {
308 *rp = bg;
309 rp += rs;
310 if (ri->ri_hwbits) {
311 *hrp = bg;
312 hrp += rs;
313 }
314 }
315 } else {
316 uc -= font->firstchar;
317 fr = (u_char *)font->data + uc * ri->ri_fontscale;
318 fs = font->stride;
319
320 /* NOT fontbits if bg is white */
321 if (bg) {
322 while (height--) {
323 *rp = ~*fr;
324 rp += rs;
325 if (ri->ri_hwbits) {
326 *hrp = ~*fr;
327 hrp += rs;
328 }
329 fr += fs;
330
331 }
332 } else {
333 while (height--) {
334 *rp = *fr;
335 rp += rs;
336 if (ri->ri_hwbits) {
337 *hrp = *fr;
338 hrp += rs;
339 }
340 fr += fs;
341 }
342 }
343
344 }
345
346 /* Do underline */
347 if ((attr & 1) != 0) {
348 rp[-(ri->ri_stride << 1)] = fg;
349 if (ri->ri_hwbits) {
350 hrp[-(ri->ri_stride << 1)] = fg;
351 }
352 }
353}
354
355/*
356 * Paint a single character. This is for 16-pixel wide fonts.
357 */
358static void
359rasops1_putchar16(void *cookie, int row, int col, u_int uc, long attr)
360{
361 int height, fs, rs, bg, fg;
362 struct rasops_info *ri = (struct rasops_info *)cookie;
363 struct wsdisplay_font *font = PICK_FONT(ri, uc);
364 u_char *fr, *rp, *hrp = NULL;
365
366#ifdef RASOPS_CLIPPING
367 /* Catches 'row < 0' case too */
368 if ((unsigned)row >= (unsigned)ri->ri_rows)
369 return;
370
371 if ((unsigned)col >= (unsigned)ri->ri_cols)
372 return;
373#endif
374
375 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
376 if (ri->ri_hwbits)
377 hrp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
378 height = font->fontheight;
379 rs = ri->ri_stride;
380
381 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
382 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
383
384 /* If fg and bg match this becomes a space character */
385 if (fg == bg || uc == ' ') {
386 while (height--) {
387 /* XXX alignment?! */
388 *(int16_t *)rp = bg;
389 rp += rs;
390 if (ri->ri_hwbits) {
391 *(int16_t *)hrp = bg;
392 hrp += rs;
393 }
394 }
395 } else {
396 uc -= font->firstchar;
397 fr = (u_char *)font->data + uc * ri->ri_fontscale;
398 fs = font->stride;
399
400 /* NOT fontbits if bg is white */
401 if (bg) {
402 while (height--) {
403 rp[0] = ~fr[0];
404 rp[1] = ~fr[1];
405 rp += rs;
406 if (ri->ri_hwbits) {
407 hrp[0] = ~fr[0];
408 hrp[1] = ~fr[1];
409 hrp += rs;
410 }
411 fr += fs;
412 }
413 } else {
414 while (height--) {
415 rp[0] = fr[0];
416 rp[1] = fr[1];
417 rp += rs;
418 if (ri->ri_hwbits) {
419 hrp[0] = fr[0];
420 hrp[1] = fr[1];
421 hrp += rs;
422 }
423 fr += fs;
424 }
425 }
426 }
427
428 /* Do underline */
429 if ((attr & 1) != 0) {
430 /* XXX alignment?! */
431 *(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
432 if (ri->ri_hwbits) {
433 *(int16_t *)(hrp - (ri->ri_stride << 1)) = fg;
434 }
435 }
436}
437#endif /* !RASOPS_SMALL */
438
439/*
440 * Grab routines common to depths where (bpp < 8)
441 */
442#define NAME(ident) rasops1_##ident
443#define PIXEL_SHIFT 0
444
445#include <dev/rasops/rasops_bitops.h>
446