1 /* $NetBSD: omrasops.c,v 1.19 2014/10/04 16:58:17 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 33 34 __KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.19 2014/10/04 16:58:17 tsutsui Exp $"); 35 36 /* 37 * Designed speficically for 'm68k bitorder'; 38 * - most significant byte is stored at lower address, 39 * - most significant bit is displayed at left most on screen. 40 * Implementation relies on; 41 * - first column is at 32bit aligned address, 42 * - font glyphs are stored in 32bit padded. 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/device.h> 48 49 #include <dev/wscons/wsconsio.h> 50 #include <dev/wscons/wsdisplayvar.h> 51 #include <dev/rasops/rasops.h> 52 53 #include <arch/luna68k/dev/omrasopsvar.h> 54 55 /* wscons emulator operations */ 56 static void om1_cursor(void *, int, int, int); 57 static void om4_cursor(void *, int, int, int); 58 static int om_mapchar(void *, int, unsigned int *); 59 static void om1_putchar(void *, int, int, u_int, long); 60 static void om4_putchar(void *, int, int, u_int, long); 61 static void om1_copycols(void *, int, int, int, int); 62 static void om4_copycols(void *, int, int, int, int); 63 static void om1_copyrows(void *, int, int, int num); 64 static void om4_copyrows(void *, int, int, int num); 65 static void om1_erasecols(void *, int, int, int, long); 66 static void om4_erasecols(void *, int, int, int, long); 67 static void om1_eraserows(void *, int, int, long); 68 static void om4_eraserows(void *, int, int, long); 69 static int om1_allocattr(void *, int, int, int, long *); 70 static int om4_allocattr(void *, int, int, int, long *); 71 static void om4_unpack_attr(long, int *, int *, int *); 72 73 static int omrasops_init(struct rasops_info *, int, int); 74 75 #define ALL1BITS (~0U) 76 #define ALL0BITS (0U) 77 #define BLITWIDTH (32) 78 #define ALIGNMASK (0x1f) 79 #define BYTESDONE (4) 80 81 /* 82 * macros to handle unaligned bit copy ops. 83 * See src/sys/dev/rasops/rasops_mask.h for MI version. 84 * Also refer src/sys/arch/hp300/dev/maskbits.h. 85 * (which was implemented for ancient src/sys/arch/hp300/dev/grf_hy.c) 86 */ 87 88 /* luna68k version GETBITS() that gets w bits from bit x at psrc memory */ 89 #define FASTGETBITS(psrc, x, w, dst) \ 90 asm("bfextu %3{%1:%2},%0" \ 91 : "=d" (dst) \ 92 : "di" (x), "di" (w), "o" (*(uint32_t *)(psrc))) 93 94 /* luna68k version PUTBITS() that puts w bits from bit x at pdst memory */ 95 /* XXX this macro assumes (x + w) <= 32 to handle unaligned residual bits */ 96 #define FASTPUTBITS(src, x, w, pdst) \ 97 asm("bfins %3,%0{%1:%2}" \ 98 : "+o" (*(uint32_t *)(pdst)) \ 99 : "di" (x), "di" (w), "d" (src) \ 100 : "memory" ); 101 102 #define GETBITS(psrc, x, w, dst) FASTGETBITS(psrc, x, w, dst) 103 #define PUTBITS(src, x, w, pdst) FASTPUTBITS(src, x, w, pdst) 104 105 /* 106 * Blit a character at the specified co-ordinates. 107 */ 108 static void 109 om1_putchar(void *cookie, int row, int startcol, u_int uc, long attr) 110 { 111 struct rasops_info *ri = cookie; 112 uint8_t *p; 113 int scanspan, startx, height, width, align, y; 114 uint32_t lmask, rmask, glyph, inverse; 115 int i; 116 uint8_t *fb; 117 118 scanspan = ri->ri_stride; 119 y = ri->ri_font->fontheight * row; 120 startx = ri->ri_font->fontwidth * startcol; 121 height = ri->ri_font->fontheight; 122 fb = (uint8_t *)ri->ri_font->data + 123 (uc - ri->ri_font->firstchar) * ri->ri_fontscale; 124 inverse = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS; 125 126 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 127 align = startx & ALIGNMASK; 128 width = ri->ri_font->fontwidth + align; 129 lmask = ALL1BITS >> align; 130 rmask = ALL1BITS << (-width & ALIGNMASK); 131 if (width <= BLITWIDTH) { 132 lmask &= rmask; 133 /* set lmask as ROP mask value, with THROUGH mode */ 134 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask; 135 136 while (height > 0) { 137 glyph = 0; 138 for (i = ri->ri_font->stride; i != 0; i--) 139 glyph = (glyph << 8) | *fb++; 140 glyph <<= (4 - ri->ri_font->stride) * NBBY; 141 glyph = (glyph >> align) ^ inverse; 142 143 *W(p) = glyph; 144 145 p += scanspan; 146 height--; 147 } 148 /* reset mask value */ 149 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 150 } else { 151 uint8_t *q = p; 152 uint32_t lhalf, rhalf; 153 154 while (height > 0) { 155 glyph = 0; 156 for (i = ri->ri_font->stride; i != 0; i--) 157 glyph = (glyph << 8) | *fb++; 158 glyph <<= (4 - ri->ri_font->stride) * NBBY; 159 lhalf = (glyph >> align) ^ inverse; 160 /* set lmask as ROP mask value, with THROUGH mode */ 161 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = 162 lmask; 163 164 *W(p) = lhalf; 165 166 p += BYTESDONE; 167 168 rhalf = (glyph << (BLITWIDTH - align)) ^ inverse; 169 /* set rmask as ROP mask value, with THROUGH mode */ 170 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = 171 rmask; 172 173 *W(p) = rhalf; 174 175 p = (q += scanspan); 176 height--; 177 } 178 /* reset mask value */ 179 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 180 } 181 } 182 183 static void 184 om4_putchar(void *cookie, int row, int startcol, u_int uc, long attr) 185 { 186 struct rasops_info *ri = cookie; 187 uint8_t *p; 188 int scanspan, startx, height, width, align, y; 189 uint32_t lmask, rmask, glyph, glyphbg, fgpat, bgpat; 190 uint32_t fgmask0, fgmask1, fgmask2, fgmask3; 191 uint32_t bgmask0, bgmask1, bgmask2, bgmask3; 192 int i, fg, bg; 193 uint8_t *fb; 194 195 scanspan = ri->ri_stride; 196 y = ri->ri_font->fontheight * row; 197 startx = ri->ri_font->fontwidth * startcol; 198 height = ri->ri_font->fontheight; 199 fb = (uint8_t *)ri->ri_font->data + 200 (uc - ri->ri_font->firstchar) * ri->ri_fontscale; 201 om4_unpack_attr(attr, &fg, &bg, NULL); 202 fgmask0 = (fg & 0x01) ? ALL1BITS : ALL0BITS; 203 fgmask1 = (fg & 0x02) ? ALL1BITS : ALL0BITS; 204 fgmask2 = (fg & 0x04) ? ALL1BITS : ALL0BITS; 205 fgmask3 = (fg & 0x08) ? ALL1BITS : ALL0BITS; 206 bgmask0 = (bg & 0x01) ? ALL1BITS : ALL0BITS; 207 bgmask1 = (bg & 0x02) ? ALL1BITS : ALL0BITS; 208 bgmask2 = (bg & 0x04) ? ALL1BITS : ALL0BITS; 209 bgmask3 = (bg & 0x08) ? ALL1BITS : ALL0BITS; 210 211 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 212 align = startx & ALIGNMASK; 213 width = ri->ri_font->fontwidth + align; 214 lmask = ALL1BITS >> align; 215 rmask = ALL1BITS << (-width & ALIGNMASK); 216 217 /* select all planes for later ROP function target */ 218 *(volatile uint32_t *)OMFB_PLANEMASK = 0xff; 219 220 if (width <= BLITWIDTH) { 221 lmask &= rmask; 222 /* set lmask as ROP mask value, with THROUGH mode */ 223 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = lmask; 224 225 while (height > 0) { 226 glyph = 0; 227 for (i = ri->ri_font->stride; i != 0; i--) 228 glyph = (glyph << 8) | *fb++; 229 glyph <<= (4 - ri->ri_font->stride) * NBBY; 230 glyph = (glyph >> align); 231 glyphbg = glyph ^ ALL1BITS; 232 233 fgpat = glyph & fgmask0; 234 bgpat = glyphbg & bgmask0; 235 *P0(p) = (fgpat | bgpat); 236 fgpat = glyph & fgmask1; 237 bgpat = glyphbg & bgmask1; 238 *P1(p) = (fgpat | bgpat); 239 fgpat = glyph & fgmask2; 240 bgpat = glyphbg & bgmask2; 241 *P2(p) = (fgpat | bgpat); 242 fgpat = glyph & fgmask3; 243 bgpat = glyphbg & bgmask3; 244 *P3(p) = (fgpat | bgpat); 245 246 p += scanspan; 247 height--; 248 } 249 /* reset mask value */ 250 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 251 } else { 252 uint8_t *q = p; 253 uint32_t lhalf, rhalf; 254 uint32_t lhalfbg, rhalfbg; 255 256 while (height > 0) { 257 glyph = 0; 258 for (i = ri->ri_font->stride; i != 0; i--) 259 glyph = (glyph << 8) | *fb++; 260 glyph <<= (4 - ri->ri_font->stride) * NBBY; 261 lhalf = (glyph >> align); 262 lhalfbg = lhalf ^ ALL1BITS; 263 /* set lmask as ROP mask value, with THROUGH mode */ 264 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = 265 lmask; 266 267 fgpat = lhalf & fgmask0; 268 bgpat = lhalfbg & bgmask0; 269 *P0(p) = (fgpat | bgpat); 270 fgpat = lhalf & fgmask1; 271 bgpat = lhalfbg & bgmask1; 272 *P1(p) = (fgpat | bgpat); 273 fgpat = lhalf & fgmask2; 274 bgpat = lhalfbg & bgmask2; 275 *P2(p) = (fgpat | bgpat); 276 fgpat = lhalf & fgmask3; 277 bgpat = lhalfbg & bgmask3; 278 *P3(p) = (fgpat | bgpat); 279 280 p += BYTESDONE; 281 282 rhalf = (glyph << (BLITWIDTH - align)); 283 rhalfbg = rhalf ^ ALL1BITS; 284 /* set rmask as ROP mask value, with THROUGH mode */ 285 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = 286 rmask; 287 288 fgpat = rhalf & fgmask0; 289 bgpat = rhalfbg & bgmask0; 290 *P0(p) = (fgpat | bgpat); 291 fgpat = rhalf & fgmask1; 292 bgpat = rhalfbg & bgmask1; 293 *P1(p) = (fgpat | bgpat); 294 fgpat = rhalf & fgmask2; 295 bgpat = rhalfbg & bgmask2; 296 *P2(p) = (fgpat | bgpat); 297 fgpat = rhalf & fgmask3; 298 bgpat = rhalfbg & bgmask3; 299 *P3(p) = (fgpat | bgpat); 300 301 p = (q += scanspan); 302 height--; 303 } 304 /* reset mask value */ 305 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 306 } 307 /* select plane #0 only; XXX need this ? */ 308 *(volatile uint32_t *)OMFB_PLANEMASK = 0x01; 309 } 310 311 static void 312 om1_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 313 { 314 struct rasops_info *ri = cookie; 315 uint8_t *p; 316 int scanspan, startx, height, width, align, w, y; 317 uint32_t lmask, rmask, fill; 318 319 scanspan = ri->ri_stride;; 320 y = ri->ri_font->fontheight * row; 321 startx = ri->ri_font->fontwidth * startcol; 322 height = ri->ri_font->fontheight; 323 w = ri->ri_font->fontwidth * ncols; 324 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS; 325 326 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 327 align = startx & ALIGNMASK; 328 width = w + align; 329 lmask = ALL1BITS >> align; 330 rmask = ALL1BITS << (-width & ALIGNMASK); 331 if (width <= BLITWIDTH) { 332 lmask &= rmask; 333 fill &= lmask; 334 while (height > 0) { 335 *P0(p) = (*P0(p) & ~lmask) | fill; 336 p += scanspan; 337 height--; 338 } 339 } else { 340 uint8_t *q = p; 341 while (height > 0) { 342 *P0(p) = (*P0(p) & ~lmask) | (fill & lmask); 343 width -= 2 * BLITWIDTH; 344 while (width > 0) { 345 p += BYTESDONE; 346 *P0(p) = fill; 347 width -= BLITWIDTH; 348 } 349 p += BYTESDONE; 350 *P0(p) = (fill & rmask) | (*P0(p) & ~rmask); 351 352 p = (q += scanspan); 353 width = w + align; 354 height--; 355 } 356 } 357 } 358 359 static void 360 om4_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 361 { 362 struct rasops_info *ri = cookie; 363 uint8_t *p; 364 int scanspan, startx, height, width, align, w, y, fg, bg; 365 uint32_t lmask, rmask, fill0, fill1, fill2, fill3; 366 367 scanspan = ri->ri_stride;; 368 y = ri->ri_font->fontheight * row; 369 startx = ri->ri_font->fontwidth * startcol; 370 height = ri->ri_font->fontheight; 371 w = ri->ri_font->fontwidth * ncols; 372 om4_unpack_attr(attr, &fg, &bg, NULL); 373 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS; 374 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS; 375 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS; 376 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS; 377 378 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 379 align = startx & ALIGNMASK; 380 width = w + align; 381 lmask = ALL1BITS >> align; 382 rmask = ALL1BITS << (-width & ALIGNMASK); 383 if (width <= BLITWIDTH) { 384 lmask &= rmask; 385 fill0 &= lmask; 386 fill1 &= lmask; 387 fill2 &= lmask; 388 fill3 &= lmask; 389 while (height > 0) { 390 *P0(p) = (*P0(p) & ~lmask) | fill0; 391 *P1(p) = (*P1(p) & ~lmask) | fill1; 392 *P2(p) = (*P2(p) & ~lmask) | fill2; 393 *P3(p) = (*P3(p) & ~lmask) | fill3; 394 p += scanspan; 395 height--; 396 } 397 } else { 398 uint8_t *q = p; 399 while (height > 0) { 400 *P0(p) = (*P0(p) & ~lmask) | (fill0 & lmask); 401 *P1(p) = (*P1(p) & ~lmask) | (fill1 & lmask); 402 *P2(p) = (*P2(p) & ~lmask) | (fill2 & lmask); 403 *P3(p) = (*P3(p) & ~lmask) | (fill3 & lmask); 404 width -= 2 * BLITWIDTH; 405 while (width > 0) { 406 p += BYTESDONE; 407 *P0(p) = fill0; 408 *P1(p) = fill1; 409 *P2(p) = fill2; 410 *P3(p) = fill3; 411 width -= BLITWIDTH; 412 } 413 p += BYTESDONE; 414 *P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask); 415 *P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask); 416 *P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask); 417 *P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask); 418 419 p = (q += scanspan); 420 width = w + align; 421 height--; 422 } 423 } 424 } 425 426 static void 427 om1_eraserows(void *cookie, int startrow, int nrows, long attr) 428 { 429 struct rasops_info *ri = cookie; 430 uint8_t *p, *q; 431 int scanspan, starty, height, width, w; 432 uint32_t rmask, fill; 433 434 scanspan = ri->ri_stride; 435 starty = ri->ri_font->fontheight * startrow; 436 height = ri->ri_font->fontheight * nrows; 437 w = ri->ri_emuwidth; 438 fill = ((attr & 0x00000001) != 0) ? ALL1BITS : ALL0BITS; 439 440 p = (uint8_t *)ri->ri_bits + starty * scanspan; 441 width = w; 442 rmask = ALL1BITS << (-width & ALIGNMASK); 443 q = p; 444 while (height > 0) { 445 *P0(p) = fill; /* always aligned */ 446 width -= 2 * BLITWIDTH; 447 while (width > 0) { 448 p += BYTESDONE; 449 *P0(p) = fill; 450 width -= BLITWIDTH; 451 } 452 p += BYTESDONE; 453 *P0(p) = (fill & rmask) | (*P0(p) & ~rmask); 454 p = (q += scanspan); 455 width = w; 456 height--; 457 } 458 } 459 460 static void 461 om4_eraserows(void *cookie, int startrow, int nrows, long attr) 462 { 463 struct rasops_info *ri = cookie; 464 uint8_t *p, *q; 465 int scanspan, starty, height, width, w, fg, bg; 466 uint32_t rmask, fill0, fill1, fill2, fill3; 467 468 scanspan = ri->ri_stride; 469 starty = ri->ri_font->fontheight * startrow; 470 height = ri->ri_font->fontheight * nrows; 471 w = ri->ri_emuwidth; 472 om4_unpack_attr(attr, &fg, &bg, NULL); 473 fill0 = ((bg & 0x01) != 0) ? ALL1BITS : ALL0BITS; 474 fill1 = ((bg & 0x02) != 0) ? ALL1BITS : ALL0BITS; 475 fill2 = ((bg & 0x04) != 0) ? ALL1BITS : ALL0BITS; 476 fill3 = ((bg & 0x08) != 0) ? ALL1BITS : ALL0BITS; 477 478 p = (uint8_t *)ri->ri_bits + starty * scanspan; 479 width = w; 480 rmask = ALL1BITS << (-width & ALIGNMASK); 481 q = p; 482 while (height > 0) { 483 *P0(p) = fill0; /* always aligned */ 484 *P1(p) = fill1; 485 *P2(p) = fill2; 486 *P3(p) = fill3; 487 width -= 2 * BLITWIDTH; 488 while (width > 0) { 489 p += BYTESDONE; 490 *P0(p) = fill0; 491 *P1(p) = fill1; 492 *P2(p) = fill2; 493 *P3(p) = fill3; 494 width -= BLITWIDTH; 495 } 496 p += BYTESDONE; 497 *P0(p) = (fill0 & rmask) | (*P0(p) & ~rmask); 498 *P1(p) = (fill1 & rmask) | (*P1(p) & ~rmask); 499 *P2(p) = (fill2 & rmask) | (*P2(p) & ~rmask); 500 *P3(p) = (fill3 & rmask) | (*P3(p) & ~rmask); 501 p = (q += scanspan); 502 width = w; 503 height--; 504 } 505 } 506 507 static void 508 om1_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 509 { 510 struct rasops_info *ri = cookie; 511 uint8_t *p, *q; 512 int scanspan, offset, srcy, height, width, w; 513 uint32_t rmask; 514 515 scanspan = ri->ri_stride; 516 height = ri->ri_font->fontheight * nrows; 517 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight; 518 srcy = ri->ri_font->fontheight * srcrow; 519 if (srcrow < dstrow && srcrow + nrows > dstrow) { 520 scanspan = -scanspan; 521 srcy = srcy + height - 1; 522 } 523 524 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride; 525 w = ri->ri_emuwidth; 526 width = w; 527 rmask = ALL1BITS << (-width & ALIGNMASK); 528 q = p; 529 while (height > 0) { 530 *P0(p + offset) = *P0(p); /* always aligned */ 531 width -= 2 * BLITWIDTH; 532 while (width > 0) { 533 p += BYTESDONE; 534 *P0(p + offset) = *P0(p); 535 width -= BLITWIDTH; 536 } 537 p += BYTESDONE; 538 *P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask); 539 540 p = (q += scanspan); 541 width = w; 542 height--; 543 } 544 } 545 546 static void 547 om4_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 548 { 549 struct rasops_info *ri = cookie; 550 uint8_t *p, *q; 551 int scanspan, offset, srcy, height, width, w; 552 uint32_t rmask; 553 554 scanspan = ri->ri_stride; 555 height = ri->ri_font->fontheight * nrows; 556 offset = (dstrow - srcrow) * scanspan * ri->ri_font->fontheight; 557 srcy = ri->ri_font->fontheight * srcrow; 558 if (srcrow < dstrow && srcrow + nrows > dstrow) { 559 scanspan = -scanspan; 560 srcy = srcy + height - 1; 561 } 562 563 p = (uint8_t *)ri->ri_bits + srcy * ri->ri_stride; 564 w = ri->ri_emuwidth; 565 width = w; 566 rmask = ALL1BITS << (-width & ALIGNMASK); 567 q = p; 568 while (height > 0) { 569 *P0(p + offset) = *P0(p); /* always aligned */ 570 *P1(p + offset) = *P1(p); 571 *P2(p + offset) = *P2(p); 572 *P3(p + offset) = *P3(p); 573 width -= 2 * BLITWIDTH; 574 while (width > 0) { 575 p += BYTESDONE; 576 *P0(p + offset) = *P0(p); 577 *P1(p + offset) = *P1(p); 578 *P2(p + offset) = *P2(p); 579 *P3(p + offset) = *P3(p); 580 width -= BLITWIDTH; 581 } 582 p += BYTESDONE; 583 *P0(p + offset) = (*P0(p) & rmask) | (*P0(p + offset) & ~rmask); 584 *P1(p + offset) = (*P1(p) & rmask) | (*P1(p + offset) & ~rmask); 585 *P2(p + offset) = (*P2(p) & rmask) | (*P2(p + offset) & ~rmask); 586 *P3(p + offset) = (*P3(p) & rmask) | (*P3(p + offset) & ~rmask); 587 588 p = (q += scanspan); 589 width = w; 590 height--; 591 } 592 } 593 594 static void 595 om1_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols) 596 { 597 struct rasops_info *ri = cookie; 598 uint8_t *sp, *dp, *sq, *dq, *basep; 599 int scanspan, height, w, y, srcx, dstx; 600 int sb, eb, db, sboff, full, cnt, lnum, rnum; 601 uint32_t lmask, rmask, tmp; 602 bool sbover; 603 604 scanspan = ri->ri_stride; 605 y = ri->ri_font->fontheight * startrow; 606 srcx = ri->ri_font->fontwidth * srccol; 607 dstx = ri->ri_font->fontwidth * dstcol; 608 height = ri->ri_font->fontheight; 609 w = ri->ri_font->fontwidth * ncols; 610 basep = (uint8_t *)ri->ri_bits + y * scanspan; 611 612 sb = srcx & ALIGNMASK; 613 db = dstx & ALIGNMASK; 614 615 if (db + w <= BLITWIDTH) { 616 /* Destination is contained within a single word */ 617 sp = basep + (srcx / 32) * 4; 618 dp = basep + (dstx / 32) * 4; 619 620 while (height > 0) { 621 GETBITS(P0(sp), sb, w, tmp); 622 PUTBITS(tmp, db, w, P0(dp)); 623 dp += scanspan; 624 sp += scanspan; 625 height--; 626 } 627 return; 628 } 629 630 lmask = (db == 0) ? 0 : ALL1BITS >> db; 631 eb = (db + w) & ALIGNMASK; 632 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb); 633 lnum = (32 - db) & ALIGNMASK; 634 rnum = (dstx + w) & ALIGNMASK; 635 636 if (lmask != 0) 637 full = (w - (32 - db)) / 32; 638 else 639 full = w / 32; 640 641 sbover = (sb + lnum) >= 32; 642 643 if (dstcol < srccol || srccol + ncols < dstcol) { 644 /* copy forward (left-to-right) */ 645 sp = basep + (srcx / 32) * 4; 646 dp = basep + (dstx / 32) * 4; 647 648 if (lmask != 0) { 649 sboff = sb + lnum; 650 if (sboff >= 32) 651 sboff -= 32; 652 } else 653 sboff = sb; 654 655 sq = sp; 656 dq = dp; 657 while (height > 0) { 658 if (lmask != 0) { 659 GETBITS(P0(sp), sb, lnum, tmp); 660 PUTBITS(tmp, db, lnum, P0(dp)); 661 dp += BYTESDONE; 662 if (sbover) 663 sp += BYTESDONE; 664 } 665 666 for (cnt = full; cnt; cnt--) { 667 GETBITS(P0(sp), sboff, 32, tmp); 668 *P0(dp) = tmp; 669 sp += BYTESDONE; 670 dp += BYTESDONE; 671 } 672 673 if (rmask != 0) { 674 GETBITS(P0(sp), sboff, rnum, tmp); 675 PUTBITS(tmp, 0, rnum, P0(dp)); 676 } 677 678 sp = (sq += scanspan); 679 dp = (dq += scanspan); 680 height--; 681 } 682 } else { 683 /* copy backward (right-to-left) */ 684 sp = basep + ((srcx + w) / 32) * 4; 685 dp = basep + ((dstx + w) / 32) * 4; 686 687 sboff = (srcx + w) & ALIGNMASK; 688 sboff -= rnum; 689 if (sboff < 0) { 690 sp -= BYTESDONE; 691 sboff += 32; 692 } 693 694 sq = sp; 695 dq = dp; 696 while (height > 0) { 697 if (rnum != 0) { 698 GETBITS(P0(sp), sboff, rnum, tmp); 699 PUTBITS(tmp, 0, rnum, P0(dp)); 700 } 701 702 for (cnt = full; cnt; cnt--) { 703 sp -= BYTESDONE; 704 dp -= BYTESDONE; 705 GETBITS(P0(sp), sboff, 32, tmp); 706 *P0(dp) = tmp; 707 } 708 709 if (lmask != 0) { 710 if (sbover) 711 sp -= BYTESDONE; 712 dp -= BYTESDONE; 713 GETBITS(P0(sp), sb, lnum, tmp); 714 PUTBITS(tmp, db, lnum, P0(dp)); 715 } 716 717 sp = (sq += scanspan); 718 dp = (dq += scanspan); 719 height--; 720 } 721 } 722 } 723 724 static void 725 om4_copycols(void *cookie, int startrow, int srccol, int dstcol, int ncols) 726 { 727 struct rasops_info *ri = cookie; 728 uint8_t *sp, *dp, *sq, *dq, *basep; 729 int scanspan, height, w, y, srcx, dstx; 730 int sb, eb, db, sboff, full, cnt, lnum, rnum; 731 uint32_t lmask, rmask, tmp; 732 bool sbover; 733 734 scanspan = ri->ri_stride; 735 y = ri->ri_font->fontheight * startrow; 736 srcx = ri->ri_font->fontwidth * srccol; 737 dstx = ri->ri_font->fontwidth * dstcol; 738 height = ri->ri_font->fontheight; 739 w = ri->ri_font->fontwidth * ncols; 740 basep = (uint8_t *)ri->ri_bits + y * scanspan; 741 742 sb = srcx & ALIGNMASK; 743 db = dstx & ALIGNMASK; 744 745 if (db + w <= BLITWIDTH) { 746 /* Destination is contained within a single word */ 747 sp = basep + (srcx / 32) * 4; 748 dp = basep + (dstx / 32) * 4; 749 750 while (height > 0) { 751 GETBITS(P0(sp), sb, w, tmp); 752 PUTBITS(tmp, db, w, P0(dp)); 753 GETBITS(P1(sp), sb, w, tmp); 754 PUTBITS(tmp, db, w, P1(dp)); 755 GETBITS(P2(sp), sb, w, tmp); 756 PUTBITS(tmp, db, w, P2(dp)); 757 GETBITS(P3(sp), sb, w, tmp); 758 PUTBITS(tmp, db, w, P3(dp)); 759 dp += scanspan; 760 sp += scanspan; 761 height--; 762 } 763 return; 764 } 765 766 lmask = (db == 0) ? 0 : ALL1BITS >> db; 767 eb = (db + w) & ALIGNMASK; 768 rmask = (eb == 0) ? 0 : ALL1BITS << (32 - eb); 769 lnum = (32 - db) & ALIGNMASK; 770 rnum = (dstx + w) & ALIGNMASK; 771 772 if (lmask != 0) 773 full = (w - (32 - db)) / 32; 774 else 775 full = w / 32; 776 777 sbover = (sb + lnum) >= 32; 778 779 if (dstcol < srccol || srccol + ncols < dstcol) { 780 /* copy forward (left-to-right) */ 781 sp = basep + (srcx / 32) * 4; 782 dp = basep + (dstx / 32) * 4; 783 784 if (lmask != 0) { 785 sboff = sb + lnum; 786 if (sboff >= 32) 787 sboff -= 32; 788 } else 789 sboff = sb; 790 791 sq = sp; 792 dq = dp; 793 while (height > 0) { 794 if (lmask != 0) { 795 GETBITS(P0(sp), sb, lnum, tmp); 796 PUTBITS(tmp, db, lnum, P0(dp)); 797 GETBITS(P1(sp), sb, lnum, tmp); 798 PUTBITS(tmp, db, lnum, P1(dp)); 799 GETBITS(P2(sp), sb, lnum, tmp); 800 PUTBITS(tmp, db, lnum, P2(dp)); 801 GETBITS(P3(sp), sb, lnum, tmp); 802 PUTBITS(tmp, db, lnum, P3(dp)); 803 dp += BYTESDONE; 804 if (sbover) 805 sp += BYTESDONE; 806 } 807 808 for (cnt = full; cnt; cnt--) { 809 GETBITS(P0(sp), sboff, 32, tmp); 810 *P0(dp) = tmp; 811 GETBITS(P1(sp), sboff, 32, tmp); 812 *P1(dp) = tmp; 813 GETBITS(P2(sp), sboff, 32, tmp); 814 *P2(dp) = tmp; 815 GETBITS(P3(sp), sboff, 32, tmp); 816 *P3(dp) = tmp; 817 sp += BYTESDONE; 818 dp += BYTESDONE; 819 } 820 821 if (rmask != 0) { 822 GETBITS(P0(sp), sboff, rnum, tmp); 823 PUTBITS(tmp, 0, rnum, P0(dp)); 824 GETBITS(P1(sp), sboff, rnum, tmp); 825 PUTBITS(tmp, 0, rnum, P1(dp)); 826 GETBITS(P2(sp), sboff, rnum, tmp); 827 PUTBITS(tmp, 0, rnum, P2(dp)); 828 GETBITS(P3(sp), sboff, rnum, tmp); 829 PUTBITS(tmp, 0, rnum, P3(dp)); 830 } 831 832 sp = (sq += scanspan); 833 dp = (dq += scanspan); 834 height--; 835 } 836 } else { 837 /* copy backward (right-to-left) */ 838 sp = basep + ((srcx + w) / 32) * 4; 839 dp = basep + ((dstx + w) / 32) * 4; 840 841 sboff = (srcx + w) & ALIGNMASK; 842 sboff -= rnum; 843 if (sboff < 0) { 844 sp -= BYTESDONE; 845 sboff += 32; 846 } 847 848 sq = sp; 849 dq = dp; 850 while (height > 0) { 851 if (rnum != 0) { 852 GETBITS(P0(sp), sboff, rnum, tmp); 853 PUTBITS(tmp, 0, rnum, P0(dp)); 854 GETBITS(P1(sp), sboff, rnum, tmp); 855 PUTBITS(tmp, 0, rnum, P1(dp)); 856 GETBITS(P2(sp), sboff, rnum, tmp); 857 PUTBITS(tmp, 0, rnum, P2(dp)); 858 GETBITS(P3(sp), sboff, rnum, tmp); 859 PUTBITS(tmp, 0, rnum, P3(dp)); 860 } 861 862 for (cnt = full; cnt; cnt--) { 863 sp -= BYTESDONE; 864 dp -= BYTESDONE; 865 GETBITS(P0(sp), sboff, 32, tmp); 866 *P0(dp) = tmp; 867 GETBITS(P1(sp), sboff, 32, tmp); 868 *P1(dp) = tmp; 869 GETBITS(P2(sp), sboff, 32, tmp); 870 *P2(dp) = tmp; 871 GETBITS(P3(sp), sboff, 32, tmp); 872 *P3(dp) = tmp; 873 } 874 875 if (lmask != 0) { 876 if (sbover) 877 sp -= BYTESDONE; 878 dp -= BYTESDONE; 879 GETBITS(P0(sp), sb, lnum, tmp); 880 PUTBITS(tmp, db, lnum, P0(dp)); 881 GETBITS(P1(sp), sb, lnum, tmp); 882 PUTBITS(tmp, db, lnum, P1(dp)); 883 GETBITS(P2(sp), sb, lnum, tmp); 884 PUTBITS(tmp, db, lnum, P2(dp)); 885 GETBITS(P3(sp), sb, lnum, tmp); 886 PUTBITS(tmp, db, lnum, P3(dp)); 887 } 888 889 sp = (sq += scanspan); 890 dp = (dq += scanspan); 891 height--; 892 } 893 } 894 } 895 896 /* 897 * Map a character. 898 */ 899 static int 900 om_mapchar(void *cookie, int c, u_int *cp) 901 { 902 struct rasops_info *ri = cookie; 903 struct wsdisplay_font *wf = ri->ri_font; 904 905 if (wf->encoding != WSDISPLAY_FONTENC_ISO) { 906 c = wsfont_map_unichar(wf, c); 907 908 if (c < 0) 909 goto fail; 910 } 911 if (c < wf->firstchar || c >= (wf->firstchar + wf->numchars)) 912 goto fail; 913 914 *cp = c; 915 return 5; 916 917 fail: 918 *cp = ' '; 919 return 0; 920 } 921 922 /* 923 * Position|{enable|disable} the cursor at the specified location. 924 */ 925 static void 926 om1_cursor(void *cookie, int on, int row, int col) 927 { 928 struct rasops_info *ri = cookie; 929 uint8_t *p; 930 int scanspan, startx, height, width, align, y; 931 uint32_t lmask, rmask; 932 933 if (!on) { 934 /* make sure it's on */ 935 if ((ri->ri_flg & RI_CURSOR) == 0) 936 return; 937 938 row = ri->ri_crow; 939 col = ri->ri_ccol; 940 } else { 941 /* unpaint the old copy. */ 942 ri->ri_crow = row; 943 ri->ri_ccol = col; 944 } 945 946 scanspan = ri->ri_stride; 947 y = ri->ri_font->fontheight * row; 948 startx = ri->ri_font->fontwidth * col; 949 height = ri->ri_font->fontheight; 950 951 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 952 align = startx & ALIGNMASK; 953 width = ri->ri_font->fontwidth + align; 954 lmask = ALL1BITS >> align; 955 rmask = ALL1BITS << (-width & ALIGNMASK); 956 if (width <= BLITWIDTH) { 957 lmask &= rmask; 958 /* set lmask as ROP mask value, with INV2 mode */ 959 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask; 960 961 while (height > 0) { 962 *P0(p) = ALL1BITS; 963 p += scanspan; 964 height--; 965 } 966 /* reset mask value */ 967 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 968 } else { 969 uint8_t *q = p; 970 971 while (height > 0) { 972 /* set lmask as ROP mask value, with INV2 mode */ 973 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask; 974 *W(p) = ALL1BITS; 975 976 p += BYTESDONE; 977 978 /* set lmask as ROP mask value, with INV2 mode */ 979 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask; 980 *W(p) = ALL1BITS; 981 982 p = (q += scanspan); 983 height--; 984 } 985 /* reset mask value */ 986 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 987 } 988 ri->ri_flg ^= RI_CURSOR; 989 } 990 991 static void 992 om4_cursor(void *cookie, int on, int row, int col) 993 { 994 struct rasops_info *ri = cookie; 995 uint8_t *p; 996 int scanspan, startx, height, width, align, y; 997 uint32_t lmask, rmask; 998 999 if (!on) { 1000 /* make sure it's on */ 1001 if ((ri->ri_flg & RI_CURSOR) == 0) 1002 return; 1003 1004 row = ri->ri_crow; 1005 col = ri->ri_ccol; 1006 } else { 1007 /* unpaint the old copy. */ 1008 ri->ri_crow = row; 1009 ri->ri_ccol = col; 1010 } 1011 1012 scanspan = ri->ri_stride; 1013 y = ri->ri_font->fontheight * row; 1014 startx = ri->ri_font->fontwidth * col; 1015 height = ri->ri_font->fontheight; 1016 1017 p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4); 1018 align = startx & ALIGNMASK; 1019 width = ri->ri_font->fontwidth + align; 1020 lmask = ALL1BITS >> align; 1021 rmask = ALL1BITS << (-width & ALIGNMASK); 1022 1023 /* select all planes for later ROP function target */ 1024 *(volatile uint32_t *)OMFB_PLANEMASK = 0xff; 1025 1026 if (width <= BLITWIDTH) { 1027 lmask &= rmask; 1028 /* set lmask as ROP mask value, with INV2 mode */ 1029 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask; 1030 1031 while (height > 0) { 1032 *W(p) = ALL1BITS; 1033 p += scanspan; 1034 height--; 1035 } 1036 /* reset mask value */ 1037 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 1038 } else { 1039 uint8_t *q = p; 1040 1041 while (height > 0) { 1042 /* set lmask as ROP mask value, with INV2 mode */ 1043 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = lmask; 1044 *W(p) = ALL1BITS; 1045 1046 p += BYTESDONE; 1047 1048 /* set rmask as ROP mask value, with INV2 mode */ 1049 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_INV2] = rmask; 1050 *W(p) = ALL1BITS; 1051 1052 p = (q += scanspan); 1053 height--; 1054 } 1055 /* reset mask value */ 1056 ((volatile uint32_t *)OMFB_ROPFUNC)[ROP_THROUGH] = ALL1BITS; 1057 } 1058 /* select plane #0 only; XXX need this ? */ 1059 *(volatile uint32_t *)OMFB_PLANEMASK = 0x01; 1060 1061 ri->ri_flg ^= RI_CURSOR; 1062 } 1063 1064 /* 1065 * Allocate attribute. We just pack these into an integer. 1066 */ 1067 static int 1068 om1_allocattr(void *id, int fg, int bg, int flags, long *attrp) 1069 { 1070 1071 if ((flags & (WSATTR_HILIT | WSATTR_BLINK | 1072 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0) 1073 return EINVAL; 1074 if ((flags & WSATTR_REVERSE) != 0) 1075 *attrp = 1; 1076 else 1077 *attrp = 0; 1078 return 0; 1079 } 1080 1081 static int 1082 om4_allocattr(void *id, int fg, int bg, int flags, long *attrp) 1083 { 1084 1085 if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0) 1086 return EINVAL; 1087 if ((flags & WSATTR_WSCOLORS) == 0) { 1088 fg = WSCOL_WHITE; 1089 bg = WSCOL_BLACK; 1090 } 1091 1092 if ((flags & WSATTR_REVERSE) != 0) { 1093 int swap; 1094 swap = fg; 1095 fg = bg; 1096 bg = swap; 1097 } 1098 1099 if ((flags & WSATTR_HILIT) != 0) 1100 fg += 8; 1101 1102 *attrp = (fg << 24) | (bg << 16); 1103 return 0; 1104 } 1105 1106 static void 1107 om4_unpack_attr(long attr, int *fg, int *bg, int *underline) 1108 { 1109 1110 *fg = ((u_int)attr >> 24) & 0xf; 1111 *bg = ((u_int)attr >> 16) & 0xf; 1112 } 1113 1114 /* 1115 * Init subset of rasops(9) for omrasops. 1116 */ 1117 int 1118 omrasops1_init(struct rasops_info *ri, int wantrows, int wantcols) 1119 { 1120 1121 omrasops_init(ri, wantrows, wantcols); 1122 1123 /* fill our own emulops */ 1124 ri->ri_ops.cursor = om1_cursor; 1125 ri->ri_ops.mapchar = om_mapchar; 1126 ri->ri_ops.putchar = om1_putchar; 1127 ri->ri_ops.copycols = om1_copycols; 1128 ri->ri_ops.erasecols = om1_erasecols; 1129 ri->ri_ops.copyrows = om1_copyrows; 1130 ri->ri_ops.eraserows = om1_eraserows; 1131 ri->ri_ops.allocattr = om1_allocattr; 1132 ri->ri_caps = WSSCREEN_REVERSE; 1133 1134 ri->ri_flg |= RI_CFGDONE; 1135 1136 return 0; 1137 } 1138 1139 int 1140 omrasops4_init(struct rasops_info *ri, int wantrows, int wantcols) 1141 { 1142 1143 omrasops_init(ri, wantrows, wantcols); 1144 1145 /* fill our own emulops */ 1146 ri->ri_ops.cursor = om4_cursor; 1147 ri->ri_ops.mapchar = om_mapchar; 1148 ri->ri_ops.putchar = om4_putchar; 1149 ri->ri_ops.copycols = om4_copycols; 1150 ri->ri_ops.erasecols = om4_erasecols; 1151 ri->ri_ops.copyrows = om4_copyrows; 1152 ri->ri_ops.eraserows = om4_eraserows; 1153 ri->ri_ops.allocattr = om4_allocattr; 1154 ri->ri_caps = WSSCREEN_HILIT | WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1155 1156 ri->ri_flg |= RI_CFGDONE; 1157 1158 return 0; 1159 } 1160 1161 static int 1162 omrasops_init(struct rasops_info *ri, int wantrows, int wantcols) 1163 { 1164 int wsfcookie, bpp; 1165 1166 if (wantrows == 0) 1167 wantrows = 34; 1168 if (wantrows < 10) 1169 wantrows = 10; 1170 if (wantcols == 0) 1171 wantcols = 80; 1172 if (wantcols < 20) 1173 wantcols = 20; 1174 1175 /* Use default font */ 1176 wsfont_init(); 1177 wsfcookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R, 1178 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP); 1179 if (wsfcookie < 0) 1180 panic("%s: no font available", __func__); 1181 if (wsfont_lock(wsfcookie, &ri->ri_font)) 1182 panic("%s: unable to lock font", __func__); 1183 ri->ri_wsfcookie = wsfcookie; 1184 1185 KASSERT(ri->ri_font->fontwidth > 4 && ri->ri_font->fontwidth <= 32); 1186 1187 /* all planes are independently addressed */ 1188 bpp = 1; 1189 1190 /* Now constrain what they get */ 1191 ri->ri_emuwidth = ri->ri_font->fontwidth * wantcols; 1192 ri->ri_emuheight = ri->ri_font->fontheight * wantrows; 1193 if (ri->ri_emuwidth > ri->ri_width) 1194 ri->ri_emuwidth = ri->ri_width; 1195 if (ri->ri_emuheight > ri->ri_height) 1196 ri->ri_emuheight = ri->ri_height; 1197 1198 /* Reduce width until aligned on a 32-bit boundary */ 1199 while ((ri->ri_emuwidth * bpp & 31) != 0) 1200 ri->ri_emuwidth--; 1201 1202 ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth; 1203 ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight; 1204 ri->ri_emustride = ri->ri_emuwidth * bpp >> 3; 1205 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 1206 ri->ri_ccol = 0; 1207 ri->ri_crow = 0; 1208 ri->ri_pelbytes = bpp >> 3; 1209 1210 ri->ri_xscale = (ri->ri_font->fontwidth * bpp) >> 3; 1211 ri->ri_yscale = ri->ri_font->fontheight * ri->ri_stride; 1212 ri->ri_fontscale = ri->ri_font->fontheight * ri->ri_font->stride; 1213 1214 /* Clear the entire display */ 1215 if ((ri->ri_flg & RI_CLEAR) != 0) 1216 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 1217 1218 /* Now centre our window if needs be */ 1219 ri->ri_origbits = ri->ri_bits; 1220 1221 if ((ri->ri_flg & RI_CENTER) != 0) { 1222 ri->ri_bits += (((ri->ri_width * bpp >> 3) - 1223 ri->ri_emustride) >> 1) & ~3; 1224 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 1225 ri->ri_stride; 1226 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 1227 / ri->ri_stride; 1228 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 1229 % ri->ri_stride) * 8 / bpp); 1230 } else 1231 ri->ri_xorigin = ri->ri_yorigin = 0; 1232 1233 return 0; 1234 } 1235