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