1 2/* 3Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 4 5Permission is hereby granted, free of charge, to any person obtaining a copy of 6this software and associated documentation files (the "Software"), to deal in 7the Software without restriction, including without limitation the rights to 8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9of the Software, and to permit persons to whom the Software is furnished to do 10so, subject to the following conditions: 11 12The above copyright notice and this permission notice shall be included in all 13copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of the XFree86 Project shall not 23be used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from the XFree86 Project. 25*/ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <unistd.h> 32#include "s3v.h" 33#include "s3v_pciids.h" 34 35#include "miline.h" 36 /* fb includes are in s3v.h */ 37#include "xaarop.h" 38 39#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */ 40 41#ifdef HAVE_XAA_H 42static void S3VWriteMask(CARD32*, int); 43 44static void S3VEngineReset(ScrnInfoPtr pScrn); 45/* s3v.h - static void S3VAccelSync(ScrnInfoPtr); */ 46static void S3VSetupForSolidFill(ScrnInfoPtr, int, int, unsigned); 47static void S3VSubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int); 48static void S3VSubsequentSolidFillRectPlaneMask(ScrnInfoPtr, int, int, 49 int, int); 50static void S3VSetupForMono8x8PatternFill(ScrnInfoPtr,int, int, int, int, 51 int, unsigned int); 52static void S3VSubsequentMono8x8PatternFillRect(ScrnInfoPtr,int, int, 53 int, int, int, int); 54static void S3VSubsequentMono8x8PatternFillRectPlaneMask(ScrnInfoPtr,int, int, 55 int, int, int, int); 56static void S3VSetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int, 57 unsigned int, int); 58static void S3VSubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int, 59 int, int); 60static void S3VSetupForCPUToScreenColorExpand(ScrnInfoPtr, int, int, int, 61 unsigned int); 62static void S3VSubsequentCPUToScreenColorExpand(ScrnInfoPtr, int, int, int, 63 int, int); 64static void S3VSetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, 65 int, int); 66static void S3VSubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int); 67static void S3VSubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int); 68static void S3VSubsequentSolidHorVertLinePlaneMask(ScrnInfoPtr, int, int, 69 int, int); 70#if 0 71static void S3VSubsequentSolidBresenhamLine(ScrnInfoPtr, int, int, int, 72 int, int, int, int); 73static void S3VPolylinesThinSolidWrapper(DrawablePtr, GCPtr, int, int, 74 DDXPointPtr); 75static void S3VPolySegmentThinSolidWrapper(DrawablePtr, GCPtr, int, xSegment*); 76#endif 77static void S3VNopAllCmdSets(ScrnInfoPtr pScrn); 78#endif 79 80Bool 81S3VAccelInit(ScreenPtr pScreen) 82{ 83#ifdef HAVE_XAA_H 84 XAAInfoRecPtr infoPtr; 85 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 86 S3VPtr ps3v = S3VPTR(pScrn); 87 BoxRec AvailFBArea; 88 89 ps3v->AccelInfoRec = infoPtr = XAACreateInfoRec(); 90 if(!infoPtr) return FALSE; 91 92 switch(ps3v->Chipset) 93 { 94 case S3_ViRGE: 95 case S3_ViRGE_VX: 96 ps3v->AccelFlags = BLT_BUG; 97 break; 98 default: 99 ps3v->AccelFlags = 0; 100 break; 101 } 102 103 ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */ 104 105 106 infoPtr->Flags = PIXMAP_CACHE | 107 LINEAR_FRAMEBUFFER | 108 OFFSCREEN_PIXMAPS; 109 110 infoPtr->Sync = S3VAccelSync; 111 112 /* Problem reports with solid fill on trio3d */ 113 if(!S3_TRIO_3D_SERIES(ps3v->Chipset)) 114 { 115 /* Solid filled rects */ 116 infoPtr->SetupForSolidFill = 117 S3VSetupForSolidFill; 118 infoPtr->SubsequentSolidFillRect = 119 S3VSubsequentSolidFillRect; 120 } 121 122 /* Screen to screen copies */ 123 infoPtr->SetupForScreenToScreenCopy = 124 S3VSetupForScreenToScreenCopy; 125 infoPtr->SubsequentScreenToScreenCopy = 126 S3VSubsequentScreenToScreenCopy; 127 infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; 128 129 /* Mono 8x8 patterns */ 130 infoPtr->SetupForMono8x8PatternFill = 131 S3VSetupForMono8x8PatternFill; 132 infoPtr->SubsequentMono8x8PatternFillRect = 133 S3VSubsequentMono8x8PatternFillRect; 134 infoPtr->Mono8x8PatternFillFlags = NO_TRANSPARENCY | 135 HARDWARE_PATTERN_PROGRAMMED_BITS | 136 HARDWARE_PATTERN_SCREEN_ORIGIN | 137 BIT_ORDER_IN_BYTE_MSBFIRST; 138 139 140#ifndef __alpha__ 141 142 /* disable color expand on GX2 until we trace down */ 143 /* lockups. locate 'html' in an xterm is a good */ 144 /* test case for an AGP GX2. */ 145 if (!S3_ViRGE_GX2_SERIES(ps3v->Chipset)) 146 { 147 148 149 /* CPU to screen color expansion */ 150 infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE | 151 CPU_TRANSFER_PAD_DWORD | 152 SCANLINE_PAD_DWORD | 153 BIT_ORDER_IN_BYTE_MSBFIRST | 154 LEFT_EDGE_CLIPPING; 155 156 if(ps3v->AccelFlags & MONO_TRANS_BUG) 157 infoPtr->CPUToScreenColorExpandFillFlags |= NO_TRANSPARENCY; 158 159 infoPtr->ColorExpandRange = 0x8000; 160 infoPtr->ColorExpandBase = ps3v->MapBaseDense; 161 infoPtr->SetupForCPUToScreenColorExpandFill = 162 S3VSetupForCPUToScreenColorExpand; 163 infoPtr->SubsequentCPUToScreenColorExpandFill = 164 S3VSubsequentCPUToScreenColorExpand; 165 166 } /* if(!GX2...) */ 167 168 169 /* Image Writes */ 170 infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE | 171 NO_TRANSPARENCY | 172 CPU_TRANSFER_PAD_DWORD | 173 SCANLINE_PAD_DWORD | 174 NO_GXCOPY | /* added - kjb */ 175 LEFT_EDGE_CLIPPING; 176 177 infoPtr->ImageWriteRange = 0x8000; 178 infoPtr->ImageWriteBase = ps3v->MapBaseDense; 179 infoPtr->SetupForImageWrite = S3VSetupForImageWrite; 180 infoPtr->SubsequentImageWriteRect = S3VSubsequentImageWriteRect; 181 182 /* on alpha, I see corruption in the xscreensaver program "hypercube" 183 as the line acceleration is just stubs, it loses us nothing to 184 disable it on alphas */ 185 186 /* Lines */ 187#if 0 188 /* Bresenham lines are broken when passed through fb to xaa 189 so I pulled all the line functions. This shouldn't hurt us 190 a whole lot, since the Subsequent..Bresen stuff doesn't have 191 any hardware accel yet anyway... And xaa will do horiz/vert 192 lines with the rect fill (like we are doing here) anyway. 193 KJB 9/11/00 194 */ 195 infoPtr->SetupForSolidLine = S3VSetupForSolidFill; 196 infoPtr->SubsequentSolidHorVertLine = S3VSubsequentSolidHorVertLine; 197 infoPtr->SubsequentSolidBresenhamLine = S3VSubsequentSolidBresenhamLine; 198 infoPtr->PolySegmentThinSolid = S3VPolySegmentThinSolidWrapper; 199 infoPtr->PolylinesThinSolid = S3VPolylinesThinSolidWrapper; 200#endif 201 202#endif /* !__alpha__ */ 203 204 /* And these are screen parameters used to setup the GE */ 205 206 ps3v->Width = pScrn->displayWidth; 207 /* Bytes per pixel */ 208 ps3v->Bpp = pScrn->bitsPerPixel / 8; 209 /* Bytes per line */ 210 ps3v->Bpl = ps3v->Width * ps3v->Bpp; 211 /* ScissB is max height, minus 1k */ 212 /* for hwcursor?, then limited by */ 213 /* ViRGE max height register of */ 214 /* 2047 */ 215 ps3v->ScissB = (pScrn->videoRam * 1024 - 1024) / ps3v->Bpl; 216 if (ps3v->ScissB > 2047) 217 ps3v->ScissB = 2047; 218 219 220 S3VEngineReset(pScrn); 221 222 223 AvailFBArea.x1 = 0; 224 AvailFBArea.y1 = 0; 225 AvailFBArea.x2 = pScrn->displayWidth; 226 AvailFBArea.y2 = (pScrn->videoRam * 1024 - 1024) / 227 (pScrn->displayWidth * pScrn->bitsPerPixel / 8); 228 229 xf86InitFBManager(pScreen, &AvailFBArea); 230 231 /* make sure offscreen pixmaps aren't bigger than our address space */ 232 infoPtr->maxOffPixWidth = 2048; 233 infoPtr->maxOffPixHeight = 2048; 234 235 return (XAAInit(pScreen, infoPtr)); 236#else 237 return FALSE; 238#endif 239} 240 241Bool 242S3VAccelInit32(ScreenPtr pScreen) 243{ 244 return FALSE; 245} 246 247void 248S3VNopAllCmdSets(ScrnInfoPtr pScrn) 249{ 250 int i; 251 int max_it=1000; 252 S3VPtr ps3v = S3VPTR(pScrn); 253 254 if (xf86GetVerbosity() > 1) { 255 ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n", 256 (unsigned long)IN_SUBSYS_STAT()); 257 } 258 259 mem_barrier(); 260 for(i=0;i<max_it;i++) { 261 if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) { 262 break; 263 } 264 } 265 266 if(i!=max_it) { 267 if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i); 268 } else { 269 if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it); 270 } 271 272 WaitQueue(5); 273 274 OUTREG(CMD_SET, CMD_NOP); 275 276 if (xf86GetVerbosity() > 1) { 277 ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n", 278 (unsigned long)IN_SUBSYS_STAT()); 279 } 280} 281 282void 283S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, const char *file) 284{ 285 unsigned long gs1, gs2; /* -- debug info for graphics state -- */ 286 unsigned char tmp, sr1, resetidx=0x66; /* FIXME */ 287 int r; 288 int ge_was_on = 0; 289 CARD32 fifo_control = 0, miu_control = 0; 290 CARD32 streams_timeout = 0, misc_timeout = 0; 291 vgaHWPtr hwp = VGAHWPTR(pScrn); 292 S3VPtr ps3v = S3VPTR(pScrn); 293 int vgaCRIndex, vgaCRReg, vgaIOBase; 294 vgaIOBase = hwp->IOBase; 295 vgaCRIndex = vgaIOBase + 4; 296 vgaCRReg = vgaIOBase + 5; 297 298 299 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) { 300 VGAOUT8(0x3c4,0x01); 301 sr1 = VGAIN8(0x3c5); 302 303 if (sr1 & 0x20) { 304 if (xf86GetVerbosity() > 1) 305 ErrorF("\tTrio3D -- Display is on...turning off\n"); 306 VGAOUT8(0x3c5,sr1 & ~0x20); 307 VerticalRetraceWait(); 308 } 309 } 310 311 if (from_timeout) { 312 if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1) 313 ErrorF("\tS3VGEReset called from %s line %d\n",file,line); 314 } 315 else { 316 if (S3_TRIO_3D_SERIES(ps3v->Chipset)) 317 S3VNopAllCmdSets(pScrn); 318 WaitIdleEmpty(); 319 } 320 321 322 if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) { 323 /* reset will trash these registers, so save them */ 324 fifo_control = INREG(FIFO_CONTROL_REG); 325 miu_control = INREG(MIU_CONTROL_REG); 326 streams_timeout = INREG(STREAMS_TIMEOUT_REG); 327 misc_timeout = INREG(MISC_TIMEOUT_REG); 328 } 329 330 if(ps3v->Chipset == S3_ViRGE_VX){ 331 VGAOUT8(vgaCRIndex, 0x63); 332 } 333 else { 334 VGAOUT8(vgaCRIndex, 0x66); 335 } 336 if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) { 337 tmp = VGAIN8(vgaCRReg); 338 339 usleep(10000); 340 for (r=1; r<10; r++) { /* try multiple times to avoid lockup of ViRGE/MX */ 341 VGAOUT8(vgaCRReg, tmp | 0x02); 342 usleep(10000); 343 VGAOUT8(vgaCRReg, tmp & ~0x02); 344 usleep(10000); 345 346 xf86ErrorFVerb(VERBLEV, " S3VGEReset sub_stat=%lx \n", 347 (unsigned long)IN_SUBSYS_STAT() 348 ); 349 350 if (!from_timeout) 351 WaitIdleEmpty(); 352 353 OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl); 354 355 usleep(10000); 356 if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000)) 357 xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r); 358 else 359 break; 360 } 361 } else { 362 usleep(10000); 363 364 for (r=1; r<10; r++) { 365 VerticalRetraceWait(); 366 VGAOUT8(vgaCRIndex,resetidx); 367 tmp = VGAIN8(vgaCRReg); 368 369 VGAOUT8(0x3c4,0x01); 370 sr1 = VGAIN8(0x3c5); 371 372 if(sr1 & 0x20) { 373 if(xf86GetVerbosity() > 1) { 374 ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n"); 375 } 376 VGAOUT8(0x3c4,0x01); 377 VerticalRetraceWait(); 378 VGAOUT8(0x3c5,sr1 & ~0x20); 379 } 380 381 VerticalRetraceWait(); 382 gs1 = (long) IN_SUBSYS_STAT(); 383 384 /* turn off the GE */ 385 386 VGAOUT8(vgaCRIndex,resetidx); 387 if(tmp & 0x01) { 388 /* tmp &= ~0x01; */ 389 VGAOUT8(vgaCRReg, tmp); 390 ge_was_on = 1; 391 usleep(10000); 392 } 393 394 gs2 = (long) IN_SUBSYS_STAT(); 395 VGAOUT8(vgaCRReg, (tmp | 0x02)); 396 usleep(10000); 397 398 VerticalRetraceWait(); 399 VGAOUT8(vgaCRIndex,resetidx); 400 VGAOUT8(vgaCRReg, (tmp & ~0x02)); 401 usleep(10000); 402 403 if(ge_was_on) { 404 tmp |= 0x01; 405 VGAOUT8(vgaCRReg, tmp); 406 usleep(10000); 407 } 408 409 if (xf86GetVerbosity() > 2) { 410 ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n", 411 (ge_was_on) ? "on" : "off", gs1, gs2); 412 } 413 414 VerticalRetraceWait(); 415 416 if (!from_timeout) { 417 S3VNopAllCmdSets(pScrn); 418 WaitIdleEmpty(); 419 } 420 421 OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl); 422 usleep(10000); 423 424 if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) { 425 if(xf86GetVerbosity() > 1) 426 ErrorF("restarting S3 graphics engine reset %2d ...%lx\n", 427 r, (unsigned long)IN_SUBSYS_STAT()); 428 } 429 else 430 break; 431 } 432 } 433 434 if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX 435 || ps3v->Chipset == S3_ViRGE_DXGX)) { 436 /* restore trashed registers */ 437 OUTREG(FIFO_CONTROL_REG, fifo_control); 438 OUTREG(MIU_CONTROL_REG, miu_control); 439 OUTREG(STREAMS_TIMEOUT_REG, streams_timeout); 440 OUTREG(MISC_TIMEOUT_REG, misc_timeout); 441 } 442 443 WAITFIFO(2); 444/* SETB_SRC_BASE(0); */ 445/* SETB_DEST_BASE(0); */ 446 OUTREG(SRC_BASE, 0); 447 OUTREG(DEST_BASE, 0); 448 449 WAITFIFO(4); 450 OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width); 451 OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB); 452 OUTREG(MONO_PAT_0, ~0); 453 OUTREG(MONO_PAT_1, ~0); 454 455 if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset)) 456 S3VNopAllCmdSets(pScrn); 457} 458 459/* The sync function for the GE */ 460void 461S3VAccelSync(ScrnInfoPtr pScrn) 462{ 463 S3VPtr ps3v = S3VPTR(pScrn); 464 465 WAITIDLE(); 466} 467 468#ifdef HAVE_XAA_H 469static void 470S3VEngineReset(ScrnInfoPtr pScrn) 471{ 472 S3VPtr ps3v = S3VPTR(pScrn); 473 474 ps3v->SrcBaseY = 0; 475 ps3v->DestBaseY = 0; 476 ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3; 477 478 switch(pScrn->bitsPerPixel) { 479 case 8: ps3v->CommonCmd = DRAW | DST_8BPP; 480 ps3v->FullPlaneMask = 0x000000ff; 481 ps3v->bltbug_width1 = 51; 482 ps3v->bltbug_width2 = 64; 483 break; 484 case 16: ps3v->CommonCmd = DRAW | DST_16BPP; 485 ps3v->FullPlaneMask = 0x0000ffff; 486 ps3v->bltbug_width1 = 26; 487 ps3v->bltbug_width2 = 32; 488 break; 489 case 24: ps3v->CommonCmd = DRAW | DST_24BPP; 490 ps3v->FullPlaneMask = 0x00ffffff; 491 ps3v->bltbug_width1 = 16; 492 ps3v->bltbug_width2 = 22; 493 break; 494 } 495 496 497 WAITFIFO(5); 498 OUTREG(SRC_BASE, 0); 499 OUTREG(DEST_BASE, 0); 500 OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16)); 501 502 OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width); 503 OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB); 504} 505 506 507static void 508S3VWriteMask( 509 CARD32 *dstBase, 510 int dwords 511){ 512 /* on alphas, be sure to call this with MapBaseDense, not MapBase! */ 513 int numLeft; 514 CARD32 *dst = dstBase; 515 516 while(dwords >= 8192) { 517 numLeft = 8192; 518 while(numLeft) { 519 dst[0] = ~0; dst[1] = ~0; 520 dst[2] = ~0; dst[3] = ~0; 521 dst += 4; 522 numLeft -= 4; 523 } 524 dwords -= 8192; 525 dst = dstBase; 526 } 527 while(dwords >= 4) { 528 dst[0] = ~0; dst[1] = ~0; 529 dst[2] = ~0; dst[3] = ~0; 530 dst += 4; 531 dwords -= 4; 532 } 533 if(!dwords) return; 534 dst[0] = ~0; 535 if(dwords == 1) return; 536 dst[1] = ~0; 537 if(dwords == 2) return; 538 dst[2] = ~0; 539 540 return; 541} 542 543 544 /************************\ 545 | Solid Filled Rects | 546 \************************/ 547 548static void 549S3VSetupForSolidFill( 550 ScrnInfoPtr pScrn, 551 int color, int rop, 552 unsigned int planemask 553){ 554 S3VPtr ps3v = S3VPTR(pScrn); 555 int mix; 556 557 mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop); 558 559 ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) | 560 CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT; 561 562 if(mix & ROP_SRC) { 563 ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC; 564 ps3v->AccelInfoRec->SubsequentSolidFillRect = 565 S3VSubsequentSolidFillRectPlaneMask; 566 ps3v->AccelInfoRec->SubsequentSolidHorVertLine = 567 S3VSubsequentSolidHorVertLinePlaneMask; 568 WAITFIFO(5); 569 OUTREG(SRC_FG_CLR, planemask); 570 } else { 571 ps3v->AccelInfoRec->SubsequentSolidFillRect = 572 S3VSubsequentSolidFillRect; 573 ps3v->AccelInfoRec->SubsequentSolidHorVertLine = 574 S3VSubsequentSolidHorVertLine; 575 WAITFIFO(4); 576 } 577 578 if(mix & ROP_PAT) { 579 ps3v->AccelCmd |= MIX_MONO_PATT; 580 OUTREG(PAT_FG_CLR, color); 581 OUTREG(MONO_PAT_0, ~0); 582 OUTREG(MONO_PAT_1, ~0); 583 } 584 585 OUTREG(CMD_SET, ps3v->AccelCmd); 586} 587 588 589void 590S3VSubsequentSolidFillRect( 591 ScrnInfoPtr pScrn, 592 int x, int y, 593 int w, int h 594){ 595 S3VPtr ps3v = S3VPTR(pScrn); 596 597 CHECK_DEST_BASE(y,h); 598 599 WAITFIFO(2); 600 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 601 WAITCMD(); 602 OUTREG(RDEST_XY, (x << 16) | y); 603} 604 605 606void 607S3VSubsequentSolidFillRectPlaneMask( 608 ScrnInfoPtr pScrn, 609 int x, int y, 610 int w, int h 611){ 612 S3VPtr ps3v = S3VPTR(pScrn); 613 int dwords; 614 615 CHECK_DEST_BASE(y,h); 616 617 dwords = ((w + 31) >> 5) * h; 618 619 WAITFIFO(2); 620 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 621 WAITCMD(); 622 OUTREG(RDEST_XY, (x << 16) | y); 623 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 624} 625 626 627 /**************************\ 628 | Screen to Screen Copies | 629 \**************************/ 630 631static void 632S3VSetupForScreenToScreenCopy( 633 ScrnInfoPtr pScrn, 634 int xdir, int ydir, 635 int rop, 636 unsigned int planemask, 637 int trans 638){ 639 S3VPtr ps3v = S3VPTR(pScrn); 640 641 planemask &= ps3v->FullPlaneMask; 642 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT; 643 644 if(planemask != ps3v->FullPlaneMask) { 645 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 646 WAITFIFO(4); 647 OUTREG(PAT_FG_CLR, planemask); 648 OUTREG(MONO_PAT_0, ~0); 649 OUTREG(MONO_PAT_1, ~0); 650 } 651 else { 652 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 653 WAITFIFO(1); 654 } 655 if(xdir == 1) ps3v->AccelCmd |= CMD_XP; 656 if(ydir == 1) ps3v->AccelCmd |= CMD_YP; 657 658 OUTREG(CMD_SET, ps3v->AccelCmd); 659} 660 661 662static void 663S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 664 int x2, int y2, int w, int h) 665{ 666 S3VPtr ps3v = S3VPTR(pScrn); 667 668 CHECK_SRC_BASE(y1,h); 669 CHECK_DEST_BASE(y2,h); 670 671 w--; 672 673 if(!(ps3v->AccelCmd & CMD_YP)) { 674 y1 += h - 1; y2 += h - 1; 675 } 676 677 if(!(ps3v->AccelCmd & CMD_XP)) { 678 x1 += w; x2 += w; 679 } 680 681 WAITFIFO(3); 682 OUTREG(RWIDTH_HEIGHT, (w << 16) | h); 683 OUTREG(RSRC_XY, (x1 << 16) | y1); 684 WAITCMD(); 685 OUTREG(RDEST_XY, (x2 << 16) | y2); 686} 687 688 689 /*********************\ 690 | 8x8 Pattern fills | 691 \*********************/ 692 693 694static void 695S3VSetupForMono8x8PatternFill( 696 ScrnInfoPtr pScrn, 697 int patx, int paty, 698 int fg, int bg, 699 int rop, unsigned int planemask 700){ 701 S3VPtr ps3v = S3VPTR(pScrn); 702 int mix; 703 704 mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop); 705 706 ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) | 707 CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT; 708 709 if(mix & ROP_SRC) { 710 ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC; 711 ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect = 712 S3VSubsequentMono8x8PatternFillRectPlaneMask; 713 WAITFIFO(6); 714 OUTREG(SRC_FG_CLR, planemask); 715 } else { 716 ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect = 717 S3VSubsequentMono8x8PatternFillRect; 718 WAITFIFO(5); 719 } 720 721 if(mix & ROP_PAT) { 722 ps3v->AccelCmd |= MIX_MONO_PATT; 723 OUTREG(PAT_FG_CLR, fg); 724 OUTREG(PAT_BG_CLR, bg); 725 OUTREG(MONO_PAT_0, patx); 726 OUTREG(MONO_PAT_1, paty); 727 } 728 729 OUTREG(CMD_SET, ps3v->AccelCmd); 730} 731 732 733static void 734S3VSubsequentMono8x8PatternFillRect( 735 ScrnInfoPtr pScrn, 736 int patx, int paty, 737 int x, int y, int w, int h 738){ 739 S3VPtr ps3v = S3VPTR(pScrn); 740 741 CHECK_DEST_BASE(y,h); 742 743 WAITFIFO(2); 744 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 745 WAITCMD(); 746 OUTREG(RDEST_XY, (x << 16) | y); 747} 748 749 750static void 751S3VSubsequentMono8x8PatternFillRectPlaneMask( 752 ScrnInfoPtr pScrn, 753 int patx, int paty, 754 int x, int y, int w, int h 755){ 756 S3VPtr ps3v = S3VPTR(pScrn); 757 int dwords; 758 759 CHECK_DEST_BASE(y,h); 760 761 dwords = ((w + 31) >> 5) * h; 762 763 WAITFIFO(2); 764 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 765 WAITCMD(); 766 OUTREG(RDEST_XY, (x << 16) | y); 767 768 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 769} 770 771 /*********************************\ 772 | CPU to Screen Color Expansion | 773 \*********************************/ 774 775 776static void 777S3VSetupForCPUToScreenColorExpand( 778 ScrnInfoPtr pScrn, 779 int fg, int bg, 780 int rop, 781 unsigned int planemask 782){ 783 S3VPtr ps3v = S3VPTR(pScrn); 784 785 planemask &= ps3v->FullPlaneMask; 786 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT | 787 CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP | 788 MIX_CPUDATA | MIX_MONO_SRC; 789 790 791 if(planemask == ps3v->FullPlaneMask) { 792 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 793 WAITFIFO(3); 794 } else { 795 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 796 WAITFIFO(6); 797 OUTREG(MONO_PAT_0, ~0); 798 OUTREG(MONO_PAT_1, ~0); 799 OUTREG(PAT_FG_CLR, planemask); 800 } 801 802 if(bg == -1) 803 ps3v->AccelCmd |= MIX_MONO_TRANSP; 804 else 805 OUTREG(SRC_BG_CLR, bg); 806 807 OUTREG(SRC_FG_CLR, fg); 808 OUTREG(CMD_SET, ps3v->AccelCmd); 809} 810 811 812void 813S3VSubsequentCPUToScreenColorExpand( 814 ScrnInfoPtr pScrn, 815 int x, int y, 816 int w, int h, 817 int skipleft 818){ 819 S3VPtr ps3v = S3VPTR(pScrn); 820 821 CHECK_DEST_BASE(y,h); 822 WAITFIFO(3); 823 OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff); 824 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 825 WAITCMD(); 826 OUTREG(RDEST_XY, (x << 16) | y); 827} 828 829 830 /****************\ 831 | Image Writes | 832 \****************/ 833 834 835static void 836S3VSetupForImageWrite( 837 ScrnInfoPtr pScrn, 838 int rop, unsigned int planemask, 839 int trans_color, int bpp, int depth 840){ 841 S3VPtr ps3v = S3VPTR(pScrn); 842 843 planemask &= ps3v->FullPlaneMask; 844 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT | 845 MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP; 846 847 if(planemask != ps3v->FullPlaneMask) { 848 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 849 WAITFIFO(4); 850 OUTREG(PAT_FG_CLR, planemask); 851 OUTREG(MONO_PAT_0, ~0); 852 OUTREG(MONO_PAT_1, ~0); 853 } else { 854 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 855 WAITFIFO(1); 856 } 857 858 OUTREG(CMD_SET, ps3v->AccelCmd); 859} 860 861 862static void 863S3VSubsequentImageWriteRect( 864 ScrnInfoPtr pScrn, 865 int x, int y, 866 int w, int h, 867 int skipleft 868){ 869 S3VPtr ps3v = S3VPTR(pScrn); 870 871 CHECK_DEST_BASE(y,h); 872 873 WAITFIFO(3); 874 OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff); 875 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 876 WAITCMD(); 877 OUTREG(RDEST_XY, (x << 16) | y); 878} 879 880 881 /***********\ 882 | Lines | 883 \***********/ 884 885 886#if 0 /* Some line funcs are disabled at the moment */ 887 888static void 889S3VPolylinesThinSolidWrapper( 890 DrawablePtr pDraw, 891 GCPtr pGC, 892 int mode, 893 int npt, 894 DDXPointPtr pPts 895){ 896 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 897 S3VPtr ps3v = S3VPTR(infoRec->pScrn); 898 ps3v->CurrentGC = pGC; 899 /* fb support */ 900 ps3v->CurrentDrawable = pDraw; 901 if(infoRec->NeedToSync) 902 S3VAccelSync(infoRec->pScrn); 903 XAAPolyLines(pDraw, pGC, mode, npt, pPts); 904} 905 906static void 907S3VPolySegmentThinSolidWrapper( 908 DrawablePtr pDraw, 909 GCPtr pGC, 910 int nseg, 911 xSegment *pSeg 912){ 913 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 914 S3VPtr ps3v = S3VPTR(infoRec->pScrn); 915 ps3v->CurrentGC = pGC; 916 /* fb support */ 917 ps3v->CurrentDrawable = pDraw; 918 if(infoRec->NeedToSync) 919 S3VAccelSync(infoRec->pScrn); 920 XAAPolySegment(pDraw, pGC, nseg, pSeg); 921} 922 923#endif 924 925static void 926S3VSubsequentSolidHorVertLine( 927 ScrnInfoPtr pScrn, 928 int x, int y, 929 int len, int dir 930){ 931 S3VPtr ps3v = S3VPTR(pScrn); 932 int w, h; 933 934 if(dir == DEGREES_0) { 935 w = len; h = 1; 936 } else { 937 w = 1; h = len; 938 } 939 940 CHECK_DEST_BASE(y,h); 941 942 WAITFIFO(2); 943 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 944 WAITCMD(); 945 OUTREG(RDEST_XY, (x << 16) | y); 946} 947 948static void 949S3VSubsequentSolidHorVertLinePlaneMask( 950 ScrnInfoPtr pScrn, 951 int x, int y, 952 int len, int dir 953){ 954 S3VPtr ps3v = S3VPTR(pScrn); 955 int w, h, dwords; 956 957 if(dir == DEGREES_0) { 958 w = len; h = 1; dwords = (len + 31) >> 5; 959 } else { 960 w = 1; h = len; dwords = len; 961 } 962 963 CHECK_DEST_BASE(y,h); 964 965 WAITFIFO(2); 966 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 967 WAITCMD(); 968 OUTREG(RDEST_XY, (x << 16) | y); 969 970 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 971} 972 973#endif 974 975void 976S3VWaitFifoGX2(S3VPtr ps3v, int slots ) 977{ 978 if(ps3v->NoPCIRetry) 979 while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){} 980} 981 982 983 984void 985S3VWaitFifoMain(S3VPtr ps3v, int slots ) 986{ 987 if(ps3v->NoPCIRetry) 988 while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){} 989} 990 991 992void 993S3VWaitCmdGX2(S3VPtr ps3v) 994{ 995 while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){} 996} 997 998 999void 1000S3VWaitDummy(S3VPtr ps3v) 1001{ 1002 /* do nothing */ 1003} 1004 1005/*EOF*/ 1006 1007