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