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