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 first generation graphics unit (GXLV, SC1200). 29 * 30 * gfx_set_bpp 31 * gfx_set_solid_pattern 32 * gfx_set_mono_pattern 33 * gfx_set_color_pattern 34 * gfx_set_solid_source 35 * gfx_set_mono_source 36 * gfx_set_raster_operation 37 * gfx_pattern_fill 38 * gfx_screen_to_screen_blt 39 * gfx_screen_to_screen_xblt 40 * gfx_color_bitmap_to_screen_blt 41 * gfx_color_bitmap_to_screen_xblt 42 * gfx_mono_bitmap_to_screen_blt 43 * gfx_bresenham_line 44 * gfx_wait_until_idle 45 * */ 46 47#if GFX_NO_IO_IN_WAIT_MACROS 48#define GFX_WAIT_PENDING \ 49 while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { ; } 50#define GFX_WAIT_BUSY \ 51 while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { ; } 52#define GFX_WAIT_PIPELINE \ 53 while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { ; } 54#else 55#define GFX_WAIT_PENDING \ 56 while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) { INB (0x80); } 57#define GFX_WAIT_BUSY \ 58 while(READ_REG16(GP_BLIT_STATUS) & BS_BLIT_BUSY) { INB (0x80); } 59#define GFX_WAIT_PIPELINE \ 60 while (READ_REG16(GP_BLIT_STATUS) & BS_PIPELINE_BUSY) { INB (0x80); } 61#endif 62 63void gu1_detect_blt_buffer_base(void); 64 65/*--------------------------------------------------------------------------- 66 * GFX_SET_BPP 67 * 68 * This routine sets the bits per pixel value in the graphics engine. 69 * It is also stored in a static variable to use in the future calls to 70 * the rendering routines. 71 *--------------------------------------------------------------------------- 72 */ 73#if GFX_2DACCEL_DYNAMIC 74void 75gu1_set_bpp(unsigned short bpp) 76#else 77void 78gfx_set_bpp(unsigned short bpp) 79#endif 80{ 81 int control = 0; 82 unsigned short pitch = gfx_get_display_pitch(); 83 84 GFXbpp = bpp; 85 86 /* DETECT BASE ADDRESSES FOR BLT BUFFERS */ 87 /* Different for 2K or 3K of scratchpad. Also need to calculate */ 88 /* the number of pixels that can fit in a BLT buffer - need to */ 89 /* subtract 16 for alignment considerations. The 2K case, for */ 90 /* example, is 816 bytes wide, allowing 800 pixels in 8 BPP, which */ 91 /* means rendering operations won't be split for 800x600. */ 92 93 gu1_detect_blt_buffer_base(); 94 GFXbufferWidthPixels = GFXbb1Base - GFXbb0Base - 16; 95 if (bpp > 8) { 96 /* If 16bpp, divide GFXbufferWidthPixels by 2 */ 97 GFXbufferWidthPixels >>= 1; 98 } 99 100 /* SET THE GRAPHICS CONTROLLER BPP AND PITCH */ 101 if (bpp > 8) { 102 /* Set the 16bpp bit if necessary */ 103 control = BC_16BPP; 104 } 105 if ((gfx_cpu_version == GFX_CPU_PYRAMID) && (pitch > 2048)) { 106 control |= BC_FB_WIDTH_4096; 107 } 108 else if (pitch > 1024) { 109 control |= BC_FB_WIDTH_2048; 110 } 111 GFX_WAIT_BUSY; 112 WRITE_REG32(GP_BLIT_STATUS, control); 113} 114 115/* 116 *--------------------------------------------------------------------------- 117 * GFX_SET_SOLID_SOURCE 118 * 119 * This routine is used to specify a solid source color. For the Xfree96 120 * display driver, the source color is used to specify a planemask and the 121 * ROP is adjusted accordingly. 122 *--------------------------------------------------------------------------- 123 */ 124#if GFX_2DACCEL_DYNAMIC 125void 126gu1_set_solid_source(unsigned long color) 127#else 128void 129gfx_set_solid_source(unsigned long color) 130#endif 131{ 132 /* CLEAR TRANSPARENCY FLAG */ 133 134 GFXsourceFlags = 0; 135 136 /* FORMAT 8 BPP COLOR */ 137 /* GX requires 8BPP color data be duplicated into bits [15:8]. */ 138 139 if (GFXbpp == 8) { 140 color &= 0x00FF; 141 color |= (color << 8); 142 } 143 144 /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */ 145 146 GFX_WAIT_PENDING; 147 WRITE_REG16(GP_SRC_COLOR_0, (unsigned short) color); 148 WRITE_REG16(GP_SRC_COLOR_1, (unsigned short) color); 149} 150 151/* 152 *--------------------------------------------------------------------------- 153 * GFX_SET_MONO_SOURCE 154 * 155 * This routine is used to specify the monochrome source colors. 156 * It must be called *after* loading any pattern data (those routines 157 * clear the source flags). 158 *--------------------------------------------------------------------------- 159 */ 160#if GFX_2DACCEL_DYNAMIC 161void 162gu1_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, 163 unsigned short transparent) 164#else 165void 166gfx_set_mono_source(unsigned long bgcolor, unsigned long fgcolor, 167 unsigned short transparent) 168#endif 169{ 170 /* SET TRANSPARENCY FLAG */ 171 172 GFXsourceFlags = transparent ? RM_SRC_TRANSPARENT : 0; 173 174 /* FORMAT 8 BPP COLOR */ 175 /* GX requires 8BPP color data be duplicated into bits [15:8]. */ 176 177 if (GFXbpp == 8) { 178 bgcolor &= 0x00FF; 179 bgcolor |= (bgcolor << 8); 180 fgcolor &= 0x00FF; 181 fgcolor |= (fgcolor << 8); 182 } 183 184 /* POLL UNTIL ABLE TO WRITE THE SOURCE COLOR */ 185 186 GFX_WAIT_PENDING; 187 WRITE_REG16(GP_SRC_COLOR_0, (unsigned short) bgcolor); 188 WRITE_REG16(GP_SRC_COLOR_1, (unsigned short) fgcolor); 189} 190 191/* 192 *--------------------------------------------------------------------------- 193 * GFX_SET_SOLID_PATTERN 194 * 195 * This routine is used to specify a solid pattern color. It is called 196 * before performing solid rectangle fills or more complicated BLTs that 197 * use a solid pattern color. 198 * 199 * The driver should always call "gfx_load_raster_operation" after a call 200 * to this routine to make sure that the pattern flags are set appropriately. 201 *--------------------------------------------------------------------------- 202 */ 203#if GFX_2DACCEL_DYNAMIC 204void 205gu1_set_solid_pattern(unsigned long color) 206#else 207void 208gfx_set_solid_pattern(unsigned long color) 209#endif 210{ 211 /* CLEAR TRANSPARENCY FLAG */ 212 213 GFXsourceFlags = 0; 214 215 /* SET PATTERN FLAGS */ 216 217 GFXpatternFlags = 0; 218 219 /* FORMAT 8 BPP COLOR */ 220 /* GX requires 8BPP color data be duplicated into bits [15:8]. */ 221 222 if (GFXbpp == 8) { 223 color &= 0x00FF; 224 color |= (color << 8); 225 } 226 227 /* SAVE THE REFORMATTED COLOR FOR LATER */ 228 /* Used to call the "GFX_solid_fill" routine for special cases. */ 229 230 GFXsavedColor = color; 231 232 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ 233 234 GFX_WAIT_PENDING; 235 WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) color); 236} 237 238/* 239 *--------------------------------------------------------------------------- 240 * GFX_SET_MONO_PATTERN 241 * 242 * This routine is used to specify a monochrome pattern. 243 *--------------------------------------------------------------------------- 244 */ 245#if GFX_2DACCEL_DYNAMIC 246void 247gu1_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, 248 unsigned long data0, unsigned long data1, 249 unsigned char transparent) 250#else 251void 252gfx_set_mono_pattern(unsigned long bgcolor, unsigned long fgcolor, 253 unsigned long data0, unsigned long data1, 254 unsigned char transparent) 255#endif 256{ 257 /* CLEAR TRANSPARENCY FLAG */ 258 259 GFXsourceFlags = 0; 260 261 /* SET PATTERN FLAGS */ 262 263 GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT : 264 RM_PAT_MONO; 265 266 /* FORMAT 8 BPP COLOR */ 267 /* GXm requires 8BPP color data be duplicated into bits [15:8]. */ 268 269 if (GFXbpp == 8) { 270 bgcolor &= 0x00FF; 271 bgcolor |= (bgcolor << 8); 272 fgcolor &= 0x00FF; 273 fgcolor |= (fgcolor << 8); 274 } 275 276 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ 277 278 GFX_WAIT_PENDING; 279 WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) bgcolor); 280 WRITE_REG16(GP_PAT_COLOR_1, (unsigned short) fgcolor); 281 WRITE_REG32(GP_PAT_DATA_0, data0); 282 WRITE_REG32(GP_PAT_DATA_1, data1); 283} 284 285/* 286 *--------------------------------------------------------------------------- 287 * GFX_SET_COLOR_PATTERN 288 * 289 * This routine is used to specify a color pattern. 290 *--------------------------------------------------------------------------- 291 */ 292#if GFX_2DACCEL_DYNAMIC 293void 294gu1_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, 295 unsigned long data0, unsigned long data1, 296 unsigned long data2, unsigned long data3, 297 unsigned char transparent) 298#else 299void 300gfx_set_color_pattern(unsigned long bgcolor, unsigned long fgcolor, 301 unsigned long data0, unsigned long data1, 302 unsigned long data2, unsigned long data3, 303 unsigned char transparent) 304#endif 305{ 306 /* CLEAR TRANSPARENCY FLAG */ 307 308 GFXsourceFlags = 0; 309 310 /* SET PATTERN FLAGS */ 311 312 GFXpatternFlags = transparent ? RM_PAT_MONO | RM_PAT_TRANSPARENT : 313 RM_PAT_MONO; 314 315 GFXpatternFlags |= RM_PAT_COLOR; 316 /* FORMAT 8 BPP COLOR */ 317 /* GXm requires 8BPP color data be duplicated into bits [15:8]. */ 318 319 if (GFXbpp == 8) { 320 bgcolor &= 0x00FF; 321 bgcolor |= (bgcolor << 8); 322 fgcolor &= 0x00FF; 323 fgcolor |= (fgcolor << 8); 324 } 325 326 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ 327 328 GFX_WAIT_PENDING; 329 WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) bgcolor); 330 WRITE_REG16(GP_PAT_COLOR_1, (unsigned short) fgcolor); 331 WRITE_REG32(GP_PAT_DATA_0, data0); 332 WRITE_REG32(GP_PAT_DATA_1, data1); 333 if (GFXbpp > 8) { 334 WRITE_REG32(GP_PAT_DATA_2, data2); 335 WRITE_REG32(GP_PAT_DATA_3, data3); 336 } 337} 338 339/* 340 *--------------------------------------------------------------------------- 341 * GFX_LOAD_COLOR_PATTERN_LINE 342 * 343 * This routine is used to load a single line of a 8x8 color pattern. 344 *--------------------------------------------------------------------------- 345 */ 346#if GFX_2DACCEL_DYNAMIC 347void 348gu1_load_color_pattern_line(short y, unsigned long *pattern_8x8) 349#else 350void 351gfx_load_color_pattern_line(short y, unsigned long *pattern_8x8) 352#endif 353{ 354 /* CLEAR TRANSPARENCY FLAG */ 355 356 GFXsourceFlags = 0; 357 358 /* SET PATTERN FLAGS */ 359 360 GFXpatternFlags = RM_PAT_COLOR; 361 362 y &= 7; 363 364 if (GFXbpp > 8) 365 pattern_8x8 += (y << 2); 366 else 367 pattern_8x8 += (y << 1); 368 369 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLORS AND DATA */ 370 371 GFX_WAIT_PENDING; 372 WRITE_REG32(GP_PAT_DATA_0, pattern_8x8[0]); 373 WRITE_REG32(GP_PAT_DATA_1, pattern_8x8[1]); 374 if (GFXbpp > 8) { 375 WRITE_REG32(GP_PAT_DATA_2, pattern_8x8[2]); 376 WRITE_REG32(GP_PAT_DATA_3, pattern_8x8[3]); 377 } 378} 379 380/* 381 *--------------------------------------------------------------------------- 382 * GFX_SET_RASTER_OPERATION 383 * 384 * This routine loads the specified raster operation. It sets the pattern 385 * flags appropriately. 386 *--------------------------------------------------------------------------- 387 */ 388#if GFX_2DACCEL_DYNAMIC 389void 390gu1_set_raster_operation(unsigned char rop) 391#else 392void 393gfx_set_raster_operation(unsigned char rop) 394#endif 395{ 396 unsigned short rop16; 397 398 /* GENERATE 16-BIT VERSION OF ROP WITH PATTERN FLAGS */ 399 400 rop16 = (unsigned short) rop | GFXpatternFlags; 401 if ((rop & 0x33) ^ ((rop >> 2) & 0x33)) 402 rop16 |= GFXsourceFlags; 403 404 /* SAVE ROP FOR LATER COMPARISONS */ 405 /* Need to have the pattern flags included */ 406 407 GFXsavedRop = rop16; 408 409 /* SET FLAG INDICATING ROP REQUIRES DESTINATION DATA */ 410 /* True if even bits (0:2:4:6) do not equal the corresponding */ 411 /* even bits (1:3:5:7). */ 412 413 GFXusesDstData = ((rop & 0x55) ^ ((rop >> 1) & 0x55)); 414 415 /* POLL UNTIL ABLE TO WRITE THE PATTERN COLOR */ 416 /* Only one operation can be pending at a time. */ 417 418 GFX_WAIT_PENDING; 419 WRITE_REG16(GP_RASTER_MODE, rop16); 420} 421 422/* 423 *--------------------------------------------------------------------------- 424 * GFX_SOLID_FILL 425 * 426 * This routine MUST be used when performing a solid rectangle fill with 427 * the ROPs of PATCOPY (0xF0), BLACKNESS (0x00), WHITENESS (0xFF), or 428 * PATINVERT (0x0F). There is a bug in GXm for these cases that requires a 429 * workaround. 430 * 431 * For BLACKNESS (ROP = 0x00), set the color to 0x0000. 432 * For WHITENESS (ROP = 0xFF), set the color to 0xFFFF. 433 * For PATINVERT (ROP = 0x0F), invert the desired color. 434 * 435 * X screen X position (left) 436 * Y screen Y position (top) 437 * WIDTH width of rectangle, in pixels 438 * HEIGHT height of rectangle, in scanlines 439 * COLOR fill color 440 * 441 * THIS ROUTINE SHOULD NOT BE DIRECTLY CALLED FROM THE DRIVER. The driver 442 * should always use GFX_pattern_fill and let that routine call this one 443 * when approipriate. This is to hide quirks specific to MediaGX hardware. 444 *--------------------------------------------------------------------------- 445 */ 446void 447gu1_solid_fill(unsigned short x, unsigned short y, 448 unsigned short width, unsigned short height, unsigned long color) 449{ 450 unsigned short section; 451 452 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 453 /* Only one operation can be pending at a time. */ 454 455 GFX_WAIT_PENDING; 456 457 /* SET REGISTERS TO DRAW RECTANGLE */ 458 459 WRITE_REG16(GP_DST_XCOOR, x); 460 WRITE_REG16(GP_DST_YCOOR, y); 461 WRITE_REG16(GP_HEIGHT, height); 462 WRITE_REG16(GP_RASTER_MODE, 0x00F0); /* PATCOPY */ 463 WRITE_REG16(GP_PAT_COLOR_0, (unsigned short) color); 464 465 /* CHECK WIDTH FOR GX BUG WORKAROUND */ 466 467 if (width <= 16) { 468 /* OK TO DRAW SMALL RECTANGLE IN ONE PASS */ 469 470 WRITE_REG16(GP_WIDTH, width); 471 WRITE_REG16(GP_BLIT_MODE, 0); 472 } 473 else { 474 /* DRAW FIRST PART OF RECTANGLE */ 475 /* Get to a 16 pixel boundary. */ 476 477 section = 0x10 - (x & 0x0F); 478 WRITE_REG16(GP_WIDTH, section); 479 WRITE_REG16(GP_BLIT_MODE, 0); 480 481 /* POLL UNTIL ABLE TO LOAD THE SECOND RECTANGLE */ 482 483 GFX_WAIT_PENDING; 484 WRITE_REG16(GP_DST_XCOOR, x + section); 485 WRITE_REG16(GP_DST_YCOOR, y); 486 WRITE_REG16(GP_WIDTH, width - section); 487 WRITE_REG16(GP_BLIT_MODE, 0); 488 } 489} 490 491/* 492 *---------------------------------------------------------------------------- 493 * GFX_PATTERN_FILL 494 * 495 * This routine is used to fill a rectangular region. The pattern must 496 * be previously loaded using one of GFX_load_*_pattern routines. Also, the 497 * raster operation must be previously specified using the 498 * "GFX_load_raster_operation" routine. 499 * 500 * X screen X position (left) 501 * Y screen Y position (top) 502 * WIDTH width of rectangle, in pixels 503 * HEIGHT height of rectangle, in scanlines 504 *---------------------------------------------------------------------------- 505 */ 506#if GFX_2DACCEL_DYNAMIC 507void 508gu1_pattern_fill(unsigned short x, unsigned short y, 509 unsigned short width, unsigned short height) 510#else 511void 512gfx_pattern_fill(unsigned short x, unsigned short y, 513 unsigned short width, unsigned short height) 514#endif 515{ 516 unsigned short section, buffer_width, blit_mode; 517 518 /* CHECK IF OPTIMIZED SOLID CASES */ 519 /* Check all 16 bits of the ROP to include solid pattern flags. */ 520 521 switch (GFXsavedRop) { 522 /* CHECK FOR SPECIAL CASES WITHOUT DESTINATION DATA */ 523 /* Need hardware workaround for fast "burst write" cases. */ 524 525 case 0x00F0: 526 gu1_solid_fill(x, y, width, height, (unsigned short) GFXsavedColor); 527 break; 528 case 0x000F: 529 gu1_solid_fill(x, y, width, height, (unsigned short) ~GFXsavedColor); 530 break; 531 case 0x0000: 532 gu1_solid_fill(x, y, width, height, 0x0000); 533 break; 534 case 0x00FF: 535 gu1_solid_fill(x, y, width, height, 0xFFFF); 536 break; 537 538 /* REMAINING CASES REQUIRE DESTINATION DATA OR NOT SOLID COLOR */ 539 540 default: 541 542 /* DETERMINE BLT MODE VALUE */ 543 /* Still here for non-solid patterns without destination data. */ 544 545 blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0; 546 547 /* SET SOURCE EXPANSION MODE */ 548 /* If the ROP requires source data, then the source data is all 1's */ 549 /* and then expanded into the desired color in GP_SRC_COLOR_1. */ 550 551 blit_mode |= BM_SOURCE_EXPAND; 552 553 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 554 /* Write the registers that do not change for each section. */ 555 556 GFX_WAIT_PENDING; 557 WRITE_REG16(GP_HEIGHT, height); 558 559 /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */ 560 /* Therefore, width available = BLT buffer width * 2. */ 561 562 buffer_width = GFXbufferWidthPixels << 1; 563 564 /* REPEAT UNTIL FINISHED WITH RECTANGLE */ 565 /* Perform BLT in vertical sections, as wide as the BLT buffer */ 566 /* allows. Hardware does not split the operations, so */ 567 /* software must do it to avoid large scanlines that would */ 568 /* overflow the BLT buffers. */ 569 570 while (width > 0) { 571 /* DETERMINE WIDTH OF SECTION */ 572 573 if (width > buffer_width) 574 section = buffer_width; 575 else 576 section = width; 577 578 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 579 580 GFX_WAIT_PENDING; 581 WRITE_REG16(GP_DST_XCOOR, x); 582 WRITE_REG16(GP_DST_YCOOR, y); 583 WRITE_REG16(GP_WIDTH, section); 584 WRITE_REG16(GP_BLIT_MODE, blit_mode); 585 586 /* ADJUST PARAMETERS FOR NEXT SECTION */ 587 588 width -= section; 589 x += section; 590 } 591 break; 592 } 593} 594 595/* 596 *---------------------------------------------------------------------------- 597 * GFX_COLOR_PATTERN_FILL 598 * 599 * This routine is used to render a rectangle using the current raster 600 * operation and the specified color pattern. It allows an 8x8 color 601 * pattern to be rendered without multiple calls to the gfx_set_color_pattern 602 * and gfx_pattern_fill routines. 603 * 604 * X screen X position (left) 605 * Y screen Y position (top) 606 * WIDTH width of rectangle, in pixels 607 * HEIGHT height of rectangle, in scanlines 608 * *PATTERN pointer to 8x8 color pattern data 609 *---------------------------------------------------------------------------- 610 */ 611#if GFX_2DACCEL_DYNAMIC 612void 613gu1_color_pattern_fill(unsigned short x, unsigned short y, 614 unsigned short width, unsigned short height, 615 unsigned long *pattern) 616#else 617void 618gfx_color_pattern_fill(unsigned short x, unsigned short y, 619 unsigned short width, unsigned short height, 620 unsigned long *pattern) 621#endif 622{ 623 unsigned short blit_mode, passes, cur_y, pat_y, i; 624 unsigned short buffer_width, line_width; 625 unsigned short bpp_shift, section, cur_x; 626 627 /* SET APPROPRIATE INCREMENT */ 628 629 bpp_shift = (GFXbpp > 8) ? 2 : 1; 630 631 /* SET DESTINATION REQUIRED */ 632 633 blit_mode = GFXusesDstData ? BM_READ_DST_FB0 : 0; 634 635 /* SET SOURCE EXPANSION */ 636 637 blit_mode |= BM_SOURCE_EXPAND; 638 639 /* OVERRIDE RASTER MODE TO FORCE A COLOR PATTERN */ 640 641 GFX_WAIT_PENDING; 642 WRITE_REG16(GP_RASTER_MODE, 643 (GFXsavedRop & ~RM_PAT_MASK & ~RM_PAT_TRANSPARENT) | 644 RM_PAT_COLOR); 645 646 /* WRITE THE REGISTERS THAT DO NOT CHANGE */ 647 /* If destination data is required, the width and */ 648 /* x position will be overwritten. */ 649 650 WRITE_REG16(GP_HEIGHT, 1); 651 WRITE_REG16(GP_WIDTH, width); 652 WRITE_REG16(GP_DST_XCOOR, x); 653 654 /* THE ENTIRE PATTERN WILL NOT BE DRAWN IF THE HEIGHT IS LESS THAN 8 */ 655 656 passes = (height < 8) ? height : 8; 657 658 /* SINCE ONLY DESTINATION DATA, WE CAN USE BOTH BB0 AND BB1. */ 659 /* Therefore, width available = BLT buffer width * 2. */ 660 661 buffer_width = GFXbufferWidthPixels << 1; 662 663 for (i = 0; i < passes; i++) { 664 pat_y = ((y + i) & 7) << bpp_shift; 665 cur_y = y + i; 666 667 /* WRITE THE PATTERN DATA FOR THE ACTIVE LINE */ 668 669 GFX_WAIT_PENDING; 670 WRITE_REG32(GP_PAT_DATA_0, pattern[pat_y]); 671 WRITE_REG32(GP_PAT_DATA_1, pattern[pat_y + 1]); 672 673 if (GFXbpp > 8) { 674 WRITE_REG32(GP_PAT_DATA_2, pattern[pat_y + 2]); 675 WRITE_REG32(GP_PAT_DATA_3, pattern[pat_y + 3]); 676 } 677 678 /* SPLIT BLT LINE INTO SECTIONS IF REQUIRED */ 679 /* If no destination data is required, we can ignore */ 680 /* the BLT buffers. Otherwise, we must separate the BLT */ 681 /* so as not to overflow the buffers */ 682 683 if (blit_mode & BM_READ_DST_BB0) { 684 line_width = width; 685 cur_x = x; 686 687 while (line_width) { 688 section = 689 (line_width > buffer_width) ? buffer_width : line_width; 690 cur_y = y + i; 691 692 GFX_WAIT_PENDING; 693 WRITE_REG16(GP_DST_XCOOR, cur_x); 694 WRITE_REG16(GP_WIDTH, section); 695 696 while (cur_y < y + height) { 697 GFX_WAIT_PENDING; 698 WRITE_REG16(GP_DST_YCOOR, cur_y); 699 WRITE_REG16(GP_BLIT_MODE, blit_mode); 700 cur_y += 8; 701 } 702 703 cur_x += section; 704 line_width -= section; 705 } 706 707 } 708 else { 709 while (cur_y < y + height) { 710 GFX_WAIT_PENDING; 711 WRITE_REG16(GP_DST_YCOOR, cur_y); 712 WRITE_REG16(GP_BLIT_MODE, blit_mode); 713 cur_y += 8; 714 } 715 } 716 717 } 718 719 /* RESTORE ORIGINAL ROP AND FLAGS */ 720 721 GFX_WAIT_PENDING; 722 WRITE_REG16(GP_RASTER_MODE, GFXsavedRop); 723 724} 725 726/* 727 *---------------------------------------------------------------------------- 728 * SCREEN TO SCREEN BLT 729 * 730 * This routine should be used to perform a screen to screen BLT when the 731 * ROP does not require destination data. 732 * 733 * SRCX screen X position to copy from 734 * SRCY screen Y position to copy from 735 * DSTX screen X position to copy to 736 * DSTY screen Y position to copy to 737 * WIDTH width of rectangle, in pixels 738 * HEIGHT height of rectangle, in scanlines 739 *---------------------------------------------------------------------------- 740 */ 741#if GFX_2DACCEL_DYNAMIC 742void 743gu1_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, 744 unsigned short dstx, unsigned short dsty, 745 unsigned short width, unsigned short height) 746#else 747void 748gfx_screen_to_screen_blt(unsigned short srcx, unsigned short srcy, 749 unsigned short dstx, unsigned short dsty, 750 unsigned short width, unsigned short height) 751#endif 752{ 753 unsigned short section, buffer_width; 754 unsigned short blit_mode; 755 756 /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ 757 758 blit_mode = GFXusesDstData ? BM_READ_DST_FB1 | BM_READ_SRC_FB : 759 BM_READ_SRC_FB; 760 761 /* CHECK Y DIRECTION */ 762 /* Hardware has support for negative Y direction. */ 763 764 if (dsty > srcy) { 765 blit_mode |= BM_REVERSE_Y; 766 srcy += height - 1; 767 dsty += height - 1; 768 } 769 770 /* CHECK X DIRECTION */ 771 /* Hardware does not support negative X direction since at the time */ 772 /* of development all supported resolutions could fit a scanline of */ 773 /* data at once into the BLT buffers (using both BB0 and BB1). This */ 774 /* code is more generic to allow for any size BLT buffer. */ 775 776 if (dstx > srcx) { 777 srcx += width; 778 dstx += width; 779 } 780 781 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 782 /* Write the registers that do not change for each section. */ 783 784 GFX_WAIT_PENDING; 785 WRITE_REG16(GP_HEIGHT, height); 786 787 /* CHECK AVAILABLE BLT BUFFER SIZE */ 788 /* Can use both BLT buffers if no destination data is required. */ 789 790 buffer_width = GFXusesDstData ? GFXbufferWidthPixels : 791 GFXbufferWidthPixels << 1; 792 793 /* REPEAT UNTIL FINISHED WITH RECTANGLE */ 794 /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */ 795 /* Hardware does not split the operations, so software must do it to */ 796 /* avoid large scanlines that would overflow the BLT buffers. */ 797 798 while (width > 0) { 799 /* CHECK WIDTH OF CURRENT SECTION */ 800 801 if (width > buffer_width) 802 section = buffer_width; 803 else 804 section = width; 805 806 /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */ 807 808 GFX_WAIT_PENDING; 809 WRITE_REG16(GP_SRC_YCOOR, srcy); 810 WRITE_REG16(GP_DST_YCOOR, dsty); 811 WRITE_REG16(GP_WIDTH, section); 812 813 /* CHECK X DIRECTION */ 814 815 if (dstx > srcx) { 816 /* NEGATIVE X DIRECTION */ 817 /* Still positive X direction within the section. */ 818 819 srcx -= section; 820 dstx -= section; 821 WRITE_REG16(GP_SRC_XCOOR, srcx); 822 WRITE_REG16(GP_DST_XCOOR, dstx); 823 WRITE_REG16(GP_BLIT_MODE, blit_mode); 824 } 825 else { 826 /* POSITIVE X DIRECTION */ 827 828 WRITE_REG16(GP_SRC_XCOOR, srcx); 829 WRITE_REG16(GP_DST_XCOOR, dstx); 830 WRITE_REG16(GP_BLIT_MODE, blit_mode); 831 dstx += section; 832 srcx += section; 833 } 834 width -= section; 835 } 836} 837 838/* 839 *---------------------------------------------------------------------------- 840 * SCREEN TO SCREEN TRANSPARENT BLT 841 * 842 * This routine should be used to perform a screen to screen BLT when a 843 * specified color should by transparent. The only supported ROP is SRCCOPY. 844 * 845 * SRCX screen X position to copy from 846 * SRCY screen Y position to copy from 847 * DSTX screen X position to copy to 848 * DSTY screen Y position to copy to 849 * WIDTH width of rectangle, in pixels 850 * HEIGHT height of rectangle, in scanlines 851 * COLOR transparent color 852 *---------------------------------------------------------------------------- 853 */ 854#if GFX_2DACCEL_DYNAMIC 855void 856gu1_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, 857 unsigned short dstx, unsigned short dsty, 858 unsigned short width, unsigned short height, 859 unsigned long color) 860#else 861void 862gfx_screen_to_screen_xblt(unsigned short srcx, unsigned short srcy, 863 unsigned short dstx, unsigned short dsty, 864 unsigned short width, unsigned short height, 865 unsigned long color) 866#endif 867{ 868 unsigned short section, buffer_width; 869 unsigned short blit_mode = BM_READ_SRC_FB; 870 871 /* CHECK Y DIRECTION */ 872 /* Hardware has support for negative Y direction. */ 873 874 if (dsty > srcy) { 875 blit_mode |= BM_REVERSE_Y; 876 srcy += height - 1; 877 dsty += height - 1; 878 } 879 880 /* CHECK X DIRECTION */ 881 /* Hardware does not support negative X direction since at the time */ 882 /* of development all supported resolutions could fit a scanline of */ 883 /* data at once into the BLT buffers (using both BB0 and BB1). This */ 884 /* code is more generic to allow for any size BLT buffer. */ 885 886 if (dstx > srcx) { 887 srcx += width; 888 dstx += width; 889 } 890 891 /* CALCULATE BLT BUFFER SIZE */ 892 /* Need to use BB1 to store the BLT buffer data. */ 893 894 buffer_width = GFXbufferWidthPixels; 895 896 /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */ 897 898 if (GFXbpp == 8) { 899 color &= 0x00FF; 900 color |= (color << 8); 901 } 902 color = (color & 0x0000FFFF) | (color << 16); 903 904 /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */ 905 /* Need to make sure any previous BLT using BB1 is complete. */ 906 /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */ 907 908 GFX_WAIT_BUSY; 909 WRITE_SCRATCH32(GFXbb1Base, color); 910 911 /* DO BOGUS BLT TO LATCH DATA FROM BB1 */ 912 /* Already know graphics pipeline is idle. */ 913 /* Only need to latch data into the holding registers for the current */ 914 /* data from BB1. A 1 pixel wide BLT will suffice. */ 915 916 WRITE_REG32(GP_DST_XCOOR, 0); 917 WRITE_REG32(GP_SRC_XCOOR, 0); 918 WRITE_REG32(GP_WIDTH, 0x00010001); 919 WRITE_REG16(GP_RASTER_MODE, 0x00CC); 920 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1); 921 922 /* WRITE REGISTERS FOR REAL SCREEN TO SCREEN BLT */ 923 924 GFX_WAIT_PENDING; 925 WRITE_REG16(GP_HEIGHT, height); 926 WRITE_REG16(GP_RASTER_MODE, 0x10C6); 927 WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF); 928 929 /* REPEAT UNTIL FINISHED WITH RECTANGLE */ 930 /* Perform BLT in vertical sections, as wide as the BLT buffer allows. */ 931 /* Hardware does not split the operations, so software must do it to */ 932 /* avoid large scanlines that would overflow the BLT buffers. */ 933 934 while (width > 0) { 935 /* CHECK WIDTH OF CURRENT SECTION */ 936 937 if (width > buffer_width) 938 section = buffer_width; 939 else 940 section = width; 941 942 /* PROGRAM REGISTERS THAT ARE THE SAME FOR EITHER X DIRECTION */ 943 944 GFX_WAIT_PENDING; 945 WRITE_REG16(GP_SRC_YCOOR, srcy); 946 WRITE_REG16(GP_DST_YCOOR, dsty); 947 WRITE_REG16(GP_WIDTH, section); 948 949 /* CHECK X DIRECTION */ 950 /* Again, this must be done in software, and can be removed if the */ 951 /* display driver knows that the BLT buffers will always be large */ 952 /* enough to contain an entire scanline of a screen to screen BLT. */ 953 954 if (dstx > srcx) { 955 /* NEGATIVE X DIRECTION */ 956 /* Still positive X direction within the section. */ 957 958 srcx -= section; 959 dstx -= section; 960 WRITE_REG16(GP_SRC_XCOOR, srcx); 961 WRITE_REG16(GP_DST_XCOOR, dstx); 962 WRITE_REG16(GP_BLIT_MODE, blit_mode); 963 } 964 else { 965 /* POSITIVE X DIRECTION */ 966 967 WRITE_REG16(GP_SRC_XCOOR, srcx); 968 WRITE_REG16(GP_DST_XCOOR, dstx); 969 WRITE_REG16(GP_BLIT_MODE, blit_mode); 970 dstx += section; 971 srcx += section; 972 } 973 width -= section; 974 } 975} 976 977/* 978 *---------------------------------------------------------------------------- 979 * COLOR BITMAP TO SCREEN BLT 980 * 981 * This routine transfers color bitmap data to the screen. For most cases, 982 * when the ROP is SRCCOPY, it may be faster to write a separate routine that 983 * copies the data to the frame buffer directly. This routine should be 984 * used when the ROP requires destination data. 985 * 986 * Transparency is handled by another routine. 987 * 988 * SRCX X offset within source bitmap 989 * SRCY Y offset within source bitmap 990 * DSTX screen X position to render data 991 * DSTY screen Y position to render data 992 * WIDTH width of rectangle, in pixels 993 * HEIGHT height of rectangle, in scanlines 994 * *DATA pointer to bitmap data 995 * PITCH pitch of bitmap data (bytes between scanlines) 996 *---------------------------------------------------------------------------- 997 */ 998 999#if GFX_2DACCEL_DYNAMIC 1000void 1001gu1_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1002 unsigned short dstx, unsigned short dsty, 1003 unsigned short width, unsigned short height, 1004 unsigned char *data, long pitch) 1005#else 1006void 1007gfx_color_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1008 unsigned short dstx, unsigned short dsty, 1009 unsigned short width, unsigned short height, 1010 unsigned char *data, long pitch) 1011#endif 1012{ 1013 unsigned short section, buffer_width; 1014 unsigned short blit_mode = BM_READ_SRC_BB0; 1015 unsigned short temp_height; 1016 unsigned long dword_bytes_needed, bytes_extra; 1017 unsigned long bpp_shift; 1018 long array_offset; 1019 1020 /* CHECK SIZE OF BLT BUFFER */ 1021 1022 buffer_width = GFXbufferWidthPixels; 1023 1024 /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ 1025 /* If no destination data, we have twice the room for */ 1026 /* source data. */ 1027 1028 if (GFXusesDstData) 1029 blit_mode |= BM_READ_DST_FB1; 1030 else 1031 buffer_width <<= 1; 1032 1033 /* SET THE SCRATCHPAD BASE */ 1034 1035 SET_SCRATCH_BASE(GFXbb0Base); 1036 1037 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1038 /* Write the registers that do not change for each section. */ 1039 1040 GFX_WAIT_PENDING; 1041 WRITE_REG16(GP_HEIGHT, 1); 1042 1043 bpp_shift = (GFXbpp + 7) >> 4; 1044 1045 while (width > 0) { 1046 if (width > buffer_width) 1047 section = buffer_width; 1048 else 1049 section = width; 1050 1051 dword_bytes_needed = (section << bpp_shift) & ~3l; 1052 bytes_extra = (section << bpp_shift) & 3l; 1053 1054 temp_height = height; 1055 1056 /* WRITE THE REGISTERS FOR EACH SECTION */ 1057 /* The GX hardware will auto-increment the Y coordinate, meaning */ 1058 /* that we don't have to. */ 1059 1060 WRITE_REG16(GP_WIDTH, section); 1061 WRITE_REG16(GP_DST_XCOOR, dstx); 1062 WRITE_REG16(GP_DST_YCOOR, dsty); 1063 1064 /* CALCULATE THE BITMAP OFFSET */ 1065 1066 array_offset = 1067 (unsigned long) srcy *(long) pitch + ((long) srcx << bpp_shift); 1068 1069 while (temp_height--) { 1070 GFX_WAIT_PIPELINE; 1071 1072 /* WRITE ALL DATA TO THE BLT BUFFERS */ 1073 /* The WRITE_SCRATCH_STRING macro assumes that the data begins 1074 * at the scratchpad offset set by the SET_SCRATCH_BASE macro. 1075 * */ 1076 1077 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 1078 array_offset); 1079 WRITE_REG16(GP_BLIT_MODE, blit_mode); 1080 1081 array_offset += pitch; 1082 } 1083 1084 width -= section; 1085 srcx += section; 1086 dstx += section; 1087 } 1088} 1089 1090/* 1091 *---------------------------------------------------------------------------- 1092 * COLOR BITMAP TO SCREEN TRANSPARENT BLT 1093 * 1094 * This routine transfers color bitmap data to the screen with transparency. 1095 * The transparent color is specified. The only supported ROP is SRCCOPY, 1096 * meaning that transparency cannot be applied if the ROP requires 1097 * destination data (this is a hardware restriction). 1098 * 1099 * SRCX X offset within source bitmap 1100 * SRCY Y offset within source bitmap 1101 * DSTX screen X position to render data 1102 * DSTY screen Y position to render data 1103 * WIDTH width of rectangle, in pixels 1104 * HEIGHT height of rectangle, in scanlines 1105 * *DATA pointer to bitmap data 1106 * PITCH pitch of bitmap data (bytes between scanlines) 1107 * COLOR transparent color 1108 *---------------------------------------------------------------------------- 1109 */ 1110#if GFX_2DACCEL_DYNAMIC 1111void 1112gu1_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, 1113 unsigned short dstx, unsigned short dsty, 1114 unsigned short width, unsigned short height, 1115 unsigned char *data, long pitch, 1116 unsigned long color) 1117#else 1118void 1119gfx_color_bitmap_to_screen_xblt(unsigned short srcx, unsigned short srcy, 1120 unsigned short dstx, unsigned short dsty, 1121 unsigned short width, unsigned short height, 1122 unsigned char *data, long pitch, 1123 unsigned long color) 1124#endif 1125{ 1126 unsigned short section, buffer_width; 1127 unsigned short temp_height; 1128 unsigned long dword_bytes_needed, bytes_extra; 1129 unsigned long bpp_shift; 1130 long array_offset; 1131 1132 /* CHECK SIZE OF BLT BUFFER */ 1133 1134 buffer_width = GFXbufferWidthPixels; 1135 1136 /* WRITE TRANSPARENCY COLOR TO BLT BUFFER 1 */ 1137 1138 if (GFXbpp == 8) { 1139 color &= 0x00FF; 1140 color |= (color << 8); 1141 } 1142 color = (color & 0x0000FFFF) | (color << 16); 1143 1144 /* WAIT UNTIL PIPELINE IS NOT BUSY BEFORE LOADING DATA INTO BB1 */ 1145 /* Need to make sure any previous BLT using BB1 is complete. */ 1146 /* Only need to load 32 bits of BB1 for the 1 pixel BLT that follows. */ 1147 1148 GFX_WAIT_PIPELINE; 1149 GFX_WAIT_PENDING; 1150 WRITE_SCRATCH32(GFXbb1Base, color); 1151 1152 /* DO BOGUS BLT TO LATCH DATA FROM BB1 */ 1153 /* Already know graphics pipeline is idle. */ 1154 /* Only need to latch data into the holding registers for the current */ 1155 /* data from BB1. A 1 pixel wide BLT will suffice. */ 1156 1157 WRITE_REG32(GP_DST_XCOOR, 0); 1158 WRITE_REG32(GP_SRC_XCOOR, 0); 1159 WRITE_REG32(GP_WIDTH, 0x00010001); 1160 WRITE_REG16(GP_RASTER_MODE, 0x00CC); 1161 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_FB | BM_READ_DST_BB1); 1162 1163 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1164 /* Write the registers that do not change for each section. */ 1165 1166 GFX_WAIT_PENDING; 1167 WRITE_REG16(GP_HEIGHT, 1); 1168 WRITE_REG16(GP_RASTER_MODE, 0x10C6); 1169 WRITE_REG32(GP_PAT_COLOR_0, 0xFFFFFFFF); 1170 1171 bpp_shift = (GFXbpp + 7) >> 4; 1172 1173 /* SET THE SCRATCHPAD BASE */ 1174 1175 SET_SCRATCH_BASE(GFXbb0Base); 1176 1177 while (width > 0) { 1178 if (width > buffer_width) 1179 section = buffer_width; 1180 else 1181 section = width; 1182 1183 dword_bytes_needed = (section << bpp_shift) & ~3l; 1184 bytes_extra = (section << bpp_shift) & 3l; 1185 1186 temp_height = height; 1187 1188 /* WRITE THE REGISTERS FOR EACH SECTION */ 1189 /* The GX hardware will auto-increment the Y coordinate, meaning */ 1190 /* that we don't have to. */ 1191 1192 WRITE_REG16(GP_WIDTH, section); 1193 WRITE_REG16(GP_DST_XCOOR, dstx); 1194 WRITE_REG16(GP_DST_YCOOR, dsty); 1195 1196 /* CALCULATE THE BITMAP OFFSET */ 1197 1198 array_offset = 1199 (unsigned long) srcy *(long) pitch + ((long) srcx << bpp_shift); 1200 1201 while (temp_height--) { 1202 GFX_WAIT_PIPELINE; 1203 1204 /* WRITE ALL DATA TO THE BLT BUFFERS */ 1205 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ 1206 /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ 1207 1208 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 1209 array_offset); 1210 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0); 1211 1212 array_offset += pitch; 1213 } 1214 1215 width -= section; 1216 srcx += section; 1217 dstx += section; 1218 } 1219} 1220 1221/* 1222 *---------------------------------------------------------------------------- 1223 * MONOCHROME BITMAP TO SCREEN BLT 1224 * 1225 * This routine transfers monochrome bitmap data to the screen. 1226 * 1227 * SRCX X offset within source bitmap 1228 * SRCY Y offset within source bitmap 1229 * DSTX screen X position to render data 1230 * DSTY screen Y position to render data 1231 * WIDTH width of rectangle, in pixels 1232 * HEIGHT height of rectangle, in scanlines 1233 * *DATA pointer to bitmap data 1234 * PITCH pitch of bitmap data (bytes between scanlines) 1235 *---------------------------------------------------------------------------- 1236 */ 1237#if GFX_2DACCEL_DYNAMIC 1238void 1239gu1_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1240 unsigned short dstx, unsigned short dsty, 1241 unsigned short width, unsigned short height, 1242 unsigned char *data, short pitch) 1243#else 1244void 1245gfx_mono_bitmap_to_screen_blt(unsigned short srcx, unsigned short srcy, 1246 unsigned short dstx, unsigned short dsty, 1247 unsigned short width, unsigned short height, 1248 unsigned char *data, short pitch) 1249#endif 1250{ 1251 unsigned short section, buffer_width; 1252 unsigned short blit_mode = BM_READ_SRC_BB0 | BM_SOURCE_EXPAND; 1253 unsigned short temp_height; 1254 unsigned long dword_bytes_needed, bytes_extra; 1255 long array_offset; 1256 1257 /* CHECK IF RASTER OPERATION REQUIRES DESTINATION DATA */ 1258 /* If no destination data, the source data will always fit. */ 1259 /* So, in that event we will set the buffer width to a */ 1260 /* fictitiously large value such that the BLT is never split. */ 1261 1262 if (GFXusesDstData) { 1263 buffer_width = GFXbufferWidthPixels; 1264 blit_mode |= BM_READ_DST_FB1; 1265 } 1266 else 1267 buffer_width = 3200; 1268 1269 /* CHECK IF DATA ALREADY IN BLIT BUFFER */ 1270 /* If the pointer is NULL, data for the full BLT is already there */ 1271 /* WARNING: This could cause problems if destination data is */ 1272 /* involved and it overflows the BLT buffer. Need to remove */ 1273 /* this option and change the drivers to use a temporary buffer. */ 1274 1275 if (!data) { 1276 GFX_WAIT_PENDING; 1277 WRITE_REG16(GP_SRC_XCOOR, srcx & 7); 1278 WRITE_REG16(GP_DST_XCOOR, dstx); 1279 WRITE_REG16(GP_DST_YCOOR, dsty); 1280 WRITE_REG16(GP_WIDTH, width); 1281 WRITE_REG16(GP_HEIGHT, height); 1282 WRITE_REG16(GP_BLIT_MODE, blit_mode); 1283 return; 1284 } 1285 1286 /* SET THE SCRATCHPAD BASE */ 1287 1288 SET_SCRATCH_BASE(GFXbb0Base); 1289 1290 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1291 /* Write the registers that do not change for each section. */ 1292 1293 GFX_WAIT_PENDING; 1294 WRITE_REG16(GP_HEIGHT, 1); 1295 1296 while (width > 0) { 1297 if (width > buffer_width) 1298 section = buffer_width; 1299 else 1300 section = width; 1301 1302 /* CALCULATE BYTES NEEDED */ 1303 /* Add 1 for possible alignment issues. */ 1304 1305 dword_bytes_needed = ((section + 7 + (srcx & 7)) >> 3) & ~3l; 1306 bytes_extra = ((section + 7 + (srcx & 7)) >> 3) & 3l; 1307 1308 temp_height = height; 1309 1310 /* WRITE THE REGISTERS FOR EACH SECTION */ 1311 /* The GX hardware will auto-increment the Y coordinate, meaning */ 1312 /* that we don't have to. */ 1313 1314 WRITE_REG16(GP_WIDTH, section); 1315 WRITE_REG16(GP_DST_XCOOR, dstx); 1316 WRITE_REG16(GP_DST_YCOOR, dsty); 1317 WRITE_REG16(GP_SRC_XCOOR, srcx & 7); 1318 1319 /* CALCULATE THE BITMAP OFFSET */ 1320 1321 array_offset = (unsigned long) srcy *(long) pitch + ((long) srcx >> 3); 1322 1323 while (temp_height--) { 1324 GFX_WAIT_PIPELINE; 1325 1326 /* WRITE ALL DATA TO THE BLT BUFFERS */ 1327 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ 1328 /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ 1329 1330 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 1331 array_offset); 1332 WRITE_REG16(GP_BLIT_MODE, blit_mode); 1333 1334 array_offset += pitch; 1335 } 1336 1337 width -= section; 1338 srcx += section; 1339 dstx += section; 1340 } 1341} 1342 1343/* 1344 *---------------------------------------------------------------------------- 1345 * MONOCHROME TEXT BLT 1346 * 1347 * This routine transfers contiguous monochrome text data to the screen. 1348 * 1349 * DSTX screen X position to render data 1350 * DSTY screen Y position to render data 1351 * WIDTH width of rectangle, in pixels 1352 * HEIGHT height of rectangle, in scanlines 1353 * *DATA pointer to bitmap data 1354 *---------------------------------------------------------------------------- 1355 */ 1356#if GFX_2DACCEL_DYNAMIC 1357void 1358gu1_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, 1359 unsigned short height, unsigned char *data) 1360#else 1361void 1362gfx_text_blt(unsigned short dstx, unsigned short dsty, unsigned short width, 1363 unsigned short height, unsigned char *data) 1364#endif 1365{ 1366 unsigned long dword_bytes_needed, bytes_extra; 1367 long pitch, buffer_bytes, data_bytes; 1368 1369 /* CALCULATE DATA SIZE */ 1370 1371 pitch = (width + 7) >> 3; 1372 data_bytes = (long) height *pitch; 1373 1374 /* CHECK FOR SIMPLE CASE */ 1375 /* This routine is designed to render a source copy text glyph. If 1376 * destination data is required or the source data will not fit, we will 1377 * punt the operation to the more versatile (and slow) mono bitmap routine 1378 * */ 1379 1380 if (GFXbpp > 8) 1381 buffer_bytes = GFXbufferWidthPixels << 1; 1382 else 1383 buffer_bytes = GFXbufferWidthPixels; 1384 1385 if (GFXusesDstData || data_bytes > buffer_bytes) { 1386 gfx_mono_bitmap_to_screen_blt(0, 0, dstx, dsty, width, height, data, 1387 (short) pitch); 1388 return; 1389 } 1390 1391 /* SET THE SCRATCHPAD BASE */ 1392 1393 SET_SCRATCH_BASE(GFXbb0Base); 1394 1395 /* POLL UNTIL ABLE TO WRITE TO THE REGISTERS */ 1396 1397 dword_bytes_needed = data_bytes & ~3l; 1398 bytes_extra = data_bytes & 3l; 1399 1400 GFX_WAIT_PENDING; 1401 WRITE_REG16(GP_HEIGHT, height); 1402 WRITE_REG16(GP_WIDTH, width); 1403 WRITE_REG16(GP_DST_XCOOR, dstx); 1404 WRITE_REG16(GP_DST_YCOOR, dsty); 1405 WRITE_REG16(GP_SRC_XCOOR, 0); 1406 1407 /* WRITE ALL DATA TO THE BLT BUFFERS */ 1408 /* The WRITE_SCRATCH_STRING macro assumes that the data begins at the */ 1409 /* scratchpad offset set by the SET_SCRATCH_BASE macro. */ 1410 1411 GFX_WAIT_PIPELINE; 1412 1413 WRITE_SCRATCH_STRING(dword_bytes_needed, bytes_extra, data, 0); 1414 WRITE_REG16(GP_BLIT_MODE, BM_READ_SRC_BB0 | BM_SOURCE_TEXT); 1415} 1416 1417/* 1418 *---------------------------------------------------------------------------- 1419 * BRESENHAM LINE 1420 * 1421 * This routine draws a vector using the specified Bresenham parameters. 1422 * Currently this file does not support a routine that accepts the two 1423 * endpoints of a vector and calculates the Bresenham parameters. If it 1424 * ever does, this routine is still required for vectors that have been 1425 * clipped. 1426 * 1427 * X screen X position to start vector 1428 * Y screen Y position to start vector 1429 * LENGTH length of the vector, in pixels 1430 * INITERR Bresenham initial error term 1431 * AXIALERR Bresenham axial error term 1432 * DIAGERR Bresenham diagonal error term 1433 * FLAGS VM_YMAJOR, VM_MAJOR_INC, VM_MINOR_INC 1434 *---------------------------------------------------------------------------- 1435 */ 1436#if GFX_2DACCEL_DYNAMIC 1437void 1438gu1_bresenham_line(unsigned short x, unsigned short y, 1439 unsigned short length, unsigned short initerr, 1440 unsigned short axialerr, unsigned short diagerr, 1441 unsigned short flags) 1442#else 1443void 1444gfx_bresenham_line(unsigned short x, unsigned short y, 1445 unsigned short length, unsigned short initerr, 1446 unsigned short axialerr, unsigned short diagerr, 1447 unsigned short flags) 1448#endif 1449{ 1450 unsigned short vector_mode = flags; 1451 1452 if (GFXusesDstData) 1453 vector_mode |= VM_READ_DST_FB; 1454 1455 /* CHECK NULL LENGTH */ 1456 1457 if (!length) 1458 return; 1459 1460 /* LOAD THE REGISTERS FOR THE VECTOR */ 1461 1462 GFX_WAIT_PENDING; 1463 WRITE_REG16(GP_DST_XCOOR, x); 1464 WRITE_REG16(GP_DST_YCOOR, y); 1465 WRITE_REG16(GP_VECTOR_LENGTH, length); 1466 WRITE_REG16(GP_INIT_ERROR, initerr); 1467 WRITE_REG16(GP_AXIAL_ERROR, axialerr); 1468 WRITE_REG16(GP_DIAG_ERROR, diagerr); 1469 WRITE_REG16(GP_VECTOR_MODE, vector_mode); 1470} 1471 1472/*--------------------------------------------------------------------------- 1473 * GFX_WAIT_UNTIL_IDLE 1474 * 1475 * This routine waits until the graphics engine is idle. This is required 1476 * before allowing direct access to the frame buffer. 1477 *--------------------------------------------------------------------------- 1478 */ 1479#if GFX_2DACCEL_DYNAMIC 1480void 1481gu1_wait_until_idle(void) 1482#else 1483void 1484gfx_wait_until_idle(void) 1485#endif 1486{ 1487 GFX_WAIT_BUSY; 1488} 1489 1490/*--------------------------------------------------------------------------- 1491 * GFX_TEST_BLT_PENDING 1492 * 1493 * This routine returns 1 if a BLT is pending, meaning that a call to 1494 * perform a rendering operation would stall. Otherwise it returns 0. 1495 * It is used by Darwin during random testing to only start a BLT 1496 * operation when it knows the Durango routines won't spin on graphics 1497 * (so Darwin can continue to do frame buffer reads and writes). 1498 *--------------------------------------------------------------------------- 1499 */ 1500#if GFX_2DACCEL_DYNAMIC 1501int 1502gu1_test_blt_pending(void) 1503#else 1504int 1505gfx_test_blt_pending(void) 1506#endif 1507{ 1508 if (READ_REG16(GP_BLIT_STATUS) & BS_BLIT_PENDING) 1509 return (1); 1510 else 1511 return (0); 1512} 1513 1514/*--------------------------------------------------------------------------- 1515 * BLT BUFFERS!!!!! 1516 *--------------------------------------------------------------------------- 1517 */ 1518 1519/* THE BOOT CODE MUST SET THE BLT BUFFER BASES USING THE "CPU_WRITE" */ 1520/* INSTRUCTION TO ONE OF THE FOLLOWING VALUES: */ 1521 1522#define BB0_BASE_2K 0x800 1523#define BB1_BASE_2K 0xB30 1524#define BB0_BASE_3K 0x400 1525#define BB1_BASE_3K 0x930 1526 1527/*--------------------------------------------------------------------------- 1528 * gu1_detect_blt_buffer_base 1529 * 1530 * This detection is hidden from the driver by being called from the 1531 * "gfx_set_bpp" routine. 1532 * 1533 * This is fairly ugly for the following reasons: 1534 * 1535 * - It is the boot code that must set the BLT buffer bases to the 1536 * appropriate values and load the scratchpad tags. 1537 * - The old drivers would also set the base address values to what they 1538 * knew they should be for the 2K or 3K scratchpad configuration. 1539 * - Unfortunately, to set the base addresses requires the use of the 1540 * CPU_WRITE instruction, an instruction specific to GX. 1541 * - Using the CPU_WRITE instruction requires the use of assembly to 1542 * produce the appropriate op codes. 1543 * - Assembly is something that is avoided in Durango because it is not 1544 * platform independent. Some compilers do not support inline assembly. 1545 * - Therefore Durango cannot use the CPU_WRITE instruction. 1546 * - Therefore drivers using Durango must rely on the boot code to set 1547 * the appropriate values. Durango uses this routine to check where 1548 * the base addresses have been set. 1549 * - Unfortunately, it is not as simple as using IO to check for 2K or 3K 1550 * scratchpad size. In VSA1, even though the boot code may set it for 1551 * 3K, SoftVGA comes along and resets it to 2K for it's use in text 1552 * redraws. It used to be that the display driver would set it back 1553 * to 3K. 1554 * - So, the Durango code was changed to just always use 2K. 1555 * - But, the XpressROM code sets it for 3K, and the newer versions of 1556 * SoftVGA do not interfere with that, so then Durango needs to use 1557 * the 3K values to work properly. 1558 * - Therefore, Durango does somewhat of a kludge by writing to directly 1559 * to the scratchpad at both the 2K and 3K locations, then performing 1560 * a unobtrusive BLT that loads data into BB0 (the graphics engine 1561 * always knows the true base). After the BLT, Durango looks to see 1562 * which location changed to know where the base address is. 1563 * - This is a relatively simple way to allow Durango to work on old 1564 * and new platforms without using theCPU_WRITE instructions. 1565 * 1566 * To summarize, the BLT buffers are one of the most painful aspects of 1567 * the GX graphics unit design, and have been removed from future designs 1568 * (the graphics unit has its own dedicated RAM). Durango has tried to 1569 * hide the BLT buffer use from the drivers. 1570 *--------------------------------------------------------------------------- 1571 */ 1572void 1573gu1_detect_blt_buffer_base(void) 1574{ 1575 /* ASSUME 2K */ 1576 1577 GFXbb0Base = BB0_BASE_2K; 1578 GFXbb1Base = BB1_BASE_2K; 1579 1580 /* CHECK IF SCRATCHPAD IS SET TO 3K OR 4K */ 1581 /* Boot code should still set 3K values for 4K. */ 1582 1583 if (gfx_gxm_config_read(GXM_CONFIG_GCR) & 0x08) { 1584 /* WRITE DATA TO 3K LOCATION */ 1585 1586 GFX_WAIT_BUSY; 1587 WRITE_SCRATCH32(BB0_BASE_3K, 0xFEEDFACE); 1588 1589 /* HAVE THE GRAPHICS UNIT STORE SOMETHING IN BB0 */ 1590 1591 WRITE_REG32(GP_DST_XCOOR, 0x00000000); /* AT (0,0) */ 1592 WRITE_REG32(GP_WIDTH, 0x00010004); /* 4x1 BLT */ 1593 WRITE_REG16(GP_RASTER_MODE, 0x00AA); /* KEEP DST */ 1594 WRITE_REG16(GP_BLIT_MODE, BM_READ_DST_FB0); /* STORE IN BB0 */ 1595 1596 /* CHECK 3K LOCATION */ 1597 /* Breaks if data happened to be 0xFEEDFACE - unlikely. */ 1598 1599 GFX_WAIT_BUSY; 1600 if (READ_SCRATCH32(BB0_BASE_3K) != 0xFEEDFACE) { 1601 GFXbb0Base = BB0_BASE_3K; 1602 GFXbb1Base = BB1_BASE_3K; 1603 } 1604 } 1605} 1606 1607/* END OF FILE */ 1608