omrasops.c revision 1.18 1 /* $NetBSD: omrasops.c,v 1.18 2014/09/28 05:00:56 tsutsui Exp $ */
2
3 /*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33
34 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.18 2014/09/28 05:00:56 tsutsui Exp $");
35
36 /*
37 * Designed speficically for 'm68k bitorder';
38 * - most significant byte is stored at lower address,
39 * - most significant bit is displayed at left most on screen.
40 * Implementation relies on;
41 * - first column is at 32bit aligned address,
42 * - font glyphs are stored in 32bit padded.
43 */
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wscons/wsdisplayvar.h>
51 #include <dev/rasops/rasops.h>
52
53 #include <arch/luna68k/dev/omrasopsvar.h>
54
55 /* wscons emulator operations */
56 static void om1_cursor(void *, int, int, int);
57 static void om4_cursor(void *, int, int, int);
58 static int om_mapchar(void *, int, unsigned int *);
59 static void om1_putchar(void *, int, int, u_int, long);
60 static void om4_putchar(void *, int, int, u_int, long);
61 static void om1_copycols(void *, int, int, int, int);
62 static void om4_copycols(void *, int, int, int, int);
63 static void om1_copyrows(void *, int, int, int num);
64 static void om4_copyrows(void *, int, int, int num);
65 static void om1_erasecols(void *, int, int, int, long);
66 static void om4_erasecols(void *, int, int, int, long);
67 static void om1_eraserows(void *, int, int, long);
68 static void om4_eraserows(void *, int, int, long);
69 static int om1_allocattr(void *, int, int, int, long *);
70 static int om4_allocattr(void *, int, int, int, long *);
71 static void om4_unpack_attr(long, int *, int *, int *);
72
73 static int omrasops_init(struct rasops_info *, int, int);
74
75 #define ALL1BITS (~0U)
76 #define ALL0BITS (0U)
77 #define BLITWIDTH (32)
78 #define ALIGNMASK (0x1f)
79 #define BYTESDONE (4)
80
81 #define W(p) (*(uint32_t *)(p))
82 #define R(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
83 #define P0(p) (*(uint32_t *)((uint8_t *)(p) + 0x40000))
84 #define P1(p) (*(uint32_t *)((uint8_t *)(p) + 0x80000))
85 #define P2(p) (*(uint32_t *)((uint8_t *)(p) + 0xc0000))
86 #define P3(p) (*(uint32_t *)((uint8_t *)(p) + 0x100000))
87
88 /*
89 * macros to handle unaligned bit copy ops.
90 * See src/sys/dev/rasops/rasops_mask.h for MI version.
91 * Also refer src/sys/arch/hp300/dev/maskbits.h.
92 * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c)
93 */
94
95 /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */
96 #define FASTGETBITS(psrc, x, w, dst) \
97 asm("bfextu %3{%1:%2},%0" \
98 : "=d" (dst) \
99 : "di" (x), "di" (w), "o" ((uint32_t *)(psrc)))
100
101 /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
102 /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
103 #define FASTPUTBITS(src, x, w, pdst) \
104 asm("bfins %3,%0{%1:%2}" \
105 : "+o" ((uint32_t *)(pdst)) \
106 : "di" (x), "di" (w), "d" (src) \
107 : "memory" );
108
109 #define GETBITS(psrc, x, w, dst) FASTGETBITS(psrc, x, w, dst)
110 #define PUTBITS(src, x, w, pdst) FASTPUTBITS(src, x, w, pdst)
111
112 /*
113 * Blit a character at the specified co-ordinates.
114 */
115 static void
116 om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
117 {
118 struct rasops_info *ri = cookie;
119 uint8_t *p;
120 int scanspan, startx, height, width, align, y;
121 uint32_t lmask, rmask, glyph, inverse;
122 int i;
123 uint8_t *fb;
124
125 scanspan = ri->ri_stride;
126 y = ri->ri_font->fontheight * row;
127 startx = ri->ri_font->fontwidth * startcol;
128 height = ri->ri_font->fontheight;
129 fb = (uint8_t *)ri->ri_font->data +
130 (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
131 inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
132
133 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
134 align = startx & ALIGNMASK;
135 width = ri->ri_font->fontwidth + align;
136 lmask = ALL1BITS >> align;
137 rmask = ALL1BITS << (-width & ALIGNMASK);
138 if (width <= BLITWIDTH) {
139 lmask &= rmask;
140 while (height > 0) {
141 glyph = 0;
142 for (i = ri->ri_font->stride; i != 0; i--)
143 glyph = (glyph << 8) | *fb++;
144 glyph <<= (4 - ri->ri_font->stride) * NBBY;
145 glyph = (glyph >> align) ^ inverse;
146 P0(p) = (P0(p) & ~lmask) | (glyph & lmask);
147 p += scanspan;
148 height--;
149 }
150 } else {
151 uint8_t *q = p;
152 uint32_t lhalf, rhalf;
153
154 while (height > 0) {
155 glyph = 0;
156 for (i = ri->ri_font->stride; i != 0; i--)
157 glyph = (glyph << 8) | *fb++;
158 glyph <<= (4 - ri->ri_font->stride) * NBBY;
159 lhalf = (glyph >> align) ^ inverse;
160 P0(p) = (P0(p) & ~lmask) | (lhalf & lmask);
161 p += BYTESDONE;
162 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
163 P0(p) = (rhalf & rmask) | (P0(p) & ~rmask);
164
165 p = (q += scanspan);
166 height--;
167 }
168 }
169 }
170
171 static void
172 om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
173 {
174 struct rasops_info *ri = cookie;
175 uint8_t *p;
176 int scanspan, startx, height, width, align, y;
177 uint32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat;
178 uint32_t fgmask0, fgmask1, fgmask2, fgmask3;
179 uint32_t bgmask0, bgmask1, bgmask2, bgmask3;
180 int i, fg, bg;
181 uint8_t *fb;
182
183 scanspan = ri->ri_stride;
184 y = ri->ri_font->fontheight * row;
185 startx = ri->ri_font->fontwidth * startcol;
186 height = ri->ri_font->fontheight;
187 fb = (uint8_t *)ri->ri_font->data +
188 (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
189 om4_unpack_attr(attr, &fg, &bg, NULL);
190 fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS;
191 fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS;
192 fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS;
193 fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS;
194 bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS;
195 bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS;
196 bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS;
197 bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS;
198
199 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
200 align = startx & ALIGNMASK;
201 width = ri->ri_font->fontwidth + align;
202 lmask = ALL1BITS >> align;
203 rmask = ALL1BITS << (-width & ALIGNMASK);
204 if (width <= BLITWIDTH) {
205 lmask &= rmask;
206 while (height > 0) {
207 glyph = 0;
208 for (i = ri->ri_font->stride; i != 0; i--)
209 glyph = (glyph << 8) | *fb++;
210 glyph <<= (4 - ri->ri_font->stride) * NBBY;
211 glyph = (glyph >> align);
212 glyphbg = glyph ^ ALL1BITS;
213 fgpat = glyph & fgmask0;
214 bgpat = glyphbg & bgmask0;
215 P0(p) = (P0(p) & ~lmask) | ((fgpat | bgpat) & lmask);
216 fgpat = glyph & fgmask1;
217 bgpat = glyphbg & bgmask1;
218 P1(p) = (P1(p) & ~lmask) | ((fgpat | bgpat) & lmask);
219 fgpat = glyph & fgmask2;
220 bgpat = glyphbg & bgmask2;
221 P2(p) = (P2(p) & ~lmask) | ((fgpat | bgpat) & lmask);
222 fgpat = glyph & fgmask3;
223 bgpat = glyphbg & bgmask3;
224 P3(p) = (P3(p) & ~lmask) | ((fgpat | bgpat) & lmask);
225 p += scanspan;
226 height--;
227 }
228 } else {
229 uint8_t *q = p;
230 uint32_t lhalf, rhalf;
231 uint32_t lhalfbg, rhalfbg;
232
233 while (height > 0) {
234 glyph = 0;
235 for (i = ri->ri_font->stride; i != 0; i--)
236 glyph = (glyph << 8) | *fb++;
237 glyph <<= (4 - ri->ri_font->stride) * NBBY;
238 lhalf = (glyph >> align);
239 lhalfbg = lhalf ^ ALL1BITS;
240 fgpat = lhalf & fgmask0;
241 bgpat = lhalfbg & bgmask0;
242 P0(p) = (P0(p) & ~lmask) | ((fgpat | bgpat) & lmask);
243 fgpat = lhalf & fgmask1;
244 bgpat = lhalfbg & bgmask1;
245 P1(p) = (P1(p) & ~lmask) | ((fgpat | bgpat) & lmask);
246 fgpat = lhalf & fgmask2;
247 bgpat = lhalfbg & bgmask2;
248 P2(p) = (P2(p) & ~lmask) | ((fgpat | bgpat) & lmask);
249 fgpat = lhalf & fgmask3;
250 bgpat = lhalfbg & bgmask3;
251 P3(p) = (P3(p) & ~lmask) | ((fgpat | bgpat) & lmask);
252 p += BYTESDONE;
253 rhalf = (glyph << (BLITWIDTH - align));
254 rhalfbg = rhalf ^ ALL1BITS;
255 fgpat = rhalf & fgmask0;
256 bgpat = rhalfbg & bgmask0;
257 P0(p) = ((fgpat | bgpat) & rmask) | (P0(p) & ~rmask);
258 fgpat = rhalf & fgmask1;
259 bgpat = rhalfbg & bgmask1;
260 P1(p) = ((fgpat | bgpat) & rmask) | (P1(p) & ~rmask);
261 fgpat = rhalf & fgmask2;
262 bgpat = rhalfbg & bgmask2;
263 P2(p) = ((fgpat | bgpat) & rmask) | (P2(p) & ~rmask);
264 fgpat = rhalf & fgmask3;
265 bgpat = rhalfbg & bgmask3;
266 P3(p) = ((fgpat | bgpat) & rmask) | (P3(p) & ~rmask);
267
268 p = (q += scanspan);
269 height--;
270 }
271 }
272 }
273
274 static void
275 om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
276 {
277 struct rasops_info *ri = cookie;
278 uint8_t *p;
279 int scanspan, startx, height, width, align, w, y;
280 uint32_t lmask, rmask, fill;
281
282 scanspan = ri->ri_stride;;
283 y = ri->ri_font->fontheight * row;
284 startx = ri->ri_font->fontwidth * startcol;
285 height = ri->ri_font->fontheight;
286 w = ri->ri_font->fontwidth * ncols;
287 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
288
289 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
290 align = startx & ALIGNMASK;
291 width = w + align;
292 lmask = ALL1BITS >> align;
293 rmask = ALL1BITS << (-width & ALIGNMASK);
294 if (width <= BLITWIDTH) {
295 lmask &= rmask;
296 fill &= lmask;
297 while (height > 0) {
298 P0(p) = (P0(p) & ~lmask) | fill;
299 p += scanspan;
300 height--;
301 }
302 } else {
303 uint8_t *q = p;
304 while (height > 0) {
305 P0(p) = (P0(p) & ~lmask) | (fill & lmask);
306 width -= 2 * BLITWIDTH;
307 while (width > 0) {
308 p += BYTESDONE;
309 P0(p) = fill;
310 width -= BLITWIDTH;
311 }
312 p += BYTESDONE;
313 P0(p) = (fill & rmask) | (P0(p) & ~rmask);
314
315 p = (q += scanspan);
316 width = w + align;
317 height--;
318 }
319 }
320 }
321
322 static void
323 om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
324 {
325 struct rasops_info *ri = cookie;
326 uint8_t *p;
327 int scanspan, startx, height, width, align, w, y, fg, bg;
328 uint32_t lmask, rmask, fill0, fill1, fill2, fill3;
329
330 scanspan = ri->ri_stride;;
331 y = ri->ri_font->fontheight * row;
332 startx = ri->ri_font->fontwidth * startcol;
333 height = ri->ri_font->fontheight;
334 w = ri->ri_font->fontwidth * ncols;
335 om4_unpack_attr(attr, &fg, &bg, NULL);
336 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
337 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
338 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
339 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
340
341 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
342 align = startx & ALIGNMASK;
343 width = w + align;
344 lmask = ALL1BITS >> align;
345 rmask = ALL1BITS << (-width & ALIGNMASK);
346 if (width <= BLITWIDTH) {
347 lmask &= rmask;
348 fill0 &= lmask;
349 fill1 &= lmask;
350 fill2 &= lmask;
351 fill3 &= lmask;
352 while (height > 0) {
353 P0(p) = (P0(p) & ~lmask) | fill0;
354 P1(p) = (P1(p) & ~lmask) | fill1;
355 P2(p) = (P2(p) & ~lmask) | fill2;
356 P3(p) = (P3(p) & ~lmask) | fill3;
357 p += scanspan;
358 height--;
359 }
360 } else {
361 uint8_t *q = p;
362 while (height > 0) {
363 P0(p) = (P0(p) & ~lmask) | (fill0 & lmask);
364 P1(p) = (P1(p) & ~lmask) | (fill1 & lmask);
365 P2(p) = (P2(p) & ~lmask) | (fill2 & lmask);
366 P3(p) = (P3(p) & ~lmask) | (fill3 & lmask);
367 width -= 2 * BLITWIDTH;
368 while (width > 0) {
369 p += BYTESDONE;
370 P0(p) = fill0;
371 P1(p) = fill1;
372 P2(p) = fill2;
373 P3(p) = fill3;
374 width -= BLITWIDTH;
375 }
376 p += BYTESDONE;
377 P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
378 P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
379 P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
380 P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
381
382 p = (q += scanspan);
383 width = w + align;
384 height--;
385 }
386 }
387 }
388
389 static void
390 om1_eraserows(void *cookie, int startrow, int nrows, long attr)
391 {
392 struct rasops_info *ri = cookie;
393 uint8_t *p, *q;
394 int scanspan, starty, height, width, w;
395 uint32_t rmask, fill;
396
397 scanspan = ri->ri_stride;
398 starty = ri->ri_font->fontheight * startrow;
399 height = ri->ri_font->fontheight * nrows;
400 w = ri->ri_emuwidth;
401 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS;
402
403 p = (uint8_t *)ri->ri_bits + starty * scanspan;
404 width = w;
405 rmask = ALL1BITS << (-width & ALIGNMASK);
406 q = p;
407 while (height > 0) {
408 P0(p) = fill; /* always aligned */
409 width -= 2 * BLITWIDTH;
410 while (width > 0) {
411 p += BYTESDONE;
412 P0(p) = fill;
413 width -= BLITWIDTH;
414 }
415 p += BYTESDONE;
416 P0(p) = (fill & rmask) | (P0(p) & ~rmask);
417 p = (q += scanspan);
418 width = w;
419 height--;
420 }
421 }
422
423 static void
424 om4_eraserows(void *cookie, int startrow, int nrows, long attr)
425 {
426 struct rasops_info *ri = cookie;
427 uint8_t *p, *q;
428 int scanspan, starty, height, width, w, fg, bg;
429 uint32_t rmask, fill0, fill1, fill2, fill3;
430
431 scanspan = ri->ri_stride;
432 starty = ri->ri_font->fontheight * startrow;
433 height = ri->ri_font->fontheight * nrows;
434 w = ri->ri_emuwidth;
435 om4_unpack_attr(attr, &fg, &bg, NULL);
436 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS;
437 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS;
438 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS;
439 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS;
440
441 p = (uint8_t *)ri->ri_bits + starty * scanspan;
442 width = w;
443 rmask = ALL1BITS << (-width & ALIGNMASK);
444 q = p;
445 while (height > 0) {
446 P0(p) = fill0; /* always aligned */
447 P1(p) = fill1;
448 P2(p) = fill2;
449 P3(p) = fill3;
450 width -= 2 * BLITWIDTH;
451 while (width > 0) {
452 p += BYTESDONE;
453 P0(p) = fill0;
454 P1(p) = fill1;
455 P2(p) = fill2;
456 P3(p) = fill3;
457 width -= BLITWIDTH;
458 }
459 p += BYTESDONE;
460 P0(p) = (fill0 & rmask) | (P0(p) & ~rmask);
461 P1(p) = (fill1 & rmask) | (P1(p) & ~rmask);
462 P2(p) = (fill2 & rmask) | (P2(p) & ~rmask);
463 P3(p) = (fill3 & rmask) | (P3(p) & ~rmask);
464 p = (q += scanspan);
465 width = w;
466 height--;
467 }
468 }
469
470 static void
471 om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
472 {
473 struct rasops_info *ri = cookie;
474 uint8_t *p, *q;
475 int scanspan, offset, srcy, height, width, w;
476 uint32_t rmask;
477
478 scanspan = ri->ri_stride;
479 height = ri->ri_font->fontheight * nrows;
480 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
481 srcy = ri->ri_font->fontheight * srcrow;
482 if (srcrow < dstrow && srcrow + nrows > dstrow) {
483 scanspan = -scanspan;
484 srcy = srcy + height - 1;
485 }
486
487 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
488 w = ri->ri_emuwidth;
489 width = w;
490 rmask = ALL1BITS << (-width & ALIGNMASK);
491 q = p;
492 while (height > 0) {
493 P0(p + offset) = P0(p); /* always aligned */
494 width -= 2 * BLITWIDTH;
495 while (width > 0) {
496 p += BYTESDONE;
497 P0(p + offset) = P0(p);
498 width -= BLITWIDTH;
499 }
500 p += BYTESDONE;
501 P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
502
503 p = (q += scanspan);
504 width = w;
505 height--;
506 }
507 }
508
509 static void
510 om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
511 {
512 struct rasops_info *ri = cookie;
513 uint8_t *p, *q;
514 int scanspan, offset, srcy, height, width, w;
515 uint32_t rmask;
516
517 scanspan = ri->ri_stride;
518 height = ri->ri_font->fontheight * nrows;
519 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
520 srcy = ri->ri_font->fontheight * srcrow;
521 if (srcrow < dstrow && srcrow + nrows > dstrow) {
522 scanspan = -scanspan;
523 srcy = srcy + height - 1;
524 }
525
526 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
527 w = ri->ri_emuwidth;
528 width = w;
529 rmask = ALL1BITS << (-width & ALIGNMASK);
530 q = p;
531 while (height > 0) {
532 P0(p + offset) = P0(p); /* always aligned */
533 P1(p + offset) = P1(p);
534 P2(p + offset) = P2(p);
535 P3(p + offset) = P3(p);
536 width -= 2 * BLITWIDTH;
537 while (width > 0) {
538 p += BYTESDONE;
539 P0(p + offset) = P0(p);
540 P1(p + offset) = P1(p);
541 P2(p + offset) = P2(p);
542 P3(p + offset) = P3(p);
543 width -= BLITWIDTH;
544 }
545 p += BYTESDONE;
546 P0(p + offset) = (P0(p) & rmask) | (P0(p + offset) & ~rmask);
547 P1(p + offset) = (P1(p) & rmask) | (P1(p + offset) & ~rmask);
548 P2(p + offset) = (P2(p) & rmask) | (P2(p + offset) & ~rmask);
549 P3(p + offset) = (P3(p) & rmask) | (P3(p + offset) & ~rmask);
550
551 p = (q += scanspan);
552 width = w;
553 height--;
554 }
555 }
556
557 static void
558 om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
559 {
560 struct rasops_info *ri = cookie;
561 uint8_t *sp, *dp, *sq, *dq, *basep;
562 int scanspan, height, w, y, srcx, dstx;
563 int sb, eb, db, sboff, full, cnt, lnum, rnum;
564 uint32_t lmask, rmask, tmp;
565 bool sbover;
566
567 scanspan = ri->ri_stride;
568 y = ri->ri_font->fontheight * startrow;
569 srcx = ri->ri_font->fontwidth * srccol;
570 dstx = ri->ri_font->fontwidth * dstcol;
571 height = ri->ri_font->fontheight;
572 w = ri->ri_font->fontwidth * ncols;
573 basep = (uint8_t *)ri->ri_bits + y * scanspan;
574
575 sb = srcx & ALIGNMASK;
576 db = dstx & ALIGNMASK;
577
578 if (db + w <= BLITWIDTH) {
579 /* Destination is contained within a single word */
580 sp = basep + (srcx / 32) * 4;
581 dp = basep + (dstx / 32) * 4;
582
583 while (height > 0) {
584 GETBITS(P0(sp), sb, w, tmp);
585 PUTBITS(tmp, db, w, P0(dp));
586 dp += scanspan;
587 sp += scanspan;
588 height--;
589 }
590 return;
591 }
592
593 lmask = (db == 0) ? 0 : ALL1BITS >> db;
594 eb = (db + w) & ALIGNMASK;
595 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
596 lnum = (32 - db) & ALIGNMASK;
597 rnum = (dstx + w) & ALIGNMASK;
598
599 if (lmask != 0)
600 full = (w - (32 - db)) / 32;
601 else
602 full = w / 32;
603
604 sbover = (sb + lnum) >= 32;
605
606 if (dstcol < srccol || srccol + ncols < dstcol) {
607 /* copy forward (left-to-right) */
608 sp = basep + (srcx / 32) * 4;
609 dp = basep + (dstx / 32) * 4;
610
611 if (lmask != 0) {
612 sboff = sb + lnum;
613 if (sboff >= 32)
614 sboff -= 32;
615 } else
616 sboff = sb;
617
618 sq = sp;
619 dq = dp;
620 while (height > 0) {
621 if (lmask != 0) {
622 GETBITS(P0(sp), sb, lnum, tmp);
623 PUTBITS(tmp, db, lnum, P0(dp));
624 dp += BYTESDONE;
625 if (sbover)
626 sp += BYTESDONE;
627 }
628
629 for (cnt = full; cnt; cnt--) {
630 GETBITS(P0(sp), sboff, 32, tmp);
631 P0(dp) = tmp;
632 sp += BYTESDONE;
633 dp += BYTESDONE;
634 }
635
636 if (rmask != 0) {
637 GETBITS(P0(sp), sboff, rnum, tmp);
638 PUTBITS(tmp, 0, rnum, P0(dp));
639 }
640
641 sp = (sq += scanspan);
642 dp = (dq += scanspan);
643 height--;
644 }
645 } else {
646 /* copy backward (right-to-left) */
647 sp = basep + ((srcx + w) / 32) * 4;
648 dp = basep + ((dstx + w) / 32) * 4;
649
650 sboff = (srcx + w) & ALIGNMASK;
651 sboff -= rnum;
652 if (sboff < 0) {
653 sp -= BYTESDONE;
654 sboff += 32;
655 }
656
657 sq = sp;
658 dq = dp;
659 while (height > 0) {
660 if (rnum != 0) {
661 GETBITS(P0(sp), sboff, rnum, tmp);
662 PUTBITS(tmp, 0, rnum, P0(dp));
663 }
664
665 for (cnt = full; cnt; cnt--) {
666 sp -= BYTESDONE;
667 dp -= BYTESDONE;
668 GETBITS(P0(sp), sboff, 32, tmp);
669 P0(dp) = tmp;
670 }
671
672 if (lmask != 0) {
673 if (sbover)
674 sp -= BYTESDONE;
675 dp -= BYTESDONE;
676 GETBITS(P0(sp), sb, lnum, tmp);
677 PUTBITS(tmp, db, lnum, P0(dp));
678 }
679
680 sp = (sq += scanspan);
681 dp = (dq += scanspan);
682 height--;
683 }
684 }
685 }
686
687 static void
688 om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
689 {
690 struct rasops_info *ri = cookie;
691 uint8_t *sp, *dp, *sq, *dq, *basep;
692 int scanspan, height, w, y, srcx, dstx;
693 int sb, eb, db, sboff, full, cnt, lnum, rnum;
694 uint32_t lmask, rmask, tmp;
695 bool sbover;
696
697 scanspan = ri->ri_stride;
698 y = ri->ri_font->fontheight * startrow;
699 srcx = ri->ri_font->fontwidth * srccol;
700 dstx = ri->ri_font->fontwidth * dstcol;
701 height = ri->ri_font->fontheight;
702 w = ri->ri_font->fontwidth * ncols;
703 basep = (uint8_t *)ri->ri_bits + y * scanspan;
704
705 sb = srcx & ALIGNMASK;
706 db = dstx & ALIGNMASK;
707
708 if (db + w <= BLITWIDTH) {
709 /* Destination is contained within a single word */
710 sp = basep + (srcx / 32) * 4;
711 dp = basep + (dstx / 32) * 4;
712
713 while (height > 0) {
714 GETBITS(P0(sp), sb, w, tmp);
715 PUTBITS(tmp, db, w, P0(dp));
716 GETBITS(P1(sp), sb, w, tmp);
717 PUTBITS(tmp, db, w, P1(dp));
718 GETBITS(P2(sp), sb, w, tmp);
719 PUTBITS(tmp, db, w, P2(dp));
720 GETBITS(P3(sp), sb, w, tmp);
721 PUTBITS(tmp, db, w, P3(dp));
722 dp += scanspan;
723 sp += scanspan;
724 height--;
725 }
726 return;
727 }
728
729 lmask = (db == 0) ? 0 : ALL1BITS >> db;
730 eb = (db + w) & ALIGNMASK;
731 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
732 lnum = (32 - db) & ALIGNMASK;
733 rnum = (dstx + w) & ALIGNMASK;
734
735 if (lmask != 0)
736 full = (w - (32 - db)) / 32;
737 else
738 full = w / 32;
739
740 sbover = (sb + lnum) >= 32;
741
742 if (dstcol < srccol || srccol + ncols < dstcol) {
743 /* copy forward (left-to-right) */
744 sp = basep + (srcx / 32) * 4;
745 dp = basep + (dstx / 32) * 4;
746
747 if (lmask != 0) {
748 sboff = sb + lnum;
749 if (sboff >= 32)
750 sboff -= 32;
751 } else
752 sboff = sb;
753
754 sq = sp;
755 dq = dp;
756 while (height > 0) {
757 if (lmask != 0) {
758 GETBITS(P0(sp), sb, lnum, tmp);
759 PUTBITS(tmp, db, lnum, P0(dp));
760 GETBITS(P1(sp), sb, lnum, tmp);
761 PUTBITS(tmp, db, lnum, P1(dp));
762 GETBITS(P2(sp), sb, lnum, tmp);
763 PUTBITS(tmp, db, lnum, P2(dp));
764 GETBITS(P3(sp), sb, lnum, tmp);
765 PUTBITS(tmp, db, lnum, P3(dp));
766 dp += BYTESDONE;
767 if (sbover)
768 sp += BYTESDONE;
769 }
770
771 for (cnt = full; cnt; cnt--) {
772 GETBITS(P0(sp), sboff, 32, tmp);
773 P0(dp) = tmp;
774 GETBITS(P1(sp), sboff, 32, tmp);
775 P1(dp) = tmp;
776 GETBITS(P2(sp), sboff, 32, tmp);
777 P2(dp) = tmp;
778 GETBITS(P3(sp), sboff, 32, tmp);
779 P3(dp) = tmp;
780 sp += BYTESDONE;
781 dp += BYTESDONE;
782 }
783
784 if (rmask != 0) {
785 GETBITS(P0(sp), sboff, rnum, tmp);
786 PUTBITS(tmp, 0, rnum, P0(dp));
787 GETBITS(P1(sp), sboff, rnum, tmp);
788 PUTBITS(tmp, 0, rnum, P1(dp));
789 GETBITS(P2(sp), sboff, rnum, tmp);
790 PUTBITS(tmp, 0, rnum, P2(dp));
791 GETBITS(P3(sp), sboff, rnum, tmp);
792 PUTBITS(tmp, 0, rnum, P3(dp));
793 }
794
795 sp = (sq += scanspan);
796 dp = (dq += scanspan);
797 height--;
798 }
799 } else {
800 /* copy backward (right-to-left) */
801 sp = basep + ((srcx + w) / 32) * 4;
802 dp = basep + ((dstx + w) / 32) * 4;
803
804 sboff = (srcx + w) & ALIGNMASK;
805 sboff -= rnum;
806 if (sboff < 0) {
807 sp -= BYTESDONE;
808 sboff += 32;
809 }
810
811 sq = sp;
812 dq = dp;
813 while (height > 0) {
814 if (rnum != 0) {
815 GETBITS(P0(sp), sboff, rnum, tmp);
816 PUTBITS(tmp, 0, rnum, P0(dp));
817 GETBITS(P1(sp), sboff, rnum, tmp);
818 PUTBITS(tmp, 0, rnum, P1(dp));
819 GETBITS(P2(sp), sboff, rnum, tmp);
820 PUTBITS(tmp, 0, rnum, P2(dp));
821 GETBITS(P3(sp), sboff, rnum, tmp);
822 PUTBITS(tmp, 0, rnum, P3(dp));
823 }
824
825 for (cnt = full; cnt; cnt--) {
826 sp -= BYTESDONE;
827 dp -= BYTESDONE;
828 GETBITS(P0(sp), sboff, 32, tmp);
829 P0(dp) = tmp;
830 GETBITS(P1(sp), sboff, 32, tmp);
831 P1(dp) = tmp;
832 GETBITS(P2(sp), sboff, 32, tmp);
833 P2(dp) = tmp;
834 GETBITS(P3(sp), sboff, 32, tmp);
835 P3(dp) = tmp;
836 }
837
838 if (lmask != 0) {
839 if (sbover)
840 sp -= BYTESDONE;
841 dp -= BYTESDONE;
842 GETBITS(P0(sp), sb, lnum, tmp);
843 PUTBITS(tmp, db, lnum, P0(dp));
844 GETBITS(P1(sp), sb, lnum, tmp);
845 PUTBITS(tmp, db, lnum, P1(dp));
846 GETBITS(P2(sp), sb, lnum, tmp);
847 PUTBITS(tmp, db, lnum, P2(dp));
848 GETBITS(P3(sp), sb, lnum, tmp);
849 PUTBITS(tmp, db, lnum, P3(dp));
850 }
851
852 sp = (sq += scanspan);
853 dp = (dq += scanspan);
854 height--;
855 }
856 }
857 }
858
859 /*
860 * Map a character.
861 */
862 static int
863 om_mapchar(void *cookie, int c, u_int *cp)
864 {
865 struct rasops_info *ri = cookie;
866 struct wsdisplay_font *wf = ri->ri_font;
867
868 if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
869 c = wsfont_map_unichar(wf, c);
870
871 if (c < 0)
872 goto fail;
873 }
874 if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
875 goto fail;
876
877 *cp = c;
878 return 5;
879
880 fail:
881 *cp = ' ';
882 return 0;
883 }
884
885 /*
886 * Position|{enable|disable} the cursor at the specified location.
887 */
888 static void
889 om1_cursor(void *cookie, int on, int row, int col)
890 {
891 struct rasops_info *ri = cookie;
892 uint8_t *p;
893 int scanspan, startx, height, width, align, y;
894 uint32_t lmask, rmask, image;
895
896 if (!on) {
897 /* make sure it's on */
898 if ((ri->ri_flg & RI_CURSOR) == 0)
899 return;
900
901 row = ri->ri_crow;
902 col = ri->ri_ccol;
903 } else {
904 /* unpaint the old copy. */
905 ri->ri_crow = row;
906 ri->ri_ccol = col;
907 }
908
909 scanspan = ri->ri_stride;
910 y = ri->ri_font->fontheight * row;
911 startx = ri->ri_font->fontwidth * col;
912 height = ri->ri_font->fontheight;
913
914 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
915 align = startx & ALIGNMASK;
916 width = ri->ri_font->fontwidth + align;
917 lmask = ALL1BITS >> align;
918 rmask = ALL1BITS << (-width & ALIGNMASK);
919 if (width <= BLITWIDTH) {
920 lmask &= rmask;
921 while (height > 0) {
922 image = P0(p);
923 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
924 p += scanspan;
925 height--;
926 }
927 } else {
928 uint8_t *q = p;
929
930 while (height > 0) {
931 image = P0(p);
932 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
933 p += BYTESDONE;
934 image = P0(p);
935 P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
936
937 p = (q += scanspan);
938 height--;
939 }
940 }
941 ri->ri_flg ^= RI_CURSOR;
942 }
943
944 static void
945 om4_cursor(void *cookie, int on, int row, int col)
946 {
947 struct rasops_info *ri = cookie;
948 uint8_t *p;
949 int scanspan, startx, height, width, align, y;
950 uint32_t lmask, rmask, image;
951
952 if (!on) {
953 /* make sure it's on */
954 if ((ri->ri_flg & RI_CURSOR) == 0)
955 return;
956
957 row = ri->ri_crow;
958 col = ri->ri_ccol;
959 } else {
960 /* unpaint the old copy. */
961 ri->ri_crow = row;
962 ri->ri_ccol = col;
963 }
964
965 scanspan = ri->ri_stride;
966 y = ri->ri_font->fontheight * row;
967 startx = ri->ri_font->fontwidth * col;
968 height = ri->ri_font->fontheight;
969
970 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
971 align = startx & ALIGNMASK;
972 width = ri->ri_font->fontwidth + align;
973 lmask = ALL1BITS >> align;
974 rmask = ALL1BITS << (-width & ALIGNMASK);
975 if (width <= BLITWIDTH) {
976 lmask &= rmask;
977 while (height > 0) {
978 image = P0(p);
979 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
980 image = P1(p);
981 P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
982 image = P2(p);
983 P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
984 image = P3(p);
985 P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
986 p += scanspan;
987 height--;
988 }
989 } else {
990 uint8_t *q = p;
991
992 while (height > 0) {
993 image = P0(p);
994 P0(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
995 image = P1(p);
996 P1(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
997 image = P2(p);
998 P2(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
999 image = P3(p);
1000 P3(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
1001 p += BYTESDONE;
1002 image = P0(p);
1003 P0(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
1004 image = P1(p);
1005 P1(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
1006 image = P2(p);
1007 P2(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
1008 image = P3(p);
1009 P3(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
1010
1011 p = (q += scanspan);
1012 height--;
1013 }
1014 }
1015 ri->ri_flg ^= RI_CURSOR;
1016 }
1017
1018 /*
1019 * Allocate attribute. We just pack these into an integer.
1020 */
1021 static int
1022 om1_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1023 {
1024
1025 if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
1026 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
1027 return EINVAL;
1028 if ((flags & WSATTR_REVERSE) != 0)
1029 *attrp = 1;
1030 else
1031 *attrp = 0;
1032 return 0;
1033 }
1034
1035 static int
1036 om4_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1037 {
1038
1039 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
1040 return EINVAL;
1041 if ((flags & WSATTR_WSCOLORS) == 0) {
1042 fg = WSCOL_WHITE;
1043 bg = WSCOL_BLACK;
1044 }
1045
1046 if ((flags & WSATTR_REVERSE) != 0) {
1047 int swap;
1048 swap = fg;
1049 fg = bg;
1050 bg = swap;
1051 }
1052
1053 if ((flags & WSATTR_HILIT) != 0)
1054 fg += 8;
1055
1056 *attrp = (fg << 24) | (bg << 16);
1057 return 0;
1058 }
1059
1060 static void
1061 om4_unpack_attr(long attr, int *fg, int *bg, int *underline)
1062 {
1063
1064 *fg = ((u_int)attr >> 24) & 0xf;
1065 *bg = ((u_int)attr >> 16) & 0xf;
1066 }
1067
1068 /*
1069 * Init subset of rasops(9) for omrasops.
1070 */
1071 int
1072 omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
1073 {
1074
1075 omrasops_init(ri, wantrows, wantcols);
1076
1077 /* fill our own emulops */
1078 ri->ri_ops.cursor = om1_cursor;
1079 ri->ri_ops.mapchar = om_mapchar;
1080 ri->ri_ops.putchar = om1_putchar;
1081 ri->ri_ops.copycols = om1_copycols;
1082 ri->ri_ops.erasecols = om1_erasecols;
1083 ri->ri_ops.copyrows = om1_copyrows;
1084 ri->ri_ops.eraserows = om1_eraserows;
1085 ri->ri_ops.allocattr = om1_allocattr;
1086 ri->ri_caps = WSSCREEN_REVERSE;
1087
1088 ri->ri_flg |= RI_CFGDONE;
1089
1090 return 0;
1091 }
1092
1093 int
1094 omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
1095 {
1096
1097 omrasops_init(ri, wantrows, wantcols);
1098
1099 /* fill our own emulops */
1100 ri->ri_ops.cursor = om4_cursor;
1101 ri->ri_ops.mapchar = om_mapchar;
1102 ri->ri_ops.putchar = om4_putchar;
1103 ri->ri_ops.copycols = om4_copycols;
1104 ri->ri_ops.erasecols = om4_erasecols;
1105 ri->ri_ops.copyrows = om4_copyrows;
1106 ri->ri_ops.eraserows = om4_eraserows;
1107 ri->ri_ops.allocattr = om4_allocattr;
1108 ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1109
1110 ri->ri_flg |= RI_CFGDONE;
1111
1112 return 0;
1113 }
1114
1115 static int
1116 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
1117 {
1118 int wsfcookie, bpp;
1119
1120 if (wantrows == 0)
1121 wantrows = 34;
1122 if (wantrows < 10)
1123 wantrows = 10;
1124 if (wantcols == 0)
1125 wantcols = 80;
1126 if (wantcols < 20)
1127 wantcols = 20;
1128
1129 /* Use default font */
1130 wsfont_init();
1131 wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
1132 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
1133 if (wsfcookie < 0)
1134 panic("%s: no font available", __func__);
1135 if (wsfont_lock(wsfcookie, &ri->ri_font))
1136 panic("%s: unable to lock font", __func__);
1137 ri->ri_wsfcookie = wsfcookie;
1138
1139 KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
1140
1141 /* all planes are independently addressed */
1142 bpp = 1;
1143
1144 /* Now constrain what they get */
1145 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
1146 ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
1147 if (ri->ri_emuwidth > ri->ri_width)
1148 ri->ri_emuwidth = ri->ri_width;
1149 if (ri->ri_emuheight > ri->ri_height)
1150 ri->ri_emuheight = ri->ri_height;
1151
1152 /* Reduce width until aligned on a 32-bit boundary */
1153 while ((ri->ri_emuwidth * bpp & 31) != 0)
1154 ri->ri_emuwidth--;
1155
1156 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
1157 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
1158 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
1159 ri->ri_delta = ri->ri_stride - ri->ri_emustride;
1160 ri->ri_ccol = 0;
1161 ri->ri_crow = 0;
1162 ri->ri_pelbytes = bpp >> 3;
1163
1164 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
1165 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
1166 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
1167
1168 /* Clear the entire display */
1169 if ((ri->ri_flg & RI_CLEAR) != 0)
1170 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
1171
1172 /* Now centre our window if needs be */
1173 ri->ri_origbits = ri->ri_bits;
1174
1175 if ((ri->ri_flg & RI_CENTER) != 0) {
1176 ri->ri_bits += (((ri->ri_width * bpp >> 3) -
1177 ri->ri_emustride) >> 1) & ~3;
1178 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
1179 ri->ri_stride;
1180 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
1181 / ri->ri_stride;
1182 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
1183 % ri->ri_stride) * 8 / bpp);
1184 } else
1185 ri->ri_xorigin = ri->ri_yorigin = 0;
1186
1187 return 0;
1188 }
1189