1 1.27 isaki /* $NetBSD: omrasops.c,v 1.27 2024/09/20 03:24:05 isaki 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.27 isaki __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.27 2024/09/20 03:24:05 isaki Exp $"); 35 1.1 nisimura 36 1.1 nisimura /* 37 1.27 isaki * Designed specifically 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