Line data Source code
1 : /* $OpenBSD: rasops8.c,v 1.10 2010/08/28 12:48:14 miod 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, long attr);
42 : #ifndef RASOPS_SMALL
43 : int rasops8_putchar8(void *, int, int, u_int, long attr);
44 : int rasops8_putchar12(void *, int, int, u_int, long attr);
45 : int rasops8_putchar16(void *, int, int, u_int, long attr);
46 : void rasops8_makestamp(struct rasops_info *ri, long);
47 :
48 : /*
49 : * 4x1 stamp for optimized character blitting
50 : */
51 : static int32_t stamp[16];
52 : static long 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
71 0 : rasops8_init(struct rasops_info *ri)
72 : {
73 :
74 0 : switch (ri->ri_font->fontwidth) {
75 : #ifndef RASOPS_SMALL
76 : case 8:
77 0 : ri->ri_ops.putchar = rasops8_putchar8;
78 0 : break;
79 : case 12:
80 0 : ri->ri_ops.putchar = rasops8_putchar12;
81 0 : break;
82 : case 16:
83 0 : ri->ri_ops.putchar = rasops8_putchar16;
84 0 : break;
85 : #endif /* !RASOPS_SMALL */
86 : default:
87 0 : ri->ri_ops.putchar = rasops8_putchar;
88 0 : break;
89 : }
90 0 : }
91 :
92 : /*
93 : * Put a single character.
94 : */
95 : int
96 0 : rasops8_putchar(void *cookie, int row, int col, u_int uc, long attr)
97 : {
98 : int width, height, cnt, fs, fb;
99 0 : u_char *dp, *rp, *fr, clr[2];
100 : struct rasops_info *ri;
101 :
102 0 : 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 0 : rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
113 :
114 0 : height = ri->ri_font->fontheight;
115 0 : width = ri->ri_font->fontwidth;
116 0 : clr[0] = (u_char)ri->ri_devcmap[(attr >> 16) & 0xf];
117 0 : clr[1] = (u_char)ri->ri_devcmap[(attr >> 24) & 0xf];
118 :
119 0 : if (uc == ' ') {
120 0 : u_char c = clr[0];
121 :
122 0 : while (height--) {
123 : dp = rp;
124 0 : rp += ri->ri_stride;
125 :
126 0 : for (cnt = width; cnt; cnt--)
127 0 : *dp++ = c;
128 : }
129 0 : } else {
130 0 : uc -= ri->ri_font->firstchar;
131 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
132 0 : fs = ri->ri_font->stride;
133 :
134 0 : while (height--) {
135 : dp = rp;
136 0 : fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
137 0 : fr += fs;
138 0 : rp += ri->ri_stride;
139 :
140 0 : for (cnt = width; cnt; cnt--) {
141 0 : *dp++ = clr[(fb >> 31) & 1];
142 0 : fb <<= 1;
143 : }
144 : }
145 : }
146 :
147 : /* Do underline */
148 0 : if ((attr & 1) != 0) {
149 0 : u_char c = clr[1];
150 :
151 0 : rp -= (ri->ri_stride << 1);
152 :
153 0 : while (width--)
154 0 : *rp++ = c;
155 0 : }
156 :
157 0 : return 0;
158 0 : }
159 :
160 : #ifndef RASOPS_SMALL
161 : /*
162 : * Recompute the 4x1 blitting stamp.
163 : */
164 : void
165 0 : rasops8_makestamp(struct rasops_info *ri, long attr)
166 : {
167 : int32_t fg, bg;
168 : int i;
169 :
170 0 : fg = ri->ri_devcmap[(attr >> 24) & 0xf] & 0xff;
171 0 : bg = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xff;
172 0 : stamp_attr = attr;
173 :
174 0 : for (i = 0; i < 16; i++) {
175 : #if BYTE_ORDER == LITTLE_ENDIAN
176 0 : stamp[i] = (i & 8 ? fg : bg);
177 0 : stamp[i] |= ((i & 4 ? fg : bg) << 8);
178 0 : stamp[i] |= ((i & 2 ? fg : bg) << 16);
179 0 : 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 0 : }
192 :
193 : /*
194 : * Put a single character. This is for 8-pixel wide fonts.
195 : */
196 : int
197 0 : rasops8_putchar8(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
206 0 : stamp_mutex--;
207 0 : return rasops8_putchar(cookie, row, col, uc, attr);
208 : }
209 :
210 0 : 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 0 : if (attr != stamp_attr)
226 0 : rasops8_makestamp(ri, attr);
227 :
228 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
229 0 : height = ri->ri_font->fontheight;
230 :
231 0 : if (uc == ' ') {
232 0 : while (height--) {
233 0 : rp[0] = rp[1] = stamp[0];
234 0 : DELTA(rp, ri->ri_stride, int32_t *);
235 : }
236 : } else {
237 0 : uc -= ri->ri_font->firstchar;
238 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
239 0 : fs = ri->ri_font->stride;
240 :
241 0 : while (height--) {
242 0 : rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
243 0 : rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
244 :
245 0 : fr += fs;
246 0 : DELTA(rp, ri->ri_stride, int32_t *);
247 : }
248 : }
249 :
250 : /* Do underline */
251 0 : if ((attr & 1) != 0) {
252 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
253 0 : rp[0] = rp[1] = stamp[15];
254 0 : }
255 :
256 0 : stamp_mutex--;
257 :
258 0 : return 0;
259 0 : }
260 :
261 : /*
262 : * Put a single character. This is for 12-pixel wide fonts.
263 : */
264 : int
265 0 : rasops8_putchar12(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
274 0 : stamp_mutex--;
275 0 : return rasops8_putchar(cookie, row, col, uc, attr);
276 : }
277 :
278 0 : 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 0 : if (attr != stamp_attr)
294 0 : rasops8_makestamp(ri, attr);
295 :
296 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
297 0 : height = ri->ri_font->fontheight;
298 :
299 0 : if (uc == ' ') {
300 0 : while (height--) {
301 0 : int32_t c = stamp[0];
302 :
303 0 : rp[0] = rp[1] = rp[2] = c;
304 0 : DELTA(rp, ri->ri_stride, int32_t *);
305 : }
306 : } else {
307 0 : uc -= ri->ri_font->firstchar;
308 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
309 0 : fs = ri->ri_font->stride;
310 :
311 0 : while (height--) {
312 0 : rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
313 0 : rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
314 0 : rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
315 :
316 0 : fr += fs;
317 0 : DELTA(rp, ri->ri_stride, int32_t *);
318 : }
319 : }
320 :
321 : /* Do underline */
322 0 : if ((attr & 1) != 0) {
323 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
324 0 : rp[0] = rp[1] = rp[2] = stamp[15];
325 0 : }
326 :
327 0 : stamp_mutex--;
328 :
329 0 : return 0;
330 0 : }
331 :
332 : /*
333 : * Put a single character. This is for 16-pixel wide fonts.
334 : */
335 : int
336 0 : rasops8_putchar16(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
345 0 : stamp_mutex--;
346 0 : return rasops8_putchar(cookie, row, col, uc, attr);
347 : }
348 :
349 0 : 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 0 : if (attr != stamp_attr)
365 0 : rasops8_makestamp(ri, attr);
366 :
367 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
368 0 : height = ri->ri_font->fontheight;
369 :
370 0 : if (uc == ' ') {
371 0 : while (height--)
372 0 : rp[0] = rp[1] = rp[2] = rp[3] = stamp[0];
373 : } else {
374 0 : uc -= ri->ri_font->firstchar;
375 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
376 0 : fs = ri->ri_font->stride;
377 :
378 0 : while (height--) {
379 0 : rp[0] = STAMP_READ(STAMP_SHIFT(fr[0], 1) & STAMP_MASK);
380 0 : rp[1] = STAMP_READ(STAMP_SHIFT(fr[0], 0) & STAMP_MASK);
381 0 : rp[2] = STAMP_READ(STAMP_SHIFT(fr[1], 1) & STAMP_MASK);
382 0 : rp[3] = STAMP_READ(STAMP_SHIFT(fr[1], 0) & STAMP_MASK);
383 :
384 0 : fr += fs;
385 0 : DELTA(rp, ri->ri_stride, int32_t *);
386 : }
387 : }
388 :
389 : /* Do underline */
390 0 : if ((attr & 1) != 0) {
391 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
392 0 : rp[0] = rp[1] = rp[2] = rp[3] = stamp[15];
393 0 : }
394 :
395 0 : stamp_mutex--;
396 :
397 0 : return 0;
398 0 : }
399 : #endif /* !RASOPS_SMALL */
|