s3_accel.c revision bd35f0db
1/* 2 * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> 3 * 4 * XFree86 4.x driver for S3 chipsets 5 * 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that copyright 10 * notice and this permission notice appear in supporting documentation and 11 * that the name of Ani Joshi not be used in advertising or 12 * publicity pertaining to distribution of the software without specific, 13 * written prior permission. Ani Joshi makes no representations 14 * about the suitability of this software for any purpose. It is provided 15 * "as-is" without express or implied warranty. 16 * 17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 * 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "xf86.h" 33 34#include "miline.h" 35 36#include "s3.h" 37#include "s3_reg.h" 38 39 40#if 0 41static Bool NicePattern; 42static int DashPatternSize; 43#define MAX_LINE_PATTERN_LENGTH 512 44#define LINE_PATTERN_START ((MAX_LINE_PATTERN_LENGTH >> 5) - 1) 45static CARD32 DashPattern[MAX_LINE_PATTERN_LENGTH >> 5]; 46#endif 47 48 49static void S3Sync(ScrnInfoPtr pScrn) 50{ 51 WaitIdle(); 52} 53 54static void S3SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 55 unsigned int planemask) 56{ 57 S3Ptr pS3 = S3PTR(pScrn); 58 59 WaitQueue16_32(4,6); 60 SET_PIX_CNTL(0); 61 SET_FRGD_COLOR(color); 62 SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]); 63 SET_WRT_MASK(planemask); 64} 65 66static void S3SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 67 int w, int h) 68{ 69#ifdef S3_NEWMMIO 70 S3Ptr pS3 = S3PTR(pScrn); 71#endif 72 73 WaitQueue(5); 74 SET_CURPT((short)x, (short)y); 75 SET_AXIS_PCNT(w - 1, h - 1); 76 SET_CMD(CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA); 77} 78 79 80static void S3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 81 int ydir, int rop, 82 unsigned int planemask, 83 int trans_color) 84{ 85 S3Ptr pS3 = S3PTR(pScrn); 86 87 pS3->BltDir = CMD_BITBLT | DRAW | WRTDATA; 88 89 if (xdir == 1) 90 pS3->BltDir |= INC_X; 91 if (ydir == 1) 92 pS3->BltDir |= INC_Y; 93 94 pS3->trans_color = trans_color; 95 96 WaitQueue16_32(3,4); 97 SET_PIX_CNTL(0); 98 SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]); 99 SET_WRT_MASK(planemask); 100} 101 102 103static void S3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, 104 int srcx, int srcy, 105 int dstx, int dsty, 106 int w, int h) 107{ 108 S3Ptr pS3 = S3PTR(pScrn); 109 110 w--; 111 h--; 112 113 if (!(pS3->BltDir & INC_Y)) { 114 srcy += h; 115 dsty += h; 116 } 117 118 if (!(pS3->BltDir & INC_X)) { 119 srcx += w; 120 dstx += w; 121 } 122 123 if (pS3->trans_color == -1) { 124 WaitQueue(7); 125 SET_CURPT((short)srcx, (short)srcy); 126 SET_DESTSTP((short)dstx, (short)dsty); 127 SET_AXIS_PCNT((short)w, (short)h); 128 SET_CMD(pS3->BltDir); 129 } else { 130 WaitQueue16_32(2,3); 131 SET_MULT_MISC(CMD_REG_WIDTH | 0x0100); 132 SET_COLOR_CMP(pS3->trans_color); 133 134 WaitQueue(8); 135 SET_CURPT((short)srcx, (short)srcy); 136 SET_DESTSTP((short)dstx, (short)dsty); 137 SET_AXIS_PCNT((short)w, (short)h); 138 SET_CMD(pS3->BltDir); 139 SET_MULT_MISC(CMD_REG_WIDTH); 140 } 141} 142 143#if 0 144static void S3SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, 145 int patx, int paty, 146 int rop, unsigned int planemask, 147 int trans_color) 148{ 149 S3Ptr pS3 = S3PTR(pScrn); 150 151 pS3->trans_color = trans_color; 152 153 WaitQueue16_32(3,4); 154 SET_PIX_CNTL(0); 155 SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]); 156 SET_WRT_MASK(planemask); 157} 158 159static void S3SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, 160 int patx, int paty, 161 int x, int y, 162 int w, int h) 163{ 164 S3Ptr pS3 = S3PTR(pScrn); 165 166 if (pS3->trans_color == -1) { 167 WaitQueue(7); 168 SET_CURPT((short)patx, (short)paty); 169 SET_DESTSTP((short)x, (short)y); 170 SET_AXIS_PCNT(w - 1, h - 1); 171 SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA); 172 } else { 173 WaitQueue16_32(2,3); 174 SET_MULT_MISC(CMD_REG_WIDTH | 0x0100); 175 SET_COLOR_CMP(pS3->trans_color); 176 177 WaitQueue(8); 178 SET_CURPT((short)patx, (short)paty); 179 SET_DESTSTP((short)x, (short)y); 180 SET_AXIS_PCNT(w - 1, h - 1); 181 SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA); 182 SET_MULT_MISC(CMD_REG_WIDTH); 183 } 184} 185#endif 186 187#ifdef S3_NEWMMIO 188static void S3SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 189 int fg, int bg, 190 int rop, 191 unsigned int planemask) 192{ 193 S3Ptr pS3 = S3PTR(pScrn); 194 195 WaitQueue16_32(3,4); 196 if (bg == -1) { 197 if (pS3->ColorExpandBug) { 198 SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_XOR); 199 SET_BKGD_COLOR(0); 200 } else 201 SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_DST); 202 } else { 203 SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | s3alu[rop]); 204 SET_BKGD_COLOR(bg); 205 } 206 207 WaitQueue16_32(3,5); 208 SET_FRGD_COLOR(fg); 209 SET_WRT_MASK(planemask); 210 SET_PIX_CNTL(MIXSEL_EXPPC); 211} 212 213 214static void S3SubsequentCPUToScreenColorExpandFill32(ScrnInfoPtr pScrn, 215 int x, int y, 216 int w, int h, 217 int skipleft) 218{ 219 S3Ptr pS3 = S3PTR(pScrn); 220 221 WaitQueue(4); 222 SET_CURPT((short)x, (short)y); 223 SET_AXIS_PCNT((short)w-1, (short)h-1); 224 225 WaitIdle(); 226 SET_CMD(CMD_RECT | BYTSEQ | _32BIT | PCDATA | DRAW | 227 PLANAR | INC_Y | INC_X | WRTDATA); 228} 229#endif 230 231#if 0 232#ifndef S3_NEWMMIO 233 234static void S3SetupForScanlineImageWriteNoMMIO(ScrnInfoPtr pScrn, int rop, 235 unsigned int planemask, 236 int trans_color, 237 int bpp, int depth) 238{ 239 S3Ptr pS3 = S3PTR(pScrn); 240 241 WaitQueue16_32(3,4) 242 SET_FRGD_MIX(FSS_PCDATA | s3alu[rop]); 243 SET_WRT_MASK(planemask); 244 SET_PIX_CNTL(0); 245} 246 247static void S3SubsequentScanlineImageWriteRectNoMMIO(ScrnInfoPtr pScrn, 248 int x, int y, 249 int w, int h, 250 int skipleft) 251{ 252 S3Ptr pS3 = S3PTR(pScrn); 253 254 pS3->imageWidth = w; 255 pS3->imageHeight = h; 256 257 WaitQueue(5); 258 SET_CURPT((short)x, (short)y); 259 SET_AXIS_PCNT((short)w-1, (short)h-1); 260 WaitIdle(); 261 SET_CMD(CMD_RECT | BYTSEQ | _16BIT | INC_Y | INC_X | DRAW | 262 PCDATA | WRTDATA); 263} 264 265 266static void S3SubsequentImageWriteScanlineNoMMIO(ScrnInfoPtr pScrn, 267 int bufno) 268{ 269 S3Ptr pS3 = S3PTR(pScrn); 270 int i, j; 271 int w, h; 272 CARD16 *src = (CARD16 *)&pS3->imageBuffer; 273 274 w = pS3->imageWidth * pS3->s3Bpp; 275 h = pS3->imageHeight; 276 277 for(j=0; j<h; j++) { 278 for(i=0; i<(w & ~1); ) { 279 /* XXX not for 32bpp */ 280 SET_PIX_TRANS_W(ldw_u(src)); 281 src++; 282 i += 2; 283 } 284 } 285} 286 287#endif 288#endif 289 290 291static void S3SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, 292 unsigned int planemask) 293{ 294 S3Ptr pS3 = S3PTR(pScrn); 295 296 WaitQueue16_32(4,6); 297 SET_PIX_CNTL(0); 298 SET_FRGD_COLOR(color); 299 SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]); 300 SET_WRT_MASK(planemask); 301} 302 303 304static void S3SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, 305 int x, int y, 306 int major, int minor, 307 int err, int len, int octant) 308{ 309#ifdef S3_NEWMMIO 310 S3Ptr pS3 = S3PTR(pScrn); 311#endif 312 unsigned short cmd; 313 int error, e1, e2; 314 315 error = minor + err; 316 e1 = minor; /* was: major, wrong (twini@xfree86.org) */ 317 e2 = minor - major; 318 319 if (major) { 320 cmd = CMD_LINE | DRAW | WRTDATA | LASTPIX; 321 322 if (octant & YMAJOR) 323 cmd |= YMAJAXIS; 324 if (!(octant & XDECREASING)) 325 cmd |= INC_X; 326 if (!(octant & YDECREASING)) 327 cmd |= INC_Y; 328 329 WaitQueue(7); 330 SET_CURPT((short)x, (short)y); 331 SET_ERR_TERM((short)error); 332 SET_DESTSTP((short)e2, (short)e1); 333 SET_MAJ_AXIS_PCNT((short)len); 334 SET_CMD(cmd); 335 } else { 336 WaitQueue(4); 337 SET_CURPT((short)x, (short)y); 338 SET_MAJ_AXIS_PCNT((short)len-1); 339 SET_CMD(CMD_LINE | DRAW | LINETYPE | WRTDATA | VECDIR_270); 340 } 341} 342 343 344 345static void S3SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, 346 int x, int y, int len, int dir) 347{ 348 if (dir == DEGREES_0) 349 S3SubsequentSolidFillRect(pScrn, x, y, len, 1); 350 else 351 S3SubsequentSolidFillRect(pScrn, x, y, 1, len); 352} 353 354 355#if 0 356 357static void S3SetupForDashedLine(ScrnInfoPtr pScrn, 358 int fg, int bg, 359 int rop, unsigned int planemask, 360 int len, unsigned char *pattern) 361{ 362#ifdef S3_NEWMMIO 363 S3Ptr pS3 = S3PTR(pScrn); 364 365 S3SetupForCPUToScreenColorExpandFill(pScrn, bg, fg, rop, planemask); 366#endif 367 368 WaitQueue(4); 369 370 NicePattern = FALSE; 371 372 if (len <= 32) { 373 register CARD32 scratch = DashPattern[LINE_PATTERN_START]; 374 375 if (len & (len - 1)) { 376 while (len < 16) { 377 scratch |= (scratch >> len); 378 len <<= 1; 379 } 380 scratch |= (scratch >> len); 381 DashPattern[LINE_PATTERN_START] = scratch; 382 } else { 383 switch (len) { 384 case 2: 385 scratch |= scratch >> 2; 386 case 4: 387 scratch |= scratch >> 4; 388 case 8: 389 scratch |= scratch >> 8; 390 case 16: 391 scratch |= scratch >> 16; 392 DashPattern[LINE_PATTERN_START] = scratch; 393 case 32: 394 NicePattern = TRUE; 395 default: 396 break; 397 } 398 } 399 } 400 401 DashPatternSize = len; 402} 403 404 405static void S3SubsequentDashedBresenhamLine32(ScrnInfoPtr pScrn, 406 int x, int y, 407 int absmaj, int absmin, 408 int err, int len, 409 int octant, int phase) 410{ 411#ifdef S3_NEWMMIO 412 S3Ptr pS3 = S3PTR(pScrn); 413#endif 414 register int count = (len + 31) >> 5; 415 register CARD32 pattern; 416 int error, e1, e2; 417 418 error = absmin + err; 419 e1 = absmaj; 420 e2 = absmin - absmaj; 421 422 if (err) { 423 unsigned short cmd = _32BIT | PLANAR | WRTDATA | DRAW | 424 PCDATA | LASTPIX | CMD_LINE; 425 426 if (octant & YMAJOR) 427 cmd |= YMAJAXIS; 428 if (!(octant & XDECREASING)) 429 cmd |= INC_X; 430 if (!(octant & YDECREASING)) 431 cmd |= INC_Y; 432 433 WaitQueue(7); 434 SET_CURPT((short)x, (short)y); 435 SET_ERR_TERM((short)error); 436 SET_DESTSTP((short)e2, (short)e1); 437 SET_MAJ_AXIS_PCNT((short)len); 438 SET_CMD(cmd); 439 } else { 440 if (octant & YMAJOR) { 441 WaitQueue(4); 442 SET_CURPT((short)x, (short)y); 443 SET_MAJ_AXIS_PCNT((short)len - 1); 444 445 if (octant & YDECREASING) { 446 SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | 447 CMD_LINE | LINETYPE | VECDIR_090); 448 } else { 449 SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | 450 CMD_LINE | LINETYPE | VECDIR_270); 451 } 452 } else { 453 if (octant & XDECREASING) { 454 WaitQueue(4); 455 SET_CURPT((short)x, (short)y); 456 SET_MAJ_AXIS_PCNT((short)len - 1); 457 SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | 458 PCDATA | CMD_LINE | LINETYPE | VECDIR_180); 459 } else { 460 WaitQueue(4); 461 SET_CURPT((short)x, (short)y); 462 SET_MAJ_AXIS_PCNT((short)len - 1); 463 SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW | 464 PCDATA | CMD_RECT | INC_Y | INC_X); 465 } 466 } 467 } 468 469 if (NicePattern) { 470#ifdef S3_NEWMMIO 471 register CARD32 *dest = (CARD32*)&IMG_TRANS; 472#endif 473 474 pattern = (phase) ? (DashPattern[LINE_PATTERN_START] << phase) | 475 (DashPattern[LINE_PATTERN_START] >> (32 - phase)) : 476 DashPattern[LINE_PATTERN_START]; 477 478#ifdef S3_NEWMMIO 479 while (count & ~0x03) { 480 dest[0] = dest[1] = dest[2] = dest[3] = pattern; 481 dest += 4; 482 count -= 4; 483 } 484 switch (count) { 485 case 1: 486 dest[0] = pattern; 487 break; 488 case 2: 489 dest[0] = dest[1] = pattern; 490 break; 491 case 3: 492 dest[0] = dest[1] = dest[2] = pattern; 493 break; 494 } 495#else 496 497 while (count--) 498 SET_PIX_TRANS_L(pattern); 499#endif 500 } else if (DashPatternSize < 32) { 501 register int offset = phase; 502 503 while (count--) { 504 SET_PIX_TRANS_L((DashPattern[LINE_PATTERN_START] << offset) | 505 (DashPattern[LINE_PATTERN_START] >> 506 (DashPatternSize - offset))); 507 offset += 32; 508 while (offset > DashPatternSize) 509 offset -= DashPatternSize; 510 } 511 } else { 512 int offset = phase; 513 register unsigned char *srcp = (unsigned char *)(DashPattern) + 514 (MAX_LINE_PATTERN_LENGTH >> 3) - 1; 515 register CARD32 *scratch; 516 int scratch2, shift; 517 518 while (count--) { 519 shift = DashPatternSize - offset; 520 scratch = (CARD32*)(srcp - (offset >> 3) - 3); 521 scratch2 = offset & 0x07; 522 523 if (shift & ~31) { 524 if (scratch2) { 525 pattern = (*scratch << scratch2) | 526 (*(scratch - 1) >> (32 - scratch2)); 527 } else 528 pattern = *scratch; 529 } else { 530 pattern = (*((CARD32*)(srcp - 3)) >> shift) | 531 (*scratch << scratch2); 532 } 533 SET_PIX_TRANS_L(pattern); 534 offset += 32; 535 while (offset >= DashPatternSize) 536 offset -= DashPatternSize; 537 } 538 } 539} 540 541#endif 542 543#ifdef S3_NEWMMIO 544Bool S3AccelInitNewMMIO(ScreenPtr pScreen) 545#else 546Bool S3AccelInitPIO(ScreenPtr pScreen) 547#endif 548{ 549 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 550 S3Ptr pS3 = S3PTR(pScrn); 551 XAAInfoRecPtr pXAA; 552 553 if (pS3->Chipset == PCI_CHIP_968) 554 pS3->ColorExpandBug = TRUE; 555 else 556 pS3->ColorExpandBug = FALSE; 557 558 if (!(pXAA = XAACreateInfoRec())) 559 return FALSE; 560 561 pS3->pXAA = pXAA; 562 563 pXAA->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS | 564 LINEAR_FRAMEBUFFER); 565 566 pXAA->Sync = S3Sync; 567 568 pXAA->SetupForSolidFill = S3SetupForSolidFill; 569 pXAA->SubsequentSolidFillRect = S3SubsequentSolidFillRect; 570 571 pXAA->SetupForScreenToScreenCopy = S3SetupForScreenToScreenCopy; 572 pXAA->SubsequentScreenToScreenCopy = S3SubsequentScreenToScreenCopy; 573 pXAA->ScreenToScreenCopyFlags = NO_TRANSPARENCY; 574 575#if 0 576/* 577 8x8 color pattern filling doesn't work properly after introducing 578 framebuffer manager initialization before XAA initialization. There 579 are problems with addressing a colour patterns from offscreen area. 580*/ 581 pXAA->SetupForColor8x8PatternFill = S3SetupForColor8x8PatternFill; 582 pXAA->SubsequentColor8x8PatternFillRect = S3SubsequentColor8x8PatternFillRect; 583 pXAA->Color8x8PatternFillFlags = NO_TRANSPARENCY | 584 HARDWARE_PATTERN_SCREEN_ORIGIN | 585 BIT_ORDER_IN_BYTE_MSBFIRST; 586 587 pXAA->CachePixelGranularity = 0; 588#endif 589 590#ifdef S3_NEWMMIO 591 pXAA->SetupForCPUToScreenColorExpandFill = 592 S3SetupForCPUToScreenColorExpandFill; 593 pXAA->SubsequentCPUToScreenColorExpandFill = 594 S3SubsequentCPUToScreenColorExpandFill32; 595 pXAA->ColorExpandBase = (void *) &IMG_TRANS; 596 pXAA->ColorExpandRange = 0x8000; 597 pXAA->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD | 598 BIT_ORDER_IN_BYTE_MSBFIRST | 599 SCANLINE_PAD_DWORD; 600#endif 601 602#if 0 603#ifndef S3_NEWMMIO 604 pXAA->ScanlineImageWriteFlags = NO_TRANSPARENCY; 605 pXAA->SetupForScanlineImageWrite = 606 S3SetupForScanlineImageWriteNoMMIO; 607 pXAA->SubsequentScanlineImageWriteRect = 608 S3SubsequentScanlineImageWriteRectNoMMIO; 609 pXAA->SubsequentImageWriteScanline = 610 S3SubsequentImageWriteScanlineNoMMIO; 611 pXAA->NumScanlineImageWriteBuffers = 1; 612 pXAA->ScanlineImageWriteBuffers = &pS3->imageBuffer; 613#endif 614#endif 615 616 pXAA->SetupForSolidLine = S3SetupForSolidLine; 617 pXAA->SubsequentSolidBresenhamLine = S3SubsequentSolidBresenhamLine; 618 pXAA->SubsequentSolidHorVertLine = S3SubsequentSolidHorVertLine; 619 pXAA->SolidBresenhamLineErrorTermBits = 12; 620#if 0 621 /* kinda buggy... and its faster without it */ 622 pXAA->SetupForDashedLine = S3SetupForDashedLine; 623 pXAA->SubsequentDashedBresenhamLine = S3SubsequentDashedBresenhamLine32; 624 pXAA->DashPatternMaxLength = MAX_LINE_PATTERN_LENGTH; 625#endif 626 627 return XAAInit(pScreen, pXAA); 628} 629