Line data Source code
1 : /* $OpenBSD: rasops24.c,v 1.10 2014/12/19 22:44:59 guenther 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_erasecols(void *, int, int, int, long);
43 : int rasops24_eraserows(void *, int, int, long);
44 : int rasops24_putchar(void *, int, int, u_int, long attr);
45 : #ifndef RASOPS_SMALL
46 : int rasops24_putchar8(void *, int, int, u_int, long attr);
47 : int rasops24_putchar12(void *, int, int, u_int, long attr);
48 : int rasops24_putchar16(void *, int, int, u_int, long attr);
49 : void rasops24_makestamp(struct rasops_info *, long);
50 :
51 : /*
52 : * 4x1 stamp for optimized character blitting
53 : */
54 : static int32_t stamp[64];
55 : static long stamp_attr;
56 : static int stamp_mutex; /* XXX see note in readme */
57 : #endif
58 :
59 : /*
60 : * XXX this confuses the hell out of gcc2 (not egcs) which always insists
61 : * that the shift count is negative.
62 : *
63 : * offset = STAMP_SHIFT(fontbits, nibble #) & STAMP_MASK
64 : * destination int32_t[0] = STAMP_READ(offset)
65 : * destination int32_t[1] = STAMP_READ(offset + 4)
66 : * destination int32_t[2] = STAMP_READ(offset + 8)
67 : */
68 : #define STAMP_SHIFT(fb,n) ((n*4-4) >= 0 ? (fb)>>(n*4-4):(fb)<<-(n*4-4))
69 : #define STAMP_MASK (0xf << 4)
70 : #define STAMP_READ(o) (*(int32_t *)((caddr_t)stamp + (o)))
71 :
72 : /*
73 : * Initialize rasops_info struct for this colordepth.
74 : */
75 : void
76 0 : rasops24_init(struct rasops_info *ri)
77 : {
78 :
79 0 : switch (ri->ri_font->fontwidth) {
80 : #ifndef RASOPS_SMALL
81 : case 8:
82 0 : ri->ri_ops.putchar = rasops24_putchar8;
83 0 : break;
84 : case 12:
85 0 : ri->ri_ops.putchar = rasops24_putchar12;
86 0 : break;
87 : case 16:
88 0 : ri->ri_ops.putchar = rasops24_putchar16;
89 0 : break;
90 : #endif
91 : default:
92 0 : ri->ri_ops.putchar = rasops24_putchar;
93 0 : break;
94 : }
95 :
96 0 : if (ri->ri_rnum == 0) {
97 0 : ri->ri_rnum = 8;
98 0 : ri->ri_rpos = 0;
99 0 : ri->ri_gnum = 8;
100 0 : ri->ri_gpos = 8;
101 0 : ri->ri_bnum = 8;
102 0 : ri->ri_bpos = 16;
103 0 : }
104 :
105 0 : ri->ri_ops.erasecols = rasops24_erasecols;
106 0 : ri->ri_ops.eraserows = rasops24_eraserows;
107 0 : }
108 :
109 : /*
110 : * Put a single character. This is the generic version.
111 : * XXX this bites - we should use masks.
112 : */
113 : int
114 0 : rasops24_putchar(void *cookie, int row, int col, u_int uc, long attr)
115 : {
116 : int fb, width, height, cnt, clr[2];
117 : struct rasops_info *ri;
118 : u_char *dp, *rp, *fr;
119 :
120 0 : ri = (struct rasops_info *)cookie;
121 :
122 : #ifdef RASOPS_CLIPPING
123 : /* Catches 'row < 0' case too */
124 : if ((unsigned)row >= (unsigned)ri->ri_rows)
125 : return 0;
126 :
127 : if ((unsigned)col >= (unsigned)ri->ri_cols)
128 : return 0;
129 : #endif
130 :
131 0 : rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
132 0 : height = ri->ri_font->fontheight;
133 0 : width = ri->ri_font->fontwidth;
134 :
135 0 : clr[1] = ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
136 0 : clr[0] = ri->ri_devcmap[((u_int)attr >> 16) & 0xf];
137 :
138 0 : if (uc == ' ') {
139 0 : while (height--) {
140 : dp = rp;
141 0 : rp += ri->ri_stride;
142 :
143 0 : for (cnt = width; cnt; cnt--) {
144 0 : *dp++ = clr[0] >> 16;
145 0 : *dp++ = clr[0] >> 8;
146 0 : *dp++ = clr[0];
147 : }
148 : }
149 : } else {
150 0 : uc -= ri->ri_font->firstchar;
151 0 : fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
152 :
153 0 : while (height--) {
154 : dp = rp;
155 0 : fb = fr[3] | (fr[2] << 8) | (fr[1] << 16) |
156 0 : (fr[0] << 24);
157 0 : fr += ri->ri_font->stride;
158 0 : rp += ri->ri_stride;
159 :
160 0 : for (cnt = width; cnt; cnt--, fb <<= 1) {
161 0 : if ((fb >> 31) & 1) {
162 0 : *dp++ = clr[1] >> 16;
163 0 : *dp++ = clr[1] >> 8;
164 0 : *dp++ = clr[1];
165 0 : } else {
166 0 : *dp++ = clr[0] >> 16;
167 0 : *dp++ = clr[0] >> 8;
168 0 : *dp++ = clr[0];
169 : }
170 : }
171 : }
172 : }
173 :
174 : /* Do underline */
175 0 : if ((attr & 1) != 0) {
176 0 : rp -= ri->ri_stride << 1;
177 :
178 0 : while (width--) {
179 0 : *rp++ = clr[1] >> 16;
180 0 : *rp++ = clr[1] >> 8;
181 0 : *rp++ = clr[1];
182 : }
183 : }
184 :
185 0 : return 0;
186 : }
187 :
188 : #ifndef RASOPS_SMALL
189 : /*
190 : * Recompute the blitting stamp.
191 : */
192 : void
193 0 : rasops24_makestamp(struct rasops_info *ri, long attr)
194 : {
195 : u_int fg, bg, c1, c2, c3, c4;
196 : int i;
197 :
198 0 : fg = ri->ri_devcmap[((u_int)attr >> 24) & 0xf] & 0xffffff;
199 0 : bg = ri->ri_devcmap[((u_int)attr >> 16) & 0xf] & 0xffffff;
200 0 : stamp_attr = attr;
201 :
202 0 : for (i = 0; i < 64; i += 4) {
203 : #if BYTE_ORDER == LITTLE_ENDIAN
204 0 : c1 = (i & 32 ? fg : bg);
205 0 : c2 = (i & 16 ? fg : bg);
206 0 : c3 = (i & 8 ? fg : bg);
207 0 : c4 = (i & 4 ? fg : bg);
208 : #else
209 : c1 = (i & 8 ? fg : bg);
210 : c2 = (i & 4 ? fg : bg);
211 : c3 = (i & 16 ? fg : bg);
212 : c4 = (i & 32 ? fg : bg);
213 : #endif
214 0 : stamp[i+0] = (c1 << 8) | (c2 >> 16);
215 0 : stamp[i+1] = (c2 << 16) | (c3 >> 8);
216 0 : stamp[i+2] = (c3 << 24) | c4;
217 :
218 : #if BYTE_ORDER == LITTLE_ENDIAN
219 0 : if ((ri->ri_flg & RI_BSWAP) == 0) {
220 : #else
221 : if ((ri->ri_flg & RI_BSWAP) != 0) {
222 : #endif
223 0 : stamp[i+0] = swap32(stamp[i+0]);
224 0 : stamp[i+1] = swap32(stamp[i+1]);
225 0 : stamp[i+2] = swap32(stamp[i+2]);
226 0 : }
227 : }
228 0 : }
229 :
230 : /*
231 : * Put a single character. This is for 8-pixel wide fonts.
232 : */
233 : int
234 0 : rasops24_putchar8(void *cookie, int row, int col, u_int uc, long attr)
235 : {
236 : struct rasops_info *ri;
237 : int height, so, fs;
238 : int32_t *rp;
239 : u_char *fr;
240 :
241 : /* Can't risk remaking the stamp if it's already in use */
242 0 : if (stamp_mutex++) {
243 0 : stamp_mutex--;
244 0 : return rasops24_putchar(cookie, row, col, uc, attr);
245 : }
246 :
247 0 : ri = (struct rasops_info *)cookie;
248 :
249 : #ifdef RASOPS_CLIPPING
250 : if ((unsigned)row >= (unsigned)ri->ri_rows) {
251 : stamp_mutex--;
252 : return 0;
253 : }
254 :
255 : if ((unsigned)col >= (unsigned)ri->ri_cols) {
256 : stamp_mutex--;
257 : return 0;
258 : }
259 : #endif
260 :
261 : /* Recompute stamp? */
262 0 : if (attr != stamp_attr)
263 0 : rasops24_makestamp(ri, attr);
264 :
265 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
266 0 : height = ri->ri_font->fontheight;
267 :
268 0 : if (uc == (u_int)-1) {
269 0 : int32_t c = stamp[0];
270 0 : while (height--) {
271 0 : rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
272 0 : DELTA(rp, ri->ri_stride, int32_t *);
273 : }
274 0 : } else {
275 0 : uc -= ri->ri_font->firstchar;
276 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
277 0 : fs = ri->ri_font->stride;
278 :
279 0 : while (height--) {
280 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
281 0 : rp[0] = STAMP_READ(so);
282 0 : rp[1] = STAMP_READ(so + 4);
283 0 : rp[2] = STAMP_READ(so + 8);
284 :
285 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
286 0 : rp[3] = STAMP_READ(so);
287 0 : rp[4] = STAMP_READ(so + 4);
288 0 : rp[5] = STAMP_READ(so + 8);
289 :
290 0 : fr += fs;
291 0 : DELTA(rp, ri->ri_stride, int32_t *);
292 : }
293 : }
294 :
295 : /* Do underline */
296 0 : if ((attr & 1) != 0) {
297 0 : int32_t c = STAMP_READ(52);
298 :
299 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
300 0 : rp[0] = rp[1] = rp[2] = rp[3] = rp[4] = rp[5] = c;
301 0 : }
302 :
303 0 : stamp_mutex--;
304 :
305 0 : return 0;
306 0 : }
307 :
308 : /*
309 : * Put a single character. This is for 12-pixel wide fonts.
310 : */
311 : int
312 0 : rasops24_putchar12(void *cookie, int row, int col, u_int uc, long attr)
313 : {
314 : struct rasops_info *ri;
315 : int height, so, fs;
316 : int32_t *rp;
317 : u_char *fr;
318 :
319 : /* Can't risk remaking the stamp if it's already in use */
320 0 : if (stamp_mutex++) {
321 0 : stamp_mutex--;
322 0 : return rasops24_putchar(cookie, row, col, uc, attr);
323 : }
324 :
325 0 : ri = (struct rasops_info *)cookie;
326 :
327 : #ifdef RASOPS_CLIPPING
328 : if ((unsigned)row >= (unsigned)ri->ri_rows) {
329 : stamp_mutex--;
330 : return 0;
331 : }
332 :
333 : if ((unsigned)col >= (unsigned)ri->ri_cols) {
334 : stamp_mutex--;
335 : return 0;
336 : }
337 : #endif
338 :
339 : /* Recompute stamp? */
340 0 : if (attr != stamp_attr)
341 0 : rasops24_makestamp(ri, attr);
342 :
343 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
344 0 : height = ri->ri_font->fontheight;
345 :
346 0 : if (uc == (u_int)-1) {
347 0 : int32_t c = stamp[0];
348 0 : while (height--) {
349 0 : rp[0] = rp[1] = rp[2] = rp[3] =
350 0 : rp[4] = rp[5] = rp[6] = rp[7] = rp[8] = c;
351 0 : DELTA(rp, ri->ri_stride, int32_t *);
352 : }
353 0 : } else {
354 0 : uc -= ri->ri_font->firstchar;
355 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
356 0 : fs = ri->ri_font->stride;
357 :
358 0 : while (height--) {
359 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
360 0 : rp[0] = STAMP_READ(so);
361 0 : rp[1] = STAMP_READ(so + 4);
362 0 : rp[2] = STAMP_READ(so + 8);
363 :
364 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
365 0 : rp[3] = STAMP_READ(so);
366 0 : rp[4] = STAMP_READ(so + 4);
367 0 : rp[5] = STAMP_READ(so + 8);
368 :
369 0 : so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
370 0 : rp[6] = STAMP_READ(so);
371 0 : rp[7] = STAMP_READ(so + 4);
372 0 : rp[8] = STAMP_READ(so + 8);
373 :
374 0 : fr += fs;
375 0 : DELTA(rp, ri->ri_stride, int32_t *);
376 : }
377 : }
378 :
379 : /* Do underline */
380 0 : if ((attr & 1) != 0) {
381 0 : int32_t c = STAMP_READ(52);
382 :
383 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
384 0 : rp[0] = rp[1] = rp[2] = rp[3] =
385 0 : rp[4] = rp[5] = rp[6] = rp[7] = rp[8] = c;
386 0 : }
387 :
388 0 : stamp_mutex--;
389 :
390 0 : return 0;
391 0 : }
392 :
393 : /*
394 : * Put a single character. This is for 16-pixel wide fonts.
395 : */
396 : int
397 0 : rasops24_putchar16(void *cookie, int row, int col, u_int uc, long attr)
398 : {
399 : struct rasops_info *ri;
400 : int height, so, fs;
401 : int32_t *rp;
402 : u_char *fr;
403 :
404 : /* Can't risk remaking the stamp if it's already in use */
405 0 : if (stamp_mutex++) {
406 0 : stamp_mutex--;
407 0 : return rasops24_putchar(cookie, row, col, uc, attr);
408 : }
409 :
410 0 : ri = (struct rasops_info *)cookie;
411 :
412 : #ifdef RASOPS_CLIPPING
413 : if ((unsigned)row >= (unsigned)ri->ri_rows) {
414 : stamp_mutex--;
415 : return 0;
416 : }
417 :
418 : if ((unsigned)col >= (unsigned)ri->ri_cols) {
419 : stamp_mutex--;
420 : return 0;
421 : }
422 : #endif
423 :
424 : /* Recompute stamp? */
425 0 : if (attr != stamp_attr)
426 0 : rasops24_makestamp(ri, attr);
427 :
428 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
429 0 : height = ri->ri_font->fontheight;
430 :
431 0 : if (uc == (u_int)-1) {
432 0 : int32_t c = stamp[0];
433 0 : while (height--) {
434 0 : rp[0] = rp[1] = rp[2] = rp[3] =
435 0 : rp[4] = rp[5] = rp[6] = rp[7] =
436 0 : rp[8] = rp[9] = rp[10] = rp[11] = c;
437 0 : DELTA(rp, ri->ri_stride, int32_t *);
438 : }
439 0 : } else {
440 0 : uc -= ri->ri_font->firstchar;
441 0 : fr = (u_char *)ri->ri_font->data + uc*ri->ri_fontscale;
442 0 : fs = ri->ri_font->stride;
443 :
444 0 : while (height--) {
445 0 : so = STAMP_SHIFT(fr[0], 1) & STAMP_MASK;
446 0 : rp[0] = STAMP_READ(so);
447 0 : rp[1] = STAMP_READ(so + 4);
448 0 : rp[2] = STAMP_READ(so + 8);
449 :
450 0 : so = STAMP_SHIFT(fr[0], 0) & STAMP_MASK;
451 0 : rp[3] = STAMP_READ(so);
452 0 : rp[4] = STAMP_READ(so + 4);
453 0 : rp[5] = STAMP_READ(so + 8);
454 :
455 0 : so = STAMP_SHIFT(fr[1], 1) & STAMP_MASK;
456 0 : rp[6] = STAMP_READ(so);
457 0 : rp[7] = STAMP_READ(so + 4);
458 0 : rp[8] = STAMP_READ(so + 8);
459 :
460 0 : so = STAMP_SHIFT(fr[1], 0) & STAMP_MASK;
461 0 : rp[9] = STAMP_READ(so);
462 0 : rp[10] = STAMP_READ(so + 4);
463 0 : rp[11] = STAMP_READ(so + 8);
464 :
465 0 : DELTA(rp, ri->ri_stride, int32_t *);
466 0 : fr += fs;
467 : }
468 : }
469 :
470 : /* Do underline */
471 0 : if ((attr & 1) != 0) {
472 0 : int32_t c = STAMP_READ(52);
473 :
474 0 : DELTA(rp, -(ri->ri_stride << 1), int32_t *);
475 0 : rp[0] = rp[1] = rp[2] = rp[3] =
476 0 : rp[4] = rp[5] = rp[6] = rp[7] =
477 0 : rp[8] = rp[9] = rp[10] = rp[11] = c;
478 0 : }
479 :
480 0 : stamp_mutex--;
481 :
482 0 : return 0;
483 0 : }
484 : #endif /* !RASOPS_SMALL */
485 :
486 : /*
487 : * Erase rows. This is nice and easy due to alignment.
488 : */
489 : int
490 0 : rasops24_eraserows(void *cookie, int row, int num, long attr)
491 : {
492 : int n9, n3, n1, cnt, stride, delta;
493 0 : u_int32_t *dp, clr, stamp[3];
494 : struct rasops_info *ri;
495 :
496 : /*
497 : * If the color is gray, we can cheat and use the generic routines
498 : * (which are faster, hopefully) since the r,g,b values are the same.
499 : */
500 0 : if ((attr & 4) != 0)
501 0 : return rasops_eraserows(cookie, row, num, attr);
502 :
503 0 : ri = (struct rasops_info *)cookie;
504 :
505 : #ifdef RASOPS_CLIPPING
506 : if (row < 0) {
507 : num += row;
508 : row = 0;
509 : }
510 :
511 : if ((row + num) > ri->ri_rows)
512 : num = ri->ri_rows - row;
513 :
514 : if (num <= 0)
515 : return 0;
516 : #endif
517 :
518 0 : clr = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xffffff;
519 0 : stamp[0] = (clr << 8) | (clr >> 16);
520 0 : stamp[1] = (clr << 16) | (clr >> 8);
521 0 : stamp[2] = (clr << 24) | clr;
522 :
523 : #if BYTE_ORDER == LITTLE_ENDIAN
524 0 : if ((ri->ri_flg & RI_BSWAP) == 0) {
525 : #else
526 : if ((ri->ri_flg & RI_BSWAP) != 0) {
527 : #endif
528 0 : stamp[0] = swap32(stamp[0]);
529 0 : stamp[1] = swap32(stamp[1]);
530 0 : stamp[2] = swap32(stamp[2]);
531 0 : }
532 :
533 : /*
534 : * XXX the wsdisplay_emulops interface seems a little deficient in
535 : * that there is no way to clear the *entire* screen. We provide a
536 : * workaround here: if the entire console area is being cleared, and
537 : * the RI_FULLCLEAR flag is set, clear the entire display.
538 : */
539 0 : if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
540 0 : stride = ri->ri_stride;
541 0 : num = ri->ri_height;
542 0 : dp = (int32_t *)ri->ri_origbits;
543 : delta = 0;
544 0 : } else {
545 0 : stride = ri->ri_emustride;
546 0 : num *= ri->ri_font->fontheight;
547 0 : dp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale);
548 0 : delta = ri->ri_delta;
549 : }
550 :
551 0 : n9 = stride / 36;
552 0 : cnt = (n9 << 5) + (n9 << 2); /* (32*n9) + (4*n9) */
553 0 : n3 = (stride - cnt) / 12;
554 0 : cnt += (n3 << 3) + (n3 << 2); /* (8*n3) + (4*n3) */
555 0 : n1 = (stride - cnt) >> 2;
556 :
557 0 : while (num--) {
558 0 : for (cnt = n9; cnt; cnt--) {
559 0 : dp[0] = stamp[0];
560 0 : dp[1] = stamp[1];
561 0 : dp[2] = stamp[2];
562 0 : dp[3] = stamp[0];
563 0 : dp[4] = stamp[1];
564 0 : dp[5] = stamp[2];
565 0 : dp[6] = stamp[0];
566 0 : dp[7] = stamp[1];
567 0 : dp[8] = stamp[2];
568 0 : dp += 9;
569 : }
570 :
571 0 : for (cnt = n3; cnt; cnt--) {
572 0 : dp[0] = stamp[0];
573 0 : dp[1] = stamp[1];
574 0 : dp[2] = stamp[2];
575 0 : dp += 3;
576 : }
577 :
578 0 : for (cnt = 0; cnt < n1; cnt++)
579 0 : *dp++ = stamp[cnt];
580 :
581 0 : DELTA(dp, delta, int32_t *);
582 : }
583 :
584 0 : return 0;
585 0 : }
586 :
587 : /*
588 : * Erase columns.
589 : */
590 : int
591 0 : rasops24_erasecols(void *cookie, int row, int col, int num, long attr)
592 : {
593 : int n12, n4, height, cnt, slop, clr, stamp[3];
594 : struct rasops_info *ri;
595 : int32_t *dp, *rp;
596 : u_char *dbp;
597 :
598 : /*
599 : * If the color is gray, we can cheat and use the generic routines
600 : * (which are faster, hopefully) since the r,g,b values are the same.
601 : */
602 0 : if ((attr & 4) != 0)
603 0 : return rasops_erasecols(cookie, row, col, num, attr);
604 :
605 0 : ri = (struct rasops_info *)cookie;
606 :
607 : #ifdef RASOPS_CLIPPING
608 : /* Catches 'row < 0' case too */
609 : if ((unsigned)row >= (unsigned)ri->ri_rows)
610 : return 0;
611 :
612 : if (col < 0) {
613 : num += col;
614 : col = 0;
615 : }
616 :
617 : if ((col + num) > ri->ri_cols)
618 : num = ri->ri_cols - col;
619 :
620 : if (num <= 0)
621 : return 0;
622 : #endif
623 :
624 0 : rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
625 0 : num *= ri->ri_font->fontwidth;
626 0 : height = ri->ri_font->fontheight;
627 :
628 0 : clr = ri->ri_devcmap[(attr >> 16) & 0xf] & 0xffffff;
629 0 : stamp[0] = (clr << 8) | (clr >> 16);
630 0 : stamp[1] = (clr << 16) | (clr >> 8);
631 0 : stamp[2] = (clr << 24) | clr;
632 :
633 : #if BYTE_ORDER == LITTLE_ENDIAN
634 0 : if ((ri->ri_flg & RI_BSWAP) == 0) {
635 : #else
636 : if ((ri->ri_flg & RI_BSWAP) != 0) {
637 : #endif
638 0 : stamp[0] = swap32(stamp[0]);
639 0 : stamp[1] = swap32(stamp[1]);
640 0 : stamp[2] = swap32(stamp[2]);
641 0 : }
642 :
643 : /*
644 : * The current byte offset mod 4 tells us the number of 24-bit pels
645 : * we need to write for alignment to 32-bits. Once we're aligned on
646 : * a 32-bit boundary, we're also aligned on a 4 pixel boundary, so
647 : * the stamp does not need to be rotated. The following shows the
648 : * layout of 4 pels in a 3 word region and illustrates this:
649 : *
650 : * aaab bbcc cddd
651 : */
652 0 : slop = (long)rp & 3; num -= slop;
653 0 : n12 = num / 12; num -= (n12 << 3) + (n12 << 2);
654 0 : n4 = num >> 2; num &= 3;
655 :
656 0 : while (height--) {
657 0 : dbp = (u_char *)rp;
658 0 : DELTA(rp, ri->ri_stride, int32_t *);
659 :
660 : /* Align to 4 bytes */
661 : /* XXX handle with masks, bring under control of RI_BSWAP */
662 0 : for (cnt = slop; cnt; cnt--) {
663 0 : *dbp++ = (clr >> 16);
664 0 : *dbp++ = (clr >> 8);
665 0 : *dbp++ = clr;
666 : }
667 :
668 0 : dp = (int32_t *)dbp;
669 :
670 : /* 12 pels per loop */
671 0 : for (cnt = n12; cnt; cnt--) {
672 0 : dp[0] = stamp[0];
673 0 : dp[1] = stamp[1];
674 0 : dp[2] = stamp[2];
675 0 : dp[3] = stamp[0];
676 0 : dp[4] = stamp[1];
677 0 : dp[5] = stamp[2];
678 0 : dp[6] = stamp[0];
679 0 : dp[7] = stamp[1];
680 0 : dp[8] = stamp[2];
681 0 : dp += 9;
682 : }
683 :
684 : /* 4 pels per loop */
685 0 : for (cnt = n4; cnt; cnt--) {
686 0 : dp[0] = stamp[0];
687 0 : dp[1] = stamp[1];
688 0 : dp[2] = stamp[2];
689 0 : dp += 3;
690 : }
691 :
692 : /* Trailing slop */
693 : /* XXX handle with masks, bring under control of RI_BSWAP */
694 0 : dbp = (u_char *)dp;
695 0 : for (cnt = num; cnt; cnt--) {
696 0 : *dbp++ = (clr >> 16);
697 0 : *dbp++ = (clr >> 8);
698 0 : *dbp++ = clr;
699 : }
700 : }
701 :
702 0 : return 0;
703 0 : }
|