rndr_gu2.c revision f29dbc25
1/* Copyright (c) 2005 Advanced Micro Devices, Inc. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 * 21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its 22 * contributors may be used to endorse or promote products derived from this 23 * software without specific prior written permission. 24 * */ 25 26/* 27 * This file contains routines to program the 2D acceleration hardware for 28 * the second generation graphics unit. 29 * 30 * Basic rendering routines (common to all Geode processors): 31 * gfx_set_bpp 32 * gfx_set_solid_pattern 33 * gfx_set_mono_pattern 34 * gfx_set_color_pattern 35 * gfx_set_solid_source 36 * gfx_set_mono_source 37 * gfx_set_raster_operation 38 * gfx_pattern_fill 39 * gfx_color_pattern_fill 40 * gfx_screen_to_screen_blt 41 * gfx_screen_to_screen_xblt 42 * gfx_color_bitmap_to_screen_blt 43 * gfx_color_bitmap_to_screen_xblt 44 * gfx_mono_bitmap_to_screen_blt 45 * gfx_bresenham_line 46 * gfx_wait_until_idle 47 * 48 * Extended rendering routines for second generation functionality: 49 * gfx2_set_source_stride 50 * gfx2_set_destination_stride 51 * gfx2_set_pattern_origins 52 * gfx2_set_source_transparency 53 * gfx2_set_alpha_mode 54 * gfx2_set_alpha_value 55 * gfx2_pattern_fill 56 * gfx2_color_pattern_fill 57 * gfx2_screen_to_screen_blt 58 * gfx2_mono_expand_blt 59 * gfx2_color_bitmap_to_screen_blt 60 * gfx2_mono_bitmap_to_screen_blt 61 * gfx2_bresenham_line 62 * gfx2_sync_to_vblank 63 * */ 64 65#define GU2_WAIT_PENDING \ 66 while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING) 67#define GU2_WAIT_BUSY \ 68 while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY) 69#define GU2_WAIT_HALF_EMPTY \ 70 while(!(READ_GP32(MGP_BLT_STATUS) & MGP_BS_HALF_EMPTY)) 71 72/* PATTERN SWIZZLES */ 73 74#define WORD_SWIZZLE(x) (((x) << 16) | ((x) >> 16)) 75#define BYTE_SWIZZLE(x) (((x) << 24) | ((x) >> 24) | (((x) << 8) & \ 76 0x00FF0000) | (((x) >> 8) & 0x0000FF00)) 77 78/* GLOBAL VARIABLES USED BY THE RENDERING ROUTINES */ 79 80unsigned long gu2_bpp; 81unsigned long gu2_pitch = 1280; 82unsigned long gu2_src_pitch = 1280; 83unsigned long gu2_dst_pitch = 1280; 84unsigned long gu2_xshift = 1; 85unsigned long gu2_pattern_origin = 0; 86unsigned long gu2_rop32; 87unsigned long gu2_alpha32 = 0; 88unsigned long gu2_alpha_value = 0; 89unsigned long gu2_alpha_mode = 0; 90unsigned long gu2_alpha_active = 0; 91unsigned short gu2_alpha_blt_mode = 0; 92unsigned short gu2_alpha_vec_mode = 0; 93unsigned short gu2_blt_mode = 0; 94unsigned short gu2_vector_mode = 0; 95unsigned short gu2_bm_throttle = 0; 96unsigned short gu2_vm_throttle = 0; 97int gu2_current_line = 0; 98 99/* Kill a warning */ 100void gfx_reset_pitch(unsigned short pitch); 101 102/*--------------------------------------------------------------------------- 103 * GFX_RESET_PITCH (PRIVATE ROUTINE - NOT PART OF API) 104 * 105 * This routine resets all pitches in the graphics engine to one value. 106 *--------------------------------------------------------------------------- 107 */ 108#if GFX_2DACCEL_DYNAMIC 109void 110gu2_reset_pitch(unsigned short pitch) 111#else 112void 113gfx_reset_pitch(unsigned short pitch) 114#endif 115{ 116 gu2_pitch = pitch; 117 gu2_dst_pitch = pitch; 118 gu2_src_pitch = pitch; 119} 120 121/*--------------------------------------------------------------------------- 122 * GFX_SET_BPP 123 * 124 * This routine sets the bits per pixel value in the graphics engine. 125 * It is also stored in the static variable "gu2_bpp" to use in the future 126 * calls to the rendering routines. That variable contains the hardware 127 * specific value to load into the MGP_RASTER_MODE register. 128 *--------------------------------------------------------------------------- 129 */ 130#if GFX_2DACCEL_DYNAMIC 131void 132gu2_set_bpp(unsigned short bpp) 133#else 134void 135gfx_set_bpp(unsigned short bpp) 136#endif 137{ 138 GFXbpp = bpp; 139 140 /* COVERT TO BPP/FORMAT VALUE */ 141 /* Save in global to combine with ROP later. */ 142 /* Could write register here and then use byte access for */ 143 /* the ROP, but would need to set other 24 bits to make */ 144 /* sure all are set to their appropriate values. */ 145 146 switch (bpp) { 147 case 8: 148 gu2_bpp = MGP_RM_BPPFMT_332; 149 gu2_xshift = 0; 150 break; 151 case 12: 152 gu2_bpp = MGP_RM_BPPFMT_4444; 153 gu2_xshift = 1; 154 break; 155 case 15: 156 gu2_bpp = MGP_RM_BPPFMT_1555; 157 gu2_xshift = 1; 158 break; 159 case 16: 160 gu2_bpp = MGP_RM_BPPFMT_565; 161 gu2_xshift = 1; 162 break; 163 case 32: 164 gu2_bpp = MGP_RM_BPPFMT_8888; 165 gu2_xshift = 2; 166 break; 167 } 168 169 /* SET INITIAL ROP BASED ONLY ON BPP */ 170 /* Needs to be set before loading any pattern or source colors. */ 171 /* We must wait for BUSY because these bits are not pipelined */ 172 /* in the hardware. */ 173 174 GU2_WAIT_BUSY; 175 WRITE_GP32(MGP_RASTER_MODE, gu2_bpp); 176} 177 178/* 179 *--------------------------------------------------------------------------- 180 * GFX_SET_SOLID_SOURCE 181 * 182 * This routine is used to specify a solid source color. For the Xfree96 183 * display driver, the source color is used to specify a planemask and the 184 * ROP is adjusted accordingly. 185 *--------------------------------------------------------------------------- 186 */ 187#if GFX_2DACCEL_DYNAMIC 188void 189gu2_set_solid_source(unsigned long color) 190#else 191void 192gfx_set_solid_source(unsigned long color) 193#endif 194{ 195 /* CLEAR TRANSPARENCY FLAG */ 196 197 GFXsourceFlags = 0; 198 199 /* WRITE REGISTERS TO SPECIFY SOURCE COLOR */ 200 201 GU2_WAIT_PENDING; 202 WRITE_GP32(MGP_SRC_COLOR_FG, color); 203} 204 205/* 206 *--------------------------------------------------------------------------- 207 * GFX_SET_MONO_SOURCE 208 * 209 * This routine is used to specify the monochrome source colors. 210 * It must be called *after* loading any pattern data (those routines 211 * clear the source flags). 212 *--------------------------------------------------------------------------- 213 */ 214#if GFX_2DACCEL_DYNAMIC 215void 216gu2_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, 217 unsigned short transparent) 218#else 219void 220gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, 221 unsigned short transparent) 222#endif 223{ 224 /* SET TRANSPARENCY FLAG */ 225 226 GFXsourceFlags = transparent ? MGP_RM_SRC_TRANS : 0; 227 228 /* WRITE COLOR VALUES */ 229 230 GU2_WAIT_PENDING; 231 WRITE_GP32(MGP_SRC_COLOR_FG, fgcolor); 232 WRITE_GP32(MGP_SRC_COLOR_BG, bgcolor); 233} 234 235/* 236 *--------------------------------------------------------------------------- 237 * GFX_SET_SOLID_PATTERN 238 * 239 * This routine is used to specify a solid pattern color. It is called 240 * before performing solid rectangle fills or more complicated BLTs that 241 * use a solid pattern color. 242 * 243 * The driver should always call "gfx_load_raster_operation" after a call 244 * to this routine to make sure that the pattern flags are set appropriately. 245 *--------------------------------------------------------------------------- 246 */ 247#if GFX_2DACCEL_DYNAMIC 248void 249gu2_set_solid_pattern(unsigned long color) 250#else 251void 252gfx_set_solid_pattern(unsigned long color) 253#endif 254{ 255 /* CLEAR TRANSPARENCY FLAG */ 256 257 GFXsourceFlags = 0; 258 259 /* SET PATTERN FLAGS */ 260 261 GFXpatternFlags = 0; 262 263 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ 264 265 GU2_WAIT_PENDING; 266 WRITE_GP32(MGP_RASTER_MODE, gu2_bpp); 267 WRITE_GP32(MGP_PAT_COLOR_0, color); 268} 269 270/* 271 *--------------------------------------------------------------------------- 272 * GFX_SET_MONO_PATTERN 273 * 274 * This routine is used to specify a monochrome pattern. 275 *--------------------------------------------------------------------------- 276 */ 277#if GFX_2DACCEL_DYNAMIC 278void 279gu2_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, 280 unsigned long data0, unsigned long data1, unsigned char transparent) 281#else 282void 283gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, 284 unsigned long data0, unsigned long data1, unsigned char transparent) 285#endif 286{ 287 /* CLEAR TRANSPARENCY FLAG */ 288 289 GFXsourceFlags = 0; 290 291 /* SET PATTERN FLAGS */ 292 293 if (transparent) 294 GFXpatternFlags = MGP_RM_PAT_MONO | MGP_RM_PAT_TRANS; 295 else 296 GFXpatternFlags = MGP_RM_PAT_MONO; 297 298 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ 299 300 GU2_WAIT_PENDING; 301 WRITE_GP32(MGP_RASTER_MODE, gu2_bpp | GFXpatternFlags); 302 WRITE_GP32(MGP_PAT_COLOR_0, bgcolor); 303 WRITE_GP32(MGP_PAT_COLOR_1, fgcolor); 304 WRITE_GP32(MGP_PAT_DATA_0, data0); 305 WRITE_GP32(MGP_PAT_DATA_1, data1); 306} 307 308/* 309 *--------------------------------------------------------------------------- 310 * GFX_SET_COLOR_PATTERN 311 * 312 * This routine is used to specify a color pattern. 313 *--------------------------------------------------------------------------- 314 */ 315#if GFX_2DACCEL_DYNAMIC 316void 317gu2_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, 318 unsigned long data0, unsigned long data1, unsigned long data2, 319 unsigned long data3, unsigned char transparent) 320#else 321void 322gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, 323 unsigned long data0, unsigned long data1, unsigned long data2, 324 unsigned long data3, unsigned char transparent) 325#endif 326{ 327 /* REMOVE */ 328} 329 330/* 331 *--------------------------------------------------------------------------- 332 * GFX_LOAD_COLOR_PATTERN_LINE 333 * 334 * This routine is used to load a single line of a 8x8 color pattern. 335 *--------------------------------------------------------------------------- */ 336#if GFX_2DACCEL_DYNAMIC 337void 338gu2_load_color_pattern_line(short y, unsigned long *pattern_8x8) 339#else 340void 341gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8) 342#endif 343{ 344 unsigned long temp1, temp2, temp3, temp4; 345 346 /* CLEAR TRANSPARENCY FLAG */ 347 348 GFXsourceFlags = 0; 349 350 /* SET PATTERN FLAGS */ 351 352 GFXpatternFlags = MGP_RM_PAT_COLOR; 353 354 /* OVERRIDE THE RASTER MODE REGISTER */ 355 /* If the pattern format is set to anything but color */ 356 /* before loading the registers, some of the data will */ 357 /* be duplicated according to the current mode. */ 358 359 GU2_WAIT_PENDING; 360 WRITE_GP32(MGP_RASTER_MODE, 361 (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR); 362 363 /* LOAD THE PATTERN DATA */ 364 /* This routine is designed to work in tandem with gfx_pattern_fill. */ 365 /* It is used for cases when multiple BLTs with color pattern data */ 366 /* are desired on the same line. It would be inefficient to */ 367 /* repeatedly call gfx_color_pattern_fill for each single-line BLT. */ 368 /* So, we will simply replicate the pattern data across all available */ 369 /* lines such that the pattern y origin plays no part in the BLT. */ 370 371 /* 8 BPP */ 372 373 if (gu2_xshift == 0) { 374 pattern_8x8 += (y & 7) << 1; 375 temp1 = BYTE_SWIZZLE(pattern_8x8[0]); 376 temp2 = BYTE_SWIZZLE(pattern_8x8[1]); 377 WRITE_GP32(MGP_PAT_DATA_1, temp1); 378 WRITE_GP32(MGP_PAT_DATA_0, temp2); 379 WRITE_GP32(MGP_PAT_COLOR_1, temp1); 380 WRITE_GP32(MGP_PAT_COLOR_0, temp2); 381 382 GU2_WAIT_BUSY; 383 WRITE_GP32(MGP_PAT_COLOR_3, temp1); 384 WRITE_GP32(MGP_PAT_COLOR_2, temp2); 385 WRITE_GP32(MGP_PAT_COLOR_5, temp1); 386 WRITE_GP32(MGP_PAT_COLOR_4, temp2); 387 } else if (gu2_xshift == 1) { 388 pattern_8x8 += (y & 7) << 2; 389 temp1 = WORD_SWIZZLE(pattern_8x8[0]); 390 temp2 = WORD_SWIZZLE(pattern_8x8[1]); 391 temp3 = WORD_SWIZZLE(pattern_8x8[2]); 392 temp4 = WORD_SWIZZLE(pattern_8x8[3]); 393 394 WRITE_GP32(MGP_PAT_COLOR_1, temp1); 395 WRITE_GP32(MGP_PAT_COLOR_0, temp2); 396 WRITE_GP32(MGP_PAT_DATA_1, temp3); 397 WRITE_GP32(MGP_PAT_DATA_0, temp4); 398 399 GU2_WAIT_BUSY; 400 WRITE_GP32(MGP_PAT_COLOR_5, temp1); 401 WRITE_GP32(MGP_PAT_COLOR_4, temp2); 402 WRITE_GP32(MGP_PAT_COLOR_3, temp3); 403 WRITE_GP32(MGP_PAT_COLOR_2, temp4); 404 } else { 405 pattern_8x8 += (y & 7) << 3; 406 407 WRITE_GP32(MGP_PAT_COLOR_1, pattern_8x8[4]); 408 WRITE_GP32(MGP_PAT_COLOR_0, pattern_8x8[5]); 409 WRITE_GP32(MGP_PAT_DATA_1, pattern_8x8[6]); 410 WRITE_GP32(MGP_PAT_DATA_0, pattern_8x8[7]); 411 412 GU2_WAIT_BUSY; 413 WRITE_GP32(MGP_PAT_COLOR_5, pattern_8x8[0]); 414 WRITE_GP32(MGP_PAT_COLOR_4, pattern_8x8[1]); 415 WRITE_GP32(MGP_PAT_COLOR_3, pattern_8x8[2]); 416 WRITE_GP32(MGP_PAT_COLOR_2, pattern_8x8[3]); 417 } 418} 419 420/* 421 *--------------------------------------------------------------------------- 422 * GFX_SET_RASTER_OPERATION 423 * 424 * This routine loads the specified raster operation. It sets the pattern 425 * flags appropriately. 426 *--------------------------------------------------------------------------- 427 */ 428#if GFX_2DACCEL_DYNAMIC 429void 430gu2_set_raster_operation(unsigned char rop) 431#else 432void 433gfx_set_raster_operation(unsigned char rop) 434#endif 435{ 436 gu2_blt_mode = 0; 437 438 /* DISABLE ALPHA BLENDING */ 439 440 gu2_alpha_active = 0; 441 442 /* GENERATE 32-BIT VERSION OF ROP WITH PATTERN FLAGS */ 443 444 gu2_rop32 = (unsigned long)rop | GFXpatternFlags | gu2_bpp; 445 446 /* CHECK IF SOURCE FLAGS SHOULD BE MERGED */ 447 448 if ((rop & 0x33) ^ ((rop >> 2) & 0x33)) 449 gu2_rop32 |= GFXsourceFlags; 450 else 451 gu2_blt_mode = 0x40; 452 453 /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */ 454 /* True if even bits (0:2:4:6) do not equal the corresponding */ 455 /* even bits (1:3:5:7). */ 456 457 if ((rop & 0x55) ^ ((rop >> 1) & 0x55)) { 458 gu2_blt_mode |= MGP_BM_DST_REQ; 459 gu2_vector_mode = MGP_VM_DST_REQ; 460 } else { 461 gu2_vector_mode = 0; 462 } 463} 464 465/* 466 *---------------------------------------------------------------------------- 467 * GFX_PATTERN_FILL 468 * 469 * This routine is used to fill a rectangular region. The pattern must 470 * be previously loaded using one of GFX_load_*_pattern routines. Also, the 471 * raster operation must be previously specified using the 472 * "GFX_load_raster_operation" routine. 473 * 474 * X screen X position (left) 475 * Y screen Y position (top) 476 * WIDTH width of rectangle, in pixels 477 * HEIGHT height of rectangle, in scanlines 478 *---------------------------------------------------------------------------- 479 */ 480#if GFX_2DACCEL_DYNAMIC 481void 482gu2_pattern_fill(unsigned short x, unsigned short y, 483 unsigned short width, unsigned short height) 484#else 485void 486gfx_pattern_fill(unsigned short x, unsigned short y, 487 unsigned short width, unsigned short height) 488#endif 489{ 490 unsigned long offset = 0, size; 491 492 size = (((unsigned long)width) << 16) | height; 493 494 /* CALCULATE STARTING OFFSET */ 495 496 offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift); 497 498 /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ 499 500 if (GFXpatternFlags) { 501 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 502 503 offset |= ((unsigned long)(x & 7)) << 26; 504 offset |= ((unsigned long)(y & 7)) << 29; 505 } 506 507 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 508 /* Put off poll for as long as possible (do most calculations first). */ 509 510 GU2_WAIT_PENDING; 511 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); 512 WRITE_GP32(MGP_DST_OFFSET, offset); 513 WRITE_GP32(MGP_WID_HEIGHT, size); 514 WRITE_GP32(MGP_STRIDE, gu2_pitch); 515 WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode); 516} 517 518/* 519 *---------------------------------------------------------------------------- 520 * GFX_COLOR_PATTERN_FILL 521 * 522 * This routine is used to render a rectangle using the current raster 523 * operation and the specified color pattern. It allows an 8x8 color 524 * pattern to be rendered without multiple calls to the gfx_set_color_pattern 525 * and gfx_pattern_fill routines. 526 * 527 * X screen X position (left) 528 * Y screen Y position (top) 529 * WIDTH width of rectangle, in pixels 530 * HEIGHT height of rectangle, in scanlines 531 * *PATTERN pointer to 8x8 color pattern data 532 *---------------------------------------------------------------------------- 533 */ 534#if GFX_2DACCEL_DYNAMIC 535void 536gu2_color_pattern_fill(unsigned short x, unsigned short y, 537 unsigned short width, unsigned short height, unsigned long *pattern) 538#else 539void 540gfx_color_pattern_fill(unsigned short x, unsigned short y, 541 unsigned short width, unsigned short height, unsigned long *pattern) 542#endif 543{ 544 /* CALL GFX2 ROUTINE TO AVOID DUPLICATION OF CODE */ 545 546 unsigned long offset = (unsigned long)y * gu2_pitch + 547 (((unsigned long)x) << gu2_xshift); 548 unsigned long origin = gu2_pattern_origin; 549 unsigned long pitch = gu2_dst_pitch; 550 551 gfx2_set_pattern_origin(x, y); 552 gfx2_set_destination_stride((unsigned short)gu2_pitch); 553 gfx2_color_pattern_fill(offset, width, height, pattern); 554 555 /* RESTORE GFX2 VALUES */ 556 557 gu2_pattern_origin = origin; 558 gu2_dst_pitch = pitch; 559} 560 561/* 562 *---------------------------------------------------------------------------- 563 * SCREEN TO SCREEN BLT 564 * 565 * This routine should be used to perform a screen to screen BLT when the 566 * ROP does not require destination data. 567 * 568 * SRCX screen X position to copy from 569 * SRCY screen Y position to copy from 570 * DSTX screen X position to copy to 571 * DSTY screen Y position to copy to 572 * WIDTH width of rectangle, in pixels 573 * HEIGHT height of rectangle, in scanlines 574 *---------------------------------------------------------------------------- 575 */ 576#if GFX_2DACCEL_DYNAMIC 577void 578gu2_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, 579 unsigned short dstx, unsigned short dsty, unsigned short width, 580 unsigned short height) 581#else 582void 583gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, 584 unsigned short dstx, unsigned short dsty, unsigned short width, 585 unsigned short height) 586#endif 587{ 588 unsigned long srcoffset, dstoffset, size; 589 unsigned short blt_mode; 590 591 size = (((unsigned long)width) << 16) | height; 592 593 /* CALCULATE THE DIRECTION OF THE BLT */ 594 595 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; 596 if (dstx > srcx) { 597 blt_mode |= MGP_BM_NEG_XDIR; 598 srcx += width - 1; 599 dstx += width - 1; 600 } 601 if (dsty > srcy) { 602 blt_mode |= MGP_BM_NEG_YDIR; 603 srcy += height - 1; 604 dsty += height - 1; 605 } 606 607 /* CALCULATE STARTING OFFSETS */ 608 609 srcoffset = (unsigned long)srcy *gu2_pitch + 610 (((unsigned long)srcx) << gu2_xshift); 611 dstoffset = ((unsigned long)dsty * gu2_pitch + 612 (((unsigned long)dstx) << gu2_xshift)) & 0xFFFFFF; 613 614 /* MERGE PATTERN INFORMATION */ 615 /* This must be done after the x and y coordinates have been updated, */ 616 /* as the x and y pattern origins correspond to the first ROPed pixel. */ 617 618 if (GFXpatternFlags) { 619 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 620 621 dstoffset |= ((unsigned long)(dstx & 7)) << 26; 622 dstoffset |= ((unsigned long)(dsty & 7)) << 29; 623 } 624 625 /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */ 626 /* This is a quirk of the hardware. */ 627 628 if (blt_mode & MGP_BM_NEG_XDIR) { 629 srcoffset += (1 << gu2_xshift) - 1; 630 dstoffset += (1 << gu2_xshift) - 1; 631 } 632 633 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 634 /* Put off poll for as long as possible (do most calculations first). */ 635 636 GU2_WAIT_PENDING; 637 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 638 WRITE_GP32(MGP_SRC_OFFSET, srcoffset); 639 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 640 WRITE_GP32(MGP_WID_HEIGHT, size); 641 WRITE_GP32(MGP_STRIDE, gu2_pitch | (gu2_pitch << 16)); 642 WRITE_GP16(MGP_BLT_MODE, blt_mode); 643} 644 645/* 646 *---------------------------------------------------------------------------- 647 * SCREEN TO SCREEN TRANSPARENT BLT 648 * 649 * This routine should be used to perform a screen to screen BLT when a 650 * specified color should by transparent. The only supported ROP is SRCCOPY. 651 * 652 * SRCX screen X position to copy from 653 * SRCY screen Y position to copy from 654 * DSTX screen X position to copy to 655 * DSTY screen Y position to copy to 656 * WIDTH width of rectangle, in pixels 657 * HEIGHT height of rectangle, in scanlines 658 * COLOR transparent color 659 *---------------------------------------------------------------------------- 660 */ 661#if GFX_2DACCEL_DYNAMIC 662void 663gu2_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, 664 unsigned short dstx, unsigned short dsty, unsigned short width, 665 unsigned short height, unsigned long color) 666#else 667void 668gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, 669 unsigned short dstx, unsigned short dsty, unsigned short width, 670 unsigned short height, unsigned long color) 671#endif 672{ 673 unsigned long rop32; 674 675 /* SAVE ORIGINAL RASTER MODE SETTINGS */ 676 677 rop32 = gu2_rop32; 678 679 /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ 680 /* Match GU1 implementation that only allows SRCCOPY for the ROP. */ 681 682 GU2_WAIT_PENDING; 683 WRITE_GP32(MGP_SRC_COLOR_FG, color); 684 WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF); 685 686 /* SET GLOBAL RASTER SETTINGS */ 687 /* This is needed, as the screen-to-screen BLT */ 688 /* routine will overwrite the raster mode register. */ 689 690 gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC; 691 692 /* CALL NORMAL SCREEN TO SCREEN BLT ROUTINE */ 693 694 gfx_screen_to_screen_blt(srcx, srcy, dstx, dsty, width, height); 695 696 /* RESTORE GLOBAL RASTER SETTINGS */ 697 698 gu2_rop32 = rop32; 699} 700 701/* 702 *---------------------------------------------------------------------------- 703 * COLOR BITMAP TO SCREEN BLT 704 * 705 * This routine transfers color bitmap data to the screen. 706 * 707 * SRCX X offset within source bitmap 708 * SRCY Y offset within source bitmap 709 * DSTX screen X position to render data 710 * DSTY screen Y position to render data 711 * WIDTH width of rectangle, in pixels 712 * HEIGHT height of rectangle, in scanlines 713 * *DATA pointer to bitmap data 714 * PITCH pitch of bitmap data (bytes between scanlines) 715 * 716 * Transparency is handled by another routine. 717 *---------------------------------------------------------------------------- 718 */ 719 720#if GFX_2DACCEL_DYNAMIC 721void 722gu2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 723 unsigned short dstx, unsigned short dsty, unsigned short width, 724 unsigned short height, unsigned char *data, long pitch) 725#else 726void 727gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 728 unsigned short dstx, unsigned short dsty, unsigned short width, 729 unsigned short height, unsigned char *data, long pitch) 730#endif 731{ 732 unsigned long dstoffset, srcoffset, size, bytes; 733 unsigned long offset, temp_offset; 734 unsigned long dword_bytes, bytes_extra; 735 unsigned short blt_mode; 736 737 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; 738 size = (((unsigned long)width) << 16) | 1; 739 740 /* CALCULATE STARTING OFFSETS */ 741 742 offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift); 743 744 dstoffset = (unsigned long)dsty *gu2_pitch + 745 (((unsigned long)dstx) << gu2_xshift); 746 747 /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ 748 749 if (GFXpatternFlags) { 750 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 751 752 dstoffset |= ((unsigned long)(dstx & 7)) << 26; 753 dstoffset |= ((unsigned long)(dsty & 7)) << 29; 754 } 755 756 bytes = width << gu2_xshift; 757 dword_bytes = bytes & ~0x3L; 758 bytes_extra = bytes & 0x3L; 759 760 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 761 /* Put off poll for as long as possible (do most calculations first). */ 762 /* The source offset is always 0 since we allow misaligned dword reads. */ 763 /* We must wait for BLT busy because the GP may be executing a screen */ 764 /* to screen BLT from the scratchpad area. */ 765 766 GU2_WAIT_BUSY; 767 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 768 WRITE_GP32(MGP_WID_HEIGHT, size); 769 WRITE_GP32(MGP_STRIDE, gu2_pitch); 770 771 /* WRITE DATA ONE LINE AT A TIME */ 772 /* For speed reasons, data is written to an offscreen scratch area and then */ 773 /* BLTed using a screen to screen BLT. This is similar to the GX1 BLT buffers, but */ 774 /* slightly more efficient in that we can queue up data while the GP is rendering */ 775 /* a line. */ 776 777 while (height--) { 778 temp_offset = offset; 779 srcoffset = gfx_gx2_scratch_base; 780 if (gu2_current_line) 781 srcoffset += 8192; 782 783 GU2_WAIT_PENDING; 784 WRITE_GP32(MGP_SRC_OFFSET, srcoffset); 785 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 786 dstoffset += gu2_pitch; 787 dstoffset += 0x20000000; 788 789 WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data, 790 temp_offset); 791 if (bytes_extra) { 792 temp_offset += dword_bytes; 793 srcoffset += dword_bytes; 794 WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data, 795 temp_offset); 796 } 797 WRITE_GP16(MGP_BLT_MODE, blt_mode); 798 offset += pitch; 799 gu2_current_line = 1 - gu2_current_line; 800 } 801} 802 803/* 804 *---------------------------------------------------------------------------- 805 * COLOR BITMAP TO SCREEN TRANSPARENT BLT 806 * 807 * This routine transfers color bitmap data to the screen with transparency. 808 * The transparent color is specified. The only supported ROP is SRCCOPY, 809 * meaning that transparency cannot be applied if the ROP requires 810 * destination data (this is a hardware restriction). 811 * 812 * SRCX X offset within source bitmap 813 * SRCY Y offset within source bitmap 814 * DSTX screen X position to render data 815 * DSTY screen Y position to render data 816 * WIDTH width of rectangle, in pixels 817 * HEIGHT height of rectangle, in scanlines 818 * *DATA pointer to bitmap data 819 * PITCH pitch of bitmap data (bytes between scanlines) 820 * COLOR transparent color 821 *---------------------------------------------------------------------------- 822 */ 823#if GFX_2DACCEL_DYNAMIC 824void 825gu2_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, 826 unsigned short dstx, unsigned short dsty, unsigned short width, 827 unsigned short height, unsigned char *data, long pitch, 828 unsigned long color) 829#else 830void 831gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, 832 unsigned short dstx, unsigned short dsty, unsigned short width, 833 unsigned short height, unsigned char *data, long pitch, 834 unsigned long color) 835#endif 836{ 837 unsigned long rop32; 838 839 /* SAVE EXISTING RASTER MODE SETTINGS */ 840 841 rop32 = gu2_rop32; 842 843 /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ 844 /* Match GU1 implementation that only allows SRCCOPY for the ROP. */ 845 846 GU2_WAIT_PENDING; 847 WRITE_GP32(MGP_SRC_COLOR_FG, color); 848 WRITE_GP32(MGP_SRC_COLOR_BG, 0xFFFFFFFF); 849 850 /* SET GLOBAL RASTER SETTINGS */ 851 /* This is needed, as the screen-to-screen BLT */ 852 /* routine will overwrite the raster mode register. */ 853 854 gu2_rop32 = gu2_bpp | MGP_RM_SRC_TRANS | 0xCC; 855 856 /* CALL NORMAL COLOR BITMAP TO SCREEN BLT ROUTINE */ 857 858 gfx_color_bitmap_to_screen_blt(srcx, srcy, dstx, dsty, width, height, 859 data, pitch); 860 861 /* RESTORE RASTER SETTINGS */ 862 863 gu2_rop32 = rop32; 864} 865 866/* 867 *---------------------------------------------------------------------------- 868 * MONOCHROME BITMAP TO SCREEN BLT 869 * 870 * This routine transfers monochrome bitmap data to the screen. 871 * 872 * SRCX X offset within source bitmap 873 * SRCY Y offset within source bitmap 874 * DSTX screen X position to render data 875 * DSTY screen Y position to render data 876 * WIDTH width of rectangle, in pixels 877 * HEIGHT height of rectangle, in scanlines 878 * *DATA pointer to bitmap data 879 * PITCH pitch of bitmap data (bytes between scanlines) 880 *---------------------------------------------------------------------------- 881 */ 882#if GFX_2DACCEL_DYNAMIC 883void 884gu2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 885 unsigned short dstx, unsigned short dsty, unsigned short width, 886 unsigned short height, unsigned char *data, short pitch) 887#else 888void 889gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 890 unsigned short dstx, unsigned short dsty, unsigned short width, 891 unsigned short height, unsigned char *data, short pitch) 892#endif 893{ 894 unsigned long dstoffset, size, bytes; 895 unsigned long offset, temp_offset, temp1 = 0, temp2 = 0; 896 unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; 897 unsigned long shift = 0; 898 899 size = (((unsigned long)width) << 16) | height; 900 901 /* CALCULATE STARTING OFFSETS */ 902 903 offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3); 904 905 dstoffset = (unsigned long)dsty *gu2_pitch + 906 (((unsigned long)dstx) << gu2_xshift); 907 908 /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ 909 910 if (GFXpatternFlags) { 911 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 912 913 dstoffset |= ((unsigned long)(dstx & 7)) << 26; 914 dstoffset |= ((unsigned long)(dsty & 7)) << 29; 915 } 916 917 bytes = ((srcx & 7) + width + 7) >> 3; 918 fifo_lines = bytes >> 5; 919 dwords_extra = (bytes & 0x0000001Cl) >> 2; 920 bytes_extra = bytes & 0x00000003l; 921 922 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 923 /* Put off poll for as long as possible (do most calculations first). */ 924 /* The source offset is always 0 since we allow misaligned dword reads. */ 925 /* Need to wait for busy instead of pending, since hardware clears */ 926 /* the host data FIFO at the beginning of a BLT. */ 927 928 GU2_WAIT_PENDING; 929 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 930 WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26); 931 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 932 WRITE_GP32(MGP_WID_HEIGHT, size); 933 WRITE_GP32(MGP_STRIDE, gu2_pitch); 934 WRITE_GP16(MGP_BLT_MODE, 935 (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST | 936 MGP_BM_SRC_MONO); 937 938 /* WAIT FOR BLT TO BE LATCHED */ 939 940 GU2_WAIT_PENDING; 941 942 /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */ 943 944 while (height--) { 945 temp_offset = offset; 946 947 /* WRITE ALL FULL FIFO LINES */ 948 949 for (i = 0; i < fifo_lines; i++) { 950 GU2_WAIT_HALF_EMPTY; 951 WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, 952 temp1); 953 temp_offset += 32; 954 } 955 956 /* WRITE ALL FULL DWORDS */ 957 958 GU2_WAIT_HALF_EMPTY; 959 if (dwords_extra) { 960 WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, 961 temp_offset, temp1); 962 temp_offset += (dwords_extra << 2); 963 } 964 965 /* WRITE REMAINING BYTES */ 966 967 shift = 0; 968 if (bytes_extra) 969 WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, 970 temp_offset, temp1, temp2); 971 972 offset += pitch; 973 } 974} 975 976/*--------------------------------------------------------------------------- 977 * GFX_TEXT_BLT 978 * 979 * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine 980 * but assumes that source data is byte-packed. 981 *--------------------------------------------------------------------------- 982 */ 983#if GFX_2DACCEL_DYNAMIC 984void 985gu2_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, 986 unsigned short height, unsigned char *data) 987#else 988void 989gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, 990 unsigned short height, unsigned char *data) 991#endif 992{ 993 unsigned long size, bytes; 994 unsigned long dstoffset, temp1 = 0, temp2 = 0, temp_offset = 0; 995 unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; 996 unsigned long shift; 997 998 size = (((unsigned long)width) << 16) | height; 999 1000 dstoffset = (unsigned long)dsty *gu2_pitch + 1001 (((unsigned long)dstx) << gu2_xshift); 1002 1003 /* CHECK IF PATTERN ORIGINS NEED TO BE SET */ 1004 1005 if (GFXpatternFlags) { 1006 /* COMBINE X AND Y PATTERN ORIGINS WITH OFFSET */ 1007 1008 dstoffset |= ((unsigned long)(dstx & 7)) << 26; 1009 dstoffset |= ((unsigned long)(dsty & 7)) << 29; 1010 } 1011 1012 /* CALCULATE STARTING OFFSETS */ 1013 1014 bytes = ((width + 7) >> 3) * height; 1015 fifo_lines = bytes >> 5; 1016 dwords_extra = (bytes & 0x0000001Cl) >> 2; 1017 bytes_extra = bytes & 0x00000003l; 1018 1019 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1020 1021 GU2_WAIT_PENDING; 1022 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 1023 WRITE_GP32(MGP_SRC_OFFSET, 0); 1024 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 1025 WRITE_GP32(MGP_WID_HEIGHT, size); 1026 WRITE_GP32(MGP_STRIDE, gu2_pitch); 1027 WRITE_GP16(MGP_BLT_MODE, 1028 (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_HOST | 1029 MGP_BM_SRC_BP_MONO); 1030 1031 /* WAIT FOR BLT TO BE LATCHED */ 1032 1033 GU2_WAIT_PENDING; 1034 1035 /* WRITE ALL FULL FIFO LINES */ 1036 1037 for (i = 0; i < fifo_lines; i++) { 1038 GU2_WAIT_HALF_EMPTY; 1039 WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1); 1040 temp_offset += 32; 1041 } 1042 1043 /* WRITE ALL FULL DWORDS */ 1044 1045 if (dwords_extra || bytes_extra) { 1046 GU2_WAIT_HALF_EMPTY; 1047 if (dwords_extra) { 1048 WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, 1049 temp_offset, temp1); 1050 temp_offset += (dwords_extra << 2); 1051 } 1052 if (bytes_extra) { 1053 shift = 0; 1054 WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, 1055 temp_offset, temp1, temp2); 1056 } 1057 } 1058} 1059 1060/* 1061 *---------------------------------------------------------------------------- 1062 * BRESENHAM LINE 1063 * 1064 * This routine draws a vector using the specified Bresenham parameters. 1065 * Currently this file does not support a routine that accepts the two 1066 * endpoints of a vector and calculates the Bresenham parameters. If it 1067 * ever does, this routine is still required for vectors that have been 1068 * clipped. 1069 * 1070 * X screen X position to start vector 1071 * Y screen Y position to start vector 1072 * LENGTH length of the vector, in pixels 1073 * INITERR Bresenham initial error term 1074 * AXIALERR Bresenham axial error term 1075 * DIAGERR Bresenham diagonal error term 1076 * FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC 1077 *---------------------------------------------------------------------------- 1078 */ 1079#if GFX_2DACCEL_DYNAMIC 1080void 1081gu2_bresenham_line(unsigned short x, unsigned short y, 1082 unsigned short length, unsigned short initerr, 1083 unsigned short axialerr, unsigned short diagerr, unsigned short flags) 1084#else 1085void 1086gfx_bresenham_line(unsigned short x, unsigned short y, 1087 unsigned short length, unsigned short initerr, 1088 unsigned short axialerr, unsigned short diagerr, unsigned short flags) 1089#endif 1090{ 1091 unsigned long offset; 1092 unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr; 1093 unsigned long data2 = (((unsigned long)length) << 16) | initerr; 1094 unsigned short vector_mode = gu2_vector_mode | flags; 1095 1096 /* CALCULATE STARTING OFFSET */ 1097 1098 offset = (unsigned long)y *gu2_pitch + (((unsigned long)x) << gu2_xshift); 1099 1100 /* CHECK NULL LENGTH */ 1101 1102 if (!length) 1103 return; 1104 1105 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1106 /* Put off poll for as long as possible (do most calculations first). */ 1107 1108 GU2_WAIT_PENDING; 1109 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); 1110 WRITE_GP32(MGP_DST_OFFSET, offset); 1111 WRITE_GP32(MGP_VEC_ERR, data1); 1112 WRITE_GP32(MGP_VEC_LEN, data2); 1113 WRITE_GP32(MGP_STRIDE, gu2_pitch); 1114 WRITE_GP32(MGP_VECTOR_MODE, vector_mode); 1115} 1116 1117/*--------------------------------------------------------------------------- 1118 * GFX_WAIT_UNTIL_IDLE 1119 * 1120 * This routine waits until the graphics engine is idle. This is required 1121 * before allowing direct access to the frame buffer. 1122 *--------------------------------------------------------------------------- 1123 */ 1124#if GFX_2DACCEL_DYNAMIC 1125void 1126gu2_wait_until_idle(void) 1127#else 1128void 1129gfx_wait_until_idle(void) 1130#endif 1131{ 1132 while (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY) ; 1133} 1134 1135/*--------------------------------------------------------------------------- 1136 * GFX_TEST_BLT_PENDING 1137 * 1138 * This routine returns 1 if a BLT is pending, meaning that a call to 1139 * perform a rendering operation would stall. Otherwise it returns 0. 1140 * It is used by Darwin during random testing to only start a BLT 1141 * operation when it knows the Durango routines won't spin on graphics 1142 * (so Darwin can continue to do frame buffer reads and writes). 1143 *--------------------------------------------------------------------------- 1144 */ 1145#if GFX_2DACCEL_DYNAMIC 1146int 1147gu2_test_blt_pending(void) 1148#else 1149int 1150gfx_test_blt_pending(void) 1151#endif 1152{ 1153 if (READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING) 1154 return (1); 1155 return (0); 1156} 1157 1158/*--------------------------------------------------------------------------- 1159 * NEW ROUTINES FOR REDCLOUD 1160 *--------------------------------------------------------------------------- 1161 */ 1162 1163/*--------------------------------------------------------------------------- 1164 * GFX2_SET_SOURCE_STRIDE 1165 * 1166 * This routine sets the stride to be used in successive screen to screen 1167 * BLTs (used by gfx2_screen_to_screen_blt and gfx2_mono_expand_blt). 1168 *--------------------------------------------------------------------------- 1169 */ 1170#if GFX_2DACCEL_DYNAMIC 1171void 1172gu22_set_source_stride(unsigned short stride) 1173#else 1174void 1175gfx2_set_source_stride(unsigned short stride) 1176#endif 1177{ 1178 /* SAVE STRIDE TO BE USED LATER */ 1179 1180 gu2_src_pitch = (unsigned long)stride; 1181} 1182 1183/*--------------------------------------------------------------------------- 1184 * GFX2_SET_DESTINATION_STRIDE 1185 * 1186 * This routine sets the stride used when rendering to the screen. 1187 *--------------------------------------------------------------------------- 1188 */ 1189#if GFX_2DACCEL_DYNAMIC 1190void 1191gu22_set_destination_stride(unsigned short stride) 1192#else 1193void 1194gfx2_set_destination_stride(unsigned short stride) 1195#endif 1196{ 1197 /* SAVE STRIDE TO BE USED LATER */ 1198 1199 gu2_dst_pitch = (unsigned long)stride; 1200} 1201 1202/*--------------------------------------------------------------------------- 1203 * GFX2_SET_PATTERN_ORIGIN 1204 * 1205 * This routine sets the origin within an 8x8 pattern. It is needed if 1206 * using a monochrome or color pattern (not used for a solid pattern). 1207 *--------------------------------------------------------------------------- 1208 */ 1209#if GFX_2DACCEL_DYNAMIC 1210void 1211gu22_set_pattern_origin(int x, int y) 1212#else 1213void 1214gfx2_set_pattern_origin(int x, int y) 1215#endif 1216{ 1217 /* STORE IN FORMAT THAT CAN BE COMBINED WITH THE DESTINATION OFFSET */ 1218 1219 gu2_pattern_origin = (((unsigned long)(x & 7)) << 26) | 1220 (((unsigned long)(y & 7)) << 29); 1221} 1222 1223/*--------------------------------------------------------------------------- 1224 * GFX2_SET_SOURCE_TRANSPARENCY 1225 * 1226 * This routine sets the source transparency color and mask to be used 1227 * in future rendering operations. If both the color and mask are set 1228 * to zero (normally completely transparent), those values indicate that 1229 * transparency should be disabled. 1230 *--------------------------------------------------------------------------- 1231 */ 1232#if GFX_2DACCEL_DYNAMIC 1233void 1234gu22_set_source_transparency(unsigned long color, unsigned long mask) 1235#else 1236void 1237gfx2_set_source_transparency(unsigned long color, unsigned long mask) 1238#endif 1239{ 1240 /* WRITE REGISTERS TO SPECIFY COLOR TRANSPARENCY */ 1241 1242 GU2_WAIT_PENDING; 1243 WRITE_GP32(MGP_SRC_COLOR_FG, color); 1244 WRITE_GP32(MGP_SRC_COLOR_BG, mask); 1245 1246 /* SET TRANSPARENCY FLAG */ 1247 1248 GFXsourceFlags = (color || mask) ? MGP_RM_SRC_TRANS : 0; 1249} 1250 1251/*--------------------------------------------------------------------------- 1252 * GFX2_SET_ALPHA_MODE 1253 * 1254 * This routine sets the alpha blending mode to be used in successive 1255 * rendering operations. 1256 *--------------------------------------------------------------------------- 1257 */ 1258#if GFX_2DACCEL_DYNAMIC 1259void 1260gu22_set_alpha_mode(int mode) 1261#else 1262void 1263gfx2_set_alpha_mode(int mode) 1264#endif 1265{ 1266 /* SAVE ALPHA MODE FOR LATER */ 1267 1268 gu2_alpha_mode = mode; 1269} 1270 1271/*--------------------------------------------------------------------------- 1272 * GFX2_SET_ALPHA_VALUE 1273 * 1274 * This routine sets the alpha value to be used with certain alpha blending 1275 * modes (ALPHA_MODE_BLEND). 1276 *--------------------------------------------------------------------------- 1277 */ 1278#if GFX_2DACCEL_DYNAMIC 1279void 1280gu22_set_alpha_value(unsigned char value) 1281#else 1282void 1283gfx2_set_alpha_value(unsigned char value) 1284#endif 1285{ 1286 /* SAVE ALPHA VALUE TO BE USED LATER */ 1287 1288 gu2_alpha_value = (unsigned long)value; 1289 1290 /* SET GLOBAL FLAG */ 1291 /* gfx2_* routines will use this flag to program alpha values */ 1292 /* appropriately. Normal gfx_* routines will always write */ 1293 /* the current ROP settings. In this way, the alpha mode */ 1294 /* affects only second generation routines. */ 1295 1296 gu2_alpha_active = 1; 1297 1298 switch (gu2_alpha_mode) { 1299 case ALPHA_MODE_BLEND: 1300 1301 /* GENERATE 32-BIT VERSION OF RASTER MODE REGISTER */ 1302 /* Pattern data is not involved in the operation. */ 1303 1304 gu2_alpha32 = gu2_alpha_value | gu2_bpp; 1305 1306 /* HANDLE SPECIAL CASES FOR ENDPOINTS */ 1307 /* The 8-bit hardware alpha value is always */ 1308 /* interpreted as a fraction. Consequently, there */ 1309 /* is no way to use values of 255 or 0 to exclude */ 1310 /* one of the inputs. */ 1311 1312 switch (gu2_alpha_value) { 1313 /* DESTINATION ONLY */ 1314 /* Operation is alpha * A, where A is destination */ 1315 /* and alpha is 1. */ 1316 1317 case 0: 1318 1319 gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 | 1320 MGP_RM_ALPHA_TIMES_A | 1321 MGP_RM_ALPHA_TO_RGB | MGP_RM_DEST_FROM_CHAN_A; 1322 break; 1323 1324 /* SOURCE ONLY */ 1325 /* Operation is alpha * A, where A is source and */ 1326 /* alpha is 1. */ 1327 1328 case 255: 1329 1330 gu2_alpha32 |= MGP_RM_SELECT_ALPHA_1 | 1331 MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_TIMES_A; 1332 break; 1333 1334 /* DEFAULT */ 1335 /* Operation is alpha * A + (1 - alpha) * B; */ 1336 /* A is source, B is destination and alpha is the */ 1337 /* programmed 8-bit value. */ 1338 1339 default: 1340 1341 gu2_alpha32 |= MGP_RM_SELECT_ALPHA_R | 1342 MGP_RM_ALPHA_TO_RGB | MGP_RM_ALPHA_A_PLUS_BETA_B; 1343 1344 } 1345 1346 /* CHECK IF SOURCE INFORMATION SHOULD BE MERGED */ 1347 /* Alpha value of 0 indicates destination only. */ 1348 1349 if (gu2_alpha_value != 0) 1350 gu2_alpha32 |= GFXsourceFlags; 1351 1352 /* SET FLAG FOR DESTINATION DATA IF NECESSARY */ 1353 /* Alpha value of 255 indicates no destination */ 1354 1355 if (gu2_alpha_value != 255) { 1356 gu2_alpha_blt_mode = MGP_BM_DST_REQ; 1357 gu2_alpha_vec_mode = MGP_VM_DST_REQ; 1358 } 1359 1360 break; 1361 } 1362} 1363 1364/*--------------------------------------------------------------------------- 1365 * GFX2_PATTERN_FILL 1366 * 1367 * This routine is similar to the gfx_pattern_fill routine, but allows the 1368 * use of an arbitrary destination stride. The rendering position is 1369 * also specified as an offset instead of an (x,y) position. 1370 *--------------------------------------------------------------------------- 1371 */ 1372#if GFX_2DACCEL_DYNAMIC 1373void 1374gu22_pattern_fill(unsigned long dstoffset, unsigned short width, 1375 unsigned short height) 1376#else 1377void 1378gfx2_pattern_fill(unsigned long dstoffset, unsigned short width, 1379 unsigned short height) 1380#endif 1381{ 1382 unsigned long size; 1383 1384 size = (((unsigned long)width) << 16) | height; 1385 1386 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1387 /* Put off poll for as long as possible (do most calculations first). */ 1388 1389 GU2_WAIT_PENDING; 1390 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); 1391 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 1392 WRITE_GP32(MGP_WID_HEIGHT, size); 1393 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); 1394 WRITE_GP32(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1395 gu2_bm_throttle = 0; 1396 gu2_vm_throttle = 0; 1397} 1398 1399/*--------------------------------------------------------------------------- 1400 * GFX2_COLOR_PATTERN_FILL 1401 * 1402 * This routine is used to render a rectangle using the current raster 1403 * operation and the specified color pattern. It allows an 8x8 color 1404 * pattern to be rendered without multiple calls to the gfx_set_color_pattern 1405 * and gfx_pattern_fill routines. 1406 *--------------------------------------------------------------------------- 1407 */ 1408#if GFX_2DACCEL_DYNAMIC 1409void 1410gu22_color_pattern_fill(unsigned long dstoffset, unsigned short width, 1411 unsigned short height, unsigned long *pattern) 1412#else 1413void 1414gfx2_color_pattern_fill(unsigned long dstoffset, unsigned short width, 1415 unsigned short height, unsigned long *pattern) 1416#endif 1417{ 1418 int pass; 1419 unsigned long lines, size, patxorigin, patoffset; 1420 1421 /* ONLY USE HW PATTERN ORIGIN FOR THE X DIRECTION */ 1422 /* Y direction handled by referencing proper location in pattern data. */ 1423 1424 patxorigin = (gu2_pattern_origin) & 0x1C000000; 1425 1426 /* OVERRIDE PATTERN FLAGS IN ROP TO FORCE COLOR PATTERN */ 1427 1428 GU2_WAIT_PENDING; 1429 WRITE_GP32(MGP_RASTER_MODE, 1430 (gu2_rop32 & ~MGP_RM_PAT_FLAGS) | MGP_RM_PAT_COLOR); 1431 1432 /* ATTEMPT TO OPTIMIZE */ 1433 /* If possible, we can perform the pattern fill in only a few passes */ 1434 /* This is performed by multiplying the pitch by an appropriate amount. */ 1435 /* Consequently, if the multiplied pitch exceeds 16 bits, this */ 1436 /* optimization is impossible. */ 1437 1438 if ((gu2_dst_pitch << (gu2_xshift + 1)) <= 0xFFFF) { 1439 /* HANDLE VARIOUS COLOR DEPTHS DIFFERENTLY */ 1440 1441 switch (gu2_xshift) { 1442 case 0: /* 8 BPP */ 1443 1444 /* TWO PASSES FOR 8 BPP */ 1445 /* Render every other line per pass by doubling the pitch. */ 1446 1447 patoffset = (gu2_pattern_origin >> 28) & 0x0E; 1448 for (pass = 0; pass < 2; pass++) { 1449 /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ 1450 1451 GU2_WAIT_PENDING; 1452 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1453 lines = (height + 1 - pass) >> 1; 1454 if (!lines) 1455 break; 1456 size = (((unsigned long)width) << 16) | lines; 1457 WRITE_GP32(MGP_WID_HEIGHT, size); 1458 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 1); 1459 WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset])); 1460 WRITE_GP32(MGP_PAT_DATA_0, 1461 BYTE_SWIZZLE(pattern[patoffset + 1])); 1462 patoffset = (patoffset + 4) & 0x0E; 1463 WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset])); 1464 WRITE_GP32(MGP_PAT_COLOR_0, 1465 BYTE_SWIZZLE(pattern[patoffset + 1])); 1466 patoffset = (patoffset + 4) & 0x0E; 1467 1468 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1469 /* Those registers are not pipelined. */ 1470 1471 GU2_WAIT_BUSY; 1472 WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset])); 1473 WRITE_GP32(MGP_PAT_COLOR_2, 1474 BYTE_SWIZZLE(pattern[patoffset + 1])); 1475 patoffset = (patoffset + 4) & 0x0E; 1476 WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset])); 1477 WRITE_GP32(MGP_PAT_COLOR_4, 1478 BYTE_SWIZZLE(pattern[patoffset + 1])); 1479 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1480 gu2_bm_throttle = 0; 1481 gu2_vm_throttle = 0; 1482 1483 /* ADJUST FOR NEXT PASS */ 1484 1485 dstoffset += gu2_dst_pitch; 1486 patoffset = (patoffset + 6) & 0x0E; 1487 } 1488 break; 1489 1490 case 1: /* 12, 15, OR 16 BPP */ 1491 1492 /* FOUR PASSES FOR 16 BPP */ 1493 /* Render every 4th line per pass by quadrupling the pitch. */ 1494 1495 patoffset = (gu2_pattern_origin >> 27) & 0x1C; 1496 for (pass = 0; pass < 4; pass++) { 1497 /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ 1498 1499 GU2_WAIT_PENDING; 1500 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1501 lines = (height + 3 - pass) >> 2; 1502 if (!lines) 1503 break; 1504 size = (((unsigned long)width) << 16) | lines; 1505 WRITE_GP32(MGP_WID_HEIGHT, size); 1506 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 2); 1507 WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset])); 1508 WRITE_GP32(MGP_PAT_COLOR_0, 1509 WORD_SWIZZLE(pattern[patoffset + 1])); 1510 WRITE_GP32(MGP_PAT_DATA_1, 1511 WORD_SWIZZLE(pattern[patoffset + 2])); 1512 WRITE_GP32(MGP_PAT_DATA_0, 1513 WORD_SWIZZLE(pattern[patoffset + 3])); 1514 patoffset = (patoffset + 16) & 0x1C; 1515 1516 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1517 /* Those registers are not pipelined. */ 1518 1519 GU2_WAIT_BUSY; 1520 WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset])); 1521 WRITE_GP32(MGP_PAT_COLOR_4, 1522 WORD_SWIZZLE(pattern[patoffset + 1])); 1523 WRITE_GP32(MGP_PAT_COLOR_3, 1524 WORD_SWIZZLE(pattern[patoffset + 2])); 1525 WRITE_GP32(MGP_PAT_COLOR_2, 1526 WORD_SWIZZLE(pattern[patoffset + 3])); 1527 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1528 gu2_bm_throttle = 0; 1529 gu2_vm_throttle = 0; 1530 1531 /* ADJUST FOR NEXT PASS */ 1532 1533 dstoffset += gu2_dst_pitch; 1534 patoffset = (patoffset + 20) & 0x1C; 1535 } 1536 break; 1537 1538 case 2: /* 32 BPP */ 1539 1540 /* EIGHT PASSES FOR 32 BPP */ 1541 /* Render every 8th line per pass by setting pitch * 8. */ 1542 1543 patoffset = (gu2_pattern_origin >> 26) & 0x38; 1544 for (pass = 0; pass < 8; pass++) { 1545 /* CAN WRITE SOME PATTERN REGISTERS WHILE "PENDING" */ 1546 1547 GU2_WAIT_PENDING; 1548 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1549 lines = (height + 7 - pass) >> 3; 1550 if (!lines) 1551 break; 1552 size = (((unsigned long)width) << 16) | lines; 1553 WRITE_GP32(MGP_WID_HEIGHT, size); 1554 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch << 3); 1555 WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]); 1556 WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]); 1557 WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]); 1558 WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]); 1559 1560 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1561 /* Those registers are not pipelined. */ 1562 1563 GU2_WAIT_BUSY; 1564 WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]); 1565 WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]); 1566 WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]); 1567 WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]); 1568 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1569 gu2_bm_throttle = 0; 1570 gu2_vm_throttle = 0; 1571 1572 /* ADJUST FOR NEXT PASS */ 1573 1574 dstoffset += gu2_dst_pitch; 1575 patoffset = (patoffset + 8) & 0x38; 1576 } 1577 break; 1578 } 1579 } 1580 1581 else { 1582 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); 1583 1584 switch (gu2_xshift) { 1585 case 0: /* 8 BPP - 4 LINES PER PASS */ 1586 1587 patoffset = (gu2_pattern_origin >> 28) & 0x0E; 1588 while (height) { 1589 lines = height > 4 ? 4 : height; 1590 1591 /* CAN WRITE SOME REGISTERS WHILE PENDING */ 1592 1593 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1594 WRITE_GP32(MGP_WID_HEIGHT, 1595 (((unsigned long)width) << 16) | lines); 1596 WRITE_GP32(MGP_PAT_DATA_1, BYTE_SWIZZLE(pattern[patoffset])); 1597 WRITE_GP32(MGP_PAT_DATA_0, 1598 BYTE_SWIZZLE(pattern[patoffset + 1])); 1599 patoffset = (patoffset + 2) & 0x0E; 1600 WRITE_GP32(MGP_PAT_COLOR_1, BYTE_SWIZZLE(pattern[patoffset])); 1601 WRITE_GP32(MGP_PAT_COLOR_0, 1602 BYTE_SWIZZLE(pattern[patoffset + 1])); 1603 patoffset = (patoffset + 2) & 0x0E; 1604 1605 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1606 /* Those registers are not pipelined. */ 1607 1608 GU2_WAIT_BUSY; 1609 WRITE_GP32(MGP_PAT_COLOR_3, BYTE_SWIZZLE(pattern[patoffset])); 1610 WRITE_GP32(MGP_PAT_COLOR_2, 1611 BYTE_SWIZZLE(pattern[patoffset + 1])); 1612 patoffset = (patoffset + 2) & 0x0E; 1613 WRITE_GP32(MGP_PAT_COLOR_5, BYTE_SWIZZLE(pattern[patoffset])); 1614 WRITE_GP32(MGP_PAT_COLOR_4, 1615 BYTE_SWIZZLE(pattern[patoffset + 1])); 1616 patoffset = (patoffset + 2) & 0x0E; 1617 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1618 1619 /* ADJUST FOR NEXT PASS */ 1620 1621 dstoffset += gu2_dst_pitch << 2; 1622 height -= (unsigned short)lines; 1623 } 1624 break; 1625 1626 case 1: /* 12, 15 AND 16 BPP - 2 LINES PER PASS */ 1627 1628 patoffset = (gu2_pattern_origin >> 27) & 0x1C; 1629 while (height) { 1630 lines = height > 2 ? 2 : height; 1631 1632 /* CAN WRITE SOME REGISTERS WHILE PENDING */ 1633 1634 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1635 WRITE_GP32(MGP_WID_HEIGHT, 1636 (((unsigned long)width) << 16) | lines); 1637 WRITE_GP32(MGP_PAT_COLOR_1, WORD_SWIZZLE(pattern[patoffset])); 1638 WRITE_GP32(MGP_PAT_COLOR_0, 1639 WORD_SWIZZLE(pattern[patoffset + 1])); 1640 WRITE_GP32(MGP_PAT_DATA_1, 1641 WORD_SWIZZLE(pattern[patoffset + 2])); 1642 WRITE_GP32(MGP_PAT_DATA_0, 1643 WORD_SWIZZLE(pattern[patoffset + 3])); 1644 patoffset = (patoffset + 4) & 0x1C; 1645 1646 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1647 /* Those registers are not pipelined. */ 1648 1649 GU2_WAIT_BUSY; 1650 WRITE_GP32(MGP_PAT_COLOR_5, WORD_SWIZZLE(pattern[patoffset])); 1651 WRITE_GP32(MGP_PAT_COLOR_4, 1652 WORD_SWIZZLE(pattern[patoffset + 1])); 1653 WRITE_GP32(MGP_PAT_COLOR_3, 1654 WORD_SWIZZLE(pattern[patoffset + 2])); 1655 WRITE_GP32(MGP_PAT_COLOR_2, 1656 WORD_SWIZZLE(pattern[patoffset + 3])); 1657 patoffset = (patoffset + 4) & 0x1C; 1658 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1659 1660 /* ADJUST FOR NEXT PASS */ 1661 1662 dstoffset += gu2_dst_pitch << 1; 1663 height -= (unsigned short)lines; 1664 } 1665 break; 1666 1667 case 2: /* 32 BPP - 1 LINE PER PASS */ 1668 1669 patoffset = (gu2_pattern_origin >> 26) & 0x38; 1670 while (height) { 1671 /* CAN WRITE SOME REGISTERS WHILE PENDING */ 1672 1673 WRITE_GP32(MGP_DST_OFFSET, dstoffset | patxorigin); 1674 WRITE_GP32(MGP_WID_HEIGHT, 1675 (((unsigned long)width) << 16) | 1l); 1676 WRITE_GP32(MGP_PAT_COLOR_1, pattern[patoffset + 4]); 1677 WRITE_GP32(MGP_PAT_COLOR_0, pattern[patoffset + 5]); 1678 WRITE_GP32(MGP_PAT_DATA_1, pattern[patoffset + 6]); 1679 WRITE_GP32(MGP_PAT_DATA_0, pattern[patoffset + 7]); 1680 1681 /* NEED TO WAIT UNTIL IDLE FOR COLORS 2 THROUGH 5 */ 1682 /* Those registers are not pipelined. */ 1683 1684 GU2_WAIT_BUSY; 1685 WRITE_GP32(MGP_PAT_COLOR_5, pattern[patoffset]); 1686 WRITE_GP32(MGP_PAT_COLOR_4, pattern[patoffset + 1]); 1687 WRITE_GP32(MGP_PAT_COLOR_3, pattern[patoffset + 2]); 1688 WRITE_GP32(MGP_PAT_COLOR_2, pattern[patoffset + 3]); 1689 patoffset = (patoffset + 8) & 0x38; 1690 WRITE_GP16(MGP_BLT_MODE, gu2_blt_mode | gu2_bm_throttle); 1691 1692 /* ADJUST FOR NEXT PASS */ 1693 1694 dstoffset += gu2_dst_pitch; 1695 height--; 1696 } 1697 break; 1698 } 1699 1700 } 1701 1702} 1703 1704/*--------------------------------------------------------------------------- 1705 * GFX2_SCREEN_TO_SCREEN_BLT 1706 * 1707 * This routine is similar to the gfx_screen_to_screen_blt routine but 1708 * allows the use of arbitrary source and destination strides and alpha 1709 * blending. It also allows the use of an arbitrary ROP with transparency. 1710 *--------------------------------------------------------------------------- 1711 */ 1712#if GFX_2DACCEL_DYNAMIC 1713void 1714gu22_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset, 1715 unsigned short width, unsigned short height, int flags) 1716#else 1717void 1718gfx2_screen_to_screen_blt(unsigned long srcoffset, unsigned long dstoffset, 1719 unsigned short width, unsigned short height, int flags) 1720#endif 1721{ 1722 unsigned long size, xbytes; 1723 unsigned short blt_mode; 1724 1725 size = (((unsigned long)width) << 16) | height; 1726 1727 /* USE ALPHA SETTINGS, IF REQUESTED */ 1728 1729 if (gu2_alpha_active) 1730 blt_mode = gu2_alpha_blt_mode | MGP_BM_SRC_FB; 1731 1732 else 1733 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK) | MGP_BM_SRC_FB; 1734 1735 /* CALCULATE THE DIRECTION OF THE BLT */ 1736 /* Using offsets, so flags from the calling routine are needed. */ 1737 1738 if (flags & 1) { 1739 xbytes = (width - 1) << gu2_xshift; 1740 srcoffset += xbytes; 1741 dstoffset += xbytes; 1742 blt_mode |= MGP_BM_NEG_XDIR; 1743 } 1744 if (flags & 2) { 1745 srcoffset += (height - 1) * gu2_src_pitch; 1746 dstoffset += (height - 1) * gu2_dst_pitch; 1747 blt_mode |= MGP_BM_NEG_YDIR; 1748 } 1749 1750 /* TURN INTO BYTE ADDRESS IF NEGATIVE X DIRECTION */ 1751 /* This is a quirk of the hardware. */ 1752 1753 if (blt_mode & MGP_BM_NEG_XDIR) { 1754 srcoffset += (1 << gu2_xshift) - 1; 1755 dstoffset += (1 << gu2_xshift) - 1; 1756 } 1757 1758 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1759 /* Put off poll for as long as possible (do most calculations first). */ 1760 1761 GU2_WAIT_PENDING; 1762 1763 if (gu2_alpha_active) { 1764 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 1765 } else { 1766 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 1767 } 1768 1769 WRITE_GP32(MGP_SRC_OFFSET, srcoffset); 1770 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 1771 WRITE_GP32(MGP_WID_HEIGHT, size); 1772 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16)); 1773 WRITE_GP16(MGP_BLT_MODE, blt_mode | gu2_bm_throttle); 1774 gu2_bm_throttle = 0; 1775 gu2_vm_throttle = 0; 1776} 1777 1778/*--------------------------------------------------------------------------- 1779 * GFX2_MONO_EXPAND_BLT 1780 * 1781 * This routine is similar to the gfx2_screen_to_screen_blt routine but 1782 * expands monochrome data stored in graphics memory. 1783 * WARNING: This routine assumes that the regions in graphics memory 1784 * will not overlap, and therefore does not check the BLT direction. 1785 *--------------------------------------------------------------------------- 1786 */ 1787#if GFX_2DACCEL_DYNAMIC 1788void 1789gu22_mono_expand_blt(unsigned long srcbase, unsigned short srcx, 1790 unsigned short srcy, unsigned long dstoffset, unsigned short width, 1791 unsigned short height, int byte_packed) 1792#else 1793void 1794gfx2_mono_expand_blt(unsigned long srcbase, unsigned short srcx, 1795 unsigned short srcy, unsigned long dstoffset, unsigned short width, 1796 unsigned short height, int byte_packed) 1797#endif 1798{ 1799 unsigned long size, srcoffset; 1800 unsigned short blt_mode; 1801 1802 size = (((unsigned long)width) << 16) | height; 1803 1804 /* CALCULATE SOURCE OFFSET */ 1805 1806 srcoffset = srcbase + (unsigned long)srcy *gu2_src_pitch; 1807 1808 srcoffset += srcx >> 3; 1809 srcoffset |= ((unsigned long)srcx & 7) << 26; 1810 1811 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1812 /* Put off poll for as long as possible (do most calculations first). */ 1813 1814 GU2_WAIT_PENDING; 1815 1816 if (gu2_alpha_active) { 1817 blt_mode = gu2_alpha_blt_mode; 1818 1819 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 1820 } else { 1821 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); 1822 1823 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 1824 } 1825 1826 if (byte_packed) 1827 blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_BP_MONO | gu2_bm_throttle; 1828 else 1829 blt_mode |= MGP_BM_SRC_FB | MGP_BM_SRC_MONO | gu2_bm_throttle; 1830 1831 WRITE_GP32(MGP_SRC_OFFSET, srcoffset); 1832 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 1833 WRITE_GP32(MGP_WID_HEIGHT, size); 1834 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch | (gu2_src_pitch << 16)); 1835 WRITE_GP16(MGP_BLT_MODE, blt_mode); 1836 gu2_bm_throttle = 0; 1837 gu2_vm_throttle = 0; 1838} 1839 1840/*--------------------------------------------------------------------------- 1841 * GFX2_COLOR_BITMAP_TO_SCREEN_BLT 1842 * 1843 * This routine is similar to the gfx_color_bitmap_to_screen_blt routine 1844 * but allows the use of an arbitrary destination stride and alpha blending. 1845 * It also allows the use of an arbitrary ROP with transparency. 1846 *--------------------------------------------------------------------------- 1847 */ 1848#if GFX_2DACCEL_DYNAMIC 1849void 1850gu22_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1851 unsigned long dstoffset, unsigned short width, 1852 unsigned short height, unsigned char *data, short pitch) 1853#else 1854void 1855gfx2_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1856 unsigned long dstoffset, unsigned short width, 1857 unsigned short height, unsigned char *data, short pitch) 1858#endif 1859{ 1860 unsigned long size, bytes; 1861 unsigned long offset, temp_offset; 1862 unsigned long srcoffset, dword_bytes, bytes_extra; 1863 unsigned short blt_mode; 1864 1865 size = (((unsigned long)width) << 16) | 1; 1866 1867 /* CALCULATE STARTING OFFSETS */ 1868 1869 offset = (unsigned long)srcy *pitch + ((unsigned long)srcx << gu2_xshift); 1870 1871 dstoffset |= gu2_pattern_origin; 1872 1873 bytes = width << gu2_xshift; 1874 dword_bytes = bytes & ~0x3L; 1875 bytes_extra = bytes & 0x3L; 1876 1877 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1878 /* Put off poll for as long as possible (do most calculations first). */ 1879 /* The source offset is always 0 since we allow misaligned dword reads. */ 1880 /* We must wait for BLT busy because the GP may be executing a screen */ 1881 /* to screen BLT from the scratchpad area. */ 1882 1883 GU2_WAIT_BUSY; 1884 1885 if (gu2_alpha_active) { 1886 blt_mode = gu2_alpha_blt_mode; 1887 1888 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 1889 } else { 1890 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); 1891 1892 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 1893 } 1894 blt_mode |= MGP_BM_SRC_FB | gu2_bm_throttle; 1895 gu2_bm_throttle = 0; 1896 gu2_vm_throttle = 0; 1897 1898 WRITE_GP32(MGP_WID_HEIGHT, size); 1899 1900 /* WRITE DATA ONE LINE AT A TIME */ 1901 /* For speed reasons, data is written to an offscreen scratch area and 1902 * then BLTed using a screen to screen BLT. This is similar to the GX1 BLT 1903 * buffers, but slightly more efficient in that we can queue up data while 1904 * the GP is rendering a line. 1905 * */ 1906 1907 while (height--) { 1908 temp_offset = offset; 1909 srcoffset = gfx_gx2_scratch_base; 1910 if (gu2_current_line) 1911 srcoffset += 8192; 1912 1913 GU2_WAIT_PENDING; 1914 WRITE_GP32(MGP_SRC_OFFSET, srcoffset); 1915 WRITE_GP32(MGP_DST_OFFSET, dstoffset); 1916 dstoffset += gu2_dst_pitch; 1917 dstoffset += 0x20000000; 1918 1919 WRITE_FRAME_BUFFER_STRING32(srcoffset, dword_bytes, data, 1920 temp_offset); 1921 if (bytes_extra) { 1922 temp_offset += dword_bytes; 1923 srcoffset += dword_bytes; 1924 WRITE_FRAME_BUFFER_STRING8(srcoffset, bytes_extra, data, 1925 temp_offset); 1926 } 1927 WRITE_GP16(MGP_BLT_MODE, blt_mode); 1928 offset += pitch; 1929 gu2_current_line = 1 - gu2_current_line; 1930 } 1931} 1932 1933/*--------------------------------------------------------------------------- 1934 * GFX2_TEXT_BLT 1935 * 1936 * This routine is similar to the gfx2_mono_bitmap_to_screen_blt routine 1937 * but assumes that source data is byte-packed. 1938 *--------------------------------------------------------------------------- 1939 */ 1940#if GFX_2DACCEL_DYNAMIC 1941void 1942gu22_text_blt(unsigned long dstoffset, unsigned short width, 1943 unsigned short height, unsigned char *data) 1944#else 1945void 1946gfx2_text_blt(unsigned long dstoffset, unsigned short width, 1947 unsigned short height, unsigned char *data) 1948#endif 1949{ 1950 unsigned long size, bytes; 1951 unsigned long temp1 = 0, temp2 = 0, temp_offset = 0; 1952 unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; 1953 unsigned long shift; 1954 unsigned short blt_mode; 1955 1956 size = (((unsigned long)width) << 16) | height; 1957 1958 /* CALCULATE STARTING OFFSETS */ 1959 1960 bytes = ((width + 7) >> 3) * height; 1961 fifo_lines = bytes >> 5; 1962 dwords_extra = (bytes & 0x0000001Cl) >> 2; 1963 bytes_extra = bytes & 0x00000003l; 1964 1965 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1966 1967 GU2_WAIT_PENDING; 1968 1969 if (gu2_alpha_active) { 1970 blt_mode = gu2_alpha_blt_mode; 1971 1972 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 1973 } else { 1974 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); 1975 1976 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 1977 } 1978 1979 WRITE_GP32(MGP_SRC_OFFSET, 0); 1980 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 1981 WRITE_GP32(MGP_WID_HEIGHT, size); 1982 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); 1983 WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST | 1984 MGP_BM_SRC_BP_MONO | gu2_bm_throttle); 1985 gu2_bm_throttle = 0; 1986 gu2_vm_throttle = 0; 1987 1988 /* WAIT FOR BLT TO BE LATCHED */ 1989 1990 GU2_WAIT_PENDING; 1991 1992 /* WRITE ALL FULL FIFO LINES */ 1993 1994 for (i = 0; i < fifo_lines; i++) { 1995 GU2_WAIT_HALF_EMPTY; 1996 WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, temp1); 1997 temp_offset += 32; 1998 } 1999 2000 /* WRITE ALL FULL DWORDS */ 2001 2002 if (dwords_extra || bytes_extra) { 2003 GU2_WAIT_HALF_EMPTY; 2004 if (dwords_extra) { 2005 WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, 2006 temp_offset, temp1); 2007 temp_offset += (dwords_extra << 2); 2008 } 2009 if (bytes_extra) { 2010 shift = 0; 2011 WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, 2012 temp_offset, temp1, temp2); 2013 } 2014 } 2015} 2016 2017/*--------------------------------------------------------------------------- 2018 * GFX2_MONO_BITMAP_TO_SCREEN_BLT 2019 * 2020 * This routine is similar to the gfx_mono_bitmap_to_screen_blt routine 2021 * but allows the use of an arbitrary destination stride and alpha blending. 2022 *--------------------------------------------------------------------------- 2023 */ 2024#if GFX_2DACCEL_DYNAMIC 2025void 2026gu22_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 2027 unsigned long dstoffset, unsigned short width, 2028 unsigned short height, unsigned char *data, short pitch) 2029#else 2030void 2031gfx2_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 2032 unsigned long dstoffset, unsigned short width, 2033 unsigned short height, unsigned char *data, short pitch) 2034#endif 2035{ 2036 unsigned long size, bytes; 2037 unsigned long offset, temp_offset, temp1 = 0, temp2 = 0; 2038 unsigned long i, j = 0, fifo_lines, dwords_extra, bytes_extra; 2039 unsigned long shift = 0; 2040 unsigned short blt_mode; 2041 2042 size = (((unsigned long)width) << 16) | height; 2043 2044 /* CALCULATE STARTING OFFSETS */ 2045 2046 offset = (unsigned long)srcy *pitch + ((unsigned long)srcx >> 3); 2047 2048 bytes = ((srcx & 7) + width + 7) >> 3; 2049 fifo_lines = bytes >> 5; 2050 dwords_extra = (bytes & 0x0000001Cl) >> 2; 2051 bytes_extra = bytes & 0x00000003l; 2052 2053 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 2054 2055 GU2_WAIT_PENDING; 2056 2057 if (gu2_alpha_active) { 2058 blt_mode = gu2_alpha_blt_mode; 2059 2060 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 2061 } else { 2062 blt_mode = (gu2_blt_mode & ~MGP_BM_SRC_TYPE_MASK); 2063 2064 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32 | GFXsourceFlags); 2065 } 2066 2067 WRITE_GP32(MGP_SRC_OFFSET, ((unsigned long)srcx & 7) << 26); 2068 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 2069 WRITE_GP32(MGP_WID_HEIGHT, size); 2070 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); 2071 WRITE_GP16(MGP_BLT_MODE, blt_mode | MGP_BM_SRC_HOST | 2072 MGP_BM_SRC_MONO | gu2_bm_throttle); 2073 gu2_bm_throttle = 0; 2074 gu2_vm_throttle = 0; 2075 2076 /* WAIT FOR BLT TO BE LATCHED */ 2077 2078 GU2_WAIT_PENDING; 2079 2080 /* WRITE ALL OF THE DATA TO THE HOST SOURCE REGISTER */ 2081 2082 while (height--) { 2083 temp_offset = offset; 2084 2085 /* WRITE ALL FULL FIFO LINES */ 2086 2087 for (i = 0; i < fifo_lines; i++) { 2088 GU2_WAIT_HALF_EMPTY; 2089 WRITE_GPREG_STRING32(MGP_HST_SOURCE, 8, j, data, temp_offset, 2090 temp1); 2091 temp_offset += 32; 2092 } 2093 2094 /* WRITE ALL FULL DWORDS */ 2095 2096 GU2_WAIT_HALF_EMPTY; 2097 if (dwords_extra) 2098 WRITE_GPREG_STRING32(MGP_HST_SOURCE, dwords_extra, i, data, 2099 temp_offset, temp1); 2100 temp_offset += (dwords_extra << 2); 2101 2102 /* WRITE REMAINING BYTES */ 2103 2104 shift = 0; 2105 if (bytes_extra) 2106 WRITE_GPREG_STRING8(MGP_HST_SOURCE, bytes_extra, shift, i, data, 2107 temp_offset, temp1, temp2); 2108 2109 offset += pitch; 2110 } 2111} 2112 2113/*--------------------------------------------------------------------------- 2114 * GFX2_BRESENHAM_LINE 2115 * 2116 * This routine is similar to the gfx_bresenam_line routine but allows 2117 * the use of an arbitrary destination stride. 2118 *--------------------------------------------------------------------------- 2119 */ 2120#if GFX_2DACCEL_DYNAMIC 2121void 2122gu22_bresenham_line(unsigned long dstoffset, 2123 unsigned short length, unsigned short initerr, 2124 unsigned short axialerr, unsigned short diagerr, unsigned short flags) 2125#else 2126void 2127gfx2_bresenham_line(unsigned long dstoffset, 2128 unsigned short length, unsigned short initerr, 2129 unsigned short axialerr, unsigned short diagerr, unsigned short flags) 2130#endif 2131{ 2132 unsigned long vector_mode = gu2_vector_mode | flags; 2133 unsigned long data1 = (((unsigned long)axialerr) << 16) | diagerr; 2134 unsigned long data2 = (((unsigned long)length) << 16) | initerr; 2135 2136 /* CHECK NULL LENGTH */ 2137 2138 if (!length) 2139 return; 2140 2141 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 2142 /* Put off poll for as long as possible (do most calculations first). */ 2143 2144 GU2_WAIT_PENDING; 2145 2146 if (gu2_alpha_active) { 2147 vector_mode = gu2_alpha_vec_mode | flags; 2148 2149 WRITE_GP32(MGP_RASTER_MODE, gu2_alpha32); 2150 } else 2151 WRITE_GP32(MGP_RASTER_MODE, gu2_rop32); 2152 2153 WRITE_GP32(MGP_DST_OFFSET, dstoffset | gu2_pattern_origin); 2154 WRITE_GP32(MGP_VEC_ERR, data1); 2155 WRITE_GP32(MGP_VEC_LEN, data2); 2156 WRITE_GP32(MGP_STRIDE, gu2_dst_pitch); 2157 WRITE_GP32(MGP_VECTOR_MODE, vector_mode | gu2_vm_throttle); 2158 gu2_bm_throttle = 0; 2159 gu2_vm_throttle = 0; 2160} 2161 2162/*--------------------------------------------------------------------------- 2163 * GFX2_SYNC_TO_VBLANK 2164 * 2165 * This routine sets a flag to synchronize the next rendering routine to 2166 * VBLANK. The flag is cleared by the rendering routine. 2167 *--------------------------------------------------------------------------- 2168 */ 2169#if GFX_2DACCEL_DYNAMIC 2170void 2171gu22_sync_to_vblank(void) 2172#else 2173void 2174gfx2_sync_to_vblank(void) 2175#endif 2176{ 2177 /* SET FLAGS TO THROTTLE NEXT RENDERING ROUTINE */ 2178 2179 gu2_bm_throttle = MGP_BM_THROTTLE; 2180 gu2_vm_throttle = MGP_VM_THROTTLE; 2181} 2182 2183/* END OF FILE */ 2184