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