rasops.c revision 1.92 1 1.92 rin /* $NetBSD: rasops.c,v 1.92 2019/07/26 11:16:19 rin Exp $ */
2 1.1 ad
3 1.9 ad /*-
4 1.9 ad * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 1.1 ad * All rights reserved.
6 1.1 ad *
7 1.9 ad * This code is derived from software contributed to The NetBSD Foundation
8 1.32 ad * by Andrew Doran.
9 1.9 ad *
10 1.1 ad * Redistribution and use in source and binary forms, with or without
11 1.1 ad * modification, are permitted provided that the following conditions
12 1.1 ad * are met:
13 1.1 ad * 1. Redistributions of source code must retain the above copyright
14 1.1 ad * notice, this list of conditions and the following disclaimer.
15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 ad * notice, this list of conditions and the following disclaimer in the
17 1.1 ad * documentation and/or other materials provided with the distribution.
18 1.1 ad *
19 1.9 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.9 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.9 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.9 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.9 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.9 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.9 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.9 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.9 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.9 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.9 ad * POSSIBILITY OF SUCH DAMAGE.
30 1.1 ad */
31 1.2 ad
32 1.1 ad #include <sys/cdefs.h>
33 1.92 rin __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.92 2019/07/26 11:16:19 rin Exp $");
34 1.1 ad
35 1.18 ad #include "opt_rasops.h"
36 1.4 ad #include "rasops_glue.h"
37 1.47 macallan #include "opt_wsmsgattrs.h"
38 1.1 ad
39 1.1 ad #include <sys/param.h>
40 1.89 rin #include <sys/bswap.h>
41 1.89 rin #include <sys/kmem.h>
42 1.1 ad #include <sys/systm.h>
43 1.1 ad #include <sys/time.h>
44 1.1 ad
45 1.4 ad #include <machine/endian.h>
46 1.3 ad
47 1.1 ad #include <dev/wscons/wsdisplayvar.h>
48 1.1 ad #include <dev/wscons/wsconsio.h>
49 1.1 ad #include <dev/wsfont/wsfont.h>
50 1.1 ad #include <dev/rasops/rasops.h>
51 1.1 ad
52 1.11 ad #ifndef _KERNEL
53 1.11 ad #include <errno.h>
54 1.11 ad #endif
55 1.11 ad
56 1.70 macallan #ifdef RASOPS_DEBUG
57 1.88 rin #define DPRINTF(...) aprint_error(...)
58 1.70 macallan #else
59 1.88 rin #define DPRINTF(...) __nothing
60 1.70 macallan #endif
61 1.70 macallan
62 1.70 macallan struct rasops_matchdata {
63 1.70 macallan struct rasops_info *ri;
64 1.70 macallan int wantcols, wantrows;
65 1.70 macallan int bestscore;
66 1.70 macallan struct wsdisplay_font *pick;
67 1.70 macallan int ident;
68 1.70 macallan };
69 1.70 macallan
70 1.1 ad /* ANSI colormap (R,G,B). Upper 8 are high-intensity */
71 1.89 rin const uint8_t rasops_cmap[256 * 3] = {
72 1.1 ad 0x00, 0x00, 0x00, /* black */
73 1.1 ad 0x7f, 0x00, 0x00, /* red */
74 1.1 ad 0x00, 0x7f, 0x00, /* green */
75 1.1 ad 0x7f, 0x7f, 0x00, /* brown */
76 1.1 ad 0x00, 0x00, 0x7f, /* blue */
77 1.1 ad 0x7f, 0x00, 0x7f, /* magenta */
78 1.1 ad 0x00, 0x7f, 0x7f, /* cyan */
79 1.1 ad 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
80 1.1 ad
81 1.1 ad 0x7f, 0x7f, 0x7f, /* black */
82 1.1 ad 0xff, 0x00, 0x00, /* red */
83 1.1 ad 0x00, 0xff, 0x00, /* green */
84 1.1 ad 0xff, 0xff, 0x00, /* brown */
85 1.1 ad 0x00, 0x00, 0xff, /* blue */
86 1.1 ad 0xff, 0x00, 0xff, /* magenta */
87 1.1 ad 0x00, 0xff, 0xff, /* cyan */
88 1.1 ad 0xff, 0xff, 0xff, /* white */
89 1.23 drochner
90 1.23 drochner /*
91 1.23 drochner * For the cursor, we need at least the last (255th)
92 1.23 drochner * color to be white. Fill up white completely for
93 1.23 drochner * simplicity.
94 1.23 drochner */
95 1.23 drochner #define _CMWHITE 0xff, 0xff, 0xff,
96 1.23 drochner #define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
97 1.23 drochner _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
98 1.23 drochner _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
99 1.23 drochner _CMWHITE _CMWHITE _CMWHITE _CMWHITE
100 1.23 drochner _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
101 1.23 drochner _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
102 1.44 uwe _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 /* but not the last one */
103 1.23 drochner #undef _CMWHITE16
104 1.23 drochner #undef _CMWHITE
105 1.44 uwe
106 1.44 uwe /*
107 1.44 uwe * For the cursor the fg/bg indices are bit inverted, so
108 1.44 uwe * provide complimentary colors in the upper 16 entries.
109 1.44 uwe */
110 1.44 uwe 0x7f, 0x7f, 0x7f, /* black */
111 1.44 uwe 0xff, 0x00, 0x00, /* red */
112 1.44 uwe 0x00, 0xff, 0x00, /* green */
113 1.44 uwe 0xff, 0xff, 0x00, /* brown */
114 1.44 uwe 0x00, 0x00, 0xff, /* blue */
115 1.44 uwe 0xff, 0x00, 0xff, /* magenta */
116 1.44 uwe 0x00, 0xff, 0xff, /* cyan */
117 1.44 uwe 0xff, 0xff, 0xff, /* white */
118 1.44 uwe
119 1.44 uwe 0x00, 0x00, 0x00, /* black */
120 1.44 uwe 0x7f, 0x00, 0x00, /* red */
121 1.44 uwe 0x00, 0x7f, 0x00, /* green */
122 1.44 uwe 0x7f, 0x7f, 0x00, /* brown */
123 1.44 uwe 0x00, 0x00, 0x7f, /* blue */
124 1.44 uwe 0x7f, 0x00, 0x7f, /* magenta */
125 1.44 uwe 0x00, 0x7f, 0x7f, /* cyan */
126 1.44 uwe 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
127 1.1 ad };
128 1.1 ad
129 1.1 ad /* True if color is gray */
130 1.81 rin const uint8_t rasops_isgray[16] = {
131 1.30 pk 1, 0, 0, 0,
132 1.1 ad 0, 0, 0, 1,
133 1.1 ad 1, 0, 0, 0,
134 1.89 rin 0, 0, 0, 1,
135 1.1 ad };
136 1.1 ad
137 1.91 rin #ifdef RASOPS_APPLE_PALETTE
138 1.91 rin /*
139 1.91 rin * Approximate ANSI colormap for legacy Apple color palettes
140 1.91 rin */
141 1.91 rin static const uint8_t apple8_devcmap[16] = {
142 1.91 rin 0xff, /* black 0x00, 0x00, 0x00 */
143 1.91 rin 0x6b, /* red 0x99, 0x00, 0x00 */
144 1.91 rin 0xc5, /* green 0x00, 0x99, 0x00 */
145 1.91 rin 0x59, /* yellow 0x99, 0x99, 0x00 */
146 1.91 rin 0xd4, /* blue 0x00, 0x00, 0x99 */
147 1.91 rin 0x68, /* magenta 0x99, 0x00, 0x99 */
148 1.91 rin 0xc2, /* cyan 0x00, 0x99, 0x99 */
149 1.91 rin 0x2b, /* white 0xcc, 0xcc, 0xcc */
150 1.91 rin
151 1.91 rin 0x56, /* black 0x99, 0x99, 0x99 */
152 1.91 rin 0x23, /* red 0xff, 0x00, 0x00 */
153 1.91 rin 0xb9, /* green 0x00, 0xff, 0x00 */
154 1.91 rin 0x05, /* yellow 0xff, 0xff, 0x00 */
155 1.91 rin 0xd2, /* blue 0x00, 0x00, 0xff */
156 1.91 rin 0x1e, /* magenta 0xff, 0x00, 0xff */
157 1.91 rin 0xb4, /* cyan 0x00, 0xff, 0xff */
158 1.91 rin 0x00, /* white 0xff, 0xff, 0xff */
159 1.91 rin };
160 1.91 rin
161 1.91 rin static const uint8_t apple4_devcmap[16] = {
162 1.91 rin 15, /* black */
163 1.91 rin 3, /* red */
164 1.91 rin 8, /* green */
165 1.91 rin 1, /* yellow */
166 1.91 rin 6, /* blue */
167 1.91 rin 4, /* magenta */
168 1.91 rin 7, /* cyan */
169 1.91 rin 12, /* light grey */
170 1.91 rin
171 1.91 rin 13, /* medium grey */
172 1.91 rin 3, /* red */
173 1.91 rin 8, /* green */
174 1.91 rin 1, /* yellow */
175 1.91 rin 6, /* blue */
176 1.91 rin 4, /* magenta */
177 1.91 rin 7, /* cyan */
178 1.91 rin 0, /* white */
179 1.91 rin };
180 1.91 rin #endif
181 1.91 rin
182 1.4 ad /* Generic functions */
183 1.45 perry static void rasops_copyrows(void *, int, int, int);
184 1.45 perry static int rasops_mapchar(void *, int, u_int *);
185 1.45 perry static void rasops_cursor(void *, int, int, int);
186 1.45 perry static int rasops_allocattr_color(void *, int, int, int, long *);
187 1.45 perry static int rasops_allocattr_mono(void *, int, int, int, long *);
188 1.45 perry static void rasops_do_cursor(struct rasops_info *);
189 1.45 perry static void rasops_init_devcmap(struct rasops_info *);
190 1.1 ad
191 1.55 ober #if NRASOPS_ROTATION > 0
192 1.62 nonaka static void rasops_rotate_font(int *, int);
193 1.55 ober static void rasops_copychar(void *, int, int, int, int);
194 1.62 nonaka
195 1.62 nonaka /* rotate clockwise */
196 1.62 nonaka static void rasops_copycols_rotated_cw(void *, int, int, int, int);
197 1.62 nonaka static void rasops_copyrows_rotated_cw(void *, int, int, int);
198 1.62 nonaka static void rasops_erasecols_rotated_cw(void *, int, int, int, long);
199 1.62 nonaka static void rasops_eraserows_rotated_cw(void *, int, int, long);
200 1.62 nonaka static void rasops_putchar_rotated_cw(void *, int, int, u_int, long);
201 1.62 nonaka
202 1.62 nonaka /* rotate counter-clockwise */
203 1.62 nonaka static void rasops_copychar_ccw(void *, int, int, int, int);
204 1.62 nonaka static void rasops_copycols_rotated_ccw(void *, int, int, int, int);
205 1.62 nonaka static void rasops_copyrows_rotated_ccw(void *, int, int, int);
206 1.62 nonaka #define rasops_erasecols_rotated_ccw rasops_erasecols_rotated_cw
207 1.62 nonaka #define rasops_eraserows_rotated_ccw rasops_eraserows_rotated_cw
208 1.62 nonaka static void rasops_putchar_rotated_ccw(void *, int, int, u_int, long);
209 1.55 ober
210 1.55 ober /*
211 1.55 ober * List of all rotated fonts
212 1.55 ober */
213 1.55 ober SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
214 1.55 ober struct rotatedfont {
215 1.55 ober SLIST_ENTRY(rotatedfont) rf_next;
216 1.55 ober int rf_cookie;
217 1.55 ober int rf_rotated;
218 1.55 ober };
219 1.55 ober #endif /* NRASOPS_ROTATION > 0 */
220 1.55 ober
221 1.63 macallan void rasops_make_box_chars_8(struct rasops_info *);
222 1.63 macallan void rasops_make_box_chars_16(struct rasops_info *);
223 1.63 macallan void rasops_make_box_chars_32(struct rasops_info *);
224 1.67 macallan void rasops_make_box_chars_alpha(struct rasops_info *);
225 1.63 macallan
226 1.64 macallan extern int cold;
227 1.64 macallan
228 1.1 ad /*
229 1.37 wiz * Initialize a 'rasops_info' descriptor.
230 1.1 ad */
231 1.1 ad int
232 1.60 dsl rasops_init(struct rasops_info *ri, int wantrows, int wantcols)
233 1.1 ad {
234 1.20 ad
235 1.63 macallan memset (&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
236 1.30 pk #ifdef _KERNEL
237 1.1 ad /* Select a font if the caller doesn't care */
238 1.1 ad if (ri->ri_font == NULL) {
239 1.67 macallan int cookie = -1;
240 1.73 mlelstv int flags;
241 1.30 pk
242 1.1 ad wsfont_init();
243 1.1 ad
244 1.70 macallan /*
245 1.70 macallan * first, try to find something that's as close as possible
246 1.70 macallan * to the caller's requested terminal size
247 1.70 macallan */
248 1.70 macallan if (wantrows == 0)
249 1.70 macallan wantrows = RASOPS_DEFAULT_HEIGHT;
250 1.70 macallan if (wantcols == 0)
251 1.70 macallan wantcols = RASOPS_DEFAULT_WIDTH;
252 1.73 mlelstv
253 1.73 mlelstv flags = WSFONT_FIND_BESTWIDTH | WSFONT_FIND_BITMAP;
254 1.73 mlelstv if ((ri->ri_flg & RI_ENABLE_ALPHA) != 0)
255 1.73 mlelstv flags |= WSFONT_FIND_ALPHA;
256 1.75 macallan if ((ri->ri_flg & RI_PREFER_ALPHA) != 0)
257 1.75 macallan flags |= WSFONT_PREFER_ALPHA;
258 1.73 mlelstv cookie = wsfont_find(NULL,
259 1.73 mlelstv ri->ri_width / wantcols,
260 1.73 mlelstv 0,
261 1.73 mlelstv 0,
262 1.73 mlelstv WSDISPLAY_FONTORDER_L2R,
263 1.73 mlelstv WSDISPLAY_FONTORDER_L2R,
264 1.73 mlelstv flags);
265 1.1 ad
266 1.70 macallan /*
267 1.70 macallan * this means there is no supported font in the list
268 1.70 macallan */
269 1.7 ad if (cookie <= 0) {
270 1.89 rin aprint_error("%s: font table is empty\n", __func__);
271 1.88 rin return -1;
272 1.1 ad }
273 1.30 pk
274 1.55 ober #if NRASOPS_ROTATION > 0
275 1.55 ober /*
276 1.55 ober * Pick the rotated version of this font. This will create it
277 1.55 ober * if necessary.
278 1.55 ober */
279 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
280 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW)
281 1.62 nonaka rasops_rotate_font(&cookie, WSFONT_ROTATE_CW);
282 1.62 nonaka else if (ri->ri_flg & RI_ROTATE_CCW)
283 1.62 nonaka rasops_rotate_font(&cookie, WSFONT_ROTATE_CCW);
284 1.62 nonaka }
285 1.55 ober #endif
286 1.55 ober
287 1.39 ad if (wsfont_lock(cookie, &ri->ri_font)) {
288 1.89 rin aprint_error("%s: couldn't lock font\n", __func__);
289 1.88 rin return -1;
290 1.1 ad }
291 1.8 ad
292 1.5 ad ri->ri_wsfcookie = cookie;
293 1.1 ad }
294 1.4 ad #endif
295 1.30 pk
296 1.1 ad /* This should never happen in reality... */
297 1.89 rin if ((uintptr_t)ri->ri_bits & 3) {
298 1.89 rin aprint_error("%s: bits not aligned on 32-bit boundary\n",
299 1.89 rin __func__);
300 1.88 rin return -1;
301 1.1 ad }
302 1.1 ad
303 1.89 rin if (ri->ri_stride & 3) {
304 1.89 rin aprint_error("%s: stride not aligned on 32-bit boundary\n",
305 1.89 rin __func__);
306 1.88 rin return -1;
307 1.1 ad }
308 1.4 ad
309 1.13 ad if (rasops_reconfig(ri, wantrows, wantcols))
310 1.88 rin return -1;
311 1.46 perry
312 1.4 ad rasops_init_devcmap(ri);
313 1.88 rin return 0;
314 1.4 ad }
315 1.4 ad
316 1.4 ad /*
317 1.13 ad * Reconfigure (because parameters have changed in some way).
318 1.4 ad */
319 1.4 ad int
320 1.60 dsl rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
321 1.4 ad {
322 1.89 rin int bpp, s;
323 1.89 rin size_t len;
324 1.30 pk
325 1.13 ad s = splhigh();
326 1.30 pk
327 1.70 macallan if (wantrows == 0)
328 1.70 macallan wantrows = RASOPS_DEFAULT_HEIGHT;
329 1.70 macallan if (wantcols == 0)
330 1.70 macallan wantcols = RASOPS_DEFAULT_WIDTH;
331 1.70 macallan
332 1.63 macallan /* throw away old line drawing character bitmaps, if we have any */
333 1.63 macallan if (ri->ri_optfont.data != NULL) {
334 1.63 macallan kmem_free(ri->ri_optfont.data, ri->ri_optfont.stride *
335 1.63 macallan ri->ri_optfont.fontheight * ri->ri_optfont.numchars);
336 1.63 macallan ri->ri_optfont.data = NULL;
337 1.63 macallan }
338 1.63 macallan
339 1.63 macallan /* autogenerate box drawing characters */
340 1.64 macallan ri->ri_optfont.firstchar = WSFONT_FLAG_OPT;
341 1.64 macallan ri->ri_optfont.numchars = 16;
342 1.63 macallan ri->ri_optfont.fontwidth = ri->ri_font->fontwidth;
343 1.63 macallan ri->ri_optfont.fontheight = ri->ri_font->fontheight;
344 1.63 macallan ri->ri_optfont.stride = ri->ri_font->stride;
345 1.64 macallan len = ri->ri_optfont.fontheight * ri->ri_optfont.stride *
346 1.89 rin ri->ri_optfont.numchars;
347 1.89 rin
348 1.89 rin if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) {
349 1.89 rin aprint_error("%s: fontwidth assumptions botched", __func__);
350 1.89 rin splx(s);
351 1.89 rin return -1;
352 1.89 rin }
353 1.64 macallan
354 1.77 chs if ((ri->ri_flg & RI_NO_AUTO) == 0) {
355 1.77 chs ri->ri_optfont.data = kmem_zalloc(len, KM_SLEEP);
356 1.89 rin if (FONT_IS_ALPHA(&ri->ri_optfont))
357 1.89 rin rasops_make_box_chars_alpha(ri);
358 1.89 rin else {
359 1.67 macallan switch (ri->ri_optfont.stride) {
360 1.67 macallan case 1:
361 1.67 macallan rasops_make_box_chars_8(ri);
362 1.67 macallan break;
363 1.67 macallan case 2:
364 1.67 macallan rasops_make_box_chars_16(ri);
365 1.67 macallan break;
366 1.67 macallan case 4:
367 1.67 macallan rasops_make_box_chars_32(ri);
368 1.67 macallan break;
369 1.89 rin default:
370 1.89 rin aprint_error(
371 1.89 rin "%s: font stride assumptions botched",
372 1.89 rin __func__);
373 1.89 rin splx(s);
374 1.89 rin return -1;
375 1.67 macallan }
376 1.63 macallan }
377 1.64 macallan } else
378 1.64 macallan memset(&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
379 1.63 macallan
380 1.4 ad /* Need this to frob the setup below */
381 1.4 ad bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
382 1.4 ad
383 1.74 nonaka if ((ri->ri_flg & RI_CFGDONE) != 0) {
384 1.4 ad ri->ri_bits = ri->ri_origbits;
385 1.74 nonaka ri->ri_hwbits = ri->ri_hworigbits;
386 1.74 nonaka }
387 1.30 pk
388 1.1 ad /* Don't care if the caller wants a hideously small console */
389 1.1 ad if (wantrows < 10)
390 1.13 ad wantrows = 10;
391 1.30 pk
392 1.1 ad if (wantcols < 20)
393 1.13 ad wantcols = 20;
394 1.30 pk
395 1.1 ad /* Now constrain what they get */
396 1.1 ad ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
397 1.1 ad ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
398 1.30 pk
399 1.1 ad if (ri->ri_emuwidth > ri->ri_width)
400 1.1 ad ri->ri_emuwidth = ri->ri_width;
401 1.30 pk
402 1.1 ad if (ri->ri_emuheight > ri->ri_height)
403 1.1 ad ri->ri_emuheight = ri->ri_height;
404 1.30 pk
405 1.1 ad /* Reduce width until aligned on a 32-bit boundary */
406 1.20 ad while ((ri->ri_emuwidth * bpp & 31) != 0)
407 1.1 ad ri->ri_emuwidth--;
408 1.30 pk
409 1.55 ober #if NRASOPS_ROTATION > 0
410 1.62 nonaka if (ri->ri_flg & (RI_ROTATE_CW|RI_ROTATE_CCW)) {
411 1.55 ober ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
412 1.55 ober ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
413 1.55 ober } else
414 1.55 ober #endif
415 1.55 ober {
416 1.55 ober
417 1.55 ober ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
418 1.55 ober ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
419 1.55 ober }
420 1.4 ad ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
421 1.1 ad ri->ri_delta = ri->ri_stride - ri->ri_emustride;
422 1.1 ad ri->ri_ccol = 0;
423 1.1 ad ri->ri_crow = 0;
424 1.4 ad ri->ri_pelbytes = bpp >> 3;
425 1.30 pk
426 1.4 ad ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
427 1.1 ad ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
428 1.1 ad ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
429 1.1 ad
430 1.89 rin if ((ri->ri_delta & 3) != 0) {
431 1.89 rin aprint_error(
432 1.89 rin "%s: ri_delta not aligned on 32-bit boundary", __func__);
433 1.89 rin splx(s);
434 1.89 rin return -1;
435 1.89 rin }
436 1.75 macallan ri->ri_origbits = ri->ri_bits;
437 1.75 macallan ri->ri_hworigbits = ri->ri_hwbits;
438 1.75 macallan
439 1.1 ad /* Clear the entire display */
440 1.13 ad if ((ri->ri_flg & RI_CLEAR) != 0)
441 1.13 ad memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
442 1.30 pk
443 1.30 pk /* Now centre our window if needs be */
444 1.13 ad if ((ri->ri_flg & RI_CENTER) != 0) {
445 1.46 perry ri->ri_bits += (((ri->ri_width * bpp >> 3) -
446 1.36 nathanw ri->ri_emustride) >> 1) & ~3;
447 1.30 pk ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
448 1.1 ad ri->ri_stride;
449 1.61 macallan if (ri->ri_hwbits != NULL) {
450 1.61 macallan ri->ri_hwbits += (((ri->ri_width * bpp >> 3) -
451 1.61 macallan ri->ri_emustride) >> 1) & ~3;
452 1.88 rin ri->ri_hwbits +=
453 1.88 rin ((ri->ri_height - ri->ri_emuheight) >> 1) *
454 1.61 macallan ri->ri_stride;
455 1.61 macallan }
456 1.89 rin ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) /
457 1.89 rin ri->ri_stride;
458 1.89 rin ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) %
459 1.89 rin ri->ri_stride) * 8 / bpp);
460 1.5 ad } else
461 1.5 ad ri->ri_xorigin = ri->ri_yorigin = 0;
462 1.4 ad
463 1.30 pk /*
464 1.4 ad * Fill in defaults for operations set. XXX this nukes private
465 1.4 ad * routines used by accelerated fb drivers.
466 1.4 ad */
467 1.1 ad ri->ri_ops.mapchar = rasops_mapchar;
468 1.1 ad ri->ri_ops.copyrows = rasops_copyrows;
469 1.1 ad ri->ri_ops.copycols = rasops_copycols;
470 1.4 ad ri->ri_ops.erasecols = rasops_erasecols;
471 1.4 ad ri->ri_ops.eraserows = rasops_eraserows;
472 1.1 ad ri->ri_ops.cursor = rasops_cursor;
473 1.4 ad ri->ri_do_cursor = rasops_do_cursor;
474 1.30 pk
475 1.76 macallan ri->ri_caps &= ~(WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
476 1.76 macallan WSSCREEN_WSCOLORS | WSSCREEN_REVERSE);
477 1.91 rin
478 1.91 rin if ((ri->ri_flg & RI_FORCEMONO) != 0 ||
479 1.91 rin #ifdef RASOPS_APPLE_PALETTE
480 1.91 rin ri->ri_depth == 1
481 1.91 rin #else
482 1.91 rin ri->ri_depth < 8
483 1.91 rin #endif
484 1.91 rin ) {
485 1.41 junyoung ri->ri_ops.allocattr = rasops_allocattr_mono;
486 1.76 macallan ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
487 1.4 ad } else {
488 1.41 junyoung ri->ri_ops.allocattr = rasops_allocattr_color;
489 1.76 macallan ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
490 1.24 drochner WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
491 1.4 ad }
492 1.4 ad
493 1.1 ad switch (ri->ri_depth) {
494 1.20 ad #if NRASOPS1 > 0
495 1.1 ad case 1:
496 1.1 ad rasops1_init(ri);
497 1.1 ad break;
498 1.1 ad #endif
499 1.20 ad #if NRASOPS2 > 0
500 1.4 ad case 2:
501 1.4 ad rasops2_init(ri);
502 1.34 takemura break;
503 1.34 takemura #endif
504 1.34 takemura #if NRASOPS4 > 0
505 1.34 takemura case 4:
506 1.34 takemura rasops4_init(ri);
507 1.4 ad break;
508 1.4 ad #endif
509 1.20 ad #if NRASOPS8 > 0
510 1.1 ad case 8:
511 1.1 ad rasops8_init(ri);
512 1.1 ad break;
513 1.1 ad #endif
514 1.20 ad #if NRASOPS15 > 0 || NRASOPS16 > 0
515 1.1 ad case 15:
516 1.1 ad case 16:
517 1.1 ad rasops15_init(ri);
518 1.1 ad break;
519 1.1 ad #endif
520 1.20 ad #if NRASOPS24 > 0
521 1.1 ad case 24:
522 1.1 ad rasops24_init(ri);
523 1.1 ad break;
524 1.1 ad #endif
525 1.20 ad #if NRASOPS32 > 0
526 1.1 ad case 32:
527 1.1 ad rasops32_init(ri);
528 1.1 ad break;
529 1.1 ad #endif
530 1.1 ad default:
531 1.13 ad ri->ri_flg &= ~RI_CFGDONE;
532 1.89 rin aprint_error("%s: depth not supported\n", __func__);
533 1.13 ad splx(s);
534 1.88 rin return -1;
535 1.1 ad }
536 1.30 pk
537 1.55 ober #if NRASOPS_ROTATION > 0
538 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
539 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW) {
540 1.62 nonaka ri->ri_real_ops = ri->ri_ops;
541 1.62 nonaka ri->ri_ops.copycols = rasops_copycols_rotated_cw;
542 1.62 nonaka ri->ri_ops.copyrows = rasops_copyrows_rotated_cw;
543 1.62 nonaka ri->ri_ops.erasecols = rasops_erasecols_rotated_cw;
544 1.62 nonaka ri->ri_ops.eraserows = rasops_eraserows_rotated_cw;
545 1.62 nonaka ri->ri_ops.putchar = rasops_putchar_rotated_cw;
546 1.62 nonaka } else if (ri->ri_flg & RI_ROTATE_CCW) {
547 1.62 nonaka ri->ri_real_ops = ri->ri_ops;
548 1.62 nonaka ri->ri_ops.copycols = rasops_copycols_rotated_ccw;
549 1.62 nonaka ri->ri_ops.copyrows = rasops_copyrows_rotated_ccw;
550 1.62 nonaka ri->ri_ops.erasecols = rasops_erasecols_rotated_ccw;
551 1.62 nonaka ri->ri_ops.eraserows = rasops_eraserows_rotated_ccw;
552 1.62 nonaka ri->ri_ops.putchar = rasops_putchar_rotated_ccw;
553 1.62 nonaka }
554 1.55 ober }
555 1.55 ober #endif
556 1.55 ober
557 1.13 ad ri->ri_flg |= RI_CFGDONE;
558 1.13 ad splx(s);
559 1.88 rin return 0;
560 1.1 ad }
561 1.1 ad
562 1.1 ad /*
563 1.1 ad * Map a character.
564 1.1 ad */
565 1.1 ad static int
566 1.59 dsl rasops_mapchar(void *cookie, int c, u_int *cp)
567 1.1 ad {
568 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
569 1.8 ad
570 1.88 rin KASSERT(ri->ri_font != NULL);
571 1.39 ad
572 1.89 rin if ((c = wsfont_map_unichar(ri->ri_font, c)) < 0 ||
573 1.89 rin c < ri->ri_font->firstchar) {
574 1.63 macallan *cp = ' ';
575 1.88 rin return 0;
576 1.35 marcus }
577 1.30 pk
578 1.89 rin #if 0 /* XXXRO */
579 1.89 rin if (CHAR_IN_FONT(c, ri->ri_font)) {
580 1.1 ad *cp = ' ';
581 1.88 rin return 0;
582 1.1 ad }
583 1.89 rin #endif
584 1.30 pk
585 1.1 ad *cp = c;
586 1.88 rin return 5;
587 1.1 ad }
588 1.1 ad
589 1.1 ad /*
590 1.1 ad * Allocate a color attribute.
591 1.1 ad */
592 1.1 ad static int
593 1.89 rin rasops_allocattr_color(void *cookie, int fg0, int bg0, int flg, long *attr)
594 1.1 ad {
595 1.89 rin uint32_t fg = fg0, bg = bg0;
596 1.1 ad
597 1.89 rin if (__predict_false(fg >= sizeof(rasops_isgray) ||
598 1.89 rin bg >= sizeof(rasops_isgray)))
599 1.88 rin return EINVAL;
600 1.56 mjf
601 1.1 ad #ifdef RASOPS_CLIPPING
602 1.1 ad fg &= 7;
603 1.1 ad bg &= 7;
604 1.1 ad #endif
605 1.17 ad if ((flg & WSATTR_BLINK) != 0)
606 1.88 rin return EINVAL;
607 1.23 drochner
608 1.23 drochner if ((flg & WSATTR_WSCOLORS) == 0) {
609 1.48 macallan #ifdef WS_DEFAULT_FG
610 1.48 macallan fg = WS_DEFAULT_FG;
611 1.48 macallan #else
612 1.48 macallan fg = WSCOL_WHITE;
613 1.48 macallan #endif
614 1.48 macallan #ifdef WS_DEFAULT_BG
615 1.48 macallan bg = WS_DEFAULT_BG;
616 1.48 macallan #else
617 1.48 macallan bg = WSCOL_BLACK;
618 1.48 macallan #endif
619 1.23 drochner }
620 1.23 drochner
621 1.17 ad if ((flg & WSATTR_REVERSE) != 0) {
622 1.89 rin uint32_t swap = fg;
623 1.1 ad fg = bg;
624 1.1 ad bg = swap;
625 1.1 ad }
626 1.1 ad
627 1.17 ad if ((flg & WSATTR_HILIT) != 0)
628 1.1 ad fg += 8;
629 1.30 pk
630 1.79 mlelstv flg = flg & WSATTR_USERMASK;
631 1.30 pk
632 1.1 ad if (rasops_isgray[fg])
633 1.79 mlelstv flg |= WSATTR_PRIVATE1;
634 1.1 ad
635 1.1 ad if (rasops_isgray[bg])
636 1.79 mlelstv flg |= WSATTR_PRIVATE2;
637 1.1 ad
638 1.1 ad *attr = (bg << 16) | (fg << 24) | flg;
639 1.88 rin return 0;
640 1.1 ad }
641 1.1 ad
642 1.1 ad /*
643 1.1 ad * Allocate a mono attribute.
644 1.1 ad */
645 1.1 ad static int
646 1.89 rin rasops_allocattr_mono(void *cookie, int fg0, int bg0, int flg, long *attr)
647 1.1 ad {
648 1.89 rin uint32_t fg = fg0, bg = bg0;
649 1.1 ad
650 1.23 drochner if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
651 1.88 rin return EINVAL;
652 1.23 drochner
653 1.23 drochner fg = 1;
654 1.23 drochner bg = 0;
655 1.23 drochner
656 1.17 ad if ((flg & WSATTR_REVERSE) != 0) {
657 1.89 rin uint32_t swap = fg;
658 1.1 ad fg = bg;
659 1.1 ad bg = swap;
660 1.1 ad }
661 1.1 ad
662 1.1 ad *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
663 1.88 rin return 0;
664 1.1 ad }
665 1.1 ad
666 1.1 ad /*
667 1.1 ad * Copy rows.
668 1.1 ad */
669 1.1 ad static void
670 1.60 dsl rasops_copyrows(void *cookie, int src, int dst, int num)
671 1.1 ad {
672 1.90 rin struct rasops_info *ri = (struct rasops_info *)cookie;
673 1.90 rin uint8_t *sp, *dp, *hp;
674 1.90 rin int n;
675 1.30 pk
676 1.90 rin hp = NULL; /* XXX GCC */
677 1.1 ad
678 1.1 ad #ifdef RASOPS_CLIPPING
679 1.1 ad if (dst == src)
680 1.1 ad return;
681 1.30 pk
682 1.1 ad if (src < 0) {
683 1.1 ad num += src;
684 1.1 ad src = 0;
685 1.1 ad }
686 1.1 ad
687 1.89 rin if (src + num > ri->ri_rows)
688 1.1 ad num = ri->ri_rows - src;
689 1.1 ad
690 1.1 ad if (dst < 0) {
691 1.1 ad num += dst;
692 1.1 ad dst = 0;
693 1.1 ad }
694 1.1 ad
695 1.89 rin if (dst + num > ri->ri_rows)
696 1.1 ad num = ri->ri_rows - dst;
697 1.30 pk
698 1.1 ad if (num <= 0)
699 1.1 ad return;
700 1.1 ad #endif
701 1.1 ad
702 1.1 ad num *= ri->ri_font->fontheight;
703 1.90 rin n = ri->ri_emustride;
704 1.30 pk
705 1.90 rin sp = ri->ri_bits + src * ri->ri_yscale;
706 1.90 rin dp = ri->ri_bits + dst * ri->ri_yscale;
707 1.90 rin if (ri->ri_hwbits)
708 1.90 rin hp = ri->ri_hwbits + dst * ri->ri_yscale;
709 1.30 pk
710 1.18 ad while (num--) {
711 1.90 rin memmove(dp, sp, n);
712 1.90 rin dp += n;
713 1.52 jmcneill if (ri->ri_hwbits) {
714 1.90 rin memcpy(hp, sp, n);
715 1.90 rin hp += n;
716 1.51 jmcneill }
717 1.90 rin sp += n;
718 1.1 ad }
719 1.1 ad }
720 1.1 ad
721 1.1 ad /*
722 1.1 ad * Copy columns. This is slow, and hard to optimize due to alignment,
723 1.1 ad * and the fact that we have to copy both left->right and right->left.
724 1.43 uwe * We simply cop-out here and use memmove(), since it handles all of
725 1.1 ad * these cases anyway.
726 1.1 ad */
727 1.4 ad void
728 1.60 dsl rasops_copycols(void *cookie, int row, int src, int dst, int num)
729 1.1 ad {
730 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
731 1.81 rin uint8_t *sp, *dp, *hp;
732 1.1 ad int height;
733 1.30 pk
734 1.89 rin hp = NULL; /* XXX GCC */
735 1.1 ad
736 1.1 ad #ifdef RASOPS_CLIPPING
737 1.1 ad if (dst == src)
738 1.1 ad return;
739 1.30 pk
740 1.3 ad /* Catches < 0 case too */
741 1.3 ad if ((unsigned)row >= (unsigned)ri->ri_rows)
742 1.1 ad return;
743 1.30 pk
744 1.1 ad if (src < 0) {
745 1.1 ad num += src;
746 1.1 ad src = 0;
747 1.1 ad }
748 1.1 ad
749 1.89 rin if (src + num > ri->ri_cols)
750 1.1 ad num = ri->ri_cols - src;
751 1.1 ad
752 1.1 ad if (dst < 0) {
753 1.1 ad num += dst;
754 1.1 ad dst = 0;
755 1.1 ad }
756 1.1 ad
757 1.89 rin if (dst + num > ri->ri_cols)
758 1.1 ad num = ri->ri_cols - dst;
759 1.30 pk
760 1.1 ad if (num <= 0)
761 1.1 ad return;
762 1.1 ad #endif
763 1.30 pk
764 1.1 ad num *= ri->ri_xscale;
765 1.1 ad row *= ri->ri_yscale;
766 1.1 ad height = ri->ri_font->fontheight;
767 1.30 pk
768 1.1 ad sp = ri->ri_bits + row + src * ri->ri_xscale;
769 1.1 ad dp = ri->ri_bits + row + dst * ri->ri_xscale;
770 1.51 jmcneill if (ri->ri_hwbits)
771 1.51 jmcneill hp = ri->ri_hwbits + row + dst * ri->ri_xscale;
772 1.30 pk
773 1.1 ad while (height--) {
774 1.43 uwe memmove(dp, sp, num);
775 1.89 rin dp += ri->ri_stride;
776 1.51 jmcneill if (ri->ri_hwbits) {
777 1.51 jmcneill memcpy(hp, sp, num);
778 1.51 jmcneill hp += ri->ri_stride;
779 1.51 jmcneill }
780 1.1 ad sp += ri->ri_stride;
781 1.1 ad }
782 1.1 ad }
783 1.1 ad
784 1.1 ad /*
785 1.1 ad * Turn cursor off/on.
786 1.1 ad */
787 1.1 ad static void
788 1.60 dsl rasops_cursor(void *cookie, int on, int row, int col)
789 1.1 ad {
790 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
791 1.30 pk
792 1.1 ad /* Turn old cursor off */
793 1.13 ad if ((ri->ri_flg & RI_CURSOR) != 0)
794 1.30 pk #ifdef RASOPS_CLIPPING
795 1.13 ad if ((ri->ri_flg & RI_CURSORCLIP) == 0)
796 1.1 ad #endif
797 1.1 ad ri->ri_do_cursor(ri);
798 1.1 ad
799 1.1 ad /* Select new cursor */
800 1.1 ad #ifdef RASOPS_CLIPPING
801 1.13 ad ri->ri_flg &= ~RI_CURSORCLIP;
802 1.30 pk
803 1.1 ad if (row < 0 || row >= ri->ri_rows)
804 1.13 ad ri->ri_flg |= RI_CURSORCLIP;
805 1.1 ad else if (col < 0 || col >= ri->ri_cols)
806 1.13 ad ri->ri_flg |= RI_CURSORCLIP;
807 1.1 ad #endif
808 1.1 ad ri->ri_crow = row;
809 1.1 ad ri->ri_ccol = col;
810 1.1 ad
811 1.1 ad if (on) {
812 1.13 ad ri->ri_flg |= RI_CURSOR;
813 1.30 pk #ifdef RASOPS_CLIPPING
814 1.13 ad if ((ri->ri_flg & RI_CURSORCLIP) == 0)
815 1.1 ad #endif
816 1.1 ad ri->ri_do_cursor(ri);
817 1.30 pk } else
818 1.13 ad ri->ri_flg &= ~RI_CURSOR;
819 1.1 ad }
820 1.1 ad
821 1.1 ad /*
822 1.1 ad * Make the device colormap
823 1.1 ad */
824 1.4 ad static void
825 1.59 dsl rasops_init_devcmap(struct rasops_info *ri)
826 1.1 ad {
827 1.89 rin int i;
828 1.89 rin uint32_t c;
829 1.81 rin const uint8_t *p;
830 1.30 pk
831 1.4 ad switch (ri->ri_depth) {
832 1.4 ad case 1:
833 1.4 ad ri->ri_devcmap[0] = 0;
834 1.4 ad for (i = 1; i < 16; i++)
835 1.4 ad ri->ri_devcmap[i] = -1;
836 1.4 ad return;
837 1.4 ad
838 1.4 ad case 2:
839 1.4 ad for (i = 1; i < 15; i++)
840 1.89 rin ri->ri_devcmap[i] = 0xaaaaaaaa;
841 1.30 pk
842 1.4 ad ri->ri_devcmap[0] = 0;
843 1.89 rin ri->ri_devcmap[8] = 0x55555555;
844 1.4 ad ri->ri_devcmap[15] = -1;
845 1.4 ad return;
846 1.4 ad
847 1.91 rin #ifdef RASOPS_APPLE_PALETTE
848 1.91 rin case 4:
849 1.91 rin for (i = 0; i < 16; i++) {
850 1.91 rin c = apple4_devcmap[i];
851 1.91 rin ri->ri_devcmap[i] =
852 1.91 rin (c << 0) | (c << 4) | (c << 8) | (c << 12) |
853 1.91 rin (c << 16) | (c << 20) | (c << 24) | (c << 28);
854 1.91 rin }
855 1.91 rin return;
856 1.91 rin #else
857 1.91 rin /* XXXRO What should we do here? */
858 1.91 rin #endif
859 1.91 rin
860 1.4 ad case 8:
861 1.68 macallan if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) {
862 1.89 rin for (i = 0; i < 16; i++) {
863 1.91 rin #ifdef RASOPS_APPLE_PALETTE
864 1.91 rin c = apple8_devcmap[i];
865 1.91 rin #else
866 1.89 rin c = i;
867 1.91 rin #endif
868 1.68 macallan ri->ri_devcmap[i] =
869 1.89 rin c | (c << 8) | (c << 16) | (c << 24);
870 1.89 rin }
871 1.68 macallan return;
872 1.68 macallan }
873 1.4 ad }
874 1.30 pk
875 1.1 ad p = rasops_cmap;
876 1.30 pk
877 1.29 nathanw for (i = 0; i < 16; i++) {
878 1.1 ad if (ri->ri_rnum <= 8)
879 1.89 rin c = (uint32_t)(*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
880 1.30 pk else
881 1.89 rin c = (uint32_t)(*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
882 1.29 nathanw p++;
883 1.1 ad
884 1.1 ad if (ri->ri_gnum <= 8)
885 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
886 1.30 pk else
887 1.89 rin c |= (uint32_t)(*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
888 1.29 nathanw p++;
889 1.1 ad
890 1.1 ad if (ri->ri_bnum <= 8)
891 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
892 1.30 pk else
893 1.89 rin c |= (uint32_t)(*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
894 1.29 nathanw p++;
895 1.4 ad
896 1.4 ad /* Fill the word for generic routines, which want this */
897 1.89 rin if (ri->ri_depth == 8) {
898 1.89 rin c |= c << 8;
899 1.89 rin c |= c << 16;
900 1.89 rin } else if (ri->ri_depth == 15 || ri->ri_depth == 16)
901 1.69 macallan c |= c << 16;
902 1.89 rin else if (ri->ri_depth == 24)
903 1.89 rin c |= (c & 0xff) << 24;
904 1.1 ad
905 1.4 ad /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
906 1.13 ad if ((ri->ri_flg & RI_BSWAP) == 0)
907 1.3 ad ri->ri_devcmap[i] = c;
908 1.89 rin else if (ri->ri_depth == 15 || ri->ri_depth == 16)
909 1.89 rin ri->ri_devcmap[i] = bswap16(c);
910 1.4 ad else if (ri->ri_depth == 32)
911 1.3 ad ri->ri_devcmap[i] = bswap32(c);
912 1.89 rin else /* 8, 24 */
913 1.4 ad ri->ri_devcmap[i] = c;
914 1.1 ad }
915 1.1 ad }
916 1.1 ad
917 1.1 ad /*
918 1.1 ad * Unpack a rasops attribute
919 1.1 ad */
920 1.1 ad void
921 1.60 dsl rasops_unpack_attr(long attr, int *fg, int *bg, int *underline)
922 1.1 ad {
923 1.30 pk
924 1.89 rin *fg = ((uint32_t)attr >> 24) & 0xf;
925 1.89 rin *bg = ((uint32_t)attr >> 16) & 0xf;
926 1.25 ad if (underline != NULL)
927 1.89 rin *underline = (uint32_t)attr & WSATTR_UNDERLINE;
928 1.4 ad }
929 1.4 ad
930 1.4 ad /*
931 1.4 ad * Erase rows. This isn't static, since 24-bpp uses it in special cases.
932 1.4 ad */
933 1.4 ad void
934 1.60 dsl rasops_eraserows(void *cookie, int row, int num, long attr)
935 1.4 ad {
936 1.90 rin struct rasops_info *ri = (struct rasops_info *)cookie;
937 1.82 rin uint32_t *dp, *hp, clr;
938 1.90 rin int n, cnt, delta;
939 1.30 pk
940 1.90 rin hp = NULL; /* XXX GCC */
941 1.4 ad
942 1.4 ad #ifdef RASOPS_CLIPPING
943 1.4 ad if (row < 0) {
944 1.4 ad num += row;
945 1.4 ad row = 0;
946 1.4 ad }
947 1.4 ad
948 1.89 rin if (row + num > ri->ri_rows)
949 1.4 ad num = ri->ri_rows - row;
950 1.30 pk
951 1.4 ad if (num <= 0)
952 1.4 ad return;
953 1.4 ad #endif
954 1.4 ad
955 1.30 pk clr = ri->ri_devcmap[(attr >> 16) & 0xf];
956 1.4 ad
957 1.30 pk /*
958 1.20 ad * XXX The wsdisplay_emulops interface seems a little deficient in
959 1.30 pk * that there is no way to clear the *entire* screen. We provide a
960 1.30 pk * workaround here: if the entire console area is being cleared, and
961 1.13 ad * the RI_FULLCLEAR flag is set, clear the entire display.
962 1.30 pk */
963 1.13 ad if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
964 1.90 rin n = ri->ri_stride >> 2;
965 1.13 ad num = ri->ri_height;
966 1.82 rin dp = (uint32_t *)ri->ri_origbits;
967 1.51 jmcneill if (ri->ri_hwbits)
968 1.82 rin hp = (uint32_t *)ri->ri_hworigbits;
969 1.14 ad delta = 0;
970 1.13 ad } else {
971 1.90 rin n = ri->ri_emustride >> 2;
972 1.13 ad num *= ri->ri_font->fontheight;
973 1.82 rin dp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
974 1.51 jmcneill if (ri->ri_hwbits)
975 1.82 rin hp = (uint32_t *)(ri->ri_hwbits + row *
976 1.51 jmcneill ri->ri_yscale);
977 1.14 ad delta = ri->ri_delta;
978 1.13 ad }
979 1.30 pk
980 1.4 ad while (num--) {
981 1.90 rin for (cnt = n; cnt; cnt--) {
982 1.90 rin *dp++ = clr;
983 1.51 jmcneill if (ri->ri_hwbits)
984 1.90 rin *hp++ = clr;
985 1.30 pk }
986 1.82 rin DELTA(dp, delta, uint32_t *);
987 1.51 jmcneill if (ri->ri_hwbits)
988 1.82 rin DELTA(hp, delta, uint32_t *);
989 1.4 ad }
990 1.4 ad }
991 1.4 ad
992 1.4 ad /*
993 1.4 ad * Actually turn the cursor on or off. This does the dirty work for
994 1.4 ad * rasops_cursor().
995 1.4 ad */
996 1.4 ad static void
997 1.59 dsl rasops_do_cursor(struct rasops_info *ri)
998 1.4 ad {
999 1.84 rin int full, height, cnt, slop1, slop2, row, col;
1000 1.85 rin uint32_t tmp32, msk1, msk2;
1001 1.84 rin uint8_t tmp8;
1002 1.81 rin uint8_t *dp, *rp, *hrp, *hp;
1003 1.51 jmcneill
1004 1.89 rin hrp = hp = NULL; /* XXX GCC */
1005 1.30 pk
1006 1.55 ober #if NRASOPS_ROTATION > 0
1007 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
1008 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW) {
1009 1.62 nonaka /* Rotate rows/columns */
1010 1.62 nonaka row = ri->ri_ccol;
1011 1.62 nonaka col = ri->ri_rows - ri->ri_crow - 1;
1012 1.62 nonaka } else if (ri->ri_flg & RI_ROTATE_CCW) {
1013 1.62 nonaka /* Rotate rows/columns */
1014 1.62 nonaka row = ri->ri_cols - ri->ri_ccol - 1;
1015 1.62 nonaka col = ri->ri_crow;
1016 1.62 nonaka } else { /* upside-down */
1017 1.62 nonaka row = ri->ri_crow;
1018 1.62 nonaka col = ri->ri_ccol;
1019 1.62 nonaka }
1020 1.55 ober } else
1021 1.55 ober #endif
1022 1.55 ober {
1023 1.55 ober row = ri->ri_crow;
1024 1.55 ober col = ri->ri_ccol;
1025 1.55 ober }
1026 1.30 pk
1027 1.4 ad rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
1028 1.51 jmcneill if (ri->ri_hwbits)
1029 1.51 jmcneill hrp = ri->ri_hwbits + row * ri->ri_yscale + col
1030 1.51 jmcneill * ri->ri_xscale;
1031 1.4 ad height = ri->ri_font->fontheight;
1032 1.30 pk
1033 1.80 rin /*
1034 1.80 rin * For ri_xscale = 1:
1035 1.80 rin *
1036 1.80 rin * Logic below does not work for ri_xscale = 1, e.g.,
1037 1.80 rin * fontwidth = 8 and bpp = 1. So we take care of it.
1038 1.80 rin */
1039 1.80 rin if (ri->ri_xscale == 1) {
1040 1.80 rin while (height--) {
1041 1.84 rin tmp8 = ~*rp;
1042 1.80 rin
1043 1.80 rin *rp = tmp8;
1044 1.80 rin rp += ri->ri_stride;
1045 1.30 pk
1046 1.80 rin if (ri->ri_hwbits) {
1047 1.80 rin *hrp = tmp8;
1048 1.80 rin hrp += ri->ri_stride;
1049 1.80 rin }
1050 1.80 rin }
1051 1.80 rin return;
1052 1.80 rin }
1053 1.80 rin
1054 1.80 rin /*
1055 1.80 rin * For ri_xscale = 2, 3, 4, ...:
1056 1.80 rin *
1057 1.80 rin * Note that siop1 <= ri_xscale even for ri_xscale = 2,
1058 1.84 rin * since rp % 3 = 0 or 2 (ri_stride % 4 = 0).
1059 1.80 rin */
1060 1.80 rin slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
1061 1.4 ad slop2 = (ri->ri_xscale - slop1) & 3;
1062 1.89 rin full = (ri->ri_xscale - slop1 /* - slop2 */) >> 2;
1063 1.30 pk
1064 1.84 rin rp = (uint8_t *)((uintptr_t)rp & ~3);
1065 1.84 rin hrp = (uint8_t *)((uintptr_t)hrp & ~3);
1066 1.30 pk
1067 1.87 rin msk1 = !slop1 ? 0 : be32toh(0xffffffffU >> (32 - (8 * slop1)));
1068 1.87 rin msk2 = !slop2 ? 0 : be32toh(0xffffffffU << (32 - (8 * slop2)));
1069 1.85 rin
1070 1.84 rin while (height--) {
1071 1.84 rin dp = rp;
1072 1.84 rin rp += ri->ri_stride;
1073 1.84 rin if (ri->ri_hwbits) {
1074 1.84 rin hp = hrp;
1075 1.84 rin hrp += ri->ri_stride;
1076 1.4 ad }
1077 1.78 macallan
1078 1.84 rin if (slop1) {
1079 1.85 rin tmp32 = *(uint32_t *)dp ^ msk1;
1080 1.84 rin *(uint32_t *)dp = tmp32;
1081 1.84 rin dp += 4;
1082 1.51 jmcneill if (ri->ri_hwbits) {
1083 1.84 rin *(uint32_t *)hp = tmp32;
1084 1.84 rin hp += 4;
1085 1.51 jmcneill }
1086 1.84 rin }
1087 1.30 pk
1088 1.84 rin for (cnt = full; cnt; cnt--) {
1089 1.84 rin tmp32 = ~*(uint32_t *)dp;
1090 1.84 rin *(uint32_t *)dp = tmp32;
1091 1.84 rin dp += 4;
1092 1.84 rin if (ri->ri_hwbits) {
1093 1.84 rin *(uint32_t *)hp = tmp32;
1094 1.84 rin hp += 4;
1095 1.4 ad }
1096 1.84 rin }
1097 1.30 pk
1098 1.84 rin if (slop2) {
1099 1.85 rin tmp32 = *(uint32_t *)dp ^ msk2;
1100 1.84 rin *(uint32_t *)dp = tmp32;
1101 1.84 rin if (ri->ri_hwbits)
1102 1.84 rin *(uint32_t *)hp = tmp32;
1103 1.4 ad }
1104 1.4 ad }
1105 1.4 ad }
1106 1.4 ad
1107 1.4 ad /*
1108 1.4 ad * Erase columns.
1109 1.4 ad */
1110 1.4 ad void
1111 1.60 dsl rasops_erasecols(void *cookie, int row, int col, int num, long attr)
1112 1.4 ad {
1113 1.90 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1114 1.90 rin int height, cnt, slop1, slop2, clr;
1115 1.82 rin uint32_t *rp, *dp, *hrp, *hp;
1116 1.30 pk
1117 1.90 rin hrp = hp = NULL; /* XXX GCC */
1118 1.30 pk
1119 1.30 pk #ifdef RASOPS_CLIPPING
1120 1.4 ad if ((unsigned)row >= (unsigned)ri->ri_rows)
1121 1.4 ad return;
1122 1.4 ad
1123 1.4 ad if (col < 0) {
1124 1.4 ad num += col;
1125 1.4 ad col = 0;
1126 1.4 ad }
1127 1.4 ad
1128 1.4 ad if ((col + num) > ri->ri_cols)
1129 1.4 ad num = ri->ri_cols - col;
1130 1.30 pk
1131 1.4 ad if (num <= 0)
1132 1.4 ad return;
1133 1.4 ad #endif
1134 1.30 pk
1135 1.90 rin num *= ri->ri_xscale;
1136 1.82 rin rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
1137 1.51 jmcneill if (ri->ri_hwbits)
1138 1.82 rin hrp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
1139 1.51 jmcneill col*ri->ri_xscale);
1140 1.4 ad height = ri->ri_font->fontheight;
1141 1.30 pk clr = ri->ri_devcmap[(attr >> 16) & 0xf];
1142 1.30 pk
1143 1.4 ad /* Don't bother using the full loop for <= 32 pels */
1144 1.4 ad if (num <= 32) {
1145 1.6 ad if (((num | ri->ri_xscale) & 3) == 0) {
1146 1.6 ad /* Word aligned blt */
1147 1.6 ad num >>= 2;
1148 1.6 ad
1149 1.6 ad while (height--) {
1150 1.6 ad dp = rp;
1151 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1152 1.51 jmcneill if (ri->ri_hwbits) {
1153 1.51 jmcneill hp = hrp;
1154 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1155 1.51 jmcneill }
1156 1.30 pk
1157 1.51 jmcneill for (cnt = num; cnt; cnt--) {
1158 1.6 ad *dp++ = clr;
1159 1.51 jmcneill if (ri->ri_hwbits)
1160 1.51 jmcneill *hp++ = clr;
1161 1.51 jmcneill }
1162 1.6 ad }
1163 1.6 ad } else if (((num | ri->ri_xscale) & 1) == 0) {
1164 1.30 pk /*
1165 1.4 ad * Halfword aligned blt. This is needed so the
1166 1.30 pk * 15/16 bit ops can use this function.
1167 1.4 ad */
1168 1.4 ad num >>= 1;
1169 1.4 ad
1170 1.4 ad while (height--) {
1171 1.4 ad dp = rp;
1172 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1173 1.51 jmcneill if (ri->ri_hwbits) {
1174 1.51 jmcneill hp = hrp;
1175 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1176 1.51 jmcneill }
1177 1.4 ad
1178 1.4 ad for (cnt = num; cnt; cnt--) {
1179 1.82 rin *(uint16_t *)dp = clr;
1180 1.82 rin DELTA(dp, 2, uint32_t *);
1181 1.51 jmcneill if (ri->ri_hwbits) {
1182 1.82 rin *(uint16_t *)hp = clr;
1183 1.82 rin DELTA(hp, 2, uint32_t *);
1184 1.51 jmcneill }
1185 1.4 ad }
1186 1.4 ad }
1187 1.4 ad } else {
1188 1.4 ad while (height--) {
1189 1.92 rin dp = rp;
1190 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1191 1.51 jmcneill if (ri->ri_hwbits) {
1192 1.92 rin hp = hrp;
1193 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1194 1.51 jmcneill }
1195 1.92 rin
1196 1.92 rin for (cnt = num; cnt; cnt--) {
1197 1.92 rin *(uint8_t *)dp = clr;
1198 1.92 rin DELTA(dp, 1, uint32_t *);
1199 1.92 rin if (ri->ri_hwbits) {
1200 1.92 rin *(uint8_t *)hp = clr;
1201 1.92 rin DELTA(hp, 1, uint32_t *);
1202 1.92 rin }
1203 1.92 rin }
1204 1.4 ad }
1205 1.4 ad }
1206 1.30 pk
1207 1.4 ad return;
1208 1.4 ad }
1209 1.30 pk
1210 1.90 rin slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
1211 1.4 ad slop2 = (num - slop1) & 3;
1212 1.90 rin num = (num - slop1 /* - slop2 */) >> 2;
1213 1.4 ad
1214 1.4 ad while (height--) {
1215 1.4 ad dp = rp;
1216 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1217 1.51 jmcneill if (ri->ri_hwbits) {
1218 1.51 jmcneill hp = hrp;
1219 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1220 1.51 jmcneill }
1221 1.30 pk
1222 1.4 ad /* Align span to 4 bytes */
1223 1.4 ad if (slop1 & 1) {
1224 1.81 rin *(uint8_t *)dp = clr;
1225 1.82 rin DELTA(dp, 1, uint32_t *);
1226 1.51 jmcneill if (ri->ri_hwbits) {
1227 1.81 rin *(uint8_t *)hp = clr;
1228 1.82 rin DELTA(hp, 1, uint32_t *);
1229 1.51 jmcneill }
1230 1.4 ad }
1231 1.4 ad
1232 1.4 ad if (slop1 & 2) {
1233 1.82 rin *(uint16_t *)dp = clr;
1234 1.82 rin DELTA(dp, 2, uint32_t *);
1235 1.51 jmcneill if (ri->ri_hwbits) {
1236 1.82 rin *(uint16_t *)hp = clr;
1237 1.82 rin DELTA(hp, 2, uint32_t *);
1238 1.51 jmcneill }
1239 1.4 ad }
1240 1.30 pk
1241 1.30 pk /* Write 4 bytes per loop */
1242 1.51 jmcneill for (cnt = num; cnt; cnt--) {
1243 1.4 ad *dp++ = clr;
1244 1.51 jmcneill if (ri->ri_hwbits)
1245 1.51 jmcneill *hp++ = clr;
1246 1.51 jmcneill }
1247 1.30 pk
1248 1.30 pk /* Write unaligned trailing slop */
1249 1.4 ad if (slop2 & 1) {
1250 1.81 rin *(uint8_t *)dp = clr;
1251 1.82 rin DELTA(dp, 1, uint32_t *);
1252 1.51 jmcneill if (ri->ri_hwbits) {
1253 1.81 rin *(uint8_t *)hp = clr;
1254 1.82 rin DELTA(hp, 1, uint32_t *);
1255 1.51 jmcneill }
1256 1.4 ad }
1257 1.4 ad
1258 1.51 jmcneill if (slop2 & 2) {
1259 1.82 rin *(uint16_t *)dp = clr;
1260 1.51 jmcneill if (ri->ri_hwbits)
1261 1.82 rin *(uint16_t *)hp = clr;
1262 1.51 jmcneill }
1263 1.4 ad }
1264 1.1 ad }
1265 1.55 ober
1266 1.55 ober #if NRASOPS_ROTATION > 0
1267 1.55 ober /*
1268 1.55 ober * Quarter clockwise rotation routines (originally intended for the
1269 1.55 ober * built-in Zaurus C3x00 display in 16bpp).
1270 1.55 ober */
1271 1.55 ober
1272 1.55 ober static void
1273 1.62 nonaka rasops_rotate_font(int *cookie, int rotate)
1274 1.55 ober {
1275 1.55 ober struct rotatedfont *f;
1276 1.55 ober int ncookie;
1277 1.55 ober
1278 1.55 ober SLIST_FOREACH(f, &rotatedfonts, rf_next) {
1279 1.55 ober if (f->rf_cookie == *cookie) {
1280 1.55 ober *cookie = f->rf_rotated;
1281 1.55 ober return;
1282 1.55 ober }
1283 1.55 ober }
1284 1.55 ober
1285 1.55 ober /*
1286 1.55 ober * We did not find a rotated version of this font. Ask the wsfont
1287 1.55 ober * code to compute one for us.
1288 1.55 ober */
1289 1.55 ober
1290 1.89 rin f = kmem_alloc(sizeof(*f), KM_SLEEP);
1291 1.55 ober
1292 1.62 nonaka if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
1293 1.89 rin goto fail;
1294 1.55 ober
1295 1.55 ober f->rf_cookie = *cookie;
1296 1.55 ober f->rf_rotated = ncookie;
1297 1.55 ober SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
1298 1.55 ober
1299 1.55 ober *cookie = ncookie;
1300 1.72 riastrad return;
1301 1.72 riastrad
1302 1.89 rin fail: free(f, sizeof(*f));
1303 1.72 riastrad return;
1304 1.55 ober }
1305 1.55 ober
1306 1.55 ober static void
1307 1.60 dsl rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
1308 1.55 ober {
1309 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1310 1.55 ober int height;
1311 1.55 ober int r_srcrow, r_dstrow, r_srccol, r_dstcol;
1312 1.89 rin uint8_t *sp, *dp;
1313 1.55 ober
1314 1.55 ober r_srcrow = srccol;
1315 1.55 ober r_dstrow = dstcol;
1316 1.55 ober r_srccol = ri->ri_rows - srcrow - 1;
1317 1.55 ober r_dstcol = ri->ri_rows - dstrow - 1;
1318 1.55 ober
1319 1.55 ober r_srcrow *= ri->ri_yscale;
1320 1.55 ober r_dstrow *= ri->ri_yscale;
1321 1.55 ober height = ri->ri_font->fontheight;
1322 1.55 ober
1323 1.55 ober sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1324 1.55 ober dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1325 1.55 ober
1326 1.55 ober while (height--) {
1327 1.55 ober memmove(dp, sp, ri->ri_xscale);
1328 1.55 ober dp += ri->ri_stride;
1329 1.55 ober sp += ri->ri_stride;
1330 1.55 ober }
1331 1.55 ober }
1332 1.55 ober
1333 1.55 ober static void
1334 1.62 nonaka rasops_putchar_rotated_cw(void *cookie, int row, int col, u_int uc, long attr)
1335 1.55 ober {
1336 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1337 1.89 rin int height;
1338 1.81 rin uint8_t *rp;
1339 1.55 ober
1340 1.56 mjf if (__predict_false((unsigned int)row > ri->ri_rows ||
1341 1.56 mjf (unsigned int)col > ri->ri_cols))
1342 1.56 mjf return;
1343 1.56 mjf
1344 1.56 mjf /* Avoid underflow */
1345 1.89 rin if (ri->ri_rows - row - 1 < 0)
1346 1.56 mjf return;
1347 1.56 mjf
1348 1.55 ober /* Do rotated char sans (side)underline */
1349 1.55 ober ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
1350 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1351 1.55 ober
1352 1.55 ober /* Do rotated underline */
1353 1.55 ober rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) *
1354 1.55 ober ri->ri_xscale;
1355 1.55 ober height = ri->ri_font->fontheight;
1356 1.55 ober
1357 1.55 ober /* XXX this assumes 16-bit color depth */
1358 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1359 1.82 rin uint16_t c =
1360 1.82 rin (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1361 1.55 ober
1362 1.55 ober while (height--) {
1363 1.82 rin *(uint16_t *)rp = c;
1364 1.55 ober rp += ri->ri_stride;
1365 1.55 ober }
1366 1.55 ober }
1367 1.55 ober }
1368 1.55 ober
1369 1.55 ober static void
1370 1.62 nonaka rasops_erasecols_rotated_cw(void *cookie, int row, int col, int num, long attr)
1371 1.55 ober {
1372 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1373 1.55 ober int i;
1374 1.55 ober
1375 1.55 ober for (i = col; i < col + num; i++)
1376 1.55 ober ri->ri_ops.putchar(cookie, row, i, ' ', attr);
1377 1.55 ober }
1378 1.55 ober
1379 1.55 ober /* XXX: these could likely be optimised somewhat. */
1380 1.55 ober static void
1381 1.62 nonaka rasops_copyrows_rotated_cw(void *cookie, int src, int dst, int num)
1382 1.55 ober {
1383 1.55 ober struct rasops_info *ri = (struct rasops_info *)cookie;
1384 1.55 ober int col, roff;
1385 1.55 ober
1386 1.55 ober if (src > dst)
1387 1.55 ober for (roff = 0; roff < num; roff++)
1388 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1389 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1390 1.55 ober col, col);
1391 1.55 ober else
1392 1.55 ober for (roff = num - 1; roff >= 0; roff--)
1393 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1394 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1395 1.55 ober col, col);
1396 1.55 ober }
1397 1.55 ober
1398 1.55 ober static void
1399 1.62 nonaka rasops_copycols_rotated_cw(void *cookie, int row, int src, int dst, int num)
1400 1.55 ober {
1401 1.55 ober int coff;
1402 1.55 ober
1403 1.55 ober if (src > dst)
1404 1.55 ober for (coff = 0; coff < num; coff++)
1405 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1406 1.88 rin dst + coff);
1407 1.55 ober else
1408 1.55 ober for (coff = num - 1; coff >= 0; coff--)
1409 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1410 1.88 rin dst + coff);
1411 1.55 ober }
1412 1.55 ober
1413 1.55 ober static void
1414 1.62 nonaka rasops_eraserows_rotated_cw(void *cookie, int row, int num, long attr)
1415 1.55 ober {
1416 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1417 1.55 ober int col, rn;
1418 1.55 ober
1419 1.55 ober for (rn = row; rn < row + num; rn++)
1420 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1421 1.55 ober ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
1422 1.55 ober }
1423 1.62 nonaka
1424 1.62 nonaka /*
1425 1.62 nonaka * Quarter counter-clockwise rotation routines (originally intended for the
1426 1.62 nonaka * built-in Sharp W-ZERO3 display in 16bpp).
1427 1.62 nonaka */
1428 1.62 nonaka static void
1429 1.88 rin rasops_copychar_ccw(void *cookie, int srcrow, int dstrow, int srccol,
1430 1.88 rin int dstcol)
1431 1.62 nonaka {
1432 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1433 1.89 rin int height, r_srcrow, r_dstrow, r_srccol, r_dstcol;
1434 1.81 rin uint8_t *sp, *dp;
1435 1.62 nonaka
1436 1.62 nonaka r_srcrow = ri->ri_cols - srccol - 1;
1437 1.62 nonaka r_dstrow = ri->ri_cols - dstcol - 1;
1438 1.62 nonaka r_srccol = srcrow;
1439 1.62 nonaka r_dstcol = dstrow;
1440 1.62 nonaka
1441 1.62 nonaka r_srcrow *= ri->ri_yscale;
1442 1.62 nonaka r_dstrow *= ri->ri_yscale;
1443 1.62 nonaka height = ri->ri_font->fontheight;
1444 1.62 nonaka
1445 1.62 nonaka sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1446 1.62 nonaka dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1447 1.62 nonaka
1448 1.62 nonaka while (height--) {
1449 1.62 nonaka memmove(dp, sp, ri->ri_xscale);
1450 1.62 nonaka dp += ri->ri_stride;
1451 1.62 nonaka sp += ri->ri_stride;
1452 1.62 nonaka }
1453 1.62 nonaka }
1454 1.62 nonaka
1455 1.62 nonaka static void
1456 1.62 nonaka rasops_putchar_rotated_ccw(void *cookie, int row, int col, u_int uc, long attr)
1457 1.62 nonaka {
1458 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1459 1.89 rin int height;
1460 1.81 rin uint8_t *rp;
1461 1.62 nonaka
1462 1.62 nonaka if (__predict_false((unsigned int)row > ri->ri_rows ||
1463 1.62 nonaka (unsigned int)col > ri->ri_cols))
1464 1.62 nonaka return;
1465 1.62 nonaka
1466 1.62 nonaka /* Avoid underflow */
1467 1.89 rin if (ri->ri_cols - col - 1 < 0)
1468 1.62 nonaka return;
1469 1.62 nonaka
1470 1.62 nonaka /* Do rotated char sans (side)underline */
1471 1.62 nonaka ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc,
1472 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1473 1.62 nonaka
1474 1.62 nonaka /* Do rotated underline */
1475 1.62 nonaka rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale +
1476 1.65 tsutsui row * ri->ri_xscale +
1477 1.65 tsutsui (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
1478 1.62 nonaka height = ri->ri_font->fontheight;
1479 1.62 nonaka
1480 1.62 nonaka /* XXX this assumes 16-bit color depth */
1481 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1482 1.82 rin uint16_t c =
1483 1.82 rin (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1484 1.62 nonaka
1485 1.62 nonaka while (height--) {
1486 1.82 rin *(uint16_t *)rp = c;
1487 1.62 nonaka rp += ri->ri_stride;
1488 1.62 nonaka }
1489 1.62 nonaka }
1490 1.62 nonaka }
1491 1.62 nonaka
1492 1.62 nonaka /* XXX: these could likely be optimised somewhat. */
1493 1.62 nonaka static void
1494 1.62 nonaka rasops_copyrows_rotated_ccw(void *cookie, int src, int dst, int num)
1495 1.62 nonaka {
1496 1.62 nonaka struct rasops_info *ri = (struct rasops_info *)cookie;
1497 1.62 nonaka int col, roff;
1498 1.62 nonaka
1499 1.62 nonaka if (src > dst)
1500 1.62 nonaka for (roff = 0; roff < num; roff++)
1501 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1502 1.62 nonaka rasops_copychar_ccw(cookie,
1503 1.62 nonaka src + roff, dst + roff, col, col);
1504 1.62 nonaka else
1505 1.62 nonaka for (roff = num - 1; roff >= 0; roff--)
1506 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1507 1.62 nonaka rasops_copychar_ccw(cookie,
1508 1.62 nonaka src + roff, dst + roff, col, col);
1509 1.62 nonaka }
1510 1.62 nonaka
1511 1.62 nonaka static void
1512 1.62 nonaka rasops_copycols_rotated_ccw(void *cookie, int row, int src, int dst, int num)
1513 1.62 nonaka {
1514 1.62 nonaka int coff;
1515 1.62 nonaka
1516 1.62 nonaka if (src > dst)
1517 1.62 nonaka for (coff = 0; coff < num; coff++)
1518 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1519 1.62 nonaka src + coff, dst + coff);
1520 1.62 nonaka else
1521 1.62 nonaka for (coff = num - 1; coff >= 0; coff--)
1522 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1523 1.62 nonaka src + coff, dst + coff);
1524 1.62 nonaka }
1525 1.55 ober #endif /* NRASOPS_ROTATION */
1526 1.63 macallan
1527 1.63 macallan void
1528 1.63 macallan rasops_make_box_chars_16(struct rasops_info *ri)
1529 1.63 macallan {
1530 1.89 rin int c, i, mid;
1531 1.63 macallan uint16_t vert_mask, hmask_left, hmask_right;
1532 1.63 macallan uint16_t *data = (uint16_t *)ri->ri_optfont.data;
1533 1.63 macallan
1534 1.89 rin vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1535 1.89 rin hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
1536 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1537 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1538 1.63 macallan
1539 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1540 1.63 macallan for (c = 1; c < 16; c++) {
1541 1.63 macallan data += ri->ri_font->fontheight;
1542 1.63 macallan if (c & 1) {
1543 1.63 macallan /* upper segment */
1544 1.63 macallan for (i = 0; i < mid; i++)
1545 1.63 macallan data[i] = vert_mask;
1546 1.63 macallan }
1547 1.63 macallan if (c & 4) {
1548 1.63 macallan /* lower segment */
1549 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1550 1.63 macallan data[i] = vert_mask;
1551 1.63 macallan }
1552 1.63 macallan if (c & 2) {
1553 1.63 macallan /* right segment */
1554 1.63 macallan i = ri->ri_font->fontheight >> 1;
1555 1.63 macallan data[mid - 1] |= hmask_right;
1556 1.63 macallan data[mid] |= hmask_right;
1557 1.63 macallan }
1558 1.63 macallan if (c & 8) {
1559 1.63 macallan /* left segment */
1560 1.63 macallan data[mid - 1] |= hmask_left;
1561 1.63 macallan data[mid] |= hmask_left;
1562 1.63 macallan }
1563 1.63 macallan }
1564 1.63 macallan }
1565 1.63 macallan
1566 1.63 macallan void
1567 1.63 macallan rasops_make_box_chars_8(struct rasops_info *ri)
1568 1.63 macallan {
1569 1.89 rin int c, i, mid;
1570 1.63 macallan uint8_t vert_mask, hmask_left, hmask_right;
1571 1.63 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1572 1.63 macallan
1573 1.89 rin vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
1574 1.89 rin hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
1575 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1576 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1577 1.63 macallan
1578 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1579 1.63 macallan for (c = 1; c < 16; c++) {
1580 1.63 macallan data += ri->ri_font->fontheight;
1581 1.63 macallan if (c & 1) {
1582 1.63 macallan /* upper segment */
1583 1.63 macallan for (i = 0; i < mid; i++)
1584 1.63 macallan data[i] = vert_mask;
1585 1.63 macallan }
1586 1.63 macallan if (c & 4) {
1587 1.63 macallan /* lower segment */
1588 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1589 1.63 macallan data[i] = vert_mask;
1590 1.63 macallan }
1591 1.63 macallan if (c & 2) {
1592 1.63 macallan /* right segment */
1593 1.63 macallan i = ri->ri_font->fontheight >> 1;
1594 1.63 macallan data[mid - 1] |= hmask_right;
1595 1.63 macallan data[mid] |= hmask_right;
1596 1.63 macallan }
1597 1.63 macallan if (c & 8) {
1598 1.63 macallan /* left segment */
1599 1.63 macallan data[mid - 1] |= hmask_left;
1600 1.63 macallan data[mid] |= hmask_left;
1601 1.63 macallan }
1602 1.63 macallan }
1603 1.63 macallan }
1604 1.63 macallan
1605 1.63 macallan void
1606 1.63 macallan rasops_make_box_chars_32(struct rasops_info *ri)
1607 1.63 macallan {
1608 1.89 rin int c, i, mid;
1609 1.63 macallan uint32_t vert_mask, hmask_left, hmask_right;
1610 1.63 macallan uint32_t *data = (uint32_t *)ri->ri_optfont.data;
1611 1.63 macallan
1612 1.88 rin vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1613 1.88 rin hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
1614 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1615 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1616 1.63 macallan
1617 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1618 1.63 macallan for (c = 1; c < 16; c++) {
1619 1.63 macallan data += ri->ri_font->fontheight;
1620 1.63 macallan if (c & 1) {
1621 1.63 macallan /* upper segment */
1622 1.63 macallan for (i = 0; i < mid; i++)
1623 1.63 macallan data[i] = vert_mask;
1624 1.63 macallan }
1625 1.63 macallan if (c & 4) {
1626 1.63 macallan /* lower segment */
1627 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1628 1.63 macallan data[i] = vert_mask;
1629 1.63 macallan }
1630 1.63 macallan if (c & 2) {
1631 1.63 macallan /* right segment */
1632 1.63 macallan i = ri->ri_font->fontheight >> 1;
1633 1.63 macallan data[mid - 1] |= hmask_right;
1634 1.63 macallan data[mid] |= hmask_right;
1635 1.63 macallan }
1636 1.63 macallan if (c & 8) {
1637 1.63 macallan /* left segment */
1638 1.63 macallan data[mid - 1] |= hmask_left;
1639 1.63 macallan data[mid] |= hmask_left;
1640 1.63 macallan }
1641 1.63 macallan }
1642 1.63 macallan }
1643 1.67 macallan
1644 1.67 macallan void
1645 1.67 macallan rasops_make_box_chars_alpha(struct rasops_info *ri)
1646 1.67 macallan {
1647 1.89 rin int c, i, hmid, vmid, wi, he;
1648 1.67 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1649 1.67 macallan uint8_t *ddata;
1650 1.67 macallan
1651 1.89 rin he = ri->ri_font->fontheight;
1652 1.67 macallan wi = ri->ri_font->fontwidth;
1653 1.67 macallan
1654 1.67 macallan vmid = (he + 1) >> 1;
1655 1.67 macallan hmid = (wi + 1) >> 1;
1656 1.67 macallan
1657 1.67 macallan /* 0x00 would be empty anyway so don't bother */
1658 1.67 macallan for (c = 1; c < 16; c++) {
1659 1.67 macallan data += ri->ri_fontscale;
1660 1.67 macallan if (c & 1) {
1661 1.67 macallan /* upper segment */
1662 1.67 macallan ddata = data + hmid;
1663 1.67 macallan for (i = 0; i <= vmid; i++) {
1664 1.67 macallan *ddata = 0xff;
1665 1.67 macallan ddata += wi;
1666 1.67 macallan }
1667 1.67 macallan }
1668 1.67 macallan if (c & 4) {
1669 1.67 macallan /* lower segment */
1670 1.67 macallan ddata = data + wi * vmid + hmid;
1671 1.67 macallan for (i = vmid; i < he; i++) {
1672 1.67 macallan *ddata = 0xff;
1673 1.67 macallan ddata += wi;
1674 1.67 macallan }
1675 1.67 macallan }
1676 1.67 macallan if (c & 2) {
1677 1.67 macallan /* right segment */
1678 1.67 macallan ddata = data + wi * vmid + hmid;
1679 1.67 macallan for (i = hmid; i < wi; i++) {
1680 1.67 macallan *ddata = 0xff;
1681 1.67 macallan ddata++;
1682 1.67 macallan }
1683 1.67 macallan }
1684 1.67 macallan if (c & 8) {
1685 1.67 macallan /* left segment */
1686 1.67 macallan ddata = data + wi * vmid;
1687 1.67 macallan for (i = 0; i <= hmid; i++) {
1688 1.67 macallan *ddata = 0xff;
1689 1.67 macallan ddata++;
1690 1.67 macallan }
1691 1.67 macallan }
1692 1.67 macallan }
1693 1.67 macallan }
1694 1.75 macallan
1695 1.71 macallan /*
1696 1.71 macallan * Return a colour map appropriate for the given struct rasops_info in the
1697 1.71 macallan * same form used by rasops_cmap[]
1698 1.71 macallan * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
1699 1.71 macallan * probably be a linear ( or gamma corrected? ) ramp for higher depths.
1700 1.71 macallan */
1701 1.71 macallan
1702 1.71 macallan int
1703 1.71 macallan rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
1704 1.71 macallan {
1705 1.88 rin
1706 1.89 rin if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
1707 1.71 macallan /* generate an R3G3B2 palette */
1708 1.71 macallan int i, idx = 0;
1709 1.71 macallan uint8_t tmp;
1710 1.71 macallan
1711 1.71 macallan if (bytes < 768)
1712 1.71 macallan return EINVAL;
1713 1.71 macallan for (i = 0; i < 256; i++) {
1714 1.71 macallan tmp = i & 0xe0;
1715 1.71 macallan /*
1716 1.71 macallan * replicate bits so 0xe0 maps to a red value of 0xff
1717 1.71 macallan * in order to make white look actually white
1718 1.71 macallan */
1719 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1720 1.71 macallan palette[idx] = tmp;
1721 1.71 macallan idx++;
1722 1.71 macallan
1723 1.71 macallan tmp = (i & 0x1c) << 3;
1724 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1725 1.71 macallan palette[idx] = tmp;
1726 1.71 macallan idx++;
1727 1.71 macallan
1728 1.71 macallan tmp = (i & 0x03) << 6;
1729 1.71 macallan tmp |= tmp >> 2;
1730 1.71 macallan tmp |= tmp >> 4;
1731 1.71 macallan palette[idx] = tmp;
1732 1.71 macallan idx++;
1733 1.71 macallan }
1734 1.88 rin } else
1735 1.89 rin memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
1736 1.71 macallan return 0;
1737 1.71 macallan }
1738