rasops.c revision 1.89 1 1.89 rin /* $NetBSD: rasops.c,v 1.89 2019/07/26 05:15:47 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.89 rin __KERNEL_RCSID(0, "$NetBSD: rasops.c,v 1.89 2019/07/26 05:15:47 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.4 ad /* Generic functions */
138 1.45 perry static void rasops_copyrows(void *, int, int, int);
139 1.45 perry static int rasops_mapchar(void *, int, u_int *);
140 1.45 perry static void rasops_cursor(void *, int, int, int);
141 1.45 perry static int rasops_allocattr_color(void *, int, int, int, long *);
142 1.45 perry static int rasops_allocattr_mono(void *, int, int, int, long *);
143 1.45 perry static void rasops_do_cursor(struct rasops_info *);
144 1.45 perry static void rasops_init_devcmap(struct rasops_info *);
145 1.1 ad
146 1.55 ober #if NRASOPS_ROTATION > 0
147 1.62 nonaka static void rasops_rotate_font(int *, int);
148 1.55 ober static void rasops_copychar(void *, int, int, int, int);
149 1.62 nonaka
150 1.62 nonaka /* rotate clockwise */
151 1.62 nonaka static void rasops_copycols_rotated_cw(void *, int, int, int, int);
152 1.62 nonaka static void rasops_copyrows_rotated_cw(void *, int, int, int);
153 1.62 nonaka static void rasops_erasecols_rotated_cw(void *, int, int, int, long);
154 1.62 nonaka static void rasops_eraserows_rotated_cw(void *, int, int, long);
155 1.62 nonaka static void rasops_putchar_rotated_cw(void *, int, int, u_int, long);
156 1.62 nonaka
157 1.62 nonaka /* rotate counter-clockwise */
158 1.62 nonaka static void rasops_copychar_ccw(void *, int, int, int, int);
159 1.62 nonaka static void rasops_copycols_rotated_ccw(void *, int, int, int, int);
160 1.62 nonaka static void rasops_copyrows_rotated_ccw(void *, int, int, int);
161 1.62 nonaka #define rasops_erasecols_rotated_ccw rasops_erasecols_rotated_cw
162 1.62 nonaka #define rasops_eraserows_rotated_ccw rasops_eraserows_rotated_cw
163 1.62 nonaka static void rasops_putchar_rotated_ccw(void *, int, int, u_int, long);
164 1.55 ober
165 1.55 ober /*
166 1.55 ober * List of all rotated fonts
167 1.55 ober */
168 1.55 ober SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
169 1.55 ober struct rotatedfont {
170 1.55 ober SLIST_ENTRY(rotatedfont) rf_next;
171 1.55 ober int rf_cookie;
172 1.55 ober int rf_rotated;
173 1.55 ober };
174 1.55 ober #endif /* NRASOPS_ROTATION > 0 */
175 1.55 ober
176 1.63 macallan void rasops_make_box_chars_8(struct rasops_info *);
177 1.63 macallan void rasops_make_box_chars_16(struct rasops_info *);
178 1.63 macallan void rasops_make_box_chars_32(struct rasops_info *);
179 1.67 macallan void rasops_make_box_chars_alpha(struct rasops_info *);
180 1.63 macallan
181 1.64 macallan extern int cold;
182 1.64 macallan
183 1.1 ad /*
184 1.37 wiz * Initialize a 'rasops_info' descriptor.
185 1.1 ad */
186 1.1 ad int
187 1.60 dsl rasops_init(struct rasops_info *ri, int wantrows, int wantcols)
188 1.1 ad {
189 1.20 ad
190 1.63 macallan memset (&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
191 1.30 pk #ifdef _KERNEL
192 1.1 ad /* Select a font if the caller doesn't care */
193 1.1 ad if (ri->ri_font == NULL) {
194 1.67 macallan int cookie = -1;
195 1.73 mlelstv int flags;
196 1.30 pk
197 1.1 ad wsfont_init();
198 1.1 ad
199 1.70 macallan /*
200 1.70 macallan * first, try to find something that's as close as possible
201 1.70 macallan * to the caller's requested terminal size
202 1.70 macallan */
203 1.70 macallan if (wantrows == 0)
204 1.70 macallan wantrows = RASOPS_DEFAULT_HEIGHT;
205 1.70 macallan if (wantcols == 0)
206 1.70 macallan wantcols = RASOPS_DEFAULT_WIDTH;
207 1.73 mlelstv
208 1.73 mlelstv flags = WSFONT_FIND_BESTWIDTH | WSFONT_FIND_BITMAP;
209 1.73 mlelstv if ((ri->ri_flg & RI_ENABLE_ALPHA) != 0)
210 1.73 mlelstv flags |= WSFONT_FIND_ALPHA;
211 1.75 macallan if ((ri->ri_flg & RI_PREFER_ALPHA) != 0)
212 1.75 macallan flags |= WSFONT_PREFER_ALPHA;
213 1.73 mlelstv cookie = wsfont_find(NULL,
214 1.73 mlelstv ri->ri_width / wantcols,
215 1.73 mlelstv 0,
216 1.73 mlelstv 0,
217 1.73 mlelstv WSDISPLAY_FONTORDER_L2R,
218 1.73 mlelstv WSDISPLAY_FONTORDER_L2R,
219 1.73 mlelstv flags);
220 1.1 ad
221 1.70 macallan /*
222 1.70 macallan * this means there is no supported font in the list
223 1.70 macallan */
224 1.7 ad if (cookie <= 0) {
225 1.89 rin aprint_error("%s: font table is empty\n", __func__);
226 1.88 rin return -1;
227 1.1 ad }
228 1.30 pk
229 1.55 ober #if NRASOPS_ROTATION > 0
230 1.55 ober /*
231 1.55 ober * Pick the rotated version of this font. This will create it
232 1.55 ober * if necessary.
233 1.55 ober */
234 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
235 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW)
236 1.62 nonaka rasops_rotate_font(&cookie, WSFONT_ROTATE_CW);
237 1.62 nonaka else if (ri->ri_flg & RI_ROTATE_CCW)
238 1.62 nonaka rasops_rotate_font(&cookie, WSFONT_ROTATE_CCW);
239 1.62 nonaka }
240 1.55 ober #endif
241 1.55 ober
242 1.39 ad if (wsfont_lock(cookie, &ri->ri_font)) {
243 1.89 rin aprint_error("%s: couldn't lock font\n", __func__);
244 1.88 rin return -1;
245 1.1 ad }
246 1.8 ad
247 1.5 ad ri->ri_wsfcookie = cookie;
248 1.1 ad }
249 1.4 ad #endif
250 1.30 pk
251 1.1 ad /* This should never happen in reality... */
252 1.89 rin if ((uintptr_t)ri->ri_bits & 3) {
253 1.89 rin aprint_error("%s: bits not aligned on 32-bit boundary\n",
254 1.89 rin __func__);
255 1.88 rin return -1;
256 1.1 ad }
257 1.1 ad
258 1.89 rin if (ri->ri_stride & 3) {
259 1.89 rin aprint_error("%s: stride not aligned on 32-bit boundary\n",
260 1.89 rin __func__);
261 1.88 rin return -1;
262 1.1 ad }
263 1.4 ad
264 1.13 ad if (rasops_reconfig(ri, wantrows, wantcols))
265 1.88 rin return -1;
266 1.46 perry
267 1.4 ad rasops_init_devcmap(ri);
268 1.88 rin return 0;
269 1.4 ad }
270 1.4 ad
271 1.4 ad /*
272 1.13 ad * Reconfigure (because parameters have changed in some way).
273 1.4 ad */
274 1.4 ad int
275 1.60 dsl rasops_reconfig(struct rasops_info *ri, int wantrows, int wantcols)
276 1.4 ad {
277 1.89 rin int bpp, s;
278 1.89 rin size_t len;
279 1.30 pk
280 1.13 ad s = splhigh();
281 1.30 pk
282 1.70 macallan if (wantrows == 0)
283 1.70 macallan wantrows = RASOPS_DEFAULT_HEIGHT;
284 1.70 macallan if (wantcols == 0)
285 1.70 macallan wantcols = RASOPS_DEFAULT_WIDTH;
286 1.70 macallan
287 1.63 macallan /* throw away old line drawing character bitmaps, if we have any */
288 1.63 macallan if (ri->ri_optfont.data != NULL) {
289 1.63 macallan kmem_free(ri->ri_optfont.data, ri->ri_optfont.stride *
290 1.63 macallan ri->ri_optfont.fontheight * ri->ri_optfont.numchars);
291 1.63 macallan ri->ri_optfont.data = NULL;
292 1.63 macallan }
293 1.63 macallan
294 1.63 macallan /* autogenerate box drawing characters */
295 1.64 macallan ri->ri_optfont.firstchar = WSFONT_FLAG_OPT;
296 1.64 macallan ri->ri_optfont.numchars = 16;
297 1.63 macallan ri->ri_optfont.fontwidth = ri->ri_font->fontwidth;
298 1.63 macallan ri->ri_optfont.fontheight = ri->ri_font->fontheight;
299 1.63 macallan ri->ri_optfont.stride = ri->ri_font->stride;
300 1.64 macallan len = ri->ri_optfont.fontheight * ri->ri_optfont.stride *
301 1.89 rin ri->ri_optfont.numchars;
302 1.89 rin
303 1.89 rin if (ri->ri_font->fontwidth > 32 || ri->ri_font->fontwidth < 4) {
304 1.89 rin aprint_error("%s: fontwidth assumptions botched", __func__);
305 1.89 rin splx(s);
306 1.89 rin return -1;
307 1.89 rin }
308 1.64 macallan
309 1.77 chs if ((ri->ri_flg & RI_NO_AUTO) == 0) {
310 1.77 chs ri->ri_optfont.data = kmem_zalloc(len, KM_SLEEP);
311 1.89 rin if (FONT_IS_ALPHA(&ri->ri_optfont))
312 1.89 rin rasops_make_box_chars_alpha(ri);
313 1.89 rin else {
314 1.67 macallan switch (ri->ri_optfont.stride) {
315 1.67 macallan case 1:
316 1.67 macallan rasops_make_box_chars_8(ri);
317 1.67 macallan break;
318 1.67 macallan case 2:
319 1.67 macallan rasops_make_box_chars_16(ri);
320 1.67 macallan break;
321 1.67 macallan case 4:
322 1.67 macallan rasops_make_box_chars_32(ri);
323 1.67 macallan break;
324 1.89 rin default:
325 1.89 rin aprint_error(
326 1.89 rin "%s: font stride assumptions botched",
327 1.89 rin __func__);
328 1.89 rin splx(s);
329 1.89 rin return -1;
330 1.67 macallan }
331 1.63 macallan }
332 1.64 macallan } else
333 1.64 macallan memset(&ri->ri_optfont, 0, sizeof(ri->ri_optfont));
334 1.63 macallan
335 1.4 ad /* Need this to frob the setup below */
336 1.4 ad bpp = (ri->ri_depth == 15 ? 16 : ri->ri_depth);
337 1.4 ad
338 1.74 nonaka if ((ri->ri_flg & RI_CFGDONE) != 0) {
339 1.4 ad ri->ri_bits = ri->ri_origbits;
340 1.74 nonaka ri->ri_hwbits = ri->ri_hworigbits;
341 1.74 nonaka }
342 1.30 pk
343 1.1 ad /* Don't care if the caller wants a hideously small console */
344 1.1 ad if (wantrows < 10)
345 1.13 ad wantrows = 10;
346 1.30 pk
347 1.1 ad if (wantcols < 20)
348 1.13 ad wantcols = 20;
349 1.30 pk
350 1.1 ad /* Now constrain what they get */
351 1.1 ad ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
352 1.1 ad ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
353 1.30 pk
354 1.1 ad if (ri->ri_emuwidth > ri->ri_width)
355 1.1 ad ri->ri_emuwidth = ri->ri_width;
356 1.30 pk
357 1.1 ad if (ri->ri_emuheight > ri->ri_height)
358 1.1 ad ri->ri_emuheight = ri->ri_height;
359 1.30 pk
360 1.1 ad /* Reduce width until aligned on a 32-bit boundary */
361 1.20 ad while ((ri->ri_emuwidth * bpp & 31) != 0)
362 1.1 ad ri->ri_emuwidth--;
363 1.30 pk
364 1.55 ober #if NRASOPS_ROTATION > 0
365 1.62 nonaka if (ri->ri_flg & (RI_ROTATE_CW|RI_ROTATE_CCW)) {
366 1.55 ober ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
367 1.55 ober ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
368 1.55 ober } else
369 1.55 ober #endif
370 1.55 ober {
371 1.55 ober
372 1.55 ober ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
373 1.55 ober ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
374 1.55 ober }
375 1.4 ad ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
376 1.1 ad ri->ri_delta = ri->ri_stride - ri->ri_emustride;
377 1.1 ad ri->ri_ccol = 0;
378 1.1 ad ri->ri_crow = 0;
379 1.4 ad ri->ri_pelbytes = bpp >> 3;
380 1.30 pk
381 1.4 ad ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
382 1.1 ad ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
383 1.1 ad ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
384 1.1 ad
385 1.89 rin if ((ri->ri_delta & 3) != 0) {
386 1.89 rin aprint_error(
387 1.89 rin "%s: ri_delta not aligned on 32-bit boundary", __func__);
388 1.89 rin splx(s);
389 1.89 rin return -1;
390 1.89 rin }
391 1.75 macallan ri->ri_origbits = ri->ri_bits;
392 1.75 macallan ri->ri_hworigbits = ri->ri_hwbits;
393 1.75 macallan
394 1.1 ad /* Clear the entire display */
395 1.13 ad if ((ri->ri_flg & RI_CLEAR) != 0)
396 1.13 ad memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
397 1.30 pk
398 1.30 pk /* Now centre our window if needs be */
399 1.13 ad if ((ri->ri_flg & RI_CENTER) != 0) {
400 1.46 perry ri->ri_bits += (((ri->ri_width * bpp >> 3) -
401 1.36 nathanw ri->ri_emustride) >> 1) & ~3;
402 1.30 pk ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
403 1.1 ad ri->ri_stride;
404 1.61 macallan if (ri->ri_hwbits != NULL) {
405 1.61 macallan ri->ri_hwbits += (((ri->ri_width * bpp >> 3) -
406 1.61 macallan ri->ri_emustride) >> 1) & ~3;
407 1.88 rin ri->ri_hwbits +=
408 1.88 rin ((ri->ri_height - ri->ri_emuheight) >> 1) *
409 1.61 macallan ri->ri_stride;
410 1.61 macallan }
411 1.89 rin ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) /
412 1.89 rin ri->ri_stride;
413 1.89 rin ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) %
414 1.89 rin ri->ri_stride) * 8 / bpp);
415 1.5 ad } else
416 1.5 ad ri->ri_xorigin = ri->ri_yorigin = 0;
417 1.4 ad
418 1.30 pk /*
419 1.4 ad * Fill in defaults for operations set. XXX this nukes private
420 1.4 ad * routines used by accelerated fb drivers.
421 1.4 ad */
422 1.1 ad ri->ri_ops.mapchar = rasops_mapchar;
423 1.1 ad ri->ri_ops.copyrows = rasops_copyrows;
424 1.1 ad ri->ri_ops.copycols = rasops_copycols;
425 1.4 ad ri->ri_ops.erasecols = rasops_erasecols;
426 1.4 ad ri->ri_ops.eraserows = rasops_eraserows;
427 1.1 ad ri->ri_ops.cursor = rasops_cursor;
428 1.4 ad ri->ri_do_cursor = rasops_do_cursor;
429 1.30 pk
430 1.76 macallan ri->ri_caps &= ~(WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
431 1.76 macallan WSSCREEN_WSCOLORS | WSSCREEN_REVERSE);
432 1.13 ad if (ri->ri_depth < 8 || (ri->ri_flg & RI_FORCEMONO) != 0) {
433 1.41 junyoung ri->ri_ops.allocattr = rasops_allocattr_mono;
434 1.76 macallan ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_REVERSE;
435 1.4 ad } else {
436 1.41 junyoung ri->ri_ops.allocattr = rasops_allocattr_color;
437 1.76 macallan ri->ri_caps |= WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
438 1.24 drochner WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
439 1.4 ad }
440 1.4 ad
441 1.1 ad switch (ri->ri_depth) {
442 1.20 ad #if NRASOPS1 > 0
443 1.1 ad case 1:
444 1.1 ad rasops1_init(ri);
445 1.1 ad break;
446 1.1 ad #endif
447 1.20 ad #if NRASOPS2 > 0
448 1.4 ad case 2:
449 1.4 ad rasops2_init(ri);
450 1.34 takemura break;
451 1.34 takemura #endif
452 1.34 takemura #if NRASOPS4 > 0
453 1.34 takemura case 4:
454 1.34 takemura rasops4_init(ri);
455 1.4 ad break;
456 1.4 ad #endif
457 1.20 ad #if NRASOPS8 > 0
458 1.1 ad case 8:
459 1.1 ad rasops8_init(ri);
460 1.1 ad break;
461 1.1 ad #endif
462 1.20 ad #if NRASOPS15 > 0 || NRASOPS16 > 0
463 1.1 ad case 15:
464 1.1 ad case 16:
465 1.1 ad rasops15_init(ri);
466 1.1 ad break;
467 1.1 ad #endif
468 1.20 ad #if NRASOPS24 > 0
469 1.1 ad case 24:
470 1.1 ad rasops24_init(ri);
471 1.1 ad break;
472 1.1 ad #endif
473 1.20 ad #if NRASOPS32 > 0
474 1.1 ad case 32:
475 1.1 ad rasops32_init(ri);
476 1.1 ad break;
477 1.1 ad #endif
478 1.1 ad default:
479 1.13 ad ri->ri_flg &= ~RI_CFGDONE;
480 1.89 rin aprint_error("%s: depth not supported\n", __func__);
481 1.13 ad splx(s);
482 1.88 rin return -1;
483 1.1 ad }
484 1.30 pk
485 1.55 ober #if NRASOPS_ROTATION > 0
486 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
487 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW) {
488 1.62 nonaka ri->ri_real_ops = ri->ri_ops;
489 1.62 nonaka ri->ri_ops.copycols = rasops_copycols_rotated_cw;
490 1.62 nonaka ri->ri_ops.copyrows = rasops_copyrows_rotated_cw;
491 1.62 nonaka ri->ri_ops.erasecols = rasops_erasecols_rotated_cw;
492 1.62 nonaka ri->ri_ops.eraserows = rasops_eraserows_rotated_cw;
493 1.62 nonaka ri->ri_ops.putchar = rasops_putchar_rotated_cw;
494 1.62 nonaka } else if (ri->ri_flg & RI_ROTATE_CCW) {
495 1.62 nonaka ri->ri_real_ops = ri->ri_ops;
496 1.62 nonaka ri->ri_ops.copycols = rasops_copycols_rotated_ccw;
497 1.62 nonaka ri->ri_ops.copyrows = rasops_copyrows_rotated_ccw;
498 1.62 nonaka ri->ri_ops.erasecols = rasops_erasecols_rotated_ccw;
499 1.62 nonaka ri->ri_ops.eraserows = rasops_eraserows_rotated_ccw;
500 1.62 nonaka ri->ri_ops.putchar = rasops_putchar_rotated_ccw;
501 1.62 nonaka }
502 1.55 ober }
503 1.55 ober #endif
504 1.55 ober
505 1.13 ad ri->ri_flg |= RI_CFGDONE;
506 1.13 ad splx(s);
507 1.88 rin return 0;
508 1.1 ad }
509 1.1 ad
510 1.1 ad /*
511 1.1 ad * Map a character.
512 1.1 ad */
513 1.1 ad static int
514 1.59 dsl rasops_mapchar(void *cookie, int c, u_int *cp)
515 1.1 ad {
516 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
517 1.8 ad
518 1.88 rin KASSERT(ri->ri_font != NULL);
519 1.39 ad
520 1.89 rin if ((c = wsfont_map_unichar(ri->ri_font, c)) < 0 ||
521 1.89 rin c < ri->ri_font->firstchar) {
522 1.63 macallan *cp = ' ';
523 1.88 rin return 0;
524 1.35 marcus }
525 1.30 pk
526 1.89 rin #if 0 /* XXXRO */
527 1.89 rin if (CHAR_IN_FONT(c, ri->ri_font)) {
528 1.1 ad *cp = ' ';
529 1.88 rin return 0;
530 1.1 ad }
531 1.89 rin #endif
532 1.30 pk
533 1.1 ad *cp = c;
534 1.88 rin return 5;
535 1.1 ad }
536 1.1 ad
537 1.1 ad /*
538 1.1 ad * Allocate a color attribute.
539 1.1 ad */
540 1.1 ad static int
541 1.89 rin rasops_allocattr_color(void *cookie, int fg0, int bg0, int flg, long *attr)
542 1.1 ad {
543 1.89 rin uint32_t fg = fg0, bg = bg0;
544 1.1 ad
545 1.89 rin if (__predict_false(fg >= sizeof(rasops_isgray) ||
546 1.89 rin bg >= sizeof(rasops_isgray)))
547 1.88 rin return EINVAL;
548 1.56 mjf
549 1.1 ad #ifdef RASOPS_CLIPPING
550 1.1 ad fg &= 7;
551 1.1 ad bg &= 7;
552 1.1 ad #endif
553 1.17 ad if ((flg & WSATTR_BLINK) != 0)
554 1.88 rin return EINVAL;
555 1.23 drochner
556 1.23 drochner if ((flg & WSATTR_WSCOLORS) == 0) {
557 1.48 macallan #ifdef WS_DEFAULT_FG
558 1.48 macallan fg = WS_DEFAULT_FG;
559 1.48 macallan #else
560 1.48 macallan fg = WSCOL_WHITE;
561 1.48 macallan #endif
562 1.48 macallan #ifdef WS_DEFAULT_BG
563 1.48 macallan bg = WS_DEFAULT_BG;
564 1.48 macallan #else
565 1.48 macallan bg = WSCOL_BLACK;
566 1.48 macallan #endif
567 1.23 drochner }
568 1.23 drochner
569 1.17 ad if ((flg & WSATTR_REVERSE) != 0) {
570 1.89 rin uint32_t swap = fg;
571 1.1 ad fg = bg;
572 1.1 ad bg = swap;
573 1.1 ad }
574 1.1 ad
575 1.17 ad if ((flg & WSATTR_HILIT) != 0)
576 1.1 ad fg += 8;
577 1.30 pk
578 1.79 mlelstv flg = flg & WSATTR_USERMASK;
579 1.30 pk
580 1.1 ad if (rasops_isgray[fg])
581 1.79 mlelstv flg |= WSATTR_PRIVATE1;
582 1.1 ad
583 1.1 ad if (rasops_isgray[bg])
584 1.79 mlelstv flg |= WSATTR_PRIVATE2;
585 1.1 ad
586 1.1 ad *attr = (bg << 16) | (fg << 24) | flg;
587 1.88 rin return 0;
588 1.1 ad }
589 1.1 ad
590 1.1 ad /*
591 1.1 ad * Allocate a mono attribute.
592 1.1 ad */
593 1.1 ad static int
594 1.89 rin rasops_allocattr_mono(void *cookie, int fg0, int bg0, int flg, long *attr)
595 1.1 ad {
596 1.89 rin uint32_t fg = fg0, bg = bg0;
597 1.1 ad
598 1.23 drochner if ((flg & (WSATTR_BLINK | WSATTR_HILIT | WSATTR_WSCOLORS)) != 0)
599 1.88 rin return EINVAL;
600 1.23 drochner
601 1.23 drochner fg = 1;
602 1.23 drochner bg = 0;
603 1.23 drochner
604 1.17 ad if ((flg & WSATTR_REVERSE) != 0) {
605 1.89 rin uint32_t swap = fg;
606 1.1 ad fg = bg;
607 1.1 ad bg = swap;
608 1.1 ad }
609 1.1 ad
610 1.1 ad *attr = (bg << 16) | (fg << 24) | ((flg & WSATTR_UNDERLINE) ? 7 : 6);
611 1.88 rin return 0;
612 1.1 ad }
613 1.1 ad
614 1.1 ad /*
615 1.1 ad * Copy rows.
616 1.1 ad */
617 1.1 ad static void
618 1.60 dsl rasops_copyrows(void *cookie, int src, int dst, int num)
619 1.1 ad {
620 1.82 rin uint32_t *sp, *dp, *hp, *srp, *drp, *hrp;
621 1.1 ad struct rasops_info *ri;
622 1.18 ad int n8, n1, cnt, delta;
623 1.30 pk
624 1.1 ad ri = (struct rasops_info *)cookie;
625 1.51 jmcneill hp = hrp = NULL;
626 1.1 ad
627 1.1 ad #ifdef RASOPS_CLIPPING
628 1.1 ad if (dst == src)
629 1.1 ad return;
630 1.30 pk
631 1.1 ad if (src < 0) {
632 1.1 ad num += src;
633 1.1 ad src = 0;
634 1.1 ad }
635 1.1 ad
636 1.89 rin if (src + num > ri->ri_rows)
637 1.1 ad num = ri->ri_rows - src;
638 1.1 ad
639 1.1 ad if (dst < 0) {
640 1.1 ad num += dst;
641 1.1 ad dst = 0;
642 1.1 ad }
643 1.1 ad
644 1.89 rin if (dst + num > ri->ri_rows)
645 1.1 ad num = ri->ri_rows - dst;
646 1.30 pk
647 1.1 ad if (num <= 0)
648 1.1 ad return;
649 1.1 ad #endif
650 1.1 ad
651 1.1 ad num *= ri->ri_font->fontheight;
652 1.1 ad n8 = ri->ri_emustride >> 5;
653 1.1 ad n1 = (ri->ri_emustride >> 2) & 7;
654 1.30 pk
655 1.1 ad if (dst < src) {
656 1.82 rin srp = (uint32_t *)(ri->ri_bits + src * ri->ri_yscale);
657 1.82 rin drp = (uint32_t *)(ri->ri_bits + dst * ri->ri_yscale);
658 1.51 jmcneill if (ri->ri_hwbits)
659 1.82 rin hrp = (uint32_t *)(ri->ri_hwbits + dst *
660 1.51 jmcneill ri->ri_yscale);
661 1.18 ad delta = ri->ri_stride;
662 1.1 ad } else {
663 1.1 ad src = ri->ri_font->fontheight * src + num - 1;
664 1.1 ad dst = ri->ri_font->fontheight * dst + num - 1;
665 1.82 rin srp = (uint32_t *)(ri->ri_bits + src * ri->ri_stride);
666 1.82 rin drp = (uint32_t *)(ri->ri_bits + dst * ri->ri_stride);
667 1.51 jmcneill if (ri->ri_hwbits)
668 1.82 rin hrp = (uint32_t *)(ri->ri_hwbits + dst *
669 1.51 jmcneill ri->ri_stride);
670 1.51 jmcneill
671 1.18 ad delta = -ri->ri_stride;
672 1.18 ad }
673 1.30 pk
674 1.18 ad while (num--) {
675 1.18 ad dp = drp;
676 1.18 ad sp = srp;
677 1.51 jmcneill if (ri->ri_hwbits)
678 1.51 jmcneill hp = hrp;
679 1.51 jmcneill
680 1.82 rin DELTA(drp, delta, uint32_t *);
681 1.82 rin DELTA(srp, delta, uint32_t *);
682 1.51 jmcneill if (ri->ri_hwbits)
683 1.82 rin DELTA(hrp, delta, uint32_t *);
684 1.18 ad
685 1.18 ad for (cnt = n8; cnt; cnt--) {
686 1.52 jmcneill dp[0] = sp[0];
687 1.52 jmcneill dp[1] = sp[1];
688 1.52 jmcneill dp[2] = sp[2];
689 1.52 jmcneill dp[3] = sp[3];
690 1.52 jmcneill dp[4] = sp[4];
691 1.52 jmcneill dp[5] = sp[5];
692 1.52 jmcneill dp[6] = sp[6];
693 1.52 jmcneill dp[7] = sp[7];
694 1.18 ad dp += 8;
695 1.18 ad sp += 8;
696 1.52 jmcneill }
697 1.52 jmcneill if (ri->ri_hwbits) {
698 1.52 jmcneill sp -= (8 * n8);
699 1.52 jmcneill for (cnt = n8; cnt; cnt--) {
700 1.52 jmcneill hp[0] = sp[0];
701 1.52 jmcneill hp[1] = sp[1];
702 1.52 jmcneill hp[2] = sp[2];
703 1.52 jmcneill hp[3] = sp[3];
704 1.52 jmcneill hp[4] = sp[4];
705 1.52 jmcneill hp[5] = sp[5];
706 1.52 jmcneill hp[6] = sp[6];
707 1.52 jmcneill hp[7] = sp[7];
708 1.51 jmcneill hp += 8;
709 1.52 jmcneill sp += 8;
710 1.52 jmcneill }
711 1.18 ad }
712 1.30 pk
713 1.51 jmcneill for (cnt = n1; cnt; cnt--) {
714 1.18 ad *dp++ = *sp++;
715 1.51 jmcneill if (ri->ri_hwbits)
716 1.51 jmcneill *hp++ = *(sp - 1);
717 1.51 jmcneill }
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.4 ad case 8:
848 1.68 macallan if ((ri->ri_flg & RI_8BIT_IS_RGB) == 0) {
849 1.89 rin for (i = 0; i < 16; i++) {
850 1.89 rin c = i;
851 1.68 macallan ri->ri_devcmap[i] =
852 1.89 rin c | (c << 8) | (c << 16) | (c << 24);
853 1.89 rin }
854 1.68 macallan return;
855 1.68 macallan }
856 1.4 ad }
857 1.30 pk
858 1.1 ad p = rasops_cmap;
859 1.30 pk
860 1.29 nathanw for (i = 0; i < 16; i++) {
861 1.1 ad if (ri->ri_rnum <= 8)
862 1.89 rin c = (uint32_t)(*p >> (8 - ri->ri_rnum)) << ri->ri_rpos;
863 1.30 pk else
864 1.89 rin c = (uint32_t)(*p << (ri->ri_rnum - 8)) << ri->ri_rpos;
865 1.29 nathanw p++;
866 1.1 ad
867 1.1 ad if (ri->ri_gnum <= 8)
868 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_gnum)) << ri->ri_gpos;
869 1.30 pk else
870 1.89 rin c |= (uint32_t)(*p << (ri->ri_gnum - 8)) << ri->ri_gpos;
871 1.29 nathanw p++;
872 1.1 ad
873 1.1 ad if (ri->ri_bnum <= 8)
874 1.89 rin c |= (uint32_t)(*p >> (8 - ri->ri_bnum)) << ri->ri_bpos;
875 1.30 pk else
876 1.89 rin c |= (uint32_t)(*p << (ri->ri_bnum - 8)) << ri->ri_bpos;
877 1.29 nathanw p++;
878 1.4 ad
879 1.4 ad /* Fill the word for generic routines, which want this */
880 1.89 rin if (ri->ri_depth == 8) {
881 1.89 rin c |= c << 8;
882 1.89 rin c |= c << 16;
883 1.89 rin } else if (ri->ri_depth == 15 || ri->ri_depth == 16)
884 1.69 macallan c |= c << 16;
885 1.89 rin else if (ri->ri_depth == 24)
886 1.89 rin c |= (c & 0xff) << 24;
887 1.1 ad
888 1.4 ad /* 24bpp does bswap on the fly. {32,16,15}bpp do it here. */
889 1.13 ad if ((ri->ri_flg & RI_BSWAP) == 0)
890 1.3 ad ri->ri_devcmap[i] = c;
891 1.89 rin else if (ri->ri_depth == 15 || ri->ri_depth == 16)
892 1.89 rin ri->ri_devcmap[i] = bswap16(c);
893 1.4 ad else if (ri->ri_depth == 32)
894 1.3 ad ri->ri_devcmap[i] = bswap32(c);
895 1.89 rin else /* 8, 24 */
896 1.4 ad ri->ri_devcmap[i] = c;
897 1.1 ad }
898 1.1 ad }
899 1.1 ad
900 1.1 ad /*
901 1.1 ad * Unpack a rasops attribute
902 1.1 ad */
903 1.1 ad void
904 1.60 dsl rasops_unpack_attr(long attr, int *fg, int *bg, int *underline)
905 1.1 ad {
906 1.30 pk
907 1.89 rin *fg = ((uint32_t)attr >> 24) & 0xf;
908 1.89 rin *bg = ((uint32_t)attr >> 16) & 0xf;
909 1.25 ad if (underline != NULL)
910 1.89 rin *underline = (uint32_t)attr & WSATTR_UNDERLINE;
911 1.4 ad }
912 1.4 ad
913 1.4 ad /*
914 1.4 ad * Erase rows. This isn't static, since 24-bpp uses it in special cases.
915 1.4 ad */
916 1.4 ad void
917 1.60 dsl rasops_eraserows(void *cookie, int row, int num, long attr)
918 1.4 ad {
919 1.4 ad struct rasops_info *ri;
920 1.14 ad int np, nw, cnt, delta;
921 1.82 rin uint32_t *dp, *hp, clr;
922 1.51 jmcneill int i;
923 1.30 pk
924 1.4 ad ri = (struct rasops_info *)cookie;
925 1.51 jmcneill hp = NULL;
926 1.4 ad
927 1.4 ad #ifdef RASOPS_CLIPPING
928 1.4 ad if (row < 0) {
929 1.4 ad num += row;
930 1.4 ad row = 0;
931 1.4 ad }
932 1.4 ad
933 1.89 rin if (row + num > ri->ri_rows)
934 1.4 ad num = ri->ri_rows - row;
935 1.30 pk
936 1.4 ad if (num <= 0)
937 1.4 ad return;
938 1.4 ad #endif
939 1.4 ad
940 1.30 pk clr = ri->ri_devcmap[(attr >> 16) & 0xf];
941 1.4 ad
942 1.30 pk /*
943 1.20 ad * XXX The wsdisplay_emulops interface seems a little deficient in
944 1.30 pk * that there is no way to clear the *entire* screen. We provide a
945 1.30 pk * workaround here: if the entire console area is being cleared, and
946 1.13 ad * the RI_FULLCLEAR flag is set, clear the entire display.
947 1.30 pk */
948 1.13 ad if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR) != 0) {
949 1.13 ad np = ri->ri_stride >> 5;
950 1.13 ad nw = (ri->ri_stride >> 2) & 7;
951 1.13 ad num = ri->ri_height;
952 1.82 rin dp = (uint32_t *)ri->ri_origbits;
953 1.51 jmcneill if (ri->ri_hwbits)
954 1.82 rin hp = (uint32_t *)ri->ri_hworigbits;
955 1.14 ad delta = 0;
956 1.13 ad } else {
957 1.13 ad np = ri->ri_emustride >> 5;
958 1.13 ad nw = (ri->ri_emustride >> 2) & 7;
959 1.13 ad num *= ri->ri_font->fontheight;
960 1.82 rin dp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale);
961 1.51 jmcneill if (ri->ri_hwbits)
962 1.82 rin hp = (uint32_t *)(ri->ri_hwbits + row *
963 1.51 jmcneill ri->ri_yscale);
964 1.14 ad delta = ri->ri_delta;
965 1.13 ad }
966 1.30 pk
967 1.4 ad while (num--) {
968 1.4 ad for (cnt = np; cnt; cnt--) {
969 1.51 jmcneill for (i = 0; i < 8; i++) {
970 1.51 jmcneill dp[i] = clr;
971 1.51 jmcneill if (ri->ri_hwbits)
972 1.51 jmcneill hp[i] = clr;
973 1.51 jmcneill }
974 1.4 ad dp += 8;
975 1.51 jmcneill if (ri->ri_hwbits)
976 1.51 jmcneill hp += 8;
977 1.4 ad }
978 1.30 pk
979 1.4 ad for (cnt = nw; cnt; cnt--) {
980 1.82 rin *(uint32_t *)dp = clr;
981 1.82 rin DELTA(dp, 4, uint32_t *);
982 1.51 jmcneill if (ri->ri_hwbits) {
983 1.82 rin *(uint32_t *)hp = clr;
984 1.82 rin DELTA(hp, 4, uint32_t *);
985 1.51 jmcneill }
986 1.30 pk }
987 1.30 pk
988 1.82 rin DELTA(dp, delta, uint32_t *);
989 1.51 jmcneill if (ri->ri_hwbits)
990 1.82 rin DELTA(hp, delta, uint32_t *);
991 1.4 ad }
992 1.4 ad }
993 1.4 ad
994 1.4 ad /*
995 1.4 ad * Actually turn the cursor on or off. This does the dirty work for
996 1.4 ad * rasops_cursor().
997 1.4 ad */
998 1.4 ad static void
999 1.59 dsl rasops_do_cursor(struct rasops_info *ri)
1000 1.4 ad {
1001 1.84 rin int full, height, cnt, slop1, slop2, row, col;
1002 1.85 rin uint32_t tmp32, msk1, msk2;
1003 1.84 rin uint8_t tmp8;
1004 1.81 rin uint8_t *dp, *rp, *hrp, *hp;
1005 1.51 jmcneill
1006 1.89 rin hrp = hp = NULL; /* XXX GCC */
1007 1.30 pk
1008 1.55 ober #if NRASOPS_ROTATION > 0
1009 1.62 nonaka if (ri->ri_flg & RI_ROTATE_MASK) {
1010 1.62 nonaka if (ri->ri_flg & RI_ROTATE_CW) {
1011 1.62 nonaka /* Rotate rows/columns */
1012 1.62 nonaka row = ri->ri_ccol;
1013 1.62 nonaka col = ri->ri_rows - ri->ri_crow - 1;
1014 1.62 nonaka } else if (ri->ri_flg & RI_ROTATE_CCW) {
1015 1.62 nonaka /* Rotate rows/columns */
1016 1.62 nonaka row = ri->ri_cols - ri->ri_ccol - 1;
1017 1.62 nonaka col = ri->ri_crow;
1018 1.62 nonaka } else { /* upside-down */
1019 1.62 nonaka row = ri->ri_crow;
1020 1.62 nonaka col = ri->ri_ccol;
1021 1.62 nonaka }
1022 1.55 ober } else
1023 1.55 ober #endif
1024 1.55 ober {
1025 1.55 ober row = ri->ri_crow;
1026 1.55 ober col = ri->ri_ccol;
1027 1.55 ober }
1028 1.30 pk
1029 1.4 ad rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
1030 1.51 jmcneill if (ri->ri_hwbits)
1031 1.51 jmcneill hrp = ri->ri_hwbits + row * ri->ri_yscale + col
1032 1.51 jmcneill * ri->ri_xscale;
1033 1.4 ad height = ri->ri_font->fontheight;
1034 1.30 pk
1035 1.80 rin /*
1036 1.80 rin * For ri_xscale = 1:
1037 1.80 rin *
1038 1.80 rin * Logic below does not work for ri_xscale = 1, e.g.,
1039 1.80 rin * fontwidth = 8 and bpp = 1. So we take care of it.
1040 1.80 rin */
1041 1.80 rin if (ri->ri_xscale == 1) {
1042 1.80 rin while (height--) {
1043 1.84 rin tmp8 = ~*rp;
1044 1.80 rin
1045 1.80 rin *rp = tmp8;
1046 1.80 rin rp += ri->ri_stride;
1047 1.30 pk
1048 1.80 rin if (ri->ri_hwbits) {
1049 1.80 rin *hrp = tmp8;
1050 1.80 rin hrp += ri->ri_stride;
1051 1.80 rin }
1052 1.80 rin }
1053 1.80 rin return;
1054 1.80 rin }
1055 1.80 rin
1056 1.80 rin /*
1057 1.80 rin * For ri_xscale = 2, 3, 4, ...:
1058 1.80 rin *
1059 1.80 rin * Note that siop1 <= ri_xscale even for ri_xscale = 2,
1060 1.84 rin * since rp % 3 = 0 or 2 (ri_stride % 4 = 0).
1061 1.80 rin */
1062 1.80 rin slop1 = (4 - ((uintptr_t)rp & 3)) & 3;
1063 1.4 ad slop2 = (ri->ri_xscale - slop1) & 3;
1064 1.89 rin full = (ri->ri_xscale - slop1 /* - slop2 */) >> 2;
1065 1.30 pk
1066 1.84 rin rp = (uint8_t *)((uintptr_t)rp & ~3);
1067 1.84 rin hrp = (uint8_t *)((uintptr_t)hrp & ~3);
1068 1.30 pk
1069 1.87 rin msk1 = !slop1 ? 0 : be32toh(0xffffffffU >> (32 - (8 * slop1)));
1070 1.87 rin msk2 = !slop2 ? 0 : be32toh(0xffffffffU << (32 - (8 * slop2)));
1071 1.85 rin
1072 1.84 rin while (height--) {
1073 1.84 rin dp = rp;
1074 1.84 rin rp += ri->ri_stride;
1075 1.84 rin if (ri->ri_hwbits) {
1076 1.84 rin hp = hrp;
1077 1.84 rin hrp += ri->ri_stride;
1078 1.4 ad }
1079 1.78 macallan
1080 1.84 rin if (slop1) {
1081 1.85 rin tmp32 = *(uint32_t *)dp ^ msk1;
1082 1.84 rin *(uint32_t *)dp = tmp32;
1083 1.84 rin dp += 4;
1084 1.51 jmcneill if (ri->ri_hwbits) {
1085 1.84 rin *(uint32_t *)hp = tmp32;
1086 1.84 rin hp += 4;
1087 1.51 jmcneill }
1088 1.84 rin }
1089 1.30 pk
1090 1.84 rin for (cnt = full; cnt; cnt--) {
1091 1.84 rin tmp32 = ~*(uint32_t *)dp;
1092 1.84 rin *(uint32_t *)dp = tmp32;
1093 1.84 rin dp += 4;
1094 1.84 rin if (ri->ri_hwbits) {
1095 1.84 rin *(uint32_t *)hp = tmp32;
1096 1.84 rin hp += 4;
1097 1.4 ad }
1098 1.84 rin }
1099 1.30 pk
1100 1.84 rin if (slop2) {
1101 1.85 rin tmp32 = *(uint32_t *)dp ^ msk2;
1102 1.84 rin *(uint32_t *)dp = tmp32;
1103 1.84 rin if (ri->ri_hwbits)
1104 1.84 rin *(uint32_t *)hp = tmp32;
1105 1.4 ad }
1106 1.4 ad }
1107 1.4 ad }
1108 1.4 ad
1109 1.4 ad /*
1110 1.4 ad * Erase columns.
1111 1.4 ad */
1112 1.4 ad void
1113 1.60 dsl rasops_erasecols(void *cookie, int row, int col, int num, long attr)
1114 1.4 ad {
1115 1.4 ad int n8, height, cnt, slop1, slop2, clr;
1116 1.4 ad struct rasops_info *ri;
1117 1.82 rin uint32_t *rp, *dp, *hrp, *hp;
1118 1.51 jmcneill int i;
1119 1.30 pk
1120 1.4 ad ri = (struct rasops_info *)cookie;
1121 1.51 jmcneill hrp = hp = NULL;
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.4 ad 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.4 ad num = 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.82 rin hrp = (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.30 pk clr = ri->ri_devcmap[(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.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1156 1.51 jmcneill if (ri->ri_hwbits) {
1157 1.51 jmcneill hp = hrp;
1158 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1159 1.51 jmcneill }
1160 1.30 pk
1161 1.51 jmcneill for (cnt = num; cnt; cnt--) {
1162 1.6 ad *dp++ = clr;
1163 1.51 jmcneill if (ri->ri_hwbits)
1164 1.51 jmcneill *hp++ = clr;
1165 1.51 jmcneill }
1166 1.6 ad }
1167 1.6 ad } else if (((num | ri->ri_xscale) & 1) == 0) {
1168 1.30 pk /*
1169 1.4 ad * Halfword aligned blt. This is needed so the
1170 1.30 pk * 15/16 bit ops can use this function.
1171 1.4 ad */
1172 1.4 ad num >>= 1;
1173 1.4 ad
1174 1.4 ad while (height--) {
1175 1.4 ad dp = rp;
1176 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1177 1.51 jmcneill if (ri->ri_hwbits) {
1178 1.51 jmcneill hp = hrp;
1179 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1180 1.51 jmcneill }
1181 1.4 ad
1182 1.4 ad for (cnt = num; cnt; cnt--) {
1183 1.82 rin *(uint16_t *)dp = clr;
1184 1.82 rin DELTA(dp, 2, uint32_t *);
1185 1.51 jmcneill if (ri->ri_hwbits) {
1186 1.82 rin *(uint16_t *)hp = clr;
1187 1.82 rin DELTA(hp, 2, uint32_t *);
1188 1.51 jmcneill }
1189 1.4 ad }
1190 1.4 ad }
1191 1.4 ad } else {
1192 1.4 ad while (height--) {
1193 1.4 ad dp = rp;
1194 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1195 1.51 jmcneill if (ri->ri_hwbits) {
1196 1.51 jmcneill hp = hrp;
1197 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1198 1.51 jmcneill }
1199 1.4 ad
1200 1.4 ad for (cnt = num; cnt; cnt--) {
1201 1.81 rin *(uint8_t *)dp = clr;
1202 1.82 rin DELTA(dp, 1, uint32_t *);
1203 1.51 jmcneill if (ri->ri_hwbits) {
1204 1.81 rin *(uint8_t *)hp = clr;
1205 1.82 rin DELTA(hp, 1, uint32_t *);
1206 1.51 jmcneill }
1207 1.4 ad }
1208 1.4 ad }
1209 1.4 ad }
1210 1.30 pk
1211 1.4 ad return;
1212 1.4 ad }
1213 1.30 pk
1214 1.27 nisimura slop1 = (4 - ((long)rp & 3)) & 3;
1215 1.4 ad slop2 = (num - slop1) & 3;
1216 1.4 ad num -= slop1 + slop2;
1217 1.4 ad n8 = num >> 5;
1218 1.4 ad num = (num >> 2) & 7;
1219 1.4 ad
1220 1.4 ad while (height--) {
1221 1.4 ad dp = rp;
1222 1.82 rin DELTA(rp, ri->ri_stride, uint32_t *);
1223 1.51 jmcneill if (ri->ri_hwbits) {
1224 1.51 jmcneill hp = hrp;
1225 1.82 rin DELTA(hrp, ri->ri_stride, uint32_t *);
1226 1.51 jmcneill }
1227 1.30 pk
1228 1.4 ad /* Align span to 4 bytes */
1229 1.4 ad if (slop1 & 1) {
1230 1.81 rin *(uint8_t *)dp = clr;
1231 1.82 rin DELTA(dp, 1, uint32_t *);
1232 1.51 jmcneill if (ri->ri_hwbits) {
1233 1.81 rin *(uint8_t *)hp = clr;
1234 1.82 rin DELTA(hp, 1, uint32_t *);
1235 1.51 jmcneill }
1236 1.4 ad }
1237 1.4 ad
1238 1.4 ad if (slop1 & 2) {
1239 1.82 rin *(uint16_t *)dp = clr;
1240 1.82 rin DELTA(dp, 2, uint32_t *);
1241 1.51 jmcneill if (ri->ri_hwbits) {
1242 1.82 rin *(uint16_t *)hp = clr;
1243 1.82 rin DELTA(hp, 2, uint32_t *);
1244 1.51 jmcneill }
1245 1.4 ad }
1246 1.30 pk
1247 1.4 ad /* Write 32 bytes per loop */
1248 1.4 ad for (cnt = n8; cnt; cnt--) {
1249 1.51 jmcneill for (i = 0; i < 8; i++) {
1250 1.51 jmcneill dp[i] = clr;
1251 1.51 jmcneill if (ri->ri_hwbits)
1252 1.51 jmcneill hp[i] = clr;
1253 1.51 jmcneill }
1254 1.4 ad dp += 8;
1255 1.51 jmcneill if (ri->ri_hwbits)
1256 1.51 jmcneill hp += 8;
1257 1.4 ad }
1258 1.30 pk
1259 1.30 pk /* Write 4 bytes per loop */
1260 1.51 jmcneill for (cnt = num; cnt; cnt--) {
1261 1.4 ad *dp++ = clr;
1262 1.51 jmcneill if (ri->ri_hwbits)
1263 1.51 jmcneill *hp++ = clr;
1264 1.51 jmcneill }
1265 1.30 pk
1266 1.30 pk /* Write unaligned trailing slop */
1267 1.4 ad if (slop2 & 1) {
1268 1.81 rin *(uint8_t *)dp = clr;
1269 1.82 rin DELTA(dp, 1, uint32_t *);
1270 1.51 jmcneill if (ri->ri_hwbits) {
1271 1.81 rin *(uint8_t *)hp = clr;
1272 1.82 rin DELTA(hp, 1, uint32_t *);
1273 1.51 jmcneill }
1274 1.4 ad }
1275 1.4 ad
1276 1.51 jmcneill if (slop2 & 2) {
1277 1.82 rin *(uint16_t *)dp = clr;
1278 1.51 jmcneill if (ri->ri_hwbits)
1279 1.82 rin *(uint16_t *)hp = clr;
1280 1.51 jmcneill }
1281 1.4 ad }
1282 1.1 ad }
1283 1.55 ober
1284 1.55 ober #if NRASOPS_ROTATION > 0
1285 1.55 ober /*
1286 1.55 ober * Quarter clockwise rotation routines (originally intended for the
1287 1.55 ober * built-in Zaurus C3x00 display in 16bpp).
1288 1.55 ober */
1289 1.55 ober
1290 1.55 ober static void
1291 1.62 nonaka rasops_rotate_font(int *cookie, int rotate)
1292 1.55 ober {
1293 1.55 ober struct rotatedfont *f;
1294 1.55 ober int ncookie;
1295 1.55 ober
1296 1.55 ober SLIST_FOREACH(f, &rotatedfonts, rf_next) {
1297 1.55 ober if (f->rf_cookie == *cookie) {
1298 1.55 ober *cookie = f->rf_rotated;
1299 1.55 ober return;
1300 1.55 ober }
1301 1.55 ober }
1302 1.55 ober
1303 1.55 ober /*
1304 1.55 ober * We did not find a rotated version of this font. Ask the wsfont
1305 1.55 ober * code to compute one for us.
1306 1.55 ober */
1307 1.55 ober
1308 1.89 rin f = kmem_alloc(sizeof(*f), KM_SLEEP);
1309 1.55 ober
1310 1.62 nonaka if ((ncookie = wsfont_rotate(*cookie, rotate)) == -1)
1311 1.89 rin goto fail;
1312 1.55 ober
1313 1.55 ober f->rf_cookie = *cookie;
1314 1.55 ober f->rf_rotated = ncookie;
1315 1.55 ober SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
1316 1.55 ober
1317 1.55 ober *cookie = ncookie;
1318 1.72 riastrad return;
1319 1.72 riastrad
1320 1.89 rin fail: free(f, sizeof(*f));
1321 1.72 riastrad return;
1322 1.55 ober }
1323 1.55 ober
1324 1.55 ober static void
1325 1.60 dsl rasops_copychar(void *cookie, int srcrow, int dstrow, int srccol, int dstcol)
1326 1.55 ober {
1327 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1328 1.55 ober int height;
1329 1.55 ober int r_srcrow, r_dstrow, r_srccol, r_dstcol;
1330 1.89 rin uint8_t *sp, *dp;
1331 1.55 ober
1332 1.55 ober r_srcrow = srccol;
1333 1.55 ober r_dstrow = dstcol;
1334 1.55 ober r_srccol = ri->ri_rows - srcrow - 1;
1335 1.55 ober r_dstcol = ri->ri_rows - dstrow - 1;
1336 1.55 ober
1337 1.55 ober r_srcrow *= ri->ri_yscale;
1338 1.55 ober r_dstrow *= ri->ri_yscale;
1339 1.55 ober height = ri->ri_font->fontheight;
1340 1.55 ober
1341 1.55 ober sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1342 1.55 ober dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1343 1.55 ober
1344 1.55 ober while (height--) {
1345 1.55 ober memmove(dp, sp, ri->ri_xscale);
1346 1.55 ober dp += ri->ri_stride;
1347 1.55 ober sp += ri->ri_stride;
1348 1.55 ober }
1349 1.55 ober }
1350 1.55 ober
1351 1.55 ober static void
1352 1.62 nonaka rasops_putchar_rotated_cw(void *cookie, int row, int col, u_int uc, long attr)
1353 1.55 ober {
1354 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1355 1.89 rin int height;
1356 1.81 rin uint8_t *rp;
1357 1.55 ober
1358 1.56 mjf if (__predict_false((unsigned int)row > ri->ri_rows ||
1359 1.56 mjf (unsigned int)col > ri->ri_cols))
1360 1.56 mjf return;
1361 1.56 mjf
1362 1.56 mjf /* Avoid underflow */
1363 1.89 rin if (ri->ri_rows - row - 1 < 0)
1364 1.56 mjf return;
1365 1.56 mjf
1366 1.55 ober /* Do rotated char sans (side)underline */
1367 1.55 ober ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
1368 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1369 1.55 ober
1370 1.55 ober /* Do rotated underline */
1371 1.55 ober rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) *
1372 1.55 ober ri->ri_xscale;
1373 1.55 ober height = ri->ri_font->fontheight;
1374 1.55 ober
1375 1.55 ober /* XXX this assumes 16-bit color depth */
1376 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1377 1.82 rin uint16_t c =
1378 1.82 rin (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1379 1.55 ober
1380 1.55 ober while (height--) {
1381 1.82 rin *(uint16_t *)rp = c;
1382 1.55 ober rp += ri->ri_stride;
1383 1.55 ober }
1384 1.55 ober }
1385 1.55 ober }
1386 1.55 ober
1387 1.55 ober static void
1388 1.62 nonaka rasops_erasecols_rotated_cw(void *cookie, int row, int col, int num, long attr)
1389 1.55 ober {
1390 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1391 1.55 ober int i;
1392 1.55 ober
1393 1.55 ober for (i = col; i < col + num; i++)
1394 1.55 ober ri->ri_ops.putchar(cookie, row, i, ' ', attr);
1395 1.55 ober }
1396 1.55 ober
1397 1.55 ober /* XXX: these could likely be optimised somewhat. */
1398 1.55 ober static void
1399 1.62 nonaka rasops_copyrows_rotated_cw(void *cookie, int src, int dst, int num)
1400 1.55 ober {
1401 1.55 ober struct rasops_info *ri = (struct rasops_info *)cookie;
1402 1.55 ober int col, roff;
1403 1.55 ober
1404 1.55 ober if (src > dst)
1405 1.55 ober for (roff = 0; roff < num; roff++)
1406 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1407 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1408 1.55 ober col, col);
1409 1.55 ober else
1410 1.55 ober for (roff = num - 1; roff >= 0; roff--)
1411 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1412 1.55 ober rasops_copychar(cookie, src + roff, dst + roff,
1413 1.55 ober col, col);
1414 1.55 ober }
1415 1.55 ober
1416 1.55 ober static void
1417 1.62 nonaka rasops_copycols_rotated_cw(void *cookie, int row, int src, int dst, int num)
1418 1.55 ober {
1419 1.55 ober int coff;
1420 1.55 ober
1421 1.55 ober if (src > dst)
1422 1.55 ober for (coff = 0; coff < num; coff++)
1423 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1424 1.88 rin dst + coff);
1425 1.55 ober else
1426 1.55 ober for (coff = num - 1; coff >= 0; coff--)
1427 1.88 rin rasops_copychar(cookie, row, row, src + coff,
1428 1.88 rin dst + coff);
1429 1.55 ober }
1430 1.55 ober
1431 1.55 ober static void
1432 1.62 nonaka rasops_eraserows_rotated_cw(void *cookie, int row, int num, long attr)
1433 1.55 ober {
1434 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1435 1.55 ober int col, rn;
1436 1.55 ober
1437 1.55 ober for (rn = row; rn < row + num; rn++)
1438 1.55 ober for (col = 0; col < ri->ri_cols; col++)
1439 1.55 ober ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
1440 1.55 ober }
1441 1.62 nonaka
1442 1.62 nonaka /*
1443 1.62 nonaka * Quarter counter-clockwise rotation routines (originally intended for the
1444 1.62 nonaka * built-in Sharp W-ZERO3 display in 16bpp).
1445 1.62 nonaka */
1446 1.62 nonaka static void
1447 1.88 rin rasops_copychar_ccw(void *cookie, int srcrow, int dstrow, int srccol,
1448 1.88 rin int dstcol)
1449 1.62 nonaka {
1450 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1451 1.89 rin int height, r_srcrow, r_dstrow, r_srccol, r_dstcol;
1452 1.81 rin uint8_t *sp, *dp;
1453 1.62 nonaka
1454 1.62 nonaka r_srcrow = ri->ri_cols - srccol - 1;
1455 1.62 nonaka r_dstrow = ri->ri_cols - dstcol - 1;
1456 1.62 nonaka r_srccol = srcrow;
1457 1.62 nonaka r_dstcol = dstrow;
1458 1.62 nonaka
1459 1.62 nonaka r_srcrow *= ri->ri_yscale;
1460 1.62 nonaka r_dstrow *= ri->ri_yscale;
1461 1.62 nonaka height = ri->ri_font->fontheight;
1462 1.62 nonaka
1463 1.62 nonaka sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
1464 1.62 nonaka dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
1465 1.62 nonaka
1466 1.62 nonaka while (height--) {
1467 1.62 nonaka memmove(dp, sp, ri->ri_xscale);
1468 1.62 nonaka dp += ri->ri_stride;
1469 1.62 nonaka sp += ri->ri_stride;
1470 1.62 nonaka }
1471 1.62 nonaka }
1472 1.62 nonaka
1473 1.62 nonaka static void
1474 1.62 nonaka rasops_putchar_rotated_ccw(void *cookie, int row, int col, u_int uc, long attr)
1475 1.62 nonaka {
1476 1.89 rin struct rasops_info *ri = (struct rasops_info *)cookie;
1477 1.89 rin int height;
1478 1.81 rin uint8_t *rp;
1479 1.62 nonaka
1480 1.62 nonaka if (__predict_false((unsigned int)row > ri->ri_rows ||
1481 1.62 nonaka (unsigned int)col > ri->ri_cols))
1482 1.62 nonaka return;
1483 1.62 nonaka
1484 1.62 nonaka /* Avoid underflow */
1485 1.89 rin if (ri->ri_cols - col - 1 < 0)
1486 1.62 nonaka return;
1487 1.62 nonaka
1488 1.62 nonaka /* Do rotated char sans (side)underline */
1489 1.62 nonaka ri->ri_real_ops.putchar(cookie, ri->ri_cols - col - 1, row, uc,
1490 1.79 mlelstv attr & ~WSATTR_UNDERLINE);
1491 1.62 nonaka
1492 1.62 nonaka /* Do rotated underline */
1493 1.62 nonaka rp = ri->ri_bits + (ri->ri_cols - col - 1) * ri->ri_yscale +
1494 1.65 tsutsui row * ri->ri_xscale +
1495 1.65 tsutsui (ri->ri_font->fontwidth - 1) * ri->ri_pelbytes;
1496 1.62 nonaka height = ri->ri_font->fontheight;
1497 1.62 nonaka
1498 1.62 nonaka /* XXX this assumes 16-bit color depth */
1499 1.79 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) {
1500 1.82 rin uint16_t c =
1501 1.82 rin (uint16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
1502 1.62 nonaka
1503 1.62 nonaka while (height--) {
1504 1.82 rin *(uint16_t *)rp = c;
1505 1.62 nonaka rp += ri->ri_stride;
1506 1.62 nonaka }
1507 1.62 nonaka }
1508 1.62 nonaka }
1509 1.62 nonaka
1510 1.62 nonaka /* XXX: these could likely be optimised somewhat. */
1511 1.62 nonaka static void
1512 1.62 nonaka rasops_copyrows_rotated_ccw(void *cookie, int src, int dst, int num)
1513 1.62 nonaka {
1514 1.62 nonaka struct rasops_info *ri = (struct rasops_info *)cookie;
1515 1.62 nonaka int col, roff;
1516 1.62 nonaka
1517 1.62 nonaka if (src > dst)
1518 1.62 nonaka for (roff = 0; roff < num; roff++)
1519 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1520 1.62 nonaka rasops_copychar_ccw(cookie,
1521 1.62 nonaka src + roff, dst + roff, col, col);
1522 1.62 nonaka else
1523 1.62 nonaka for (roff = num - 1; roff >= 0; roff--)
1524 1.62 nonaka for (col = 0; col < ri->ri_cols; col++)
1525 1.62 nonaka rasops_copychar_ccw(cookie,
1526 1.62 nonaka src + roff, dst + roff, col, col);
1527 1.62 nonaka }
1528 1.62 nonaka
1529 1.62 nonaka static void
1530 1.62 nonaka rasops_copycols_rotated_ccw(void *cookie, int row, int src, int dst, int num)
1531 1.62 nonaka {
1532 1.62 nonaka int coff;
1533 1.62 nonaka
1534 1.62 nonaka if (src > dst)
1535 1.62 nonaka for (coff = 0; coff < num; coff++)
1536 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1537 1.62 nonaka src + coff, dst + coff);
1538 1.62 nonaka else
1539 1.62 nonaka for (coff = num - 1; coff >= 0; coff--)
1540 1.62 nonaka rasops_copychar_ccw(cookie, row, row,
1541 1.62 nonaka src + coff, dst + coff);
1542 1.62 nonaka }
1543 1.55 ober #endif /* NRASOPS_ROTATION */
1544 1.63 macallan
1545 1.63 macallan void
1546 1.63 macallan rasops_make_box_chars_16(struct rasops_info *ri)
1547 1.63 macallan {
1548 1.89 rin int c, i, mid;
1549 1.63 macallan uint16_t vert_mask, hmask_left, hmask_right;
1550 1.63 macallan uint16_t *data = (uint16_t *)ri->ri_optfont.data;
1551 1.63 macallan
1552 1.89 rin vert_mask = 0xc000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1553 1.89 rin hmask_left = 0xff00U << (8 - (ri->ri_font->fontwidth >> 1));
1554 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1555 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1556 1.63 macallan
1557 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1558 1.63 macallan for (c = 1; c < 16; c++) {
1559 1.63 macallan data += ri->ri_font->fontheight;
1560 1.63 macallan if (c & 1) {
1561 1.63 macallan /* upper segment */
1562 1.63 macallan for (i = 0; i < mid; i++)
1563 1.63 macallan data[i] = vert_mask;
1564 1.63 macallan }
1565 1.63 macallan if (c & 4) {
1566 1.63 macallan /* lower segment */
1567 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1568 1.63 macallan data[i] = vert_mask;
1569 1.63 macallan }
1570 1.63 macallan if (c & 2) {
1571 1.63 macallan /* right segment */
1572 1.63 macallan i = ri->ri_font->fontheight >> 1;
1573 1.63 macallan data[mid - 1] |= hmask_right;
1574 1.63 macallan data[mid] |= hmask_right;
1575 1.63 macallan }
1576 1.63 macallan if (c & 8) {
1577 1.63 macallan /* left segment */
1578 1.63 macallan data[mid - 1] |= hmask_left;
1579 1.63 macallan data[mid] |= hmask_left;
1580 1.63 macallan }
1581 1.63 macallan }
1582 1.63 macallan }
1583 1.63 macallan
1584 1.63 macallan void
1585 1.63 macallan rasops_make_box_chars_8(struct rasops_info *ri)
1586 1.63 macallan {
1587 1.89 rin int c, i, mid;
1588 1.63 macallan uint8_t vert_mask, hmask_left, hmask_right;
1589 1.63 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1590 1.63 macallan
1591 1.89 rin vert_mask = 0xc0U >> ((ri->ri_font->fontwidth >> 1) - 1);
1592 1.89 rin hmask_left = 0xf0U << (4 - (ri->ri_font->fontwidth >> 1));
1593 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1594 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1595 1.63 macallan
1596 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1597 1.63 macallan for (c = 1; c < 16; c++) {
1598 1.63 macallan data += ri->ri_font->fontheight;
1599 1.63 macallan if (c & 1) {
1600 1.63 macallan /* upper segment */
1601 1.63 macallan for (i = 0; i < mid; i++)
1602 1.63 macallan data[i] = vert_mask;
1603 1.63 macallan }
1604 1.63 macallan if (c & 4) {
1605 1.63 macallan /* lower segment */
1606 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1607 1.63 macallan data[i] = vert_mask;
1608 1.63 macallan }
1609 1.63 macallan if (c & 2) {
1610 1.63 macallan /* right segment */
1611 1.63 macallan i = ri->ri_font->fontheight >> 1;
1612 1.63 macallan data[mid - 1] |= hmask_right;
1613 1.63 macallan data[mid] |= hmask_right;
1614 1.63 macallan }
1615 1.63 macallan if (c & 8) {
1616 1.63 macallan /* left segment */
1617 1.63 macallan data[mid - 1] |= hmask_left;
1618 1.63 macallan data[mid] |= hmask_left;
1619 1.63 macallan }
1620 1.63 macallan }
1621 1.63 macallan }
1622 1.63 macallan
1623 1.63 macallan void
1624 1.63 macallan rasops_make_box_chars_32(struct rasops_info *ri)
1625 1.63 macallan {
1626 1.89 rin int c, i, mid;
1627 1.63 macallan uint32_t vert_mask, hmask_left, hmask_right;
1628 1.63 macallan uint32_t *data = (uint32_t *)ri->ri_optfont.data;
1629 1.63 macallan
1630 1.88 rin vert_mask = 0xc0000000U >> ((ri->ri_font->fontwidth >> 1) - 1);
1631 1.88 rin hmask_left = 0xffff0000U << (16 - (ri->ri_font->fontwidth >> 1));
1632 1.88 rin hmask_right = hmask_left >> ((ri->ri_font->fontwidth + 1) >> 1);
1633 1.63 macallan mid = (ri->ri_font->fontheight + 1) >> 1;
1634 1.63 macallan
1635 1.63 macallan /* 0x00 would be empty anyway so don't bother */
1636 1.63 macallan for (c = 1; c < 16; c++) {
1637 1.63 macallan data += ri->ri_font->fontheight;
1638 1.63 macallan if (c & 1) {
1639 1.63 macallan /* upper segment */
1640 1.63 macallan for (i = 0; i < mid; i++)
1641 1.63 macallan data[i] = vert_mask;
1642 1.63 macallan }
1643 1.63 macallan if (c & 4) {
1644 1.63 macallan /* lower segment */
1645 1.63 macallan for (i = mid; i < ri->ri_font->fontheight; i++)
1646 1.63 macallan data[i] = vert_mask;
1647 1.63 macallan }
1648 1.63 macallan if (c & 2) {
1649 1.63 macallan /* right segment */
1650 1.63 macallan i = ri->ri_font->fontheight >> 1;
1651 1.63 macallan data[mid - 1] |= hmask_right;
1652 1.63 macallan data[mid] |= hmask_right;
1653 1.63 macallan }
1654 1.63 macallan if (c & 8) {
1655 1.63 macallan /* left segment */
1656 1.63 macallan data[mid - 1] |= hmask_left;
1657 1.63 macallan data[mid] |= hmask_left;
1658 1.63 macallan }
1659 1.63 macallan }
1660 1.63 macallan }
1661 1.67 macallan
1662 1.67 macallan void
1663 1.67 macallan rasops_make_box_chars_alpha(struct rasops_info *ri)
1664 1.67 macallan {
1665 1.89 rin int c, i, hmid, vmid, wi, he;
1666 1.67 macallan uint8_t *data = (uint8_t *)ri->ri_optfont.data;
1667 1.67 macallan uint8_t *ddata;
1668 1.67 macallan
1669 1.89 rin he = ri->ri_font->fontheight;
1670 1.67 macallan wi = ri->ri_font->fontwidth;
1671 1.67 macallan
1672 1.67 macallan vmid = (he + 1) >> 1;
1673 1.67 macallan hmid = (wi + 1) >> 1;
1674 1.67 macallan
1675 1.67 macallan /* 0x00 would be empty anyway so don't bother */
1676 1.67 macallan for (c = 1; c < 16; c++) {
1677 1.67 macallan data += ri->ri_fontscale;
1678 1.67 macallan if (c & 1) {
1679 1.67 macallan /* upper segment */
1680 1.67 macallan ddata = data + hmid;
1681 1.67 macallan for (i = 0; i <= vmid; i++) {
1682 1.67 macallan *ddata = 0xff;
1683 1.67 macallan ddata += wi;
1684 1.67 macallan }
1685 1.67 macallan }
1686 1.67 macallan if (c & 4) {
1687 1.67 macallan /* lower segment */
1688 1.67 macallan ddata = data + wi * vmid + hmid;
1689 1.67 macallan for (i = vmid; i < he; i++) {
1690 1.67 macallan *ddata = 0xff;
1691 1.67 macallan ddata += wi;
1692 1.67 macallan }
1693 1.67 macallan }
1694 1.67 macallan if (c & 2) {
1695 1.67 macallan /* right segment */
1696 1.67 macallan ddata = data + wi * vmid + hmid;
1697 1.67 macallan for (i = hmid; i < wi; i++) {
1698 1.67 macallan *ddata = 0xff;
1699 1.67 macallan ddata++;
1700 1.67 macallan }
1701 1.67 macallan }
1702 1.67 macallan if (c & 8) {
1703 1.67 macallan /* left segment */
1704 1.67 macallan ddata = data + wi * vmid;
1705 1.67 macallan for (i = 0; i <= hmid; i++) {
1706 1.67 macallan *ddata = 0xff;
1707 1.67 macallan ddata++;
1708 1.67 macallan }
1709 1.67 macallan }
1710 1.67 macallan }
1711 1.67 macallan }
1712 1.75 macallan
1713 1.71 macallan /*
1714 1.71 macallan * Return a colour map appropriate for the given struct rasops_info in the
1715 1.71 macallan * same form used by rasops_cmap[]
1716 1.71 macallan * For now this is either a copy of rasops_cmap[] or an R3G3B2 map, it should
1717 1.71 macallan * probably be a linear ( or gamma corrected? ) ramp for higher depths.
1718 1.71 macallan */
1719 1.71 macallan
1720 1.71 macallan int
1721 1.71 macallan rasops_get_cmap(struct rasops_info *ri, uint8_t *palette, size_t bytes)
1722 1.71 macallan {
1723 1.88 rin
1724 1.89 rin if ((ri->ri_depth == 8) && ((ri->ri_flg & RI_8BIT_IS_RGB) != 0)) {
1725 1.71 macallan /* generate an R3G3B2 palette */
1726 1.71 macallan int i, idx = 0;
1727 1.71 macallan uint8_t tmp;
1728 1.71 macallan
1729 1.71 macallan if (bytes < 768)
1730 1.71 macallan return EINVAL;
1731 1.71 macallan for (i = 0; i < 256; i++) {
1732 1.71 macallan tmp = i & 0xe0;
1733 1.71 macallan /*
1734 1.71 macallan * replicate bits so 0xe0 maps to a red value of 0xff
1735 1.71 macallan * in order to make white look actually white
1736 1.71 macallan */
1737 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1738 1.71 macallan palette[idx] = tmp;
1739 1.71 macallan idx++;
1740 1.71 macallan
1741 1.71 macallan tmp = (i & 0x1c) << 3;
1742 1.71 macallan tmp |= (tmp >> 3) | (tmp >> 6);
1743 1.71 macallan palette[idx] = tmp;
1744 1.71 macallan idx++;
1745 1.71 macallan
1746 1.71 macallan tmp = (i & 0x03) << 6;
1747 1.71 macallan tmp |= tmp >> 2;
1748 1.71 macallan tmp |= tmp >> 4;
1749 1.71 macallan palette[idx] = tmp;
1750 1.71 macallan idx++;
1751 1.71 macallan }
1752 1.88 rin } else
1753 1.89 rin memcpy(palette, rasops_cmap, uimin(bytes, sizeof(rasops_cmap)));
1754 1.71 macallan return 0;
1755 1.71 macallan }
1756