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