omrasops.c revision 1.7 1 /* $NetBSD: omrasops.c,v 1.7 2009/03/14 14:46:00 dsl 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.7 2009/03/14 14:46:00 dsl 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 relys on;
41 * - every memory references is done in aligned 32bit chunk,
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/rcons/raster.h>
50 #include <dev/wscons/wscons_raster.h>
51 #include <dev/wscons/wscons_rfont.h>
52 #include <dev/wscons/wsdisplayvar.h>
53
54 void rcons_init(struct rcons *, int, int);
55
56 /* wscons emulator operations */
57 static void om_cursor(void *, int, int, int);
58 static int om_mapchar(void *, int, unsigned int *);
59 static void om_putchar(void *, int, int, u_int, long);
60 static void om_copycols(void *, int, int, int, int);
61 static void om_copyrows(void *, int, int, int num);
62 static void om_erasecols(void *, int, int, int, long);
63 static void om_eraserows(void *, int, int, long);
64 static int om_allocattr(void *, int, int, int, long *);
65
66 struct wsdisplay_emulops omfb_emulops = {
67 om_cursor,
68 om_mapchar,
69 om_putchar,
70 om_copycols,
71 om_erasecols,
72 om_copyrows,
73 om_eraserows,
74 om_allocattr
75 };
76
77 #define ALL1BITS (~0U)
78 #define ALL0BITS (0U)
79 #define BLITWIDTH (32)
80 #define ALIGNMASK (0x1f)
81 #define BYTESDONE (4)
82
83 #define W(p) (*(u_int32_t *)(p))
84 #define R(p) (*(u_int32_t *)((uint8_t *)(p) + 0x40000))
85
86 /*
87 * Blit a character at the specified co-ordinates.
88 */
89 static void
90 om_putchar(cookie, row, startcol, uc, attr)
91 void *cookie;
92 int row, startcol;
93 u_int uc;
94 long attr;
95 {
96 struct rcons *rc = cookie;
97 struct raster *rap = rc->rc_sp;
98 uint8_t *p;
99 int scanspan, startx, height, width, align, y;
100 u_int32_t lmask, rmask, glyph, inverse;
101 u_int32_t *g;
102
103 scanspan = rap->linelongs * 4;
104 y = rc->rc_yorigin + rc->rc_font->height * row;
105 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
106 height = rc->rc_font->height;
107 g = rc->rc_font->chars[uc].r->pixels;
108 inverse = (attr != 0) ? ALL1BITS : ALL0BITS;
109
110 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
111 align = startx & ALIGNMASK;
112 width = rc->rc_font->width + align;
113 lmask = ALL1BITS >> align;
114 rmask = ALL1BITS << (-width & ALIGNMASK);
115 if (width <= BLITWIDTH) {
116 lmask &= rmask;
117 while (height > 0) {
118 glyph = *g;
119 glyph = (glyph >> align) ^ inverse;
120 W(p) = (R(p) & ~lmask) | (glyph & lmask);
121 p += scanspan;
122 g += 1;
123 height--;
124 }
125 }
126 else {
127 uint8_t *q = p;
128 u_int32_t lhalf, rhalf;
129
130 while (height > 0) {
131 glyph = *g;
132 lhalf = (glyph >> align) ^ inverse;
133 W(p) = (R(p) & ~lmask) | (lhalf & lmask);
134 p += BYTESDONE;
135 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse;
136 W(p) = (rhalf & rmask) | (R(p) & ~rmask);
137
138 p = (q += scanspan);
139 g += 1;
140 height--;
141 }
142 }
143 }
144
145 static void
146 om_erasecols(cookie, row, startcol, ncols, attr)
147 void *cookie;
148 int row, startcol, ncols;
149 long attr;
150 {
151 struct rcons *rc = cookie;
152 struct raster *rap = rc->rc_sp;
153 uint8_t *p;
154 int scanspan, startx, height, width, align, w, y;
155 u_int32_t lmask, rmask, fill;
156
157 scanspan = rap->linelongs * 4;
158 y = rc->rc_yorigin + rc->rc_font->height * row;
159 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
160 height = rc->rc_font->height;
161 w = rc->rc_font->width * ncols;
162 fill = (attr != 0) ? ALL1BITS : ALL0BITS;
163
164 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
165 align = startx & ALIGNMASK;
166 width = w + align;
167 lmask = ALL1BITS >> align;
168 rmask = ALL1BITS << (-width & ALIGNMASK);
169 if (width <= BLITWIDTH) {
170 lmask &= rmask;
171 fill &= lmask;
172 while (height > 0) {
173 W(p) = (R(p) & ~lmask) | fill;
174 p += scanspan;
175 height--;
176 }
177 }
178 else {
179 uint8_t *q = p;
180 while (height > 0) {
181 W(p) = (R(p) & ~lmask) | (fill & lmask);
182 width -= 2 * BLITWIDTH;
183 while (width > 0) {
184 p += BYTESDONE;
185 W(p) = fill;
186 width -= BLITWIDTH;
187 }
188 p += BYTESDONE;
189 W(p) = (fill & rmask) | (R(p) & ~rmask);
190
191 p = (q += scanspan);
192 width = w + align;
193 height--;
194 }
195 }
196 }
197
198 static void
199 om_eraserows(cookie, startrow, nrows, attr)
200 void *cookie;
201 int startrow, nrows;
202 long attr;
203 {
204 struct rcons *rc = cookie;
205 struct raster *rap = rc->rc_sp;
206 uint8_t *p, *q;
207 int scanspan, starty, height, width, w;
208 u_int32_t rmask, fill;
209
210 scanspan = rap->linelongs * 4;
211 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
212 height = rc->rc_font->height * nrows;
213 w = rc->rc_font->width * rc->rc_maxcol;
214 fill = (attr == 1) ? ALL1BITS : ALL0BITS;
215
216 p = (uint8_t *)rap->pixels + starty * scanspan;
217 p += (rc->rc_xorigin / 32) * 4;
218 width = w;
219 rmask = ALL1BITS << (-width & ALIGNMASK);
220 q = p;
221 while (height > 0) {
222 W(p) = fill; /* always aligned */
223 width -= 2 * BLITWIDTH;
224 while (width > 0) {
225 p += BYTESDONE;
226 W(p) = fill;
227 width -= BLITWIDTH;
228 }
229 p += BYTESDONE;
230 W(p) = (fill & rmask) | (R(p) & ~rmask);
231 p = (q += scanspan);
232 width = w;
233 height--;
234 }
235 }
236
237 static void
238 om_copyrows(cookie, srcrow, dstrow, nrows)
239 void *cookie;
240 int srcrow, dstrow, nrows;
241 {
242 struct rcons *rc = cookie;
243 struct raster *rap = rc->rc_sp;
244 uint8_t *p, *q;
245 int scanspan, offset, srcy, height, width, w;
246 u_int32_t rmask;
247
248 scanspan = rap->linelongs * 4;
249 height = rc->rc_font->height * nrows;
250 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
251 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
252 if (srcrow < dstrow && srcrow + nrows > dstrow) {
253 scanspan = -scanspan;
254 srcy += height;
255 }
256
257 p = (uint8_t *)rap->pixels + srcy * (rap->linelongs * 4);
258 p += (rc->rc_xorigin / 32) * 4;
259 w = rc->rc_font->width * rc->rc_maxcol;
260 width = w;
261 rmask = ALL1BITS << (-width & ALIGNMASK);
262 q = p;
263 while (height > 0) {
264 W(p + offset) = R(p); /* always aligned */
265 width -= 2 * BLITWIDTH;
266 while (width > 0) {
267 p += BYTESDONE;
268 W(p + offset) = R(p);
269 width -= BLITWIDTH;
270 }
271 p += BYTESDONE;
272 W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask);
273
274 p = (q += scanspan);
275 width = w;
276 height--;
277 }
278 }
279
280 static void
281 om_copycols(cookie, startrow, srccol, dstcol, ncols)
282 void *cookie;
283 int startrow, srccol, dstcol, ncols;
284 {
285 struct rcons *rc = cookie;
286 struct raster *rap = rc->rc_sp;
287 uint8_t *sp, *dp, *basep;
288 int scanspan, height, width, align, shift, w, y, srcx, dstx;
289 u_int32_t lmask, rmask;
290
291 scanspan = rap->linelongs * 4;
292 y = rc->rc_yorigin + rc->rc_font->height * startrow;
293 srcx = rc->rc_xorigin + rc->rc_font->width * srccol;
294 dstx = rc->rc_xorigin + rc->rc_font->width * dstcol;
295 height = rc->rc_font->height;
296 w = rc->rc_font->width * ncols;
297 basep = (uint8_t *)rap->pixels + y * scanspan;
298
299 align = shift = srcx & ALIGNMASK;
300 width = w + align;
301 align = dstx & ALIGNMASK;
302 lmask = ALL1BITS >> align;
303 rmask = ALL1BITS << (-(w + align) & ALIGNMASK);
304 shift = align - shift;
305 sp = basep + (srcx / 32) * 4;
306 dp = basep + (dstx / 32) * 4;
307
308 if (shift != 0)
309 goto hardluckalignment;
310
311 /* alignments comfortably match */
312 if (width <= BLITWIDTH) {
313 lmask &= rmask;
314 while (height > 0) {
315 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
316 dp += scanspan;
317 sp += scanspan;
318 height--;
319 }
320 }
321 /* copy forward (left-to-right) */
322 else if (dstcol < srccol || srccol + ncols < dstcol) {
323 uint8_t *sq = sp, *dq = dp;
324
325 w = width;
326 while (height > 0) {
327 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
328 width -= 2 * BLITWIDTH;
329 while (width > 0) {
330 sp += BYTESDONE;
331 dp += BYTESDONE;
332 W(dp) = R(sp);
333 width -= BLITWIDTH;
334 }
335 sp += BYTESDONE;
336 dp += BYTESDONE;
337 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
338 sp = (sq += scanspan);
339 dp = (dq += scanspan);
340 width = w;
341 height--;
342 }
343 }
344 /* copy backward (right-to-left) */
345 else {
346 uint8_t *sq, *dq;
347
348 sq = (sp += width / 32 * 4);
349 dq = (dp += width / 32 * 4);
350 w = width;
351 while (height > 0) {
352 W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask);
353 width -= 2 * BLITWIDTH;
354 while (width > 0) {
355 sp -= BYTESDONE;
356 dp -= BYTESDONE;
357 W(dp) = R(sp);
358 width -= BLITWIDTH;
359 }
360 sp -= BYTESDONE;
361 dp -= BYTESDONE;
362 W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask);
363
364 sp = (sq += scanspan);
365 dp = (dq += scanspan);
366 width = w;
367 height--;
368 }
369 }
370 return;
371
372 hardluckalignment:
373 /* alignments painfully disagree */
374 return;
375 }
376
377 /*
378 * Map a character.
379 */
380 static int
381 om_mapchar(cookie, c, cp)
382 void *cookie;
383 int c;
384 u_int *cp;
385 {
386 if (c < 128) {
387 *cp = c;
388 return (5);
389 }
390 *cp = ' ';
391 return (0);
392 }
393
394 /*
395 * Position|{enable|disable} the cursor at the specified location.
396 */
397 static void
398 om_cursor(cookie, on, row, col)
399 void *cookie;
400 int on, row, col;
401 {
402 struct rcons *rc = cookie;
403 struct raster *rap = rc->rc_sp;
404 uint8_t *p;
405 int scanspan, startx, height, width, align, y;
406 u_int32_t lmask, rmask, image;
407
408 if (!on) {
409 /* make sure it's on */
410 if ((rc->rc_bits & RC_CURSOR) == 0)
411 return;
412
413 row = *rc->rc_crowp;
414 col = *rc->rc_ccolp;
415 } else {
416 /* unpaint the old copy. */
417 *rc->rc_crowp = row;
418 *rc->rc_ccolp = col;
419 }
420
421 scanspan = rap->linelongs * 4;
422 y = rc->rc_yorigin + rc->rc_font->height * row;
423 startx = rc->rc_xorigin + rc->rc_font->width * col;
424 height = rc->rc_font->height;
425
426 p = (uint8_t *)rap->pixels + y * scanspan + ((startx / 32) * 4);
427 align = startx & ALIGNMASK;
428 width = rc->rc_font->width + align;
429 lmask = ALL1BITS >> align;
430 rmask = ALL1BITS << (-width & ALIGNMASK);
431 if (width <= BLITWIDTH) {
432 lmask &= rmask;
433 while (height > 0) {
434 image = R(p);
435 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
436 p += scanspan;
437 height--;
438 }
439 }
440 else {
441 uint8_t *q = p;
442
443 while (height > 0) {
444 image = R(p);
445 W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask);
446 p += BYTESDONE;
447 image = R(p);
448 W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask);
449
450 p = (q += scanspan);
451 height--;
452 }
453 }
454 rc->rc_bits ^= RC_CURSOR;
455 }
456
457 /*
458 * Allocate attribute. We just pack these into an integer.
459 */
460 static int
461 om_allocattr(id, fg, bg, flags, attrp)
462 void *id;
463 int fg, bg, flags;
464 long *attrp;
465 {
466 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
467 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
468 return (EINVAL);
469 if (flags & WSATTR_REVERSE)
470 *attrp = 1;
471 else
472 *attrp = 0;
473 return (0);
474 }
475
476 void
477 rcons_init(rc, mrow, mcol)
478 struct rcons *rc;
479 int mrow, mcol;
480 {
481 struct raster *rp = rc->rc_sp;
482 int i;
483
484 rc->rc_font = &gallant19; /* 12x22 monospacing font */
485
486 /* Get distance to top and bottom of font from font origin */
487 rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey;
488
489 i = rp->height / rc->rc_font->height;
490 rc->rc_maxrow = min(i, mrow);
491
492 i = rp->width / rc->rc_font->width;
493 rc->rc_maxcol = min(i, mcol);
494
495 /* Center emulator screen (but align x origin to 32 bits) */
496 rc->rc_xorigin =
497 ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK;
498 rc->rc_yorigin =
499 (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2;
500 #if 0
501 /* Raster width used for row copies */
502 rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width;
503 if (rc->rc_raswidth & ALIGNMASK) {
504 /* Pad to 32 bits */
505 i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK;
506 /* Make sure width isn't too wide */
507 if (rc->rc_xorigin + i <= rp->width)
508 rc->rc_raswidth = i;
509 }
510 #endif
511 rc->rc_bits = 0;
512 }
513