omrasops.c revision 1.26 1 1.26 tsutsui /* $NetBSD: omrasops.c,v 1.26 2023/01/15 05:08:33 tsutsui Exp $ */
2 1.1 nisimura
3 1.1 nisimura /*-
4 1.1 nisimura * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 1.1 nisimura * All rights reserved.
6 1.1 nisimura *
7 1.1 nisimura * This code is derived from software contributed to The NetBSD Foundation
8 1.1 nisimura * by Tohru Nishimura.
9 1.1 nisimura *
10 1.1 nisimura * Redistribution and use in source and binary forms, with or without
11 1.1 nisimura * modification, are permitted provided that the following conditions
12 1.1 nisimura * are met:
13 1.1 nisimura * 1. Redistributions of source code must retain the above copyright
14 1.1 nisimura * notice, this list of conditions and the following disclaimer.
15 1.1 nisimura * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 nisimura * notice, this list of conditions and the following disclaimer in the
17 1.1 nisimura * documentation and/or other materials provided with the distribution.
18 1.1 nisimura *
19 1.1 nisimura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 nisimura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 nisimura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 nisimura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 nisimura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 nisimura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 nisimura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 nisimura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 nisimura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 nisimura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 nisimura * POSSIBILITY OF SUCH DAMAGE.
30 1.1 nisimura */
31 1.1 nisimura
32 1.1 nisimura #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33 1.1 nisimura
34 1.26 tsutsui __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.26 2023/01/15 05:08:33 tsutsui Exp $");
35 1.1 nisimura
36 1.1 nisimura /*
37 1.1 nisimura * Designed speficically for 'm68k bitorder';
38 1.1 nisimura * - most significant byte is stored at lower address,
39 1.1 nisimura * - most significant bit is displayed at left most on screen.
40 1.12 tsutsui * Implementation relies on;
41 1.15 tsutsui * - first column is at 32bit aligned address,
42 1.1 nisimura * - font glyphs are stored in 32bit padded.
43 1.1 nisimura */
44 1.23 isaki /*
45 1.23 isaki * BMSEL affects both of
46 1.23 isaki * 1) which plane a write to the common bitmap plane is reflected on and
47 1.23 isaki * 2) which plane's ROP a write to the common ROP is reflected on.
48 1.23 isaki *
49 1.23 isaki * The common ROP is not a ROP applied to write to the common bitmap plane.
50 1.23 isaki * It's equivalent to set ROPs of the plane selected in the plane mask one
51 1.23 isaki * by one.
52 1.23 isaki */
53 1.1 nisimura
54 1.1 nisimura #include <sys/param.h>
55 1.1 nisimura #include <sys/systm.h>
56 1.1 nisimura #include <sys/device.h>
57 1.1 nisimura
58 1.13 tsutsui #include <dev/wscons/wsconsio.h>
59 1.1 nisimura #include <dev/wscons/wsdisplayvar.h>
60 1.13 tsutsui #include <dev/rasops/rasops.h>
61 1.1 nisimura
62 1.13 tsutsui #include <arch/luna68k/dev/omrasopsvar.h>
63 1.1 nisimura
64 1.23 isaki #ifdef luna68k
65 1.23 isaki #define USE_M68K_ASM 1
66 1.23 isaki #endif
67 1.23 isaki
68 1.23 isaki /* To provide optimization conditions to compilers */
69 1.23 isaki #if defined(__GNUC__)
70 1.23 isaki #define ASSUME(cond) if (!(cond)) __unreachable()
71 1.23 isaki #elif defined(__clang__) && __has_builtin(__builtin_assume)
72 1.23 isaki #define ASSUME(cond) __builtin_assume(cond)
73 1.23 isaki #else
74 1.23 isaki #define ASSUME(cond) (void)(cond)
75 1.23 isaki #endif
76 1.23 isaki
77 1.23 isaki /* XXX it should be redesigned, including making the attributes support 8bpp */
78 1.23 isaki typedef struct {
79 1.23 isaki union {
80 1.23 isaki int32_t all;
81 1.23 isaki struct {
82 1.23 isaki int8_t ismulti; /* is multi color used */
83 1.23 isaki uint8_t fg;
84 1.23 isaki uint8_t bg;
85 1.23 isaki uint8_t reserved;
86 1.23 isaki };
87 1.23 isaki };
88 1.23 isaki } rowattr_t;
89 1.23 isaki
90 1.1 nisimura /* wscons emulator operations */
91 1.23 isaki static void om_cursor(void *, int, int, int);
92 1.23 isaki static int om_mapchar(void *, int, u_int *);
93 1.23 isaki static void om_putchar(void *, int, int, u_int, long);
94 1.16 tsutsui static void om1_copycols(void *, int, int, int, int);
95 1.16 tsutsui static void om4_copycols(void *, int, int, int, int);
96 1.16 tsutsui static void om1_copyrows(void *, int, int, int num);
97 1.16 tsutsui static void om4_copyrows(void *, int, int, int num);
98 1.23 isaki static void om_erasecols(void *, int, int, int, long);
99 1.23 isaki static void om_eraserows(void *, int, int, long);
100 1.23 isaki static int om_allocattr(void *, int, int, int, long *);
101 1.23 isaki
102 1.23 isaki static void om_fill(int, int, uint8_t *, int, int, uint32_t, int, int);
103 1.25 tsutsui static void om_fill_color(int, int, uint8_t *, int, int, int, int);
104 1.25 tsutsui static void om_rascopy_single(int, uint8_t *, uint8_t *, int16_t, int16_t,
105 1.23 isaki uint8_t[]);
106 1.23 isaki static void om4_rascopy_multi(uint8_t *, uint8_t *, int16_t, int16_t);
107 1.23 isaki static void om_unpack_attr(long, uint8_t *, uint8_t *, int *);
108 1.16 tsutsui
109 1.16 tsutsui static int omrasops_init(struct rasops_info *, int, int);
110 1.1 nisimura
111 1.23 isaki /*
112 1.23 isaki * XXX should be fixed...
113 1.23 isaki * This number of elements is derived from howmany(1024, fontheight = 24).
114 1.23 isaki * But it is currently initialized with row = 34, so it is used only up to 34.
115 1.23 isaki */
116 1.24 tsutsui #define OMRASOPS_MAX_ROWS 43
117 1.24 tsutsui static rowattr_t rowattr[OMRASOPS_MAX_ROWS];
118 1.23 isaki
119 1.1 nisimura #define ALL1BITS (~0U)
120 1.1 nisimura #define ALL0BITS (0U)
121 1.1 nisimura #define BLITWIDTH (32)
122 1.1 nisimura #define ALIGNMASK (0x1f)
123 1.1 nisimura #define BYTESDONE (4)
124 1.1 nisimura
125 1.23 isaki #if 0 /* XXX not used yet */
126 1.23 isaki /*
127 1.23 isaki * internal attributes. see om_allocattr().
128 1.23 isaki */
129 1.23 isaki #define OMFB_ATTR_MULTICOLOR (1U << 31)
130 1.23 isaki #define OMFB_ATTR_UNDERLINE (1U << 17)
131 1.23 isaki #define OMFB_ATTR_BOLD (1U << 16)
132 1.23 isaki #endif
133 1.23 isaki
134 1.23 isaki /*
135 1.23 isaki * XXX deprecated.
136 1.23 isaki * This way cannot be extended to 8bpp, so don't use it in new code.
137 1.23 isaki */
138 1.23 isaki #define P0(addr) ((uint32_t *)((uint8_t *)(addr) + OMFB_PLANEOFFS * 1))
139 1.23 isaki #define P1(addr) ((uint32_t *)((uint8_t *)(addr) + OMFB_PLANEOFFS * 2))
140 1.23 isaki #define P2(addr) ((uint32_t *)((uint8_t *)(addr) + OMFB_PLANEOFFS * 3))
141 1.23 isaki #define P3(addr) ((uint32_t *)((uint8_t *)(addr) + OMFB_PLANEOFFS * 4))
142 1.23 isaki
143 1.1 nisimura /*
144 1.15 tsutsui * macros to handle unaligned bit copy ops.
145 1.22 isaki * See src/sys/dev/rasops/rasops_masks.h for MI version.
146 1.15 tsutsui * Also refer src/sys/arch/hp300/dev/maskbits.h.
147 1.15 tsutsui * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c)
148 1.15 tsutsui */
149 1.15 tsutsui
150 1.15 tsutsui /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */
151 1.15 tsutsui #define FASTGETBITS(psrc, x, w, dst) \
152 1.15 tsutsui asm("bfextu %3{%1:%2},%0" \
153 1.26 tsutsui : "=d" (dst) \
154 1.19 tsutsui : "di" (x), "di" (w), "o" (*(uint32_t *)(psrc)))
155 1.15 tsutsui
156 1.15 tsutsui /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */
157 1.15 tsutsui /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */
158 1.15 tsutsui #define FASTPUTBITS(src, x, w, pdst) \
159 1.15 tsutsui asm("bfins %3,%0{%1:%2}" \
160 1.19 tsutsui : "+o" (*(uint32_t *)(pdst)) \
161 1.16 tsutsui : "di" (x), "di" (w), "d" (src) \
162 1.22 isaki : "memory" )
163 1.15 tsutsui
164 1.15 tsutsui #define GETBITS(psrc, x, w, dst) FASTGETBITS(psrc, x, w, dst)
165 1.15 tsutsui #define PUTBITS(src, x, w, pdst) FASTPUTBITS(src, x, w, pdst)
166 1.15 tsutsui
167 1.15 tsutsui /*
168 1.23 isaki * Clear lower w bits from x.
169 1.23 isaki * x must be filled with 1 at least lower w bits.
170 1.1 nisimura */
171 1.23 isaki #if USE_M68K_ASM
172 1.23 isaki #define CLEAR_LOWER_BITS(x, w) \
173 1.23 isaki asm volatile( \
174 1.23 isaki " bclr %[width],%[data] ;\n" \
175 1.23 isaki " addq.l #1,%[data] ;\n" \
176 1.23 isaki : [data] "+&d" (x) \
177 1.23 isaki : [width] "d" (w) \
178 1.23 isaki : \
179 1.23 isaki )
180 1.23 isaki #else
181 1.23 isaki #define CLEAR_LOWER_BITS(x, w) x = ((x) & ~(1U << (w))) + 1
182 1.23 isaki #endif
183 1.23 isaki
184 1.23 isaki /* Set planemask for the common plane and the common ROP */
185 1.23 isaki static inline void
186 1.23 isaki om_set_planemask(int planemask)
187 1.23 isaki {
188 1.23 isaki
189 1.23 isaki *(volatile uint32_t *)OMFB_PLANEMASK = planemask;
190 1.23 isaki }
191 1.23 isaki
192 1.23 isaki /* Get a ROP address */
193 1.23 isaki static inline volatile uint32_t *
194 1.23 isaki om_rop_addr(int plane, int rop)
195 1.1 nisimura {
196 1.1 nisimura
197 1.23 isaki return (volatile uint32_t *)
198 1.23 isaki (OMFB_ROP_P0 + OMFB_PLANEOFFS * plane + rop * 4);
199 1.23 isaki }
200 1.1 nisimura
201 1.23 isaki /* Set ROP and ROP's mask for individual plane */
202 1.23 isaki static inline void
203 1.23 isaki om_set_rop(int plane, int rop, uint32_t mask)
204 1.23 isaki {
205 1.19 tsutsui
206 1.23 isaki *om_rop_addr(plane, rop) = mask;
207 1.23 isaki }
208 1.19 tsutsui
209 1.23 isaki /* Set ROP and ROP's mask for current setplanemask-ed plane(s) */
210 1.23 isaki static inline void
211 1.23 isaki om_set_rop_curplane(int rop, uint32_t mask)
212 1.23 isaki {
213 1.19 tsutsui
214 1.23 isaki ((volatile uint32_t *)(OMFB_ROP_COMMON))[rop] = mask;
215 1.23 isaki }
216 1.1 nisimura
217 1.23 isaki /* Reset planemask and ROP */
218 1.23 isaki static inline void
219 1.23 isaki om_reset_planemask_and_rop(void)
220 1.23 isaki {
221 1.19 tsutsui
222 1.23 isaki om_set_planemask(hwplanemask);
223 1.23 isaki om_set_rop_curplane(ROP_THROUGH, ~0U);
224 1.23 isaki }
225 1.19 tsutsui
226 1.23 isaki static inline void
227 1.23 isaki om_set_rowattr(int row, uint8_t fg, uint8_t bg)
228 1.23 isaki {
229 1.19 tsutsui
230 1.23 isaki if (rowattr[row].fg == fg && rowattr[row].bg == bg)
231 1.23 isaki return;
232 1.23 isaki if (rowattr[row].ismulti)
233 1.23 isaki return;
234 1.16 tsutsui
235 1.23 isaki if (rowattr[row].fg == rowattr[row].bg) {
236 1.23 isaki /* From the initial (erased) state, */
237 1.23 isaki if (rowattr[row].fg != fg && rowattr[row].bg != bg) {
238 1.23 isaki /* if both are changed at once, it's multi color */
239 1.23 isaki rowattr[row].ismulti = true;
240 1.23 isaki } else {
241 1.23 isaki /* otherwise, it's single color */
242 1.23 isaki rowattr[row].fg = fg;
243 1.23 isaki rowattr[row].bg = bg;
244 1.16 tsutsui }
245 1.23 isaki } else {
246 1.23 isaki rowattr[row].ismulti = true;
247 1.16 tsutsui }
248 1.16 tsutsui }
249 1.16 tsutsui
250 1.23 isaki static inline void
251 1.23 isaki om_reset_rowattr(int row, uint8_t bg)
252 1.23 isaki {
253 1.23 isaki
254 1.23 isaki /* Setting fg equal to bg means 'reset' or 'erased'. */
255 1.23 isaki rowattr[row].ismulti = false;
256 1.23 isaki rowattr[row].bg = bg;
257 1.23 isaki rowattr[row].fg = bg;
258 1.23 isaki }
259 1.23 isaki
260 1.23 isaki /*
261 1.23 isaki * Fill rectangle.
262 1.23 isaki * val is assumed only ALL0BITS or ALL1BITS, because all bits are used as is
263 1.23 isaki * regardless of bit offset of the destination.
264 1.23 isaki */
265 1.16 tsutsui static void
266 1.23 isaki om_fill(int planemask, int rop, uint8_t *dstptr, int dstbitoffs, int dstspan,
267 1.23 isaki uint32_t val, int width, int height)
268 1.16 tsutsui {
269 1.23 isaki uint32_t mask;
270 1.23 isaki uint32_t prev_mask;
271 1.23 isaki int32_t height_m1;
272 1.23 isaki int dw; /* 1 pass width bits */
273 1.23 isaki
274 1.23 isaki ASSUME(width > 0);
275 1.23 isaki ASSUME(height > 0);
276 1.23 isaki ASSUME(0 <= dstbitoffs && dstbitoffs < 32);
277 1.23 isaki
278 1.23 isaki om_set_planemask(planemask);
279 1.23 isaki
280 1.23 isaki height_m1 = height - 1;
281 1.23 isaki mask = ALL1BITS >> dstbitoffs;
282 1.23 isaki prev_mask = ~mask;
283 1.23 isaki dw = 32 - dstbitoffs;
284 1.23 isaki
285 1.23 isaki /* do-while loop seems slightly faster than a for loop */
286 1.23 isaki do {
287 1.23 isaki uint8_t *d;
288 1.23 isaki int32_t h;
289 1.23 isaki
290 1.23 isaki width -= dw;
291 1.23 isaki if (width < 0) {
292 1.23 isaki CLEAR_LOWER_BITS(mask, -width);
293 1.23 isaki /* To exit this loop. */
294 1.23 isaki width = 0;
295 1.23 isaki }
296 1.23 isaki
297 1.23 isaki if (prev_mask != mask) {
298 1.23 isaki om_set_rop_curplane(rop, mask);
299 1.23 isaki prev_mask = mask;
300 1.23 isaki }
301 1.23 isaki
302 1.23 isaki d = dstptr;
303 1.23 isaki dstptr += 4;
304 1.23 isaki h = height_m1;
305 1.23 isaki
306 1.23 isaki #if USE_M68K_ASM
307 1.23 isaki asm volatile("\n"
308 1.23 isaki "om_fill_loop_h:\n"
309 1.23 isaki " move.l %[val],(%[d]) ;\n"
310 1.23 isaki " add.l %[dstspan],%[d] ;\n"
311 1.23 isaki " dbra %[h],om_fill_loop_h ;\n"
312 1.23 isaki : /* output */
313 1.23 isaki [d] "+&a" (d),
314 1.23 isaki [h] "+&d" (h)
315 1.23 isaki : /* input */
316 1.23 isaki [val] "d" (val),
317 1.23 isaki [dstspan] "r" (dstspan)
318 1.23 isaki : /* clobbers */
319 1.23 isaki "memory"
320 1.23 isaki );
321 1.23 isaki #else
322 1.23 isaki do {
323 1.23 isaki *(uint32_t *)d = val;
324 1.23 isaki d += dstspan;
325 1.23 isaki } while (--h >= 0);
326 1.23 isaki #endif
327 1.23 isaki mask = ALL1BITS;
328 1.23 isaki dw = 32;
329 1.23 isaki } while (width > 0);
330 1.23 isaki }
331 1.23 isaki
332 1.23 isaki static void
333 1.25 tsutsui om_fill_color(int planecount, int color, uint8_t *dstptr, int dstbitoffs,
334 1.25 tsutsui int dstspan, int width, int height)
335 1.23 isaki {
336 1.23 isaki uint32_t mask;
337 1.23 isaki uint32_t prev_mask;
338 1.23 isaki int32_t height_m1;
339 1.23 isaki int dw; /* 1 pass width bits */
340 1.23 isaki
341 1.23 isaki ASSUME(width > 0);
342 1.23 isaki ASSUME(height > 0);
343 1.25 tsutsui ASSUME(planecount > 0);
344 1.23 isaki
345 1.23 isaki /* select all planes */
346 1.23 isaki om_set_planemask(hwplanemask);
347 1.23 isaki
348 1.23 isaki mask = ALL1BITS >> dstbitoffs;
349 1.23 isaki prev_mask = ~mask;
350 1.23 isaki dw = 32 - dstbitoffs;
351 1.23 isaki height_m1 = height - 1;
352 1.23 isaki
353 1.23 isaki do {
354 1.23 isaki uint8_t *d;
355 1.23 isaki int32_t plane;
356 1.23 isaki int32_t h;
357 1.23 isaki int16_t rop;
358 1.23 isaki
359 1.23 isaki width -= dw;
360 1.23 isaki if (width < 0) {
361 1.23 isaki CLEAR_LOWER_BITS(mask, -width);
362 1.23 isaki /* To exit this loop. */
363 1.23 isaki width = 0;
364 1.23 isaki }
365 1.23 isaki
366 1.23 isaki if (prev_mask != mask) {
367 1.25 tsutsui for (plane = 0; plane < planecount; plane++) {
368 1.23 isaki if ((color & (1U << plane)) != 0)
369 1.23 isaki rop = ROP_ONE;
370 1.23 isaki else
371 1.23 isaki rop = ROP_ZERO;
372 1.23 isaki om_set_rop(plane, rop, mask);
373 1.23 isaki }
374 1.23 isaki prev_mask = mask;
375 1.23 isaki }
376 1.16 tsutsui
377 1.23 isaki d = dstptr;
378 1.23 isaki dstptr += 4;
379 1.23 isaki h = height_m1;
380 1.23 isaki
381 1.23 isaki #if USE_M68K_ASM
382 1.23 isaki asm volatile("\n"
383 1.23 isaki "om_fill_color_loop_h:\n"
384 1.23 isaki " clr.l (%[d]) ;\n"
385 1.23 isaki " add.l %[dstspan],%[d] ;\n"
386 1.23 isaki " dbra %[h],om_fill_color_loop_h ;\n"
387 1.23 isaki : /* output */
388 1.23 isaki [d] "+&a" (d),
389 1.23 isaki [h] "+&d" (h)
390 1.23 isaki : /* input */
391 1.23 isaki [dstspan] "r" (dstspan)
392 1.23 isaki : /* clobbers */
393 1.23 isaki "memory"
394 1.23 isaki );
395 1.23 isaki #else
396 1.23 isaki do {
397 1.23 isaki /*
398 1.23 isaki * ROP is either ONE or ZERO,
399 1.23 isaki * so don't care what you write to *d.
400 1.23 isaki */
401 1.23 isaki *(uint32_t *)d = 0;
402 1.23 isaki d += dstspan;
403 1.23 isaki } while (--h >= 0);
404 1.23 isaki #endif
405 1.23 isaki mask = ALL1BITS;
406 1.23 isaki dw = 32;
407 1.23 isaki } while (width > 0);
408 1.23 isaki }
409 1.19 tsutsui
410 1.23 isaki /*
411 1.23 isaki * Calculate ROP depending on fg/bg color combination as follows.
412 1.23 isaki * This is called per individual plane while shifting fg and bg.
413 1.23 isaki * So the LSB of fg and bg points to this plane.
414 1.23 isaki *
415 1.23 isaki * All ROP values we want to use here happens to be a multiple of 5.
416 1.23 isaki *
417 1.23 isaki * bg fg rop result
418 1.23 isaki * -- -- ---------------- ------
419 1.23 isaki * 0 0 ROP_ZERO = 0 0
420 1.23 isaki * 0 1 ROP_THROUGH = 5 D
421 1.23 isaki * 1 0 ROP_INV1 = 10 ~D
422 1.23 isaki * 1 1 ROP_ONE = 15 1
423 1.23 isaki *
424 1.23 isaki * This allows characters to be drawn in the specified fg/bg colors with
425 1.23 isaki * a single write to the common plane.
426 1.23 isaki */
427 1.23 isaki static inline int
428 1.23 isaki om_fgbg2rop(uint8_t fg, uint8_t bg)
429 1.23 isaki {
430 1.23 isaki int t;
431 1.19 tsutsui
432 1.23 isaki t = (bg & 1) * 2 + (fg & 1);
433 1.23 isaki return t * 5;
434 1.23 isaki }
435 1.19 tsutsui
436 1.23 isaki /*
437 1.23 isaki * Blit a character at the specified co-ordinates.
438 1.23 isaki * This function modifies(breaks) the planemask and ROPs.
439 1.23 isaki */
440 1.23 isaki static void
441 1.23 isaki om_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
442 1.23 isaki {
443 1.23 isaki struct rasops_info *ri = cookie;
444 1.23 isaki uint8_t *fontptr;
445 1.23 isaki uint8_t *dstcmn;
446 1.23 isaki uint32_t mask;
447 1.23 isaki int width;
448 1.23 isaki int height;
449 1.25 tsutsui int planecount;
450 1.23 isaki int x, y;
451 1.23 isaki int fontstride;
452 1.23 isaki int fontx;
453 1.23 isaki int plane;
454 1.23 isaki int dw; /* 1 pass width bits */
455 1.23 isaki int xh, xl;
456 1.23 isaki uint8_t fg, bg;
457 1.23 isaki /* ROP address cache */
458 1.23 isaki static volatile uint32_t *ropaddr[OMFB_MAX_PLANECOUNT];
459 1.23 isaki static uint8_t last_fg, last_bg;
460 1.19 tsutsui
461 1.23 isaki if (uc >= 0x80)
462 1.23 isaki return;
463 1.16 tsutsui
464 1.23 isaki width = ri->ri_font->fontwidth;
465 1.23 isaki height = ri->ri_font->fontheight;
466 1.25 tsutsui planecount = ri->ri_depth;
467 1.23 isaki fontstride = ri->ri_font->stride;
468 1.23 isaki y = height * row;
469 1.23 isaki x = width * startcol;
470 1.23 isaki fontptr = (uint8_t *)ri->ri_font->data +
471 1.23 isaki (uc - ri->ri_font->firstchar) * ri->ri_fontscale;
472 1.19 tsutsui
473 1.23 isaki om_unpack_attr(attr, &fg, &bg, NULL);
474 1.23 isaki om_set_rowattr(row, fg, bg);
475 1.19 tsutsui
476 1.23 isaki if (last_fg != fg || last_bg != bg) {
477 1.23 isaki last_fg = fg;
478 1.23 isaki last_bg = bg;
479 1.23 isaki /* calculate ROP */
480 1.25 tsutsui for (plane = 0; plane < planecount; plane++) {
481 1.23 isaki int t = om_fgbg2rop(fg, bg);
482 1.23 isaki ropaddr[plane] = om_rop_addr(plane, t);
483 1.23 isaki fg >>= 1;
484 1.23 isaki bg >>= 1;
485 1.23 isaki }
486 1.23 isaki }
487 1.23 isaki
488 1.23 isaki /* divide x into the lower 5 bits and the rest. */
489 1.23 isaki xh = x >> 5;
490 1.23 isaki xl = x & 0x1f;
491 1.23 isaki
492 1.23 isaki /* write to common plane */
493 1.23 isaki dstcmn = (uint8_t *)ri->ri_bits + xh * 4 + y * OMFB_STRIDE;
494 1.23 isaki
495 1.23 isaki /* select all plane */
496 1.23 isaki om_set_planemask(hwplanemask);
497 1.23 isaki
498 1.23 isaki fontx = 0;
499 1.23 isaki mask = ALL1BITS >> xl;
500 1.23 isaki dw = 32 - xl;
501 1.23 isaki
502 1.25 tsutsui ASSUME(planecount == 1 ||
503 1.25 tsutsui planecount == 4 ||
504 1.25 tsutsui planecount == 8);
505 1.23 isaki
506 1.23 isaki do {
507 1.23 isaki uint8_t *d;
508 1.23 isaki uint8_t *f;
509 1.23 isaki int32_t h;
510 1.23 isaki
511 1.23 isaki width -= dw;
512 1.23 isaki if (width < 0) {
513 1.23 isaki CLEAR_LOWER_BITS(mask, -width);
514 1.23 isaki /* To exit this loop. */
515 1.23 isaki width = 0;
516 1.23 isaki }
517 1.23 isaki
518 1.25 tsutsui switch (planecount) {
519 1.23 isaki case 8:
520 1.23 isaki *(ropaddr[7]) = mask;
521 1.23 isaki *(ropaddr[6]) = mask;
522 1.23 isaki *(ropaddr[5]) = mask;
523 1.23 isaki *(ropaddr[4]) = mask;
524 1.23 isaki /* FALLTHROUGH */
525 1.23 isaki case 4:
526 1.23 isaki *(ropaddr[3]) = mask;
527 1.23 isaki *(ropaddr[2]) = mask;
528 1.23 isaki *(ropaddr[1]) = mask;
529 1.23 isaki /* FALLTHROUGH */
530 1.23 isaki case 1:
531 1.23 isaki *(ropaddr[0]) = mask;
532 1.23 isaki break;
533 1.23 isaki }
534 1.23 isaki
535 1.23 isaki d = dstcmn;
536 1.23 isaki f = fontptr;
537 1.23 isaki h = height - 1;
538 1.23 isaki do {
539 1.23 isaki uint32_t v;
540 1.23 isaki GETBITS(f, fontx, dw, v);
541 1.23 isaki /* no need to shift v because it's masked by ROP */
542 1.23 isaki *(uint32_t *)d = v;
543 1.23 isaki d += OMFB_STRIDE;
544 1.23 isaki f += fontstride;
545 1.23 isaki } while (--h >= 0);
546 1.23 isaki
547 1.23 isaki dstcmn += 4;
548 1.23 isaki fontx += dw;
549 1.23 isaki mask = ALL1BITS;
550 1.23 isaki dw = 32;
551 1.23 isaki } while (width > 0);
552 1.1 nisimura
553 1.23 isaki om_reset_planemask_and_rop();
554 1.1 nisimura }
555 1.1 nisimura
556 1.1 nisimura static void
557 1.23 isaki om_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
558 1.1 nisimura {
559 1.13 tsutsui struct rasops_info *ri = cookie;
560 1.23 isaki int startx;
561 1.23 isaki int width;
562 1.23 isaki int height;
563 1.25 tsutsui int planecount;
564 1.23 isaki int sh, sl;
565 1.23 isaki int y;
566 1.23 isaki int scanspan;
567 1.13 tsutsui uint8_t *p;
568 1.23 isaki uint8_t fg, bg;
569 1.13 tsutsui
570 1.20 maya scanspan = ri->ri_stride;
571 1.13 tsutsui y = ri->ri_font->fontheight * row;
572 1.13 tsutsui startx = ri->ri_font->fontwidth * startcol;
573 1.23 isaki width = ri->ri_font->fontwidth * ncols;
574 1.13 tsutsui height = ri->ri_font->fontheight;
575 1.25 tsutsui planecount = ri->ri_depth;
576 1.23 isaki om_unpack_attr(attr, &fg, &bg, NULL);
577 1.23 isaki sh = startx >> 5;
578 1.23 isaki sl = startx & 0x1f;
579 1.23 isaki p = (uint8_t *)ri->ri_bits + y * scanspan + sh * 4;
580 1.23 isaki
581 1.23 isaki /* I'm not sure */
582 1.23 isaki om_set_rowattr(row, fg, bg);
583 1.23 isaki
584 1.23 isaki if (bg == 0) {
585 1.23 isaki /* om_fill seems slightly efficient */
586 1.23 isaki om_fill(hwplanemask, ROP_ZERO,
587 1.23 isaki p, sl, scanspan, 0, width, height);
588 1.11 tsutsui } else {
589 1.25 tsutsui om_fill_color(planecount, bg, p, sl, scanspan, width, height);
590 1.23 isaki }
591 1.1 nisimura
592 1.23 isaki /* reset mask value */
593 1.23 isaki om_reset_planemask_and_rop();
594 1.1 nisimura }
595 1.1 nisimura
596 1.1 nisimura static void
597 1.23 isaki om_eraserows(void *cookie, int startrow, int nrows, long attr)
598 1.16 tsutsui {
599 1.16 tsutsui struct rasops_info *ri = cookie;
600 1.23 isaki int startx;
601 1.23 isaki int width;
602 1.23 isaki int height;
603 1.25 tsutsui int planecount;
604 1.23 isaki int sh, sl;
605 1.23 isaki int y;
606 1.23 isaki int scanspan;
607 1.23 isaki int row;
608 1.16 tsutsui uint8_t *p;
609 1.23 isaki uint8_t fg, bg;
610 1.16 tsutsui
611 1.20 maya scanspan = ri->ri_stride;
612 1.23 isaki y = ri->ri_font->fontheight * startrow;
613 1.23 isaki startx = 0;
614 1.23 isaki width = ri->ri_emuwidth;
615 1.23 isaki height = ri->ri_font->fontheight * nrows;
616 1.25 tsutsui planecount = ri->ri_depth;
617 1.23 isaki om_unpack_attr(attr, &fg, &bg, NULL);
618 1.23 isaki sh = startx >> 5;
619 1.23 isaki sl = startx & 0x1f;
620 1.23 isaki p = (uint8_t *)ri->ri_bits + y * scanspan + sh * 4;
621 1.23 isaki
622 1.23 isaki for (row = startrow; row < startrow + nrows; row++) {
623 1.23 isaki om_reset_rowattr(row, bg);
624 1.23 isaki }
625 1.23 isaki
626 1.23 isaki if (bg == 0) {
627 1.23 isaki /* om_fill seems slightly efficient */
628 1.23 isaki om_fill(hwplanemask, ROP_ZERO,
629 1.23 isaki p, sl, scanspan, 0, width, height);
630 1.16 tsutsui } else {
631 1.25 tsutsui om_fill_color(planecount, bg, p, sl, scanspan, width, height);
632 1.16 tsutsui }
633 1.23 isaki /* reset mask value */
634 1.23 isaki om_reset_planemask_and_rop();
635 1.16 tsutsui }
636 1.16 tsutsui
637 1.23 isaki /*
638 1.23 isaki * Single plane raster copy.
639 1.23 isaki * dst: destination plane pointer.
640 1.23 isaki * src: source plane pointer.
641 1.23 isaki * if y-forward, src > dst, point to left-top.
642 1.23 isaki * if y-backward, src < dst, point to left-bottom.
643 1.23 isaki * width: pixel width (must > 0)
644 1.23 isaki * height: pixel height (> 0 if forward, < 0 if backward)
645 1.25 tsutsui * rop: ROP array with planecount elements.
646 1.23 isaki *
647 1.23 isaki * This function modifies(breaks) the planemask and ROPs.
648 1.23 isaki */
649 1.16 tsutsui static void
650 1.25 tsutsui om_rascopy_single(int planecount, uint8_t *dst, uint8_t *src,
651 1.25 tsutsui int16_t width, int16_t height, uint8_t rop[])
652 1.1 nisimura {
653 1.23 isaki uint32_t mask;
654 1.23 isaki int wh;
655 1.23 isaki int wl;
656 1.23 isaki int step;
657 1.23 isaki int plane;
658 1.23 isaki int16_t height_m1;
659 1.23 isaki int16_t w, h;
660 1.23 isaki
661 1.23 isaki step = OMFB_STRIDE;
662 1.23 isaki
663 1.23 isaki /*
664 1.23 isaki * X direction is always forward (or ascend order) to use (An)+
665 1.23 isaki * addressing mode in asm.
666 1.23 isaki */
667 1.23 isaki
668 1.23 isaki /* Reverse order Y if backward copy */
669 1.23 isaki if (height < 0) {
670 1.23 isaki /* The sign is managed by step, height is always positive */
671 1.23 isaki step = -step;
672 1.23 isaki height = -height;
673 1.23 isaki }
674 1.23 isaki height_m1 = height - 1;
675 1.23 isaki
676 1.23 isaki /*
677 1.23 isaki * On single, it's not necessary to process two longwords at a time,
678 1.23 isaki * but we do so for symmetry and speedup.
679 1.23 isaki */
680 1.23 isaki
681 1.23 isaki /* First, transfer a rectangle consist of two longwords */
682 1.23 isaki wh = (width >> 6);
683 1.23 isaki if (wh > 0) {
684 1.23 isaki int step8 = step - wh * 8;
685 1.23 isaki
686 1.23 isaki #if USE_M68K_ASM
687 1.23 isaki wh--; /* for dbra */
688 1.23 isaki h = height_m1;
689 1.23 isaki asm volatile("\n"
690 1.23 isaki "om_rascopy_single_LL:\n"
691 1.23 isaki " move.w %[wh],%[w] ;\n"
692 1.23 isaki "1:\n"
693 1.23 isaki " move.l (%[src])+,(%[dst])+ ;\n"
694 1.23 isaki " move.l (%[src])+,(%[dst])+ ;\n"
695 1.23 isaki " dbra %[w],1b ;\n"
696 1.23 isaki
697 1.23 isaki " adda.l %[step8],%[src] ;\n"
698 1.23 isaki " adda.l %[step8],%[dst] ;\n"
699 1.23 isaki " dbra %[h],om_rascopy_single_LL ;\n"
700 1.23 isaki : /* output */
701 1.23 isaki [src] "+&a" (src),
702 1.23 isaki [dst] "+&a" (dst),
703 1.23 isaki [h] "+&d" (h),
704 1.23 isaki [w] "=&d" (w)
705 1.23 isaki : /* input */
706 1.23 isaki [wh] "r" (wh),
707 1.23 isaki [step8] "r" (step8)
708 1.23 isaki : /* clobbers */
709 1.23 isaki "memory"
710 1.23 isaki );
711 1.23 isaki #else
712 1.23 isaki wh--; /* to match to asm side */
713 1.23 isaki for (h = height_m1; h >= 0; h--) {
714 1.23 isaki uint32_t *s32 = (uint32_t *)src;
715 1.23 isaki uint32_t *d32 = (uint32_t *)dst;
716 1.23 isaki for (w = wh; w >= 0; w--) {
717 1.23 isaki *d32++ = *s32++;
718 1.23 isaki *d32++ = *s32++;
719 1.23 isaki }
720 1.23 isaki src = (uint8_t *)s32 + step8;
721 1.23 isaki dst = (uint8_t *)d32 + step8;
722 1.23 isaki }
723 1.23 isaki #endif
724 1.23 isaki
725 1.23 isaki if ((width & 0x3f) == 0) {
726 1.23 isaki /* transfer completed */
727 1.23 isaki return;
728 1.23 isaki }
729 1.1 nisimura
730 1.23 isaki /* rewind y for the next transfer */
731 1.23 isaki src -= height * step;
732 1.23 isaki dst -= height * step;
733 1.23 isaki }
734 1.23 isaki
735 1.23 isaki if ((width & 32) != 0) {
736 1.23 isaki /* Transfer one longword since an odd longword */
737 1.23 isaki #if USE_M68K_ASM
738 1.23 isaki h = height_m1;
739 1.23 isaki asm volatile("\n"
740 1.23 isaki "om_rascopy_single_L:\n"
741 1.23 isaki " move.l (%[src]),(%[dst]) ;\n"
742 1.23 isaki " adda.l %[step],%[src] ;\n"
743 1.23 isaki " adda.l %[step],%[dst] ;\n"
744 1.23 isaki " dbra %[h],om_rascopy_single_L ;\n"
745 1.23 isaki : /* output */
746 1.23 isaki [src] "+&a" (src),
747 1.23 isaki [dst] "+&a" (dst),
748 1.23 isaki [h] "+&d" (h)
749 1.23 isaki : /* input */
750 1.23 isaki [step] "r" (step)
751 1.23 isaki : /* clobbers */
752 1.23 isaki "memory"
753 1.23 isaki );
754 1.23 isaki #else
755 1.23 isaki for (h = height_m1; h >= 0; h--) {
756 1.23 isaki *(uint32_t *)dst = *(uint32_t *)src;
757 1.23 isaki dst += step;
758 1.23 isaki src += step;
759 1.23 isaki }
760 1.23 isaki #endif
761 1.1 nisimura
762 1.23 isaki if ((width & 0x1f) == 0) {
763 1.23 isaki /* transfer completed */
764 1.23 isaki return;
765 1.1 nisimura }
766 1.23 isaki
767 1.23 isaki /* rewind y for the next transfer */
768 1.23 isaki src += 4 - height * step;
769 1.23 isaki dst += 4 - height * step;
770 1.23 isaki }
771 1.23 isaki
772 1.23 isaki wl = width & 0x1f;
773 1.23 isaki /* wl > 0 at this point */
774 1.23 isaki
775 1.23 isaki /* Then, transfer residual bits */
776 1.23 isaki
777 1.23 isaki mask = ALL1BITS << (32 - wl);
778 1.23 isaki /*
779 1.23 isaki * The common ROP cannot be used here. Because the hardware doesn't
780 1.23 isaki * allow you to set the mask while keeping the ROP states.
781 1.23 isaki */
782 1.25 tsutsui for (plane = 0; plane < planecount; plane++) {
783 1.23 isaki om_set_rop(plane, rop[plane], mask);
784 1.23 isaki }
785 1.23 isaki
786 1.23 isaki #if USE_M68K_ASM
787 1.23 isaki h = height_m1;
788 1.23 isaki asm volatile("\n"
789 1.23 isaki "om_rascopy_single_bit:\n"
790 1.23 isaki " move.l (%[src]),(%[dst]) ;\n"
791 1.23 isaki " adda.l %[step],%[src] ;\n"
792 1.23 isaki " adda.l %[step],%[dst] ;\n"
793 1.23 isaki " dbra %[h],om_rascopy_single_bit ;\n"
794 1.23 isaki : /* output */
795 1.23 isaki [src] "+&a" (src),
796 1.23 isaki [dst] "+&a" (dst),
797 1.23 isaki [h] "+&d" (h)
798 1.23 isaki : /* input */
799 1.23 isaki [step] "r" (step)
800 1.23 isaki : /* clobbers */
801 1.23 isaki "memory"
802 1.23 isaki );
803 1.23 isaki #else
804 1.23 isaki for (h = height_m1; h >= 0; h--) {
805 1.23 isaki *(uint32_t *)dst = *(uint32_t *)src;
806 1.23 isaki dst += step;
807 1.23 isaki src += step;
808 1.23 isaki }
809 1.23 isaki #endif
810 1.23 isaki
811 1.25 tsutsui for (plane = 0; plane < planecount; plane++) {
812 1.23 isaki om_set_rop(plane, rop[plane], ALL1BITS);
813 1.1 nisimura }
814 1.1 nisimura }
815 1.1 nisimura
816 1.23 isaki /*
817 1.23 isaki * Multiple plane raster copy.
818 1.23 isaki * dst0: destination pointer in Plane0.
819 1.23 isaki * src0: source pointer in Plane0.
820 1.23 isaki * if y-forward, src0 > dst0, point to left-top.
821 1.23 isaki * if y-backward, src0 < dst0, point to left-bottom.
822 1.23 isaki * width: pixel width (must > 0)
823 1.23 isaki * height: pixel height (> 0 if forward, < 0 if backward)
824 1.23 isaki *
825 1.23 isaki * This function modifies(breaks) the planemask and ROPs.
826 1.23 isaki */
827 1.1 nisimura static void
828 1.23 isaki om4_rascopy_multi(uint8_t *dst0, uint8_t *src0, int16_t width, int16_t height)
829 1.16 tsutsui {
830 1.23 isaki uint8_t *dst1, *dst2, *dst3;
831 1.23 isaki int wh;
832 1.23 isaki int wl;
833 1.23 isaki int rewind;
834 1.23 isaki int step;
835 1.23 isaki uint32_t mask;
836 1.23 isaki int16_t height_m1;
837 1.23 isaki int16_t w, h;
838 1.23 isaki
839 1.23 isaki step = OMFB_STRIDE;
840 1.23 isaki
841 1.23 isaki /*
842 1.23 isaki * X direction is always forward (or ascend order) to use (An)+
843 1.23 isaki * addressing mode in asm.
844 1.23 isaki */
845 1.23 isaki
846 1.23 isaki /* Reverse order Y if backward copy */
847 1.23 isaki if (height < 0) {
848 1.23 isaki /* The sign is managed by step, height is always positive */
849 1.23 isaki step = -step;
850 1.23 isaki height = -height;
851 1.23 isaki }
852 1.23 isaki height_m1 = height - 1;
853 1.23 isaki
854 1.23 isaki dst1 = dst0 + OMFB_PLANEOFFS;
855 1.23 isaki dst2 = dst1 + OMFB_PLANEOFFS;
856 1.23 isaki dst3 = dst2 + OMFB_PLANEOFFS;
857 1.23 isaki
858 1.23 isaki /* First, transfer a rectangle consist of two longwords */
859 1.23 isaki wh = width >> 6;
860 1.23 isaki if (wh > 0) {
861 1.23 isaki int step8 = step - wh * 8;
862 1.23 isaki
863 1.23 isaki #if USE_M68K_ASM
864 1.23 isaki wh--; /* for dbra */
865 1.23 isaki h = height_m1;
866 1.23 isaki asm volatile("\n"
867 1.23 isaki "om4_rascopy_multi_LL:\n"
868 1.23 isaki " move.w %[wh],%[w] ;\n"
869 1.23 isaki "1:\n"
870 1.23 isaki /*
871 1.23 isaki * Optimized for 68030.
872 1.23 isaki *
873 1.23 isaki * On LUNA, the following is faster than any of
874 1.23 isaki * "MOVE.L (An)+,(An)+", "MOVE.L (An,Dn),(An,Dn)", or
875 1.23 isaki * "MOVEM.L", due to the relationship of instruction
876 1.23 isaki * overlaps and access waits.
877 1.23 isaki *
878 1.23 isaki * The head time of (An)+ as source operand is 0 and
879 1.23 isaki * the head time of ADDA instruction is 2. If the
880 1.23 isaki * previous instruction has some write wait cycles,
881 1.23 isaki * i.e., tail cycles, (An)+ as source operand cannot
882 1.23 isaki * overlap it but ADDA instruction can.
883 1.23 isaki */
884 1.23 isaki " move.l (%[src0]),(%[dst0])+ ;\n" /* P0 */
885 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
886 1.23 isaki " move.l (%[src0]),(%[dst1])+ ;\n" /* P1 */
887 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
888 1.23 isaki " move.l (%[src0]),(%[dst2])+ ;\n" /* P2 */
889 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
890 1.23 isaki " move.l (%[src0]),(%[dst3])+ ;\n" /* P3 */
891 1.23 isaki /* Expect an overlap, so don't use (An)+ */
892 1.23 isaki " addq.l #4,%[src0] ;\n"
893 1.23 isaki
894 1.23 isaki " move.l (%[src0]),(%[dst3])+ ;\n" /* P3 */
895 1.23 isaki " suba.l %[PLANEOFFS],%[src0] ;\n"
896 1.23 isaki " move.l (%[src0]),(%[dst2])+ ;\n" /* P2 */
897 1.23 isaki " suba.l %[PLANEOFFS],%[src0] ;\n"
898 1.23 isaki " move.l (%[src0]),(%[dst1])+ ;\n" /* P1 */
899 1.23 isaki " suba.l %[PLANEOFFS],%[src0] ;\n"
900 1.23 isaki " move.l (%[src0])+,(%[dst0])+ ;\n" /* P0 */
901 1.23 isaki " dbra %[w],1b ;\n"
902 1.23 isaki
903 1.23 isaki " adda.l %[step8],%[src0] ;\n"
904 1.23 isaki " adda.l %[step8],%[dst0] ;\n"
905 1.23 isaki " adda.l %[step8],%[dst1] ;\n"
906 1.23 isaki " adda.l %[step8],%[dst2] ;\n"
907 1.23 isaki " adda.l %[step8],%[dst3] ;\n"
908 1.23 isaki " dbra %[h],om4_rascopy_multi_LL ;\n"
909 1.23 isaki : /* output */
910 1.23 isaki [src0] "+&a" (src0),
911 1.23 isaki [dst0] "+&a" (dst0),
912 1.23 isaki [dst1] "+&a" (dst1),
913 1.23 isaki [dst2] "+&a" (dst2),
914 1.23 isaki [dst3] "+&a" (dst3),
915 1.23 isaki [h] "+&d" (h),
916 1.23 isaki [w] "=&d" (w)
917 1.23 isaki : /* input */
918 1.23 isaki [wh] "r" (wh),
919 1.23 isaki [PLANEOFFS] "r" (OMFB_PLANEOFFS),
920 1.23 isaki [step8] "r" (step8)
921 1.23 isaki : /* clobbers */
922 1.23 isaki "memory"
923 1.23 isaki );
924 1.23 isaki #else
925 1.23 isaki wh--; /* to match to asm side */
926 1.23 isaki for (h = height_m1; h >= 0; h--) {
927 1.23 isaki for (w = wh; w >= 0; w--) {
928 1.23 isaki *(uint32_t *)dst0 = *(uint32_t *)src0;
929 1.23 isaki dst0 += 4;
930 1.23 isaki src0 += OMFB_PLANEOFFS;
931 1.23 isaki *(uint32_t *)dst1 = *(uint32_t *)src0;
932 1.23 isaki dst1 += 4;
933 1.23 isaki src0 += OMFB_PLANEOFFS;
934 1.23 isaki *(uint32_t *)dst2 = *(uint32_t *)src0;
935 1.23 isaki dst2 += 4;
936 1.23 isaki src0 += OMFB_PLANEOFFS;
937 1.23 isaki *(uint32_t *)dst3 = *(uint32_t *)src0;
938 1.23 isaki dst3 += 4;
939 1.23 isaki src0 += 4;
940 1.23 isaki
941 1.23 isaki *(uint32_t *)dst3 = *(uint32_t *)src0;
942 1.23 isaki dst3 += 4;
943 1.23 isaki src0 -= OMFB_PLANEOFFS;
944 1.23 isaki *(uint32_t *)dst2 = *(uint32_t *)src0;
945 1.23 isaki dst2 += 4;
946 1.23 isaki src0 -= OMFB_PLANEOFFS;
947 1.23 isaki *(uint32_t *)dst1 = *(uint32_t *)src0;
948 1.23 isaki dst1 += 4;
949 1.23 isaki src0 -= OMFB_PLANEOFFS;
950 1.23 isaki *(uint32_t *)dst0 = *(uint32_t *)src0;
951 1.23 isaki dst0 += 4;
952 1.23 isaki src0 += 4;
953 1.23 isaki }
954 1.23 isaki src0 += step8;
955 1.23 isaki dst0 += step8;
956 1.23 isaki dst1 += step8;
957 1.23 isaki dst2 += step8;
958 1.23 isaki dst3 += step8;
959 1.23 isaki }
960 1.23 isaki #endif
961 1.23 isaki
962 1.23 isaki if ((width & 0x3f) == 0) {
963 1.23 isaki /* transfer completed */
964 1.23 isaki return;
965 1.23 isaki }
966 1.16 tsutsui
967 1.23 isaki /* rewind y for the next transfer */
968 1.23 isaki src0 -= height * step;
969 1.23 isaki dst0 -= height * step;
970 1.23 isaki dst1 -= height * step;
971 1.23 isaki dst2 -= height * step;
972 1.23 isaki dst3 -= height * step;
973 1.23 isaki }
974 1.23 isaki
975 1.23 isaki /* This rewind rewinds the plane, so Y order is irrelevant */
976 1.23 isaki rewind = OMFB_STRIDE - OMFB_PLANEOFFS * 3;
977 1.23 isaki
978 1.23 isaki if ((width & 32) != 0) {
979 1.23 isaki /* Transfer one longword since an odd longword */
980 1.23 isaki #if USE_M68K_ASM
981 1.23 isaki h = height_m1;
982 1.23 isaki asm volatile("\n"
983 1.23 isaki "om4_rascopy_multi_L:\n"
984 1.23 isaki " move.l (%[src0]),(%[dst0]) ;\n"
985 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
986 1.23 isaki " move.l (%[src0]),(%[dst1]) ;\n"
987 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
988 1.23 isaki " move.l (%[src0]),(%[dst2]) ;\n"
989 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
990 1.23 isaki " move.l (%[src0]),(%[dst3]) ;\n"
991 1.23 isaki " adda.l %[rewind],%[src0] ;\n"
992 1.23 isaki
993 1.23 isaki " adda.l %[step],%[dst0] ;\n"
994 1.23 isaki " adda.l %[step],%[dst1] ;\n"
995 1.23 isaki " adda.l %[step],%[dst2] ;\n"
996 1.23 isaki " adda.l %[step],%[dst3] ;\n"
997 1.23 isaki " dbra %[h],om4_rascopy_multi_L ;\n"
998 1.23 isaki : /* output */
999 1.23 isaki [src0] "+&a" (src0),
1000 1.23 isaki [dst0] "+&a" (dst0),
1001 1.23 isaki [dst1] "+&a" (dst1),
1002 1.23 isaki [dst2] "+&a" (dst2),
1003 1.23 isaki [dst3] "+&a" (dst3),
1004 1.23 isaki [h] "+&d" (h)
1005 1.23 isaki : /* input */
1006 1.23 isaki [PLANEOFFS] "r" (OMFB_PLANEOFFS),
1007 1.23 isaki [rewind] "r" (rewind),
1008 1.23 isaki [step] "r" (step)
1009 1.23 isaki : /* clobbers */
1010 1.23 isaki "memory"
1011 1.23 isaki );
1012 1.23 isaki #else
1013 1.23 isaki for (h = height_m1; h >= 0; h--) {
1014 1.23 isaki *(uint32_t *)dst0 = *(uint32_t *)src0;
1015 1.23 isaki src0 += OMFB_PLANEOFFS;
1016 1.23 isaki *(uint32_t *)dst1 = *(uint32_t *)src0;
1017 1.23 isaki src0 += OMFB_PLANEOFFS;
1018 1.23 isaki *(uint32_t *)dst2 = *(uint32_t *)src0;
1019 1.23 isaki src0 += OMFB_PLANEOFFS;
1020 1.23 isaki *(uint32_t *)dst3 = *(uint32_t *)src0;
1021 1.23 isaki src0 += rewind;
1022 1.23 isaki
1023 1.23 isaki dst0 += step;
1024 1.23 isaki dst1 += step;
1025 1.23 isaki dst2 += step;
1026 1.23 isaki dst3 += step;
1027 1.23 isaki }
1028 1.23 isaki #endif
1029 1.16 tsutsui
1030 1.23 isaki if ((width & 0x1f) == 0) {
1031 1.23 isaki /* transfer completed */
1032 1.23 isaki return;
1033 1.16 tsutsui }
1034 1.23 isaki
1035 1.23 isaki /* rewind y for the next transfer */
1036 1.23 isaki src0 += 4 - height * step;
1037 1.23 isaki dst0 += 4 - height * step;
1038 1.23 isaki dst1 += 4 - height * step;
1039 1.23 isaki dst2 += 4 - height * step;
1040 1.23 isaki dst3 += 4 - height * step;
1041 1.23 isaki }
1042 1.23 isaki
1043 1.23 isaki wl = width & 0x1f;
1044 1.23 isaki /* wl > 0 at this point */
1045 1.23 isaki
1046 1.23 isaki /* Then, transfer residual bits */
1047 1.23 isaki
1048 1.23 isaki mask = ALL1BITS << (32 - wl);
1049 1.23 isaki om_set_planemask(hwplanemask);
1050 1.23 isaki om_set_rop_curplane(ROP_THROUGH, mask);
1051 1.23 isaki
1052 1.23 isaki #if USE_M68K_ASM
1053 1.23 isaki h = height_m1;
1054 1.23 isaki asm volatile("\n"
1055 1.23 isaki "om4_rascopy_multi_bit:\n"
1056 1.23 isaki " move.l (%[src0]),(%[dst0]) ;\n"
1057 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
1058 1.23 isaki " move.l (%[src0]),(%[dst1]) ;\n"
1059 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
1060 1.23 isaki " move.l (%[src0]),(%[dst2]) ;\n"
1061 1.23 isaki " adda.l %[PLANEOFFS],%[src0] ;\n"
1062 1.23 isaki " move.l (%[src0]),(%[dst3]) ;\n"
1063 1.23 isaki " adda.l %[rewind],%[src0] ;\n"
1064 1.23 isaki
1065 1.23 isaki " adda.l %[step],%[dst0] ;\n"
1066 1.23 isaki " adda.l %[step],%[dst1] ;\n"
1067 1.23 isaki " adda.l %[step],%[dst2] ;\n"
1068 1.23 isaki " adda.l %[step],%[dst3] ;\n"
1069 1.23 isaki " dbra %[h],om4_rascopy_multi_bit ;\n"
1070 1.23 isaki : /* output */
1071 1.23 isaki [src0] "+&a" (src0),
1072 1.23 isaki [dst0] "+&a" (dst0),
1073 1.23 isaki [dst1] "+&a" (dst1),
1074 1.23 isaki [dst2] "+&a" (dst2),
1075 1.23 isaki [dst3] "+&a" (dst3),
1076 1.23 isaki [h] "+&d" (h)
1077 1.23 isaki : /* input */
1078 1.23 isaki [PLANEOFFS] "r" (OMFB_PLANEOFFS),
1079 1.23 isaki [rewind] "r" (rewind),
1080 1.23 isaki [step] "r" (step)
1081 1.23 isaki : /* clobbers */
1082 1.23 isaki "memory"
1083 1.23 isaki );
1084 1.23 isaki #else
1085 1.23 isaki for (h = height_m1; h >= 0; h--) {
1086 1.23 isaki *(uint32_t *)dst0 = *(uint32_t *)src0;
1087 1.23 isaki src0 += OMFB_PLANEOFFS;
1088 1.23 isaki *(uint32_t *)dst1 = *(uint32_t *)src0;
1089 1.23 isaki src0 += OMFB_PLANEOFFS;
1090 1.23 isaki *(uint32_t *)dst2 = *(uint32_t *)src0;
1091 1.23 isaki src0 += OMFB_PLANEOFFS;
1092 1.23 isaki *(uint32_t *)dst3 = *(uint32_t *)src0;
1093 1.23 isaki src0 += rewind;
1094 1.23 isaki
1095 1.23 isaki dst0 += step;
1096 1.23 isaki dst1 += step;
1097 1.23 isaki dst2 += step;
1098 1.23 isaki dst3 += step;
1099 1.16 tsutsui }
1100 1.23 isaki #endif
1101 1.23 isaki om_reset_planemask_and_rop();
1102 1.16 tsutsui }
1103 1.16 tsutsui
1104 1.16 tsutsui static void
1105 1.16 tsutsui om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1106 1.1 nisimura {
1107 1.13 tsutsui struct rasops_info *ri = cookie;
1108 1.13 tsutsui uint8_t *p, *q;
1109 1.1 nisimura int scanspan, offset, srcy, height, width, w;
1110 1.13 tsutsui uint32_t rmask;
1111 1.13 tsutsui
1112 1.13 tsutsui scanspan = ri->ri_stride;
1113 1.13 tsutsui height = ri->ri_font->fontheight * nrows;
1114 1.13 tsutsui offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight;
1115 1.13 tsutsui srcy = ri->ri_font->fontheight * srcrow;
1116 1.1 nisimura if (srcrow < dstrow && srcrow + nrows > dstrow) {
1117 1.1 nisimura scanspan = -scanspan;
1118 1.14 tsutsui srcy = srcy + height - 1;
1119 1.1 nisimura }
1120 1.1 nisimura
1121 1.13 tsutsui p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride;
1122 1.13 tsutsui w = ri->ri_emuwidth;
1123 1.1 nisimura width = w;
1124 1.1 nisimura rmask = ALL1BITS << (-width & ALIGNMASK);
1125 1.1 nisimura q = p;
1126 1.1 nisimura while (height > 0) {
1127 1.19 tsutsui *P0(p + offset) = *P0(p); /* always aligned */
1128 1.1 nisimura width -= 2 * BLITWIDTH;
1129 1.1 nisimura while (width > 0) {
1130 1.1 nisimura p += BYTESDONE;
1131 1.19 tsutsui *P0(p + offset) = *P0(p);
1132 1.1 nisimura width -= BLITWIDTH;
1133 1.1 nisimura }
1134 1.1 nisimura p += BYTESDONE;
1135 1.19 tsutsui *P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask);
1136 1.1 nisimura
1137 1.1 nisimura p = (q += scanspan);
1138 1.1 nisimura width = w;
1139 1.1 nisimura height--;
1140 1.1 nisimura }
1141 1.1 nisimura }
1142 1.1 nisimura
1143 1.1 nisimura static void
1144 1.16 tsutsui om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1145 1.16 tsutsui {
1146 1.16 tsutsui struct rasops_info *ri = cookie;
1147 1.23 isaki uint8_t *src, *dst;
1148 1.23 isaki int width, rowheight;
1149 1.25 tsutsui int planecount;
1150 1.23 isaki int ptrstep, rowstep;
1151 1.23 isaki int srcplane;
1152 1.23 isaki int i;
1153 1.23 isaki int r;
1154 1.23 isaki uint8_t rop[OMFB_MAX_PLANECOUNT];
1155 1.23 isaki
1156 1.23 isaki width = ri->ri_emuwidth;
1157 1.23 isaki rowheight = ri->ri_font->fontheight;
1158 1.25 tsutsui planecount = ri->ri_depth;
1159 1.23 isaki src = (uint8_t *)ri->ri_bits + srcrow * rowheight * ri->ri_stride;
1160 1.23 isaki dst = (uint8_t *)ri->ri_bits + dstrow * rowheight * ri->ri_stride;
1161 1.23 isaki
1162 1.23 isaki if (nrows <= 0 || srcrow == dstrow) {
1163 1.23 isaki return;
1164 1.23 isaki } else if (srcrow < dstrow) {
1165 1.23 isaki /* y-backward */
1166 1.16 tsutsui
1167 1.23 isaki /* select the bottom raster of the bottom row */
1168 1.23 isaki srcrow += nrows - 1;
1169 1.23 isaki dstrow += nrows - 1;
1170 1.23 isaki src += nrows * rowheight * ri->ri_stride - ri->ri_stride;
1171 1.23 isaki dst += nrows * rowheight * ri->ri_stride - ri->ri_stride;
1172 1.23 isaki rowstep = -1;
1173 1.23 isaki rowheight = -rowheight;
1174 1.23 isaki } else {
1175 1.23 isaki /* y-forward */
1176 1.23 isaki rowstep = 1;
1177 1.16 tsutsui }
1178 1.23 isaki ptrstep = ri->ri_stride * rowheight;
1179 1.23 isaki
1180 1.23 isaki om_set_planemask(hwplanemask);
1181 1.16 tsutsui
1182 1.23 isaki srcplane = 0;
1183 1.23 isaki while (nrows > 0) {
1184 1.23 isaki r = 1;
1185 1.23 isaki if (rowattr[srcrow].ismulti == false &&
1186 1.23 isaki rowattr[srcrow].fg == rowattr[srcrow].bg &&
1187 1.23 isaki rowattr[srcrow].all == rowattr[dstrow].all) {
1188 1.23 isaki goto skip;
1189 1.23 isaki }
1190 1.23 isaki
1191 1.23 isaki /* count the number of rows with the same attributes */
1192 1.23 isaki for (; r < nrows; r++) {
1193 1.23 isaki if (rowattr[srcrow + r * rowstep].all !=
1194 1.23 isaki rowattr[srcrow].all) {
1195 1.23 isaki break;
1196 1.23 isaki }
1197 1.16 tsutsui }
1198 1.23 isaki /* r is the number of rows including srcrow itself */
1199 1.23 isaki
1200 1.23 isaki if (rowattr[srcrow].ismulti) {
1201 1.23 isaki /*
1202 1.23 isaki * src,dst point to the common plane. src0,dst0 will
1203 1.23 isaki * point to the same offset in plane0 because plane0
1204 1.23 isaki * is placed just after the common plane.
1205 1.23 isaki */
1206 1.23 isaki uint8_t *src0 = src + OMFB_PLANEOFFS;
1207 1.23 isaki uint8_t *dst0 = dst + OMFB_PLANEOFFS;
1208 1.23 isaki om_set_rop_curplane(ROP_THROUGH, ALL1BITS);
1209 1.23 isaki om4_rascopy_multi(dst0, src0, width, rowheight * r);
1210 1.23 isaki } else {
1211 1.23 isaki uint8_t *srcp;
1212 1.23 isaki uint8_t fg;
1213 1.23 isaki uint8_t bg;
1214 1.23 isaki uint8_t set;
1215 1.23 isaki
1216 1.23 isaki fg = rowattr[srcrow].fg;
1217 1.23 isaki bg = rowattr[srcrow].bg;
1218 1.23 isaki set = fg ^ bg;
1219 1.23 isaki if (set == 0) {
1220 1.23 isaki /* use fg since both can be acceptable */
1221 1.23 isaki set = fg;
1222 1.23 isaki } else if ((set & fg) != 0) {
1223 1.23 isaki /*
1224 1.23 isaki * set is the set of bits that set in fg and
1225 1.23 isaki * cleared in bg.
1226 1.23 isaki */
1227 1.23 isaki set &= fg;
1228 1.23 isaki } else {
1229 1.23 isaki /*
1230 1.23 isaki * otherwise, set is the set of bits that
1231 1.23 isaki * (probably) set in bg and cleared in fg.
1232 1.23 isaki */
1233 1.23 isaki uint8_t tmp;
1234 1.23 isaki
1235 1.23 isaki set &= bg;
1236 1.23 isaki /* and swap fg and bg */
1237 1.23 isaki tmp = fg;
1238 1.23 isaki fg = bg;
1239 1.23 isaki bg = tmp;
1240 1.23 isaki }
1241 1.23 isaki
1242 1.25 tsutsui for (i = 0; i < planecount; i++) {
1243 1.23 isaki int t = om_fgbg2rop(fg, bg);
1244 1.23 isaki rop[i] = t;
1245 1.23 isaki om_set_rop(i, rop[i], ALL1BITS);
1246 1.23 isaki fg >>= 1;
1247 1.23 isaki bg >>= 1;
1248 1.23 isaki }
1249 1.16 tsutsui
1250 1.23 isaki /*
1251 1.23 isaki * If any bit in 'set' is set, any of them can be used.
1252 1.23 isaki * If all bits in 'set' are cleared, use plane 0.
1253 1.23 isaki * srcplane is the plane that fg is set and bg is
1254 1.23 isaki * cleared.
1255 1.23 isaki */
1256 1.23 isaki srcplane = (set != 0) ? (31 - __builtin_clz(set)) : 0;
1257 1.23 isaki
1258 1.23 isaki srcp = src + OMFB_PLANEOFFS + srcplane * OMFB_PLANEOFFS;
1259 1.25 tsutsui om_rascopy_single(planecount, dst, srcp,
1260 1.25 tsutsui width, rowheight * r, rop);
1261 1.23 isaki }
1262 1.23 isaki
1263 1.23 isaki skip:
1264 1.23 isaki for (i = 0; i < r; i++) {
1265 1.23 isaki rowattr[dstrow] = rowattr[srcrow];
1266 1.23 isaki
1267 1.23 isaki srcrow += rowstep;
1268 1.23 isaki dstrow += rowstep;
1269 1.23 isaki src += ptrstep;
1270 1.23 isaki dst += ptrstep;
1271 1.23 isaki nrows--;
1272 1.23 isaki }
1273 1.16 tsutsui }
1274 1.16 tsutsui }
1275 1.16 tsutsui
1276 1.23 isaki /*
1277 1.23 isaki * XXX om{1,4}_copycols can be merged, but these are not frequently executed
1278 1.23 isaki * and have low execution costs. So I'm putting it off for now.
1279 1.23 isaki */
1280 1.23 isaki
1281 1.16 tsutsui static void
1282 1.16 tsutsui om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
1283 1.16 tsutsui {
1284 1.16 tsutsui struct rasops_info *ri = cookie;
1285 1.16 tsutsui uint8_t *sp, *dp, *sq, *dq, *basep;
1286 1.16 tsutsui int scanspan, height, w, y, srcx, dstx;
1287 1.16 tsutsui int sb, eb, db, sboff, full, cnt, lnum, rnum;
1288 1.16 tsutsui uint32_t lmask, rmask, tmp;
1289 1.16 tsutsui bool sbover;
1290 1.16 tsutsui
1291 1.16 tsutsui scanspan = ri->ri_stride;
1292 1.16 tsutsui y = ri->ri_font->fontheight * startrow;
1293 1.16 tsutsui srcx = ri->ri_font->fontwidth * srccol;
1294 1.16 tsutsui dstx = ri->ri_font->fontwidth * dstcol;
1295 1.16 tsutsui height = ri->ri_font->fontheight;
1296 1.16 tsutsui w = ri->ri_font->fontwidth * ncols;
1297 1.16 tsutsui basep = (uint8_t *)ri->ri_bits + y * scanspan;
1298 1.16 tsutsui
1299 1.16 tsutsui sb = srcx & ALIGNMASK;
1300 1.16 tsutsui db = dstx & ALIGNMASK;
1301 1.16 tsutsui
1302 1.23 isaki om_reset_planemask_and_rop();
1303 1.23 isaki
1304 1.16 tsutsui if (db + w <= BLITWIDTH) {
1305 1.16 tsutsui /* Destination is contained within a single word */
1306 1.16 tsutsui sp = basep + (srcx / 32) * 4;
1307 1.16 tsutsui dp = basep + (dstx / 32) * 4;
1308 1.16 tsutsui
1309 1.16 tsutsui while (height > 0) {
1310 1.16 tsutsui GETBITS(P0(sp), sb, w, tmp);
1311 1.16 tsutsui PUTBITS(tmp, db, w, P0(dp));
1312 1.16 tsutsui dp += scanspan;
1313 1.16 tsutsui sp += scanspan;
1314 1.16 tsutsui height--;
1315 1.16 tsutsui }
1316 1.16 tsutsui return;
1317 1.16 tsutsui }
1318 1.16 tsutsui
1319 1.16 tsutsui lmask = (db == 0) ? 0 : ALL1BITS >> db;
1320 1.16 tsutsui eb = (db + w) & ALIGNMASK;
1321 1.22 isaki rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
1322 1.16 tsutsui lnum = (32 - db) & ALIGNMASK;
1323 1.16 tsutsui rnum = (dstx + w) & ALIGNMASK;
1324 1.16 tsutsui
1325 1.16 tsutsui if (lmask != 0)
1326 1.16 tsutsui full = (w - (32 - db)) / 32;
1327 1.16 tsutsui else
1328 1.16 tsutsui full = w / 32;
1329 1.16 tsutsui
1330 1.16 tsutsui sbover = (sb + lnum) >= 32;
1331 1.16 tsutsui
1332 1.16 tsutsui if (dstcol < srccol || srccol + ncols < dstcol) {
1333 1.16 tsutsui /* copy forward (left-to-right) */
1334 1.16 tsutsui sp = basep + (srcx / 32) * 4;
1335 1.16 tsutsui dp = basep + (dstx / 32) * 4;
1336 1.16 tsutsui
1337 1.16 tsutsui if (lmask != 0) {
1338 1.16 tsutsui sboff = sb + lnum;
1339 1.16 tsutsui if (sboff >= 32)
1340 1.16 tsutsui sboff -= 32;
1341 1.23 isaki } else {
1342 1.16 tsutsui sboff = sb;
1343 1.23 isaki }
1344 1.16 tsutsui
1345 1.16 tsutsui sq = sp;
1346 1.16 tsutsui dq = dp;
1347 1.16 tsutsui while (height > 0) {
1348 1.16 tsutsui if (lmask != 0) {
1349 1.16 tsutsui GETBITS(P0(sp), sb, lnum, tmp);
1350 1.16 tsutsui PUTBITS(tmp, db, lnum, P0(dp));
1351 1.16 tsutsui dp += BYTESDONE;
1352 1.16 tsutsui if (sbover)
1353 1.16 tsutsui sp += BYTESDONE;
1354 1.16 tsutsui }
1355 1.16 tsutsui
1356 1.16 tsutsui for (cnt = full; cnt; cnt--) {
1357 1.16 tsutsui GETBITS(P0(sp), sboff, 32, tmp);
1358 1.19 tsutsui *P0(dp) = tmp;
1359 1.16 tsutsui sp += BYTESDONE;
1360 1.16 tsutsui dp += BYTESDONE;
1361 1.16 tsutsui }
1362 1.16 tsutsui
1363 1.16 tsutsui if (rmask != 0) {
1364 1.16 tsutsui GETBITS(P0(sp), sboff, rnum, tmp);
1365 1.16 tsutsui PUTBITS(tmp, 0, rnum, P0(dp));
1366 1.16 tsutsui }
1367 1.16 tsutsui
1368 1.16 tsutsui sp = (sq += scanspan);
1369 1.16 tsutsui dp = (dq += scanspan);
1370 1.16 tsutsui height--;
1371 1.16 tsutsui }
1372 1.16 tsutsui } else {
1373 1.16 tsutsui /* copy backward (right-to-left) */
1374 1.16 tsutsui sp = basep + ((srcx + w) / 32) * 4;
1375 1.16 tsutsui dp = basep + ((dstx + w) / 32) * 4;
1376 1.16 tsutsui
1377 1.16 tsutsui sboff = (srcx + w) & ALIGNMASK;
1378 1.16 tsutsui sboff -= rnum;
1379 1.16 tsutsui if (sboff < 0) {
1380 1.16 tsutsui sp -= BYTESDONE;
1381 1.16 tsutsui sboff += 32;
1382 1.16 tsutsui }
1383 1.16 tsutsui
1384 1.16 tsutsui sq = sp;
1385 1.16 tsutsui dq = dp;
1386 1.16 tsutsui while (height > 0) {
1387 1.16 tsutsui if (rnum != 0) {
1388 1.16 tsutsui GETBITS(P0(sp), sboff, rnum, tmp);
1389 1.16 tsutsui PUTBITS(tmp, 0, rnum, P0(dp));
1390 1.16 tsutsui }
1391 1.16 tsutsui
1392 1.16 tsutsui for (cnt = full; cnt; cnt--) {
1393 1.16 tsutsui sp -= BYTESDONE;
1394 1.16 tsutsui dp -= BYTESDONE;
1395 1.16 tsutsui GETBITS(P0(sp), sboff, 32, tmp);
1396 1.19 tsutsui *P0(dp) = tmp;
1397 1.16 tsutsui }
1398 1.16 tsutsui
1399 1.16 tsutsui if (lmask != 0) {
1400 1.16 tsutsui if (sbover)
1401 1.16 tsutsui sp -= BYTESDONE;
1402 1.16 tsutsui dp -= BYTESDONE;
1403 1.16 tsutsui GETBITS(P0(sp), sb, lnum, tmp);
1404 1.16 tsutsui PUTBITS(tmp, db, lnum, P0(dp));
1405 1.16 tsutsui }
1406 1.16 tsutsui
1407 1.16 tsutsui sp = (sq += scanspan);
1408 1.16 tsutsui dp = (dq += scanspan);
1409 1.16 tsutsui height--;
1410 1.16 tsutsui }
1411 1.16 tsutsui }
1412 1.16 tsutsui }
1413 1.16 tsutsui
1414 1.16 tsutsui static void
1415 1.16 tsutsui om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols)
1416 1.1 nisimura {
1417 1.13 tsutsui struct rasops_info *ri = cookie;
1418 1.15 tsutsui uint8_t *sp, *dp, *sq, *dq, *basep;
1419 1.15 tsutsui int scanspan, height, w, y, srcx, dstx;
1420 1.15 tsutsui int sb, eb, db, sboff, full, cnt, lnum, rnum;
1421 1.15 tsutsui uint32_t lmask, rmask, tmp;
1422 1.15 tsutsui bool sbover;
1423 1.1 nisimura
1424 1.13 tsutsui scanspan = ri->ri_stride;
1425 1.13 tsutsui y = ri->ri_font->fontheight * startrow;
1426 1.13 tsutsui srcx = ri->ri_font->fontwidth * srccol;
1427 1.13 tsutsui dstx = ri->ri_font->fontwidth * dstcol;
1428 1.13 tsutsui height = ri->ri_font->fontheight;
1429 1.13 tsutsui w = ri->ri_font->fontwidth * ncols;
1430 1.13 tsutsui basep = (uint8_t *)ri->ri_bits + y * scanspan;
1431 1.1 nisimura
1432 1.15 tsutsui sb = srcx & ALIGNMASK;
1433 1.15 tsutsui db = dstx & ALIGNMASK;
1434 1.1 nisimura
1435 1.23 isaki om_reset_planemask_and_rop();
1436 1.23 isaki
1437 1.15 tsutsui if (db + w <= BLITWIDTH) {
1438 1.15 tsutsui /* Destination is contained within a single word */
1439 1.15 tsutsui sp = basep + (srcx / 32) * 4;
1440 1.15 tsutsui dp = basep + (dstx / 32) * 4;
1441 1.1 nisimura
1442 1.1 nisimura while (height > 0) {
1443 1.16 tsutsui GETBITS(P0(sp), sb, w, tmp);
1444 1.16 tsutsui PUTBITS(tmp, db, w, P0(dp));
1445 1.16 tsutsui GETBITS(P1(sp), sb, w, tmp);
1446 1.16 tsutsui PUTBITS(tmp, db, w, P1(dp));
1447 1.16 tsutsui GETBITS(P2(sp), sb, w, tmp);
1448 1.16 tsutsui PUTBITS(tmp, db, w, P2(dp));
1449 1.16 tsutsui GETBITS(P3(sp), sb, w, tmp);
1450 1.16 tsutsui PUTBITS(tmp, db, w, P3(dp));
1451 1.1 nisimura dp += scanspan;
1452 1.1 nisimura sp += scanspan;
1453 1.1 nisimura height--;
1454 1.1 nisimura }
1455 1.15 tsutsui return;
1456 1.1 nisimura }
1457 1.1 nisimura
1458 1.15 tsutsui lmask = (db == 0) ? 0 : ALL1BITS >> db;
1459 1.15 tsutsui eb = (db + w) & ALIGNMASK;
1460 1.22 isaki rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb);
1461 1.15 tsutsui lnum = (32 - db) & ALIGNMASK;
1462 1.15 tsutsui rnum = (dstx + w) & ALIGNMASK;
1463 1.15 tsutsui
1464 1.15 tsutsui if (lmask != 0)
1465 1.15 tsutsui full = (w - (32 - db)) / 32;
1466 1.15 tsutsui else
1467 1.15 tsutsui full = w / 32;
1468 1.15 tsutsui
1469 1.15 tsutsui sbover = (sb + lnum) >= 32;
1470 1.15 tsutsui
1471 1.15 tsutsui if (dstcol < srccol || srccol + ncols < dstcol) {
1472 1.15 tsutsui /* copy forward (left-to-right) */
1473 1.15 tsutsui sp = basep + (srcx / 32) * 4;
1474 1.15 tsutsui dp = basep + (dstx / 32) * 4;
1475 1.15 tsutsui
1476 1.15 tsutsui if (lmask != 0) {
1477 1.15 tsutsui sboff = sb + lnum;
1478 1.15 tsutsui if (sboff >= 32)
1479 1.15 tsutsui sboff -= 32;
1480 1.23 isaki } else {
1481 1.15 tsutsui sboff = sb;
1482 1.23 isaki }
1483 1.15 tsutsui
1484 1.15 tsutsui sq = sp;
1485 1.15 tsutsui dq = dp;
1486 1.1 nisimura while (height > 0) {
1487 1.15 tsutsui if (lmask != 0) {
1488 1.16 tsutsui GETBITS(P0(sp), sb, lnum, tmp);
1489 1.16 tsutsui PUTBITS(tmp, db, lnum, P0(dp));
1490 1.16 tsutsui GETBITS(P1(sp), sb, lnum, tmp);
1491 1.16 tsutsui PUTBITS(tmp, db, lnum, P1(dp));
1492 1.16 tsutsui GETBITS(P2(sp), sb, lnum, tmp);
1493 1.16 tsutsui PUTBITS(tmp, db, lnum, P2(dp));
1494 1.16 tsutsui GETBITS(P3(sp), sb, lnum, tmp);
1495 1.16 tsutsui PUTBITS(tmp, db, lnum, P3(dp));
1496 1.15 tsutsui dp += BYTESDONE;
1497 1.15 tsutsui if (sbover)
1498 1.15 tsutsui sp += BYTESDONE;
1499 1.15 tsutsui }
1500 1.15 tsutsui
1501 1.15 tsutsui for (cnt = full; cnt; cnt--) {
1502 1.16 tsutsui GETBITS(P0(sp), sboff, 32, tmp);
1503 1.19 tsutsui *P0(dp) = tmp;
1504 1.16 tsutsui GETBITS(P1(sp), sboff, 32, tmp);
1505 1.19 tsutsui *P1(dp) = tmp;
1506 1.16 tsutsui GETBITS(P2(sp), sboff, 32, tmp);
1507 1.19 tsutsui *P2(dp) = tmp;
1508 1.16 tsutsui GETBITS(P3(sp), sboff, 32, tmp);
1509 1.19 tsutsui *P3(dp) = tmp;
1510 1.1 nisimura sp += BYTESDONE;
1511 1.1 nisimura dp += BYTESDONE;
1512 1.1 nisimura }
1513 1.15 tsutsui
1514 1.15 tsutsui if (rmask != 0) {
1515 1.16 tsutsui GETBITS(P0(sp), sboff, rnum, tmp);
1516 1.16 tsutsui PUTBITS(tmp, 0, rnum, P0(dp));
1517 1.16 tsutsui GETBITS(P1(sp), sboff, rnum, tmp);
1518 1.16 tsutsui PUTBITS(tmp, 0, rnum, P1(dp));
1519 1.16 tsutsui GETBITS(P2(sp), sboff, rnum, tmp);
1520 1.16 tsutsui PUTBITS(tmp, 0, rnum, P2(dp));
1521 1.16 tsutsui GETBITS(P3(sp), sboff, rnum, tmp);
1522 1.16 tsutsui PUTBITS(tmp, 0, rnum, P3(dp));
1523 1.15 tsutsui }
1524 1.15 tsutsui
1525 1.1 nisimura sp = (sq += scanspan);
1526 1.1 nisimura dp = (dq += scanspan);
1527 1.1 nisimura height--;
1528 1.1 nisimura }
1529 1.15 tsutsui } else {
1530 1.15 tsutsui /* copy backward (right-to-left) */
1531 1.15 tsutsui sp = basep + ((srcx + w) / 32) * 4;
1532 1.15 tsutsui dp = basep + ((dstx + w) / 32) * 4;
1533 1.15 tsutsui
1534 1.15 tsutsui sboff = (srcx + w) & ALIGNMASK;
1535 1.15 tsutsui sboff -= rnum;
1536 1.15 tsutsui if (sboff < 0) {
1537 1.15 tsutsui sp -= BYTESDONE;
1538 1.15 tsutsui sboff += 32;
1539 1.15 tsutsui }
1540 1.15 tsutsui
1541 1.15 tsutsui sq = sp;
1542 1.15 tsutsui dq = dp;
1543 1.1 nisimura while (height > 0) {
1544 1.15 tsutsui if (rnum != 0) {
1545 1.16 tsutsui GETBITS(P0(sp), sboff, rnum, tmp);
1546 1.16 tsutsui PUTBITS(tmp, 0, rnum, P0(dp));
1547 1.16 tsutsui GETBITS(P1(sp), sboff, rnum, tmp);
1548 1.16 tsutsui PUTBITS(tmp, 0, rnum, P1(dp));
1549 1.16 tsutsui GETBITS(P2(sp), sboff, rnum, tmp);
1550 1.16 tsutsui PUTBITS(tmp, 0, rnum, P2(dp));
1551 1.16 tsutsui GETBITS(P3(sp), sboff, rnum, tmp);
1552 1.16 tsutsui PUTBITS(tmp, 0, rnum, P3(dp));
1553 1.15 tsutsui }
1554 1.15 tsutsui
1555 1.15 tsutsui for (cnt = full; cnt; cnt--) {
1556 1.1 nisimura sp -= BYTESDONE;
1557 1.1 nisimura dp -= BYTESDONE;
1558 1.16 tsutsui GETBITS(P0(sp), sboff, 32, tmp);
1559 1.19 tsutsui *P0(dp) = tmp;
1560 1.16 tsutsui GETBITS(P1(sp), sboff, 32, tmp);
1561 1.19 tsutsui *P1(dp) = tmp;
1562 1.16 tsutsui GETBITS(P2(sp), sboff, 32, tmp);
1563 1.19 tsutsui *P2(dp) = tmp;
1564 1.16 tsutsui GETBITS(P3(sp), sboff, 32, tmp);
1565 1.19 tsutsui *P3(dp) = tmp;
1566 1.15 tsutsui }
1567 1.15 tsutsui
1568 1.15 tsutsui if (lmask != 0) {
1569 1.15 tsutsui if (sbover)
1570 1.15 tsutsui sp -= BYTESDONE;
1571 1.15 tsutsui dp -= BYTESDONE;
1572 1.16 tsutsui GETBITS(P0(sp), sb, lnum, tmp);
1573 1.16 tsutsui PUTBITS(tmp, db, lnum, P0(dp));
1574 1.16 tsutsui GETBITS(P1(sp), sb, lnum, tmp);
1575 1.16 tsutsui PUTBITS(tmp, db, lnum, P1(dp));
1576 1.16 tsutsui GETBITS(P2(sp), sb, lnum, tmp);
1577 1.16 tsutsui PUTBITS(tmp, db, lnum, P2(dp));
1578 1.16 tsutsui GETBITS(P3(sp), sb, lnum, tmp);
1579 1.16 tsutsui PUTBITS(tmp, db, lnum, P3(dp));
1580 1.1 nisimura }
1581 1.1 nisimura
1582 1.1 nisimura sp = (sq += scanspan);
1583 1.1 nisimura dp = (dq += scanspan);
1584 1.1 nisimura height--;
1585 1.1 nisimura }
1586 1.1 nisimura }
1587 1.1 nisimura }
1588 1.1 nisimura
1589 1.1 nisimura /*
1590 1.1 nisimura * Map a character.
1591 1.1 nisimura */
1592 1.1 nisimura static int
1593 1.8 dsl om_mapchar(void *cookie, int c, u_int *cp)
1594 1.1 nisimura {
1595 1.13 tsutsui struct rasops_info *ri = cookie;
1596 1.13 tsutsui struct wsdisplay_font *wf = ri->ri_font;
1597 1.11 tsutsui
1598 1.13 tsutsui if (wf->encoding != WSDISPLAY_FONTENC_ISO) {
1599 1.13 tsutsui c = wsfont_map_unichar(wf, c);
1600 1.13 tsutsui
1601 1.13 tsutsui if (c < 0)
1602 1.13 tsutsui goto fail;
1603 1.1 nisimura }
1604 1.13 tsutsui if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars))
1605 1.13 tsutsui goto fail;
1606 1.13 tsutsui
1607 1.13 tsutsui *cp = c;
1608 1.13 tsutsui return 5;
1609 1.13 tsutsui
1610 1.13 tsutsui fail:
1611 1.1 nisimura *cp = ' ';
1612 1.11 tsutsui return 0;
1613 1.1 nisimura }
1614 1.1 nisimura
1615 1.1 nisimura /*
1616 1.1 nisimura * Position|{enable|disable} the cursor at the specified location.
1617 1.1 nisimura */
1618 1.1 nisimura static void
1619 1.23 isaki om_cursor(void *cookie, int on, int row, int col)
1620 1.1 nisimura {
1621 1.13 tsutsui struct rasops_info *ri = cookie;
1622 1.23 isaki int startx;
1623 1.23 isaki int width;
1624 1.23 isaki int height;
1625 1.23 isaki int sh, sl;
1626 1.23 isaki int y;
1627 1.23 isaki int scanspan;
1628 1.5 tsutsui uint8_t *p;
1629 1.1 nisimura
1630 1.1 nisimura if (!on) {
1631 1.1 nisimura /* make sure it's on */
1632 1.13 tsutsui if ((ri->ri_flg & RI_CURSOR) == 0)
1633 1.1 nisimura return;
1634 1.1 nisimura
1635 1.13 tsutsui row = ri->ri_crow;
1636 1.13 tsutsui col = ri->ri_ccol;
1637 1.1 nisimura } else {
1638 1.1 nisimura /* unpaint the old copy. */
1639 1.13 tsutsui ri->ri_crow = row;
1640 1.13 tsutsui ri->ri_ccol = col;
1641 1.1 nisimura }
1642 1.1 nisimura
1643 1.13 tsutsui scanspan = ri->ri_stride;
1644 1.13 tsutsui y = ri->ri_font->fontheight * row;
1645 1.13 tsutsui startx = ri->ri_font->fontwidth * col;
1646 1.23 isaki width = ri->ri_font->fontwidth;
1647 1.13 tsutsui height = ri->ri_font->fontheight;
1648 1.23 isaki sh = startx >> 5;
1649 1.23 isaki sl = startx & 0x1f;
1650 1.23 isaki p = (uint8_t *)ri->ri_bits + y * scanspan + sh * 4;
1651 1.1 nisimura
1652 1.23 isaki /* ROP_INV2 ignores data from MPU and inverts the current VRAM data */
1653 1.23 isaki om_fill(hwplanemask, ROP_INV2, p, sl, scanspan, 0, width, height);
1654 1.19 tsutsui
1655 1.16 tsutsui ri->ri_flg ^= RI_CURSOR;
1656 1.19 tsutsui
1657 1.23 isaki /* reset mask value */
1658 1.23 isaki om_reset_planemask_and_rop();
1659 1.1 nisimura }
1660 1.1 nisimura
1661 1.1 nisimura /*
1662 1.1 nisimura * Allocate attribute. We just pack these into an integer.
1663 1.23 isaki *
1664 1.23 isaki * Attribute bitmap:
1665 1.23 isaki * b31: Multi color (used by copyrows)
1666 1.23 isaki * b30-18: 0 (reserved)
1667 1.23 isaki * b17: Underline (not supported yet)
1668 1.23 isaki * b16: Bold (or HILIT if 1bpp; not supported yet)
1669 1.23 isaki * b15-8: fg color code
1670 1.23 isaki * b7-0: bg color code
1671 1.23 isaki */
1672 1.23 isaki #if 0
1673 1.23 isaki /*
1674 1.23 isaki * Future plan:
1675 1.23 isaki * Place fg and bg side by side in advance to reduce the computation cost
1676 1.23 isaki * at the time of ROP setting.
1677 1.23 isaki *
1678 1.23 isaki * bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1679 1.23 isaki * f7 b7 f6 b6 f5 b5 f4 b4 f3 b3 f2 b2 f1 b1 f0 b0
1680 1.23 isaki *
1681 1.23 isaki * In this form, use bit1..0 if 1bpp, use bit7..0 if 4bpp.
1682 1.1 nisimura */
1683 1.23 isaki #endif
1684 1.1 nisimura static int
1685 1.25 tsutsui om_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
1686 1.1 nisimura {
1687 1.25 tsutsui struct rasops_info *ri = cookie;
1688 1.25 tsutsui int planecount = ri->ri_depth;
1689 1.23 isaki uint32_t a;
1690 1.23 isaki uint16_t c;
1691 1.23 isaki
1692 1.23 isaki a = 0;
1693 1.23 isaki c = 0;
1694 1.11 tsutsui
1695 1.23 isaki if ((flags & WSATTR_BLINK) != 0)
1696 1.11 tsutsui return EINVAL;
1697 1.1 nisimura
1698 1.16 tsutsui if ((flags & WSATTR_WSCOLORS) == 0) {
1699 1.23 isaki fg = WSCOL_WHITE; /* maybe 7 or 1 */
1700 1.23 isaki bg = WSCOL_BLACK; /* maybe 0 */
1701 1.16 tsutsui }
1702 1.16 tsutsui
1703 1.16 tsutsui if ((flags & WSATTR_REVERSE) != 0) {
1704 1.23 isaki int tmp;
1705 1.23 isaki tmp = fg;
1706 1.16 tsutsui fg = bg;
1707 1.23 isaki bg = tmp;
1708 1.16 tsutsui }
1709 1.16 tsutsui
1710 1.23 isaki if ((flags & WSATTR_HILIT) != 0) {
1711 1.25 tsutsui if (planecount == 1) {
1712 1.23 isaki #if 0
1713 1.23 isaki a |= OMFB_ATTR_BOLD;
1714 1.23 isaki #else
1715 1.23 isaki return EINVAL;
1716 1.23 isaki #endif
1717 1.23 isaki } else if (fg < 8) {
1718 1.23 isaki fg += 8;
1719 1.23 isaki }
1720 1.23 isaki }
1721 1.23 isaki
1722 1.23 isaki if ((flags & WSATTR_UNDERLINE) != 0) {
1723 1.23 isaki #if 0
1724 1.23 isaki a |= OMFB_ATTR_UNDERLINE;
1725 1.23 isaki #else
1726 1.23 isaki return EINVAL;
1727 1.23 isaki #endif
1728 1.23 isaki }
1729 1.16 tsutsui
1730 1.23 isaki fg &= hwplanemask;
1731 1.23 isaki bg &= hwplanemask;
1732 1.23 isaki
1733 1.23 isaki #if 0
1734 1.23 isaki int i;
1735 1.25 tsutsui for (i = 0; i < planecount; i++) {
1736 1.23 isaki c += c;
1737 1.23 isaki c += ((fg & 1) << 1) | (bg & 1);
1738 1.23 isaki fg >>= 1;
1739 1.23 isaki bg >>= 1;
1740 1.23 isaki }
1741 1.23 isaki #else
1742 1.23 isaki c = (fg << 8) | bg;
1743 1.23 isaki #endif
1744 1.23 isaki a |= c;
1745 1.23 isaki
1746 1.23 isaki *attrp = a;
1747 1.16 tsutsui return 0;
1748 1.16 tsutsui }
1749 1.16 tsutsui
1750 1.17 tsutsui static void
1751 1.23 isaki om_unpack_attr(long attr, uint8_t *fg, uint8_t *bg, int *underline)
1752 1.17 tsutsui {
1753 1.23 isaki uint8_t f, b;
1754 1.23 isaki
1755 1.23 isaki f = (attr >> 8) & hwplanemask;
1756 1.23 isaki b = attr & hwplanemask;
1757 1.17 tsutsui
1758 1.23 isaki if (fg)
1759 1.23 isaki *fg = f;
1760 1.23 isaki if (bg)
1761 1.23 isaki *bg = b;
1762 1.17 tsutsui }
1763 1.17 tsutsui
1764 1.13 tsutsui /*
1765 1.13 tsutsui * Init subset of rasops(9) for omrasops.
1766 1.13 tsutsui */
1767 1.13 tsutsui int
1768 1.16 tsutsui omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols)
1769 1.16 tsutsui {
1770 1.16 tsutsui
1771 1.16 tsutsui omrasops_init(ri, wantrows, wantcols);
1772 1.16 tsutsui
1773 1.16 tsutsui /* fill our own emulops */
1774 1.23 isaki ri->ri_ops.cursor = om_cursor;
1775 1.16 tsutsui ri->ri_ops.mapchar = om_mapchar;
1776 1.23 isaki ri->ri_ops.putchar = om_putchar;
1777 1.16 tsutsui ri->ri_ops.copycols = om1_copycols;
1778 1.23 isaki ri->ri_ops.erasecols = om_erasecols;
1779 1.16 tsutsui ri->ri_ops.copyrows = om1_copyrows;
1780 1.23 isaki ri->ri_ops.eraserows = om_eraserows;
1781 1.23 isaki ri->ri_ops.allocattr = om_allocattr;
1782 1.16 tsutsui ri->ri_caps = WSSCREEN_REVERSE;
1783 1.16 tsutsui
1784 1.16 tsutsui ri->ri_flg |= RI_CFGDONE;
1785 1.16 tsutsui
1786 1.16 tsutsui return 0;
1787 1.16 tsutsui }
1788 1.16 tsutsui
1789 1.16 tsutsui int
1790 1.16 tsutsui omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols)
1791 1.16 tsutsui {
1792 1.16 tsutsui
1793 1.16 tsutsui omrasops_init(ri, wantrows, wantcols);
1794 1.16 tsutsui
1795 1.16 tsutsui /* fill our own emulops */
1796 1.23 isaki ri->ri_ops.cursor = om_cursor;
1797 1.16 tsutsui ri->ri_ops.mapchar = om_mapchar;
1798 1.23 isaki ri->ri_ops.putchar = om_putchar;
1799 1.16 tsutsui ri->ri_ops.copycols = om4_copycols;
1800 1.23 isaki ri->ri_ops.erasecols = om_erasecols;
1801 1.16 tsutsui ri->ri_ops.copyrows = om4_copyrows;
1802 1.23 isaki ri->ri_ops.eraserows = om_eraserows;
1803 1.23 isaki ri->ri_ops.allocattr = om_allocattr;
1804 1.16 tsutsui ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
1805 1.16 tsutsui
1806 1.16 tsutsui ri->ri_flg |= RI_CFGDONE;
1807 1.16 tsutsui
1808 1.16 tsutsui return 0;
1809 1.16 tsutsui }
1810 1.16 tsutsui
1811 1.16 tsutsui static int
1812 1.13 tsutsui omrasops_init(struct rasops_info *ri, int wantrows, int wantcols)
1813 1.1 nisimura {
1814 1.13 tsutsui int wsfcookie, bpp;
1815 1.13 tsutsui
1816 1.24 tsutsui if (wantrows > OMRASOPS_MAX_ROWS)
1817 1.24 tsutsui wantrows = OMRASOPS_MAX_ROWS;
1818 1.13 tsutsui if (wantrows == 0)
1819 1.13 tsutsui wantrows = 34;
1820 1.13 tsutsui if (wantrows < 10)
1821 1.13 tsutsui wantrows = 10;
1822 1.13 tsutsui if (wantcols == 0)
1823 1.13 tsutsui wantcols = 80;
1824 1.13 tsutsui if (wantcols < 20)
1825 1.13 tsutsui wantcols = 20;
1826 1.13 tsutsui
1827 1.13 tsutsui /* Use default font */
1828 1.13 tsutsui wsfont_init();
1829 1.13 tsutsui wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
1830 1.13 tsutsui WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
1831 1.13 tsutsui if (wsfcookie < 0)
1832 1.13 tsutsui panic("%s: no font available", __func__);
1833 1.13 tsutsui if (wsfont_lock(wsfcookie, &ri->ri_font))
1834 1.13 tsutsui panic("%s: unable to lock font", __func__);
1835 1.13 tsutsui ri->ri_wsfcookie = wsfcookie;
1836 1.13 tsutsui
1837 1.13 tsutsui KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32);
1838 1.13 tsutsui
1839 1.16 tsutsui /* all planes are independently addressed */
1840 1.16 tsutsui bpp = 1;
1841 1.13 tsutsui
1842 1.13 tsutsui /* Now constrain what they get */
1843 1.13 tsutsui ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols;
1844 1.13 tsutsui ri->ri_emuheight = ri->ri_font->fontheight * wantrows;
1845 1.13 tsutsui if (ri->ri_emuwidth > ri->ri_width)
1846 1.13 tsutsui ri->ri_emuwidth = ri->ri_width;
1847 1.13 tsutsui if (ri->ri_emuheight > ri->ri_height)
1848 1.13 tsutsui ri->ri_emuheight = ri->ri_height;
1849 1.13 tsutsui
1850 1.13 tsutsui /* Reduce width until aligned on a 32-bit boundary */
1851 1.13 tsutsui while ((ri->ri_emuwidth * bpp & 31) != 0)
1852 1.13 tsutsui ri->ri_emuwidth--;
1853 1.13 tsutsui
1854 1.13 tsutsui ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
1855 1.13 tsutsui ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
1856 1.13 tsutsui ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
1857 1.13 tsutsui ri->ri_ccol = 0;
1858 1.13 tsutsui ri->ri_crow = 0;
1859 1.13 tsutsui ri->ri_pelbytes = bpp >> 3;
1860 1.13 tsutsui
1861 1.13 tsutsui ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3;
1862 1.13 tsutsui ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride;
1863 1.13 tsutsui ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride;
1864 1.13 tsutsui
1865 1.13 tsutsui /* Clear the entire display */
1866 1.13 tsutsui if ((ri->ri_flg & RI_CLEAR) != 0)
1867 1.13 tsutsui memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
1868 1.13 tsutsui
1869 1.13 tsutsui /* Now centre our window if needs be */
1870 1.13 tsutsui ri->ri_origbits = ri->ri_bits;
1871 1.13 tsutsui
1872 1.13 tsutsui if ((ri->ri_flg & RI_CENTER) != 0) {
1873 1.13 tsutsui ri->ri_bits += (((ri->ri_width * bpp >> 3) -
1874 1.13 tsutsui ri->ri_emustride) >> 1) & ~3;
1875 1.13 tsutsui ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
1876 1.13 tsutsui ri->ri_stride;
1877 1.13 tsutsui ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
1878 1.13 tsutsui / ri->ri_stride;
1879 1.13 tsutsui ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
1880 1.13 tsutsui % ri->ri_stride) * 8 / bpp);
1881 1.13 tsutsui } else
1882 1.13 tsutsui ri->ri_xorigin = ri->ri_yorigin = 0;
1883 1.13 tsutsui
1884 1.13 tsutsui return 0;
1885 1.1 nisimura }
1886