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