Line data Source code
1 : /* $OpenBSD: rasops15.c,v 1.8 2010/08/28 12:48:14 miod 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, long attr);
42 : #ifndef RASOPS_SMALL
43 : int rasops15_putchar8(void *, int, int, u_int, long attr);
44 : int rasops15_putchar12(void *, int, int, u_int, long attr);
45 : int rasops15_putchar16(void *, int, int, u_int, long attr);
46 : void rasops15_makestamp(struct rasops_info *, long);
47 :
48 : /*
49 : * (2x2)x1 stamp for optimized character blitting
50 : */
51 : static int32_t stamp[32];
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 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
72 0 : rasops15_init(struct rasops_info *ri)
73 : {
74 :
75 0 : switch (ri->ri_font->fontwidth) {
76 : #ifndef RASOPS_SMALL
77 : case 8:
78 0 : ri->ri_ops.putchar = rasops15_putchar8;
79 0 : break;
80 :
81 : case 12:
82 0 : ri->ri_ops.putchar = rasops15_putchar12;
83 0 : break;
84 :
85 : case 16:
86 0 : ri->ri_ops.putchar = rasops15_putchar16;
87 0 : break;
88 : #endif /* !RASOPS_SMALL */
89 : default:
90 0 : ri->ri_ops.putchar = rasops15_putchar;
91 0 : break;
92 : }
93 :
94 0 : if (ri->ri_rnum == 0) {
95 0 : ri->ri_rnum = 5;
96 0 : ri->ri_rpos = 0;
97 0 : ri->ri_gnum = 5 + (ri->ri_depth == 16);
98 0 : ri->ri_gpos = 5;
99 0 : ri->ri_bnum = 5;
100 0 : ri->ri_bpos = 10 + (ri->ri_depth == 16);
101 0 : }
102 0 : }
103 :
104 : /*
105 : * Paint a single character.
106 : */
107 : int
108 0 : rasops15_putchar(void *cookie, int row, int col, u_int uc, long attr)
109 : {
110 0 : int fb, width, height, cnt, clr[2];
111 : struct rasops_info *ri;
112 : u_char *dp, *rp, *fr;
113 :
114 0 : 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 0 : rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
126 0 : height = ri->ri_font->fontheight;
127 0 : width = ri->ri_font->fontwidth;
128 :
129 0 : clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
130 0 : clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
131 :
132 0 : if (uc == ' ') {
133 0 : int16_t c = (int16_t)clr[0];
134 0 : while (height--) {
135 : dp = rp;
136 0 : rp += ri->ri_stride;
137 :
138 0 : for (cnt = width; cnt; cnt--) {
139 0 : *(int16_t *)dp = c;
140 0 : dp += 2;
141 : }
142 : }
143 0 : } else {
144 0 : uc -= ri->ri_font->firstchar;
145 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
146 :
147 0 : while (height--) {
148 : dp = rp;
149 0 : fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) | (fr[0] << 24);
150 0 : fr += ri->ri_font->stride;
151 0 : rp += ri->ri_stride;
152 :
153 0 : for (cnt = width; cnt; cnt--) {
154 0 : *(int16_t *)dp = (int16_t)clr[(fb >> 31) & 1];
155 0 : fb <<= 1;
156 0 : dp += 2;
157 : }
158 : }
159 : }
160 :
161 : /* Do underline */
162 0 : if ((attr & 1) != 0) {
163 0 : int16_t c = (int16_t)clr[1];
164 0 : rp -= ri->ri_stride << 1;
165 :
166 0 : while (width--) {
167 0 : *(int16_t *)rp = c;
168 0 : rp += 2;
169 : }
170 0 : }
171 :
172 0 : return 0;
173 0 : }
174 :
175 : #ifndef RASOPS_SMALL
176 : /*
177 : * Recompute the (2x2)x1 blitting stamp.
178 : */
179 : void
180 0 : rasops15_makestamp(struct rasops_info *ri, long attr)
181 : {
182 : int32_t fg, bg;
183 : int i;
184 :
185 0 : fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffff;
186 0 : bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffff;
187 0 : stamp_attr = attr;
188 :
189 0 : for (i = 0; i < 32; i += 2) {
190 : #if BYTE_ORDER == LITTLE_ENDIAN
191 0 : stamp[i] = (i & 16 ? fg : bg);
192 0 : stamp[i] |= ((i & 8 ? fg : bg) << 16);
193 0 : stamp[i + 1] = (i & 4 ? fg : bg);
194 0 : 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 0 : }
203 :
204 : /*
205 : * Paint a single character. This is for 8-pixel wide fonts.
206 : */
207 : int
208 0 : rasops15_putchar8(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
217 0 : stamp_mutex--;
218 0 : return rasops15_putchar(cookie, row, col, uc, attr);
219 : }
220 :
221 0 : 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 0 : if (attr != stamp_attr)
237 0 : rasops15_makestamp(ri, attr);
238 :
239 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
240 0 : height = ri->ri_font->fontheight;
241 :
242 0 : if (uc == (u_int)-1) {
243 0 : int32_t c = stamp[0];
244 0 : while (height--) {
245 0 : rp[0] = rp[1] = rp[2] = rp[3] = c;
246 0 : DELTA(rp, ri->ri_stride, int32_t *);
247 : }
248 0 : } else {
249 0 : uc -= ri->ri_font->firstchar;
250 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
251 0 : fs = ri->ri_font->stride;
252 :
253 0 : while (height--) {
254 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
255 0 : rp[0] = STAMP_READ(so);
256 0 : rp[1] = STAMP_READ(so + 4);
257 :
258 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
259 0 : rp[2] = STAMP_READ(so);
260 0 : rp[3] = STAMP_READ(so + 4);
261 :
262 0 : fr += fs;
263 0 : DELTA(rp, ri->ri_stride, int32_t *);
264 : }
265 : }
266 :
267 : /* Do underline */
268 0 : if ((attr & 1) != 0) {
269 0 : int32_t c = STAMP_READ(28);
270 :
271 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
272 0 : rp[0] = rp[1] = rp[2] = rp[3] = c;
273 0 : }
274 :
275 0 : stamp_mutex--;
276 :
277 0 : return 0;
278 0 : }
279 :
280 : /*
281 : * Paint a single character. This is for 12-pixel wide fonts.
282 : */
283 : int
284 0 : rasops15_putchar12(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
293 0 : stamp_mutex--;
294 0 : return rasops15_putchar(cookie, row, col, uc, attr);
295 : }
296 :
297 0 : 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 0 : if (attr != stamp_attr)
313 0 : rasops15_makestamp(ri, attr);
314 :
315 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
316 0 : height = ri->ri_font->fontheight;
317 :
318 0 : if (uc == (u_int)-1) {
319 0 : int32_t c = stamp[0];
320 0 : while (height--) {
321 0 : rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
322 0 : DELTA(rp, ri->ri_stride, int32_t *);
323 : }
324 0 : } else {
325 0 : uc -= ri->ri_font->firstchar;
326 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
327 0 : fs = ri->ri_font->stride;
328 :
329 0 : while (height--) {
330 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
331 0 : rp[0] = STAMP_READ(so);
332 0 : rp[1] = STAMP_READ(so + 4);
333 :
334 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
335 0 : rp[2] = STAMP_READ(so);
336 0 : rp[3] = STAMP_READ(so + 4);
337 :
338 0 : so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
339 0 : rp[4] = STAMP_READ(so);
340 0 : rp[5] = STAMP_READ(so + 4);
341 :
342 0 : fr += fs;
343 0 : DELTA(rp, ri->ri_stride, int32_t *);
344 : }
345 : }
346 :
347 : /* Do underline */
348 0 : if (attr & 1) {
349 0 : int32_t c = STAMP_READ(28);
350 :
351 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
352 0 : rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
353 0 : }
354 :
355 0 : stamp_mutex--;
356 :
357 0 : return 0;
358 0 : }
359 :
360 : /*
361 : * Paint a single character. This is for 16-pixel wide fonts.
362 : */
363 : int
364 0 : rasops15_putchar16(void *cookie, int row, int col, u_int uc, long 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 0 : if (stamp_mutex++) {
373 0 : stamp_mutex--;
374 0 : return rasops15_putchar(cookie, row, col, uc, attr);
375 : }
376 :
377 0 : 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 0 : if (attr != stamp_attr)
393 0 : rasops15_makestamp(ri, attr);
394 :
395 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
396 0 : height = ri->ri_font->fontheight;
397 :
398 0 : if (uc == (u_int)-1) {
399 0 : int32_t c = stamp[0];
400 0 : while (height--) {
401 0 : rp[0] = rp[1] = rp[2] = rp[3] =
402 0 : rp[4] = rp[5] = rp[6] = rp[7] = c;
403 0 : DELTA(rp, ri->ri_stride, int32_t *);
404 : }
405 0 : } else {
406 0 : uc -= ri->ri_font->firstchar;
407 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
408 0 : fs = ri->ri_font->stride;
409 :
410 0 : while (height--) {
411 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
412 0 : rp[0] = STAMP_READ(so);
413 0 : rp[1] = STAMP_READ(so + 4);
414 :
415 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
416 0 : rp[2] = STAMP_READ(so);
417 0 : rp[3] = STAMP_READ(so + 4);
418 :
419 0 : so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
420 0 : rp[4] = STAMP_READ(so);
421 0 : rp[5] = STAMP_READ(so + 4);
422 :
423 0 : so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
424 0 : rp[6] = STAMP_READ(so);
425 0 : rp[7] = STAMP_READ(so + 4);
426 :
427 0 : DELTA(rp, ri->ri_stride, int32_t *);
428 0 : fr += fs;
429 : }
430 : }
431 :
432 : /* Do underline */
433 0 : if (attr & 1) {
434 0 : int32_t c = STAMP_READ(28);
435 :
436 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
437 0 : rp[0] = rp[1] = rp[2] = rp[3] =
438 0 : rp[4] = rp[5] = rp[6] = rp[7] = c;
439 0 : }
440 :
441 0 : stamp_mutex--;
442 :
443 0 : return 0;
444 0 : }
445 : #endif /* !RASOPS_SMALL */
|