rasops.c revision 1.101 1 1.101 rin /* $NetBSD: rasops.c,v 1.101 2019/07/30 15:29:40 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.101 rin __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.101 2019/07/30 15:29:40 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.94 rin 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.95 rin #if (NRASOPS15 + 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.98 rin if ((flg & WSATTR_HILIT) != 0)
622 1.98 rin fg += 8;
623 1.98 rin
624 1.17 ad if ((flg & WSATTR_REVERSE) != 0) {
625 1.89 rin uint32_t swap = fg;
626 1.1 ad fg = bg;
627 1.1 ad bg = swap;
628 1.1 ad }
629 1.1 ad
630 1.98 rin 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.95 rin *attr = (bg << 16) | (fg << 24) | flg;
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.99 rin int n, stride;
675 1.30 pk
676 1.90 rin hp = NULL; /* XXX GCC */
677 1.1 ad
678 1.100 rin if (__predict_false(dst == src))
679 1.1 ad return;
680 1.30 pk
681 1.100 rin #ifdef RASOPS_CLIPPING
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.99 rin stride = ri->ri_stride;
705 1.30 pk
706 1.90 rin sp = ri->ri_bits + src * ri->ri_yscale;
707 1.90 rin dp = ri->ri_bits + dst * ri->ri_yscale;
708 1.90 rin if (ri->ri_hwbits)
709 1.90 rin hp = ri->ri_hwbits + dst * ri->ri_yscale;
710 1.30 pk
711 1.18 ad while (num--) {
712 1.100 rin memcpy(dp, sp, n);
713 1.99 rin dp += stride;
714 1.52 jmcneill if (ri->ri_hwbits) {
715 1.90 rin memcpy(hp, sp, n);
716 1.99 rin hp += stride;
717 1.51 jmcneill }
718 1.99 rin sp += stride;
719 1.1 ad }
720 1.1 ad }
721 1.1 ad
722 1.1 ad /*
723 1.1 ad * Copy columns. This is slow, and hard to optimize due to alignment,
724 1.1 ad * and the fact that we have to copy both left->right and right->left.
725 1.43 uwe * We simply cop-out here and use memmove(), since it handles all of
726 1.1 ad * these cases anyway.
727 1.1 ad */
728 1.4 ad void
729 1.60 dsl rasops_copycols(void *cookie, int row, int src, int dst, int num)
730 1.1 ad {
731 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
732 1.81 rin uint8_t *sp, *dp, *hp;
733 1.1 ad int height;
734 1.30 pk
735 1.89 rin hp = NULL; /* XXX GCC */
736 1.1 ad
737 1.100 rin if (__predict_false(dst == src))
738 1.1 ad return;
739 1.30 pk
740 1.100 rin #ifdef RASOPS_CLIPPING
741 1.3 ad /* Catches < 0 case too */
742 1.3 ad if ((unsigned)row >= (unsigned)ri->ri_rows)
743 1.1 ad return;
744 1.30 pk
745 1.1 ad if (src < 0) {
746 1.1 ad num += src;
747 1.1 ad src = 0;
748 1.1 ad }
749 1.1 ad
750 1.89 rin if (src + num > ri->ri_cols)
751 1.1 ad num = ri->ri_cols - src;
752 1.1 ad
753 1.1 ad if (dst < 0) {
754 1.1 ad num += dst;
755 1.1 ad dst = 0;
756 1.1 ad }
757 1.1 ad
758 1.89 rin if (dst + num > ri->ri_cols)
759 1.1 ad num = ri->ri_cols - dst;
760 1.30 pk
761 1.1 ad if (num <= 0)
762 1.1 ad return;
763 1.1 ad #endif
764 1.30 pk
765 1.1 ad num *= ri->ri_xscale;
766 1.1 ad row *= ri->ri_yscale;
767 1.1 ad height = ri->ri_font->fontheight;
768 1.30 pk
769 1.1 ad sp = ri->ri_bits + row + src * ri->ri_xscale;
770 1.1 ad dp = ri->ri_bits + row + dst * ri->ri_xscale;
771 1.51 jmcneill if (ri->ri_hwbits)
772 1.51 jmcneill hp = ri->ri_hwbits + row + dst * ri->ri_xscale;
773 1.30 pk
774 1.1 ad while (height--) {
775 1.100 rin memcpy(dp, sp, num);
776 1.89 rin dp += ri->ri_stride;
777 1.51 jmcneill if (ri->ri_hwbits) {
778 1.51 jmcneill memcpy(hp, sp, num);
779 1.51 jmcneill hp += ri->ri_stride;
780 1.51 jmcneill }
781 1.1 ad sp += ri->ri_stride;
782 1.1 ad }
783 1.1 ad }
784 1.1 ad
785 1.1 ad /*
786 1.1 ad * Turn cursor off/on.
787 1.1 ad */
788 1.1 ad static void
789 1.60 dsl rasops_cursor(void *cookie, int on, int row, int col)
790 1.1 ad {
791 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
792 1.30 pk
793 1.1 ad /* Turn old cursor off */
794 1.13 ad if ((ri->ri_flg & RI_CURSOR) != 0)
795 1.30 pk #ifdef RASOPS_CLIPPING
796 1.13 ad if ((ri->ri_flg & RI_CURSORCLIP) == 0)
797 1.1 ad #endif
798 1.1 ad ri->ri_do_cursor(ri);
799 1.1 ad
800 1.1 ad /* Select new cursor */
801 1.1 ad #ifdef RASOPS_CLIPPING
802 1.13 ad ri->ri_flg &= ~RI_CURSORCLIP;
803 1.30 pk
804 1.1 ad if (row < 0 || row >= ri->ri_rows)
805 1.13 ad ri->ri_flg |= RI_CURSORCLIP;
806 1.1 ad else if (col < 0 || col >= ri->ri_cols)
807 1.13 ad ri->ri_flg |= RI_CURSORCLIP;
808 1.1 ad #endif
809 1.1 ad ri->ri_crow = row;
810 1.1 ad ri->ri_ccol = col;
811 1.1 ad
812 1.1 ad if (on) {
813 1.13 ad ri->ri_flg |= RI_CURSOR;
814 1.30 pk #ifdef RASOPS_CLIPPING
815 1.13 ad if ((ri->ri_flg & RI_CURSORCLIP) == 0)
816 1.1 ad #endif
817 1.1 ad ri->ri_do_cursor(ri);
818 1.30 pk } else
819 1.13 ad ri->ri_flg &= ~RI_CURSOR;
820 1.1 ad }
821 1.1 ad
822 1.1 ad /*
823 1.1 ad * Make the device colormap
824 1.1 ad */
825 1.4 ad static void
826 1.59 dsl rasops_init_devcmap(struct rasops_info *ri)
827 1.1 ad {
828 1.89 rin int i;
829 1.89 rin uint32_t c;
830 1.81 rin const uint8_t *p;
831 1.30 pk
832 1.4 ad switch (ri->ri_depth) {
833 1.4 ad case 1:
834 1.4 ad ri->ri_devcmap[0] = 0;
835 1.4 ad for (i = 1; i < 16; i++)
836 1.4 ad ri->ri_devcmap[i] = -1;
837 1.4 ad return;
838 1.4 ad
839 1.4 ad case 2:
840 1.4 ad for (i = 1; i < 15; i++)
841 1.89 rin ri->ri_devcmap[i] = 0xaaaaaaaa;
842 1.30 pk
843 1.4 ad ri->ri_devcmap[0] = 0;
844 1.89 rin ri->ri_devcmap[8] = 0x55555555;
845 1.4 ad ri->ri_devcmap[15] = -1;
846 1.4 ad return;
847 1.4 ad
848 1.91 rin #ifdef RASOPS_APPLE_PALETTE
849 1.91 rin case 4:
850 1.91 rin for (i = 0; i < 16; i++) {
851 1.91 rin c = apple4_devcmap[i];
852 1.91 rin ri->ri_devcmap[i] =
853 1.91 rin (c << 0) | (c << 4) | (c << 8) | (c << 12) |
854 1.91 rin (c << 16) | (c << 20) | (c << 24) | (c << 28);
855 1.91 rin }
856 1.91 rin return;
857 1.91 rin #else
858 1.91 rin /* XXXRO What should we do here? */
859 1.91 rin #endif
860 1.91 rin
861 1.4 ad case 8:
862 1.68 macallan if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) {
863 1.89 rin for (i = 0; i < 16; i++) {
864 1.91 rin #ifdef RASOPS_APPLE_PALETTE
865 1.91 rin c = apple8_devcmap[i];
866 1.91 rin #else
867 1.89 rin c = i;
868 1.91 rin #endif
869 1.68 macallan ri->ri_devcmap[i] =
870 1.89 rin c | (c << 8) | (c << 16) | (c << 24);
871 1.89 rin }
872 1.68 macallan return;
873 1.68 macallan }
874 1.4 ad }
875 1.30 pk
876 1.1 ad p = rasops_cmap;
877 1.30 pk
878 1.29 nathanw for (i = 0; i < 16; i++) {
879 1.1 ad if (ri->ri_rnum <= 8)
880 1.89 rin c = (uint32_t)(*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
881 1.30 pk else
882 1.89 rin c = (uint32_t)(*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
883 1.29 nathanw p++;
884 1.1 ad
885 1.1 ad if (ri->ri_gnum <= 8)
886 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
887 1.30 pk else
888 1.89 rin c |= (uint32_t)(*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
889 1.29 nathanw p++;
890 1.1 ad
891 1.1 ad if (ri->ri_bnum <= 8)
892 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
893 1.30 pk else
894 1.89 rin c |= (uint32_t)(*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
895 1.29 nathanw p++;
896 1.4 ad
897 1.4 ad /* Fill the word for generic routines, which want this */
898 1.89 rin if (ri->ri_depth == 8) {
899 1.89 rin c |= c << 8;
900 1.89 rin c |= c << 16;
901 1.89 rin } else if (ri->ri_depth == 15 || ri->ri_depth == 16)
902 1.69 macallan c |= c << 16;
903 1.96 rin else if (ri->ri_depth == 24) {
904 1.96 rin #if BYTE_ORDER == LITTLE_ENDIAN
905 1.97 rin # ifndef RASOPS_SMALL
906 1.97 rin if (ri->ri_font->fontwidth != 12)
907 1.97 rin # endif
908 1.97 rin c = (c & 0x0000ff) << 16 | (c & 0x00ff00) |
909 1.97 rin (c & 0xff0000) >> 16;
910 1.97 rin # ifndef RASOPS_SMALL
911 1.97 rin else
912 1.97 rin c = (c & 0x0000ff) | (c & 0x00ff00) << 8 |
913 1.97 rin (c & 0xff0000) >> 8;
914 1.97 rin # endif
915 1.97 rin #else
916 1.97 rin /* XXXRO What should we do here? */
917 1.96 rin #endif
918 1.89 rin c |= (c & 0xff) << 24;
919 1.96 rin }
920 1.1 ad
921 1.4 ad /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
922 1.13 ad if ((ri->ri_flg & RI_BSWAP) == 0)
923 1.3 ad ri->ri_devcmap[i] = c;
924 1.89 rin else if (ri->ri_depth == 15 || ri->ri_depth == 16)
925 1.89 rin ri->ri_devcmap[i] = bswap16(c);
926 1.4 ad else if (ri->ri_depth == 32)
927 1.3 ad ri->ri_devcmap[i] = bswap32(c);
928 1.89 rin else /* 8, 24 */
929 1.4 ad ri->ri_devcmap[i] = c;
930 1.1 ad }
931 1.1 ad }
932 1.1 ad
933 1.1 ad /*
934 1.1 ad * Unpack a rasops attribute
935 1.1 ad */
936 1.1 ad void
937 1.60 dsl rasops_unpack_attr(long attr, int *fg, int *bg, int *underline)
938 1.1 ad {
939 1.30 pk
940 1.89 rin *fg = ((uint32_t)attr >> 24) & 0xf;
941 1.89 rin *bg = ((uint32_t)attr >> 16) & 0xf;
942 1.25 ad if (underline != NULL)
943 1.89 rin *underline = (uint32_t)attr & WSATTR_UNDERLINE;
944 1.4 ad }
945 1.4 ad
946 1.4 ad /*
947 1.4 ad * Erase rows. This isn't static, since 24-bpp uses it in special cases.
948 1.4 ad */
949 1.4 ad void
950 1.60 dsl rasops_eraserows(void *cookie, int row, int num, long attr)
951 1.4 ad {
952 1.90 rin struct rasops_info *ri = (struct rasops_info *)cookie;
953 1.101 rin uint32_t *rp, *dp, *hp, clr;
954 1.101 rin int n, cnt;
955 1.30 pk
956 1.90 rin hp = NULL; /* XXX GCC */
957 1.4 ad
958 1.4 ad #ifdef RASOPS_CLIPPING
959 1.4 ad if (row < 0) {
960 1.4 ad num += row;
961 1.4 ad row = 0;
962 1.4 ad }
963 1.4 ad
964 1.89 rin if (row + num > ri->ri_rows)
965 1.4 ad num = ri->ri_rows - row;
966 1.30 pk
967 1.4 ad if (num <= 0)
968 1.4 ad return;
969 1.4 ad #endif
970 1.4 ad
971 1.94 rin clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
972 1.4 ad
973 1.30 pk /*
974 1.20 ad * XXX The wsdisplay_emulops interface seems a little deficient in
975 1.30 pk * that there is no way to clear the *entire* screen. We provide a
976 1.30 pk * workaround here: if the entire console area is being cleared, and
977 1.13 ad * the RI_FULLCLEAR flag is set, clear the entire display.
978 1.30 pk */
979 1.13 ad if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
980 1.90 rin n = ri->ri_stride >> 2;
981 1.13 ad num = ri->ri_height;
982 1.101 rin rp = (uint32_t *)ri->ri_origbits;
983 1.51 jmcneill if (ri->ri_hwbits)
984 1.82 rin hp = (uint32_t *)ri->ri_hworigbits;
985 1.13 ad } else {
986 1.90 rin n = ri->ri_emustride >> 2;
987 1.13 ad num *= ri->ri_font->fontheight;
988 1.101 rin rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
989 1.51 jmcneill if (ri->ri_hwbits)
990 1.101 rin hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale);
991 1.13 ad }
992 1.30 pk
993 1.4 ad while (num--) {
994 1.101 rin dp = rp;
995 1.101 rin for (cnt = n; cnt; cnt--)
996 1.90 rin *dp++ = clr;
997 1.101 rin if (ri->ri_hwbits) {
998 1.101 rin memcpy(hp, rp, n << 2);
999 1.101 rin DELTA(hp, ri->ri_stride, uint32_t *);
1000 1.30 pk }
1001 1.101 rin DELTA(rp, ri->ri_stride, uint32_t *);
1002 1.4 ad }
1003 1.4 ad }
1004 1.4 ad
1005 1.4 ad /*
1006 1.4 ad * Actually turn the cursor on or off. This does the dirty work for
1007 1.4 ad * rasops_cursor().
1008 1.4 ad */
1009 1.4 ad static void
1010 1.59 dsl rasops_do_cursor(struct rasops_info *ri)
1011 1.4 ad {
1012 1.84 rin int full, height, cnt, slop1, slop2, row, col;
1013 1.85 rin uint32_t tmp32, msk1, msk2;
1014 1.84 rin uint8_t tmp8;
1015 1.101 rin uint8_t *dp, *rp, *hp;
1016 1.51 jmcneill
1017 1.101 rin hp = NULL; /* XXX GCC */
1018 1.30 pk
1019 1.55 ober #if NRASOPS_ROTATION > 0
1020 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
1021 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW) {
1022 1.62 nonaka /* Rotate rows/columns */
1023 1.62 nonaka row = ri->ri_ccol;
1024 1.62 nonaka col = ri->ri_rows - ri->ri_crow - 1;
1025 1.62 nonaka } else if (ri->ri_flg & RI_ROTATE_CCW) {
1026 1.62 nonaka /* Rotate rows/columns */
1027 1.62 nonaka row = ri->ri_cols - ri->ri_ccol - 1;
1028 1.62 nonaka col = ri->ri_crow;
1029 1.62 nonaka } else { /* upside-down */
1030 1.62 nonaka row = ri->ri_crow;
1031 1.62 nonaka col = ri->ri_ccol;
1032 1.62 nonaka }
1033 1.55 ober } else
1034 1.55 ober #endif
1035 1.55 ober {
1036 1.55 ober row = ri->ri_crow;
1037 1.55 ober col = ri->ri_ccol;
1038 1.55 ober }
1039 1.30 pk
1040 1.4 ad rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
1041 1.51 jmcneill if (ri->ri_hwbits)
1042 1.101 rin hp = ri->ri_hwbits + row * ri->ri_yscale + col * ri->ri_xscale;
1043 1.4 ad height = ri->ri_font->fontheight;
1044 1.30 pk
1045 1.80 rin /*
1046 1.80 rin * For ri_xscale = 1:
1047 1.80 rin *
1048 1.80 rin * Logic below does not work for ri_xscale = 1, e.g.,
1049 1.80 rin * fontwidth = 8 and bpp = 1. So we take care of it.
1050 1.80 rin */
1051 1.80 rin if (ri->ri_xscale == 1) {
1052 1.80 rin while (height--) {
1053 1.84 rin tmp8 = ~*rp;
1054 1.80 rin
1055 1.80 rin *rp = tmp8;
1056 1.80 rin rp += ri->ri_stride;
1057 1.30 pk
1058 1.80 rin if (ri->ri_hwbits) {
1059 1.101 rin *hp = tmp8;
1060 1.101 rin hp += ri->ri_stride;
1061 1.80 rin }
1062 1.80 rin }
1063 1.80 rin return;
1064 1.80 rin }
1065 1.80 rin
1066 1.80 rin /*
1067 1.80 rin * For ri_xscale = 2, 3, 4, ...:
1068 1.80 rin *
1069 1.80 rin * Note that siop1 <= ri_xscale even for ri_xscale = 2,
1070 1.84 rin * since rp % 3 = 0 or 2 (ri_stride % 4 = 0).
1071 1.80 rin */
1072 1.80 rin slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
1073 1.4 ad slop2 = (ri->ri_xscale - slop1) & 3;
1074 1.89 rin full = (ri->ri_xscale - slop1 /* - slop2 */) >> 2;
1075 1.30 pk
1076 1.84 rin rp = (uint8_t *)((uintptr_t)rp & ~3);
1077 1.101 rin hp = (uint8_t *)((uintptr_t)hp & ~3);
1078 1.30 pk
1079 1.87 rin msk1 = !slop1 ? 0 : be32toh(0xffffffffU >> (32 - (8 * slop1)));
1080 1.87 rin msk2 = !slop2 ? 0 : be32toh(0xffffffffU << (32 - (8 * slop2)));
1081 1.85 rin
1082 1.84 rin while (height--) {
1083 1.84 rin dp = rp;
1084 1.78 macallan
1085 1.84 rin if (slop1) {
1086 1.85 rin tmp32 = *(uint32_t *)dp ^ msk1;
1087 1.84 rin *(uint32_t *)dp = tmp32;
1088 1.84 rin dp += 4;
1089 1.84 rin }
1090 1.30 pk
1091 1.84 rin for (cnt = full; cnt; cnt--) {
1092 1.84 rin tmp32 = ~*(uint32_t *)dp;
1093 1.84 rin *(uint32_t *)dp = tmp32;
1094 1.84 rin dp += 4;
1095 1.84 rin }
1096 1.30 pk
1097 1.84 rin if (slop2) {
1098 1.85 rin tmp32 = *(uint32_t *)dp ^ msk2;
1099 1.84 rin *(uint32_t *)dp = tmp32;
1100 1.4 ad }
1101 1.101 rin
1102 1.101 rin if (ri->ri_hwbits) {
1103 1.101 rin memcpy(hp, rp, ((slop1 != 0) + full +
1104 1.101 rin (slop2 != 0)) << 2);
1105 1.101 rin hp += ri->ri_stride;
1106 1.101 rin }
1107 1.101 rin rp += ri->ri_stride;
1108 1.4 ad }
1109 1.4 ad }
1110 1.4 ad
1111 1.4 ad /*
1112 1.4 ad * Erase columns.
1113 1.4 ad */
1114 1.4 ad void
1115 1.60 dsl rasops_erasecols(void *cookie, int row, int col, int num, long attr)
1116 1.4 ad {
1117 1.90 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1118 1.90 rin int height, cnt, slop1, slop2, clr;
1119 1.101 rin uint32_t *rp, *dp, *hp;
1120 1.30 pk
1121 1.101 rin hp = NULL; /* XXX GCC */
1122 1.30 pk
1123 1.30 pk #ifdef RASOPS_CLIPPING
1124 1.4 ad if ((unsigned)row >= (unsigned)ri->ri_rows)
1125 1.4 ad return;
1126 1.4 ad
1127 1.4 ad if (col < 0) {
1128 1.4 ad num += col;
1129 1.4 ad col = 0;
1130 1.4 ad }
1131 1.4 ad
1132 1.101 rin if (col + num > ri->ri_cols)
1133 1.4 ad num = ri->ri_cols - col;
1134 1.30 pk
1135 1.4 ad if (num <= 0)
1136 1.4 ad return;
1137 1.4 ad #endif
1138 1.30 pk
1139 1.90 rin num *= ri->ri_xscale;
1140 1.82 rin rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
1141 1.51 jmcneill if (ri->ri_hwbits)
1142 1.101 rin hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
1143 1.51 jmcneill col*ri->ri_xscale);
1144 1.4 ad height = ri->ri_font->fontheight;
1145 1.94 rin clr = ri->ri_devcmap[((uint32_t)attr >> 16) & 0xf];
1146 1.30 pk
1147 1.4 ad /* Don't bother using the full loop for <= 32 pels */
1148 1.4 ad if (num <= 32) {
1149 1.6 ad if (((num | ri->ri_xscale) & 3) == 0) {
1150 1.6 ad /* Word aligned blt */
1151 1.6 ad num >>= 2;
1152 1.6 ad
1153 1.6 ad while (height--) {
1154 1.6 ad dp = rp;
1155 1.101 rin for (cnt = num; cnt; cnt--)
1156 1.101 rin *dp++ = clr;
1157 1.51 jmcneill if (ri->ri_hwbits) {
1158 1.101 rin memcpy(hp, rp, num << 2);
1159 1.101 rin DELTA(hp, ri->ri_stride, uint32_t *);
1160 1.51 jmcneill }
1161 1.101 rin DELTA(rp, ri->ri_stride, uint32_t *);
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.4 ad for (cnt = num; cnt; cnt--) {
1173 1.82 rin *(uint16_t *)dp = clr;
1174 1.82 rin DELTA(dp, 2, uint32_t *);
1175 1.4 ad }
1176 1.101 rin if (ri->ri_hwbits) {
1177 1.101 rin memcpy(hp, rp, num << 1);
1178 1.101 rin DELTA(hp, ri->ri_stride, uint32_t *);
1179 1.101 rin }
1180 1.101 rin DELTA(rp, ri->ri_stride, uint32_t *);
1181 1.4 ad }
1182 1.4 ad } else {
1183 1.4 ad while (height--) {
1184 1.92 rin dp = rp;
1185 1.92 rin for (cnt = num; cnt; cnt--) {
1186 1.92 rin *(uint8_t *)dp = clr;
1187 1.92 rin DELTA(dp, 1, uint32_t *);
1188 1.92 rin }
1189 1.101 rin if (ri->ri_hwbits) {
1190 1.101 rin memcpy(hp, rp, num);
1191 1.101 rin DELTA(hp, ri->ri_stride, uint32_t *);
1192 1.101 rin }
1193 1.101 rin DELTA(rp, ri->ri_stride, uint32_t *);
1194 1.4 ad }
1195 1.4 ad }
1196 1.30 pk
1197 1.4 ad return;
1198 1.4 ad }
1199 1.30 pk
1200 1.90 rin slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
1201 1.4 ad slop2 = (num - slop1) & 3;
1202 1.90 rin num = (num - slop1 /* - slop2 */) >> 2;
1203 1.4 ad
1204 1.4 ad while (height--) {
1205 1.4 ad dp = rp;
1206 1.30 pk
1207 1.4 ad /* Align span to 4 bytes */
1208 1.4 ad if (slop1 & 1) {
1209 1.81 rin *(uint8_t *)dp = clr;
1210 1.82 rin DELTA(dp, 1, uint32_t *);
1211 1.4 ad }
1212 1.4 ad
1213 1.4 ad if (slop1 & 2) {
1214 1.82 rin *(uint16_t *)dp = clr;
1215 1.82 rin DELTA(dp, 2, uint32_t *);
1216 1.4 ad }
1217 1.30 pk
1218 1.30 pk /* Write 4 bytes per loop */
1219 1.101 rin for (cnt = num; cnt; cnt--)
1220 1.4 ad *dp++ = clr;
1221 1.30 pk
1222 1.30 pk /* Write unaligned trailing slop */
1223 1.4 ad if (slop2 & 1) {
1224 1.81 rin *(uint8_t *)dp = clr;
1225 1.82 rin DELTA(dp, 1, uint32_t *);
1226 1.4 ad }
1227 1.4 ad
1228 1.101 rin if (slop2 & 2)
1229 1.82 rin *(uint16_t *)dp = clr;
1230 1.101 rin
1231 1.101 rin if (ri->ri_hwbits) {
1232 1.101 rin memcpy(hp, rp, slop1 + (num << 2) + slop2);
1233 1.101 rin DELTA(hp, ri->ri_stride, uint32_t *);
1234 1.51 jmcneill }
1235 1.101 rin DELTA(rp, ri->ri_stride, uint32_t *);
1236 1.4 ad }
1237 1.1 ad }
1238 1.55 ober
1239 1.55 ober #if NRASOPS_ROTATION > 0
1240 1.55 ober /*
1241 1.55 ober * Quarter clockwise rotation routines (originally intended for the
1242 1.55 ober * built-in Zaurus C3x00 display in 16bpp).
1243 1.55 ober */
1244 1.55 ober
1245 1.55 ober static void
1246 1.62 nonaka rasops_rotate_font(int *cookie, int rotate)
1247 1.55 ober {
1248 1.55 ober struct rotatedfont *f;
1249 1.55 ober int ncookie;
1250 1.55 ober
1251 1.55 ober SLIST_FOREACH(f, &rotatedfonts, rf_next) {
1252 1.55 ober if (f->rf_cookie == *cookie) {
1253 1.55 ober *cookie = f->rf_rotated;
1254 1.55 ober return;
1255 1.55 ober }
1256 1.55 ober }
1257 1.55 ober
1258 1.55 ober /*
1259 1.55 ober * We did not find a rotated version of this font. Ask the wsfont
1260 1.55 ober * code to compute one for us.
1261 1.55 ober */
1262 1.55 ober
1263 1.89 rin f = kmem_alloc(sizeof(*f), KM_SLEEP);
1264 1.55 ober
1265 1.62 nonaka if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
1266 1.89 rin goto fail;
1267 1.55 ober
1268 1.55 ober f->rf_cookie = *cookie;
1269 1.55 ober f->rf_rotated = ncookie;
1270 1.55 ober SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
1271 1.55 ober
1272 1.55 ober *cookie = ncookie;
1273 1.72 riastrad return;
1274 1.72 riastrad
1275 1.93 martin fail: kmem_free(f, sizeof(*f));
1276 1.72 riastrad return;
1277 1.55 ober }
1278 1.55 ober
1279 1.55 ober static void
1280 1.60 dsl rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
1281 1.55 ober {
1282 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1283 1.55 ober int height;
1284 1.55 ober int r_srcrow, r_dstrow, r_srccol, r_dstcol;
1285 1.89 rin uint8_t *sp, *dp;
1286 1.55 ober
1287 1.55 ober r_srcrow = srccol;
1288 1.55 ober r_dstrow = dstcol;
1289 1.55 ober r_srccol = ri->ri_rows - srcrow - 1;
1290 1.55 ober r_dstcol = ri->ri_rows - dstrow - 1;
1291 1.55 ober
1292 1.55 ober r_srcrow *= ri->ri_yscale;
1293 1.55 ober r_dstrow *= ri->ri_yscale;
1294 1.55 ober height = ri->ri_font->fontheight;
1295 1.55 ober
1296 1.55 ober sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1297 1.55 ober dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1298 1.55 ober
1299 1.55 ober while (height--) {
1300 1.55 ober memmove(dp, sp, ri->ri_xscale);
1301 1.55 ober dp += ri->ri_stride;
1302 1.55 ober sp += ri->ri_stride;
1303 1.55 ober }
1304 1.55 ober }
1305 1.55 ober
1306 1.55 ober static void
1307 1.62 nonaka rasops_putchar_rotated_cw(void *cookie, int row, int col, u_int uc, long attr)
1308 1.55 ober {
1309 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1310 1.89 rin int height;
1311 1.81 rin uint8_t *rp;
1312 1.55 ober
1313 1.56 mjf if (__predict_false((unsigned int)row > ri->ri_rows ||
1314 1.56 mjf (unsigned int)col > ri->ri_cols))
1315 1.56 mjf return;
1316 1.56 mjf
1317 1.56 mjf /* Avoid underflow */
1318 1.89 rin if (ri->ri_rows - row - 1 < 0)
1319 1.56 mjf return;
1320 1.56 mjf
1321 1.55 ober /* Do rotated char sans (side)underline */
1322 1.55 ober ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
1323 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1324 1.55 ober
1325 1.55 ober /* Do rotated underline */
1326 1.55 ober rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) *
1327 1.55 ober ri->ri_xscale;
1328 1.55 ober height = ri->ri_font->fontheight;
1329 1.55 ober
1330 1.55 ober /* XXX this assumes 16-bit color depth */
1331 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1332 1.82 rin uint16_t c =
1333 1.94 rin (uint16_t)ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
1334 1.55 ober
1335 1.55 ober while (height--) {
1336 1.82 rin *(uint16_t *)rp = c;
1337 1.55 ober rp += ri->ri_stride;
1338 1.55 ober }
1339 1.55 ober }
1340 1.55 ober }
1341 1.55 ober
1342 1.55 ober static void
1343 1.62 nonaka rasops_erasecols_rotated_cw(void *cookie, int row, int col, int num, long attr)
1344 1.55 ober {
1345 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1346 1.55 ober int i;
1347 1.55 ober
1348 1.55 ober for (i = col; i < col + num; i++)
1349 1.55 ober ri->ri_ops.putchar(cookie, row, i, ' ', attr);
1350 1.55 ober }
1351 1.55 ober
1352 1.55 ober /* XXX: these could likely be optimised somewhat. */
1353 1.55 ober static void
1354 1.62 nonaka rasops_copyrows_rotated_cw(void *cookie, int src, int dst, int num)
1355 1.55 ober {
1356 1.55 ober struct rasops_info *ri = (struct rasops_info *)cookie;
1357 1.55 ober int col, roff;
1358 1.55 ober
1359 1.55 ober if (src > dst)
1360 1.55 ober for (roff = 0; roff < num; roff++)
1361 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1362 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1363 1.55 ober col, col);
1364 1.55 ober else
1365 1.55 ober for (roff = num - 1; roff >= 0; roff--)
1366 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1367 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1368 1.55 ober col, col);
1369 1.55 ober }
1370 1.55 ober
1371 1.55 ober static void
1372 1.62 nonaka rasops_copycols_rotated_cw(void *cookie, int row, int src, int dst, int num)
1373 1.55 ober {
1374 1.55 ober int coff;
1375 1.55 ober
1376 1.55 ober if (src > dst)
1377 1.55 ober for (coff = 0; coff < num; coff++)
1378 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1379 1.88 rin dst + coff);
1380 1.55 ober else
1381 1.55 ober for (coff = num - 1; coff >= 0; coff--)
1382 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1383 1.88 rin dst + coff);
1384 1.55 ober }
1385 1.55 ober
1386 1.55 ober static void
1387 1.62 nonaka rasops_eraserows_rotated_cw(void *cookie, int row, int num, long attr)
1388 1.55 ober {
1389 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1390 1.55 ober int col, rn;
1391 1.55 ober
1392 1.55 ober for (rn = row; rn < row + num; rn++)
1393 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1394 1.55 ober ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
1395 1.55 ober }
1396 1.62 nonaka
1397 1.62 nonaka /*
1398 1.62 nonaka * Quarter counter-clockwise rotation routines (originally intended for the
1399 1.62 nonaka * built-in Sharp W-ZERO3 display in 16bpp).
1400 1.62 nonaka */
1401 1.62 nonaka static void
1402 1.88 rin rasops_copychar_ccw(void *cookie, int srcrow, int dstrow, int srccol,
1403 1.88 rin int dstcol)
1404 1.62 nonaka {
1405 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1406 1.89 rin int height, r_srcrow, r_dstrow, r_srccol, r_dstcol;
1407 1.81 rin uint8_t *sp, *dp;
1408 1.62 nonaka
1409 1.62 nonaka r_srcrow = ri->ri_cols - srccol - 1;
1410 1.62 nonaka r_dstrow = ri->ri_cols - dstcol - 1;
1411 1.62 nonaka r_srccol = srcrow;
1412 1.62 nonaka r_dstcol = dstrow;
1413 1.62 nonaka
1414 1.62 nonaka r_srcrow *= ri->ri_yscale;
1415 1.62 nonaka r_dstrow *= ri->ri_yscale;
1416 1.62 nonaka height = ri->ri_font->fontheight;
1417 1.62 nonaka
1418 1.62 nonaka sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1419 1.62 nonaka dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1420 1.62 nonaka
1421 1.62 nonaka while (height--) {
1422 1.62 nonaka memmove(dp, sp, ri->ri_xscale);
1423 1.62 nonaka dp += ri->ri_stride;
1424 1.62 nonaka sp += ri->ri_stride;
1425 1.62 nonaka }
1426 1.62 nonaka }
1427 1.62 nonaka
1428 1.62 nonaka static void
1429 1.62 nonaka rasops_putchar_rotated_ccw(void *cookie, int row, int col, u_int uc, long attr)
1430 1.62 nonaka {
1431 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1432 1.89 rin int height;
1433 1.81 rin uint8_t *rp;
1434 1.62 nonaka
1435 1.62 nonaka if (__predict_false((unsigned int)row > ri->ri_rows ||
1436 1.62 nonaka (unsigned int)col > ri->ri_cols))
1437 1.62 nonaka return;
1438 1.62 nonaka
1439 1.62 nonaka /* Avoid underflow */
1440 1.89 rin if (ri->ri_cols - col - 1 < 0)
1441 1.62 nonaka return;
1442 1.62 nonaka
1443 1.62 nonaka /* Do rotated char sans (side)underline */
1444 1.62 nonaka ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc,
1445 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1446 1.62 nonaka
1447 1.62 nonaka /* Do rotated underline */
1448 1.62 nonaka rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale +
1449 1.65 tsutsui row * ri->ri_xscale +
1450 1.65 tsutsui (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
1451 1.62 nonaka height = ri->ri_font->fontheight;
1452 1.62 nonaka
1453 1.62 nonaka /* XXX this assumes 16-bit color depth */
1454 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1455 1.82 rin uint16_t c =
1456 1.94 rin (uint16_t)ri->ri_devcmap[((uint32_t)attr >> 24) & 0xf];
1457 1.62 nonaka
1458 1.62 nonaka while (height--) {
1459 1.82 rin *(uint16_t *)rp = c;
1460 1.62 nonaka rp += ri->ri_stride;
1461 1.62 nonaka }
1462 1.62 nonaka }
1463 1.62 nonaka }
1464 1.62 nonaka
1465 1.62 nonaka /* XXX: these could likely be optimised somewhat. */
1466 1.62 nonaka static void
1467 1.62 nonaka rasops_copyrows_rotated_ccw(void *cookie, int src, int dst, int num)
1468 1.62 nonaka {
1469 1.62 nonaka struct rasops_info *ri = (struct rasops_info *)cookie;
1470 1.62 nonaka int col, roff;
1471 1.62 nonaka
1472 1.62 nonaka if (src > dst)
1473 1.62 nonaka for (roff = 0; roff < num; roff++)
1474 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1475 1.62 nonaka rasops_copychar_ccw(cookie,
1476 1.62 nonaka src + roff, dst + roff, col, col);
1477 1.62 nonaka else
1478 1.62 nonaka for (roff = num - 1; roff >= 0; roff--)
1479 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1480 1.62 nonaka rasops_copychar_ccw(cookie,
1481 1.62 nonaka src + roff, dst + roff, col, col);
1482 1.62 nonaka }
1483 1.62 nonaka
1484 1.62 nonaka static void
1485 1.62 nonaka rasops_copycols_rotated_ccw(void *cookie, int row, int src, int dst, int num)
1486 1.62 nonaka {
1487 1.62 nonaka int coff;
1488 1.62 nonaka
1489 1.62 nonaka if (src > dst)
1490 1.62 nonaka for (coff = 0; coff < num; coff++)
1491 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1492 1.62 nonaka src + coff, dst + coff);
1493 1.62 nonaka else
1494 1.62 nonaka for (coff = num - 1; coff >= 0; coff--)
1495 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1496 1.62 nonaka src + coff, dst + coff);
1497 1.62 nonaka }
1498 1.55 ober #endif /* NRASOPS_ROTATION */
1499 1.63 macallan
1500 1.63 macallan void
1501 1.63 macallan rasops_make_box_chars_16(struct rasops_info *ri)
1502 1.63 macallan {
1503 1.89 rin int c, i, mid;
1504 1.63 macallan uint16_t vert_mask, hmask_left, hmask_right;
1505 1.63 macallan uint16_t *data = (uint16_t *)ri->ri_optfont.data;
1506 1.63 macallan
1507 1.89 rin vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1508 1.89 rin hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
1509 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1510 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1511 1.63 macallan
1512 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1513 1.63 macallan for (c = 1; c < 16; c++) {
1514 1.63 macallan data += ri->ri_font->fontheight;
1515 1.63 macallan if (c & 1) {
1516 1.63 macallan /* upper segment */
1517 1.63 macallan for (i = 0; i < mid; i++)
1518 1.63 macallan data[i] = vert_mask;
1519 1.63 macallan }
1520 1.63 macallan if (c & 4) {
1521 1.63 macallan /* lower segment */
1522 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1523 1.63 macallan data[i] = vert_mask;
1524 1.63 macallan }
1525 1.63 macallan if (c & 2) {
1526 1.63 macallan /* right segment */
1527 1.63 macallan i = ri->ri_font->fontheight >> 1;
1528 1.63 macallan data[mid - 1] |= hmask_right;
1529 1.63 macallan data[mid] |= hmask_right;
1530 1.63 macallan }
1531 1.63 macallan if (c & 8) {
1532 1.63 macallan /* left segment */
1533 1.63 macallan data[mid - 1] |= hmask_left;
1534 1.63 macallan data[mid] |= hmask_left;
1535 1.63 macallan }
1536 1.63 macallan }
1537 1.63 macallan }
1538 1.63 macallan
1539 1.63 macallan void
1540 1.63 macallan rasops_make_box_chars_8(struct rasops_info *ri)
1541 1.63 macallan {
1542 1.89 rin int c, i, mid;
1543 1.63 macallan uint8_t vert_mask, hmask_left, hmask_right;
1544 1.63 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1545 1.63 macallan
1546 1.89 rin vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
1547 1.89 rin hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
1548 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1549 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1550 1.63 macallan
1551 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1552 1.63 macallan for (c = 1; c < 16; c++) {
1553 1.63 macallan data += ri->ri_font->fontheight;
1554 1.63 macallan if (c & 1) {
1555 1.63 macallan /* upper segment */
1556 1.63 macallan for (i = 0; i < mid; i++)
1557 1.63 macallan data[i] = vert_mask;
1558 1.63 macallan }
1559 1.63 macallan if (c & 4) {
1560 1.63 macallan /* lower segment */
1561 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1562 1.63 macallan data[i] = vert_mask;
1563 1.63 macallan }
1564 1.63 macallan if (c & 2) {
1565 1.63 macallan /* right segment */
1566 1.63 macallan i = ri->ri_font->fontheight >> 1;
1567 1.63 macallan data[mid - 1] |= hmask_right;
1568 1.63 macallan data[mid] |= hmask_right;
1569 1.63 macallan }
1570 1.63 macallan if (c & 8) {
1571 1.63 macallan /* left segment */
1572 1.63 macallan data[mid - 1] |= hmask_left;
1573 1.63 macallan data[mid] |= hmask_left;
1574 1.63 macallan }
1575 1.63 macallan }
1576 1.63 macallan }
1577 1.63 macallan
1578 1.63 macallan void
1579 1.63 macallan rasops_make_box_chars_32(struct rasops_info *ri)
1580 1.63 macallan {
1581 1.89 rin int c, i, mid;
1582 1.63 macallan uint32_t vert_mask, hmask_left, hmask_right;
1583 1.63 macallan uint32_t *data = (uint32_t *)ri->ri_optfont.data;
1584 1.63 macallan
1585 1.88 rin vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1586 1.88 rin hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
1587 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1588 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1589 1.63 macallan
1590 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1591 1.63 macallan for (c = 1; c < 16; c++) {
1592 1.63 macallan data += ri->ri_font->fontheight;
1593 1.63 macallan if (c & 1) {
1594 1.63 macallan /* upper segment */
1595 1.63 macallan for (i = 0; i < mid; i++)
1596 1.63 macallan data[i] = vert_mask;
1597 1.63 macallan }
1598 1.63 macallan if (c & 4) {
1599 1.63 macallan /* lower segment */
1600 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1601 1.63 macallan data[i] = vert_mask;
1602 1.63 macallan }
1603 1.63 macallan if (c & 2) {
1604 1.63 macallan /* right segment */
1605 1.63 macallan i = ri->ri_font->fontheight >> 1;
1606 1.63 macallan data[mid - 1] |= hmask_right;
1607 1.63 macallan data[mid] |= hmask_right;
1608 1.63 macallan }
1609 1.63 macallan if (c & 8) {
1610 1.63 macallan /* left segment */
1611 1.63 macallan data[mid - 1] |= hmask_left;
1612 1.63 macallan data[mid] |= hmask_left;
1613 1.63 macallan }
1614 1.63 macallan }
1615 1.63 macallan }
1616 1.67 macallan
1617 1.67 macallan void
1618 1.67 macallan rasops_make_box_chars_alpha(struct rasops_info *ri)
1619 1.67 macallan {
1620 1.89 rin int c, i, hmid, vmid, wi, he;
1621 1.67 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1622 1.67 macallan uint8_t *ddata;
1623 1.67 macallan
1624 1.89 rin he = ri->ri_font->fontheight;
1625 1.67 macallan wi = ri->ri_font->fontwidth;
1626 1.67 macallan
1627 1.67 macallan vmid = (he + 1) >> 1;
1628 1.67 macallan hmid = (wi + 1) >> 1;
1629 1.67 macallan
1630 1.67 macallan /* 0x00 would be empty anyway so don't bother */
1631 1.67 macallan for (c = 1; c < 16; c++) {
1632 1.67 macallan data += ri->ri_fontscale;
1633 1.67 macallan if (c & 1) {
1634 1.67 macallan /* upper segment */
1635 1.67 macallan ddata = data + hmid;
1636 1.67 macallan for (i = 0; i <= vmid; i++) {
1637 1.67 macallan *ddata = 0xff;
1638 1.67 macallan ddata += wi;
1639 1.67 macallan }
1640 1.67 macallan }
1641 1.67 macallan if (c & 4) {
1642 1.67 macallan /* lower segment */
1643 1.67 macallan ddata = data + wi * vmid + hmid;
1644 1.67 macallan for (i = vmid; i < he; i++) {
1645 1.67 macallan *ddata = 0xff;
1646 1.67 macallan ddata += wi;
1647 1.67 macallan }
1648 1.67 macallan }
1649 1.67 macallan if (c & 2) {
1650 1.67 macallan /* right segment */
1651 1.67 macallan ddata = data + wi * vmid + hmid;
1652 1.67 macallan for (i = hmid; i < wi; i++) {
1653 1.67 macallan *ddata = 0xff;
1654 1.67 macallan ddata++;
1655 1.67 macallan }
1656 1.67 macallan }
1657 1.67 macallan if (c & 8) {
1658 1.67 macallan /* left segment */
1659 1.67 macallan ddata = data + wi * vmid;
1660 1.67 macallan for (i = 0; i <= hmid; i++) {
1661 1.67 macallan *ddata = 0xff;
1662 1.67 macallan ddata++;
1663 1.67 macallan }
1664 1.67 macallan }
1665 1.67 macallan }
1666 1.67 macallan }
1667 1.75 macallan
1668 1.71 macallan /*
1669 1.71 macallan * Return a colour map appropriate for the given struct rasops_info in the
1670 1.71 macallan * same form used by rasops_cmap[]
1671 1.71 macallan * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
1672 1.71 macallan * probably be a linear ( or gamma corrected? ) ramp for higher depths.
1673 1.71 macallan */
1674 1.71 macallan
1675 1.71 macallan int
1676 1.71 macallan rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
1677 1.71 macallan {
1678 1.88 rin
1679 1.89 rin if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
1680 1.71 macallan /* generate an R3G3B2 palette */
1681 1.71 macallan int i, idx = 0;
1682 1.71 macallan uint8_t tmp;
1683 1.71 macallan
1684 1.71 macallan if (bytes < 768)
1685 1.71 macallan return EINVAL;
1686 1.71 macallan for (i = 0; i < 256; i++) {
1687 1.71 macallan tmp = i & 0xe0;
1688 1.71 macallan /*
1689 1.71 macallan * replicate bits so 0xe0 maps to a red value of 0xff
1690 1.71 macallan * in order to make white look actually white
1691 1.71 macallan */
1692 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1693 1.71 macallan palette[idx] = tmp;
1694 1.71 macallan idx++;
1695 1.71 macallan
1696 1.71 macallan tmp = (i & 0x1c) << 3;
1697 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1698 1.71 macallan palette[idx] = tmp;
1699 1.71 macallan idx++;
1700 1.71 macallan
1701 1.71 macallan tmp = (i & 0x03) << 6;
1702 1.71 macallan tmp |= tmp >> 2;
1703 1.71 macallan tmp |= tmp >> 4;
1704 1.71 macallan palette[idx] = tmp;
1705 1.71 macallan idx++;
1706 1.71 macallan }
1707 1.88 rin } else
1708 1.89 rin memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
1709 1.71 macallan return 0;
1710 1.71 macallan }
1711