s3v_accel.c revision 84fd5825
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, 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 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#ifdef HAVE_XAA_H 544 545 /************************\ 546 | Solid Filled Rects | 547 \************************/ 548 549static void 550S3VSetupForSolidFill( 551 ScrnInfoPtr pScrn, 552 int color, int rop, 553 unsigned int planemask 554){ 555 S3VPtr ps3v = S3VPTR(pScrn); 556 int mix; 557 558 mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop); 559 560 ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) | 561 CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT; 562 563 if(mix & ROP_SRC) { 564 ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC; 565 ps3v->AccelInfoRec->SubsequentSolidFillRect = 566 S3VSubsequentSolidFillRectPlaneMask; 567 ps3v->AccelInfoRec->SubsequentSolidHorVertLine = 568 S3VSubsequentSolidHorVertLinePlaneMask; 569 WAITFIFO(5); 570 OUTREG(SRC_FG_CLR, planemask); 571 } else { 572 ps3v->AccelInfoRec->SubsequentSolidFillRect = 573 S3VSubsequentSolidFillRect; 574 ps3v->AccelInfoRec->SubsequentSolidHorVertLine = 575 S3VSubsequentSolidHorVertLine; 576 WAITFIFO(4); 577 } 578 579 if(mix & ROP_PAT) { 580 ps3v->AccelCmd |= MIX_MONO_PATT; 581 OUTREG(PAT_FG_CLR, color); 582 OUTREG(MONO_PAT_0, ~0); 583 OUTREG(MONO_PAT_1, ~0); 584 } 585 586 OUTREG(CMD_SET, ps3v->AccelCmd); 587} 588 589 590void 591S3VSubsequentSolidFillRect( 592 ScrnInfoPtr pScrn, 593 int x, int y, 594 int w, int h 595){ 596 S3VPtr ps3v = S3VPTR(pScrn); 597 598 CHECK_DEST_BASE(y,h); 599 600 WAITFIFO(2); 601 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 602 WAITCMD(); 603 OUTREG(RDEST_XY, (x << 16) | y); 604} 605 606 607void 608S3VSubsequentSolidFillRectPlaneMask( 609 ScrnInfoPtr pScrn, 610 int x, int y, 611 int w, int h 612){ 613 S3VPtr ps3v = S3VPTR(pScrn); 614 int dwords; 615 616 CHECK_DEST_BASE(y,h); 617 618 dwords = ((w + 31) >> 5) * h; 619 620 WAITFIFO(2); 621 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 622 WAITCMD(); 623 OUTREG(RDEST_XY, (x << 16) | y); 624 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 625} 626 627 628 /**************************\ 629 | Screen to Screen Copies | 630 \**************************/ 631 632static void 633S3VSetupForScreenToScreenCopy( 634 ScrnInfoPtr pScrn, 635 int xdir, int ydir, 636 int rop, 637 unsigned int planemask, 638 int trans 639){ 640 S3VPtr ps3v = S3VPTR(pScrn); 641 642 planemask &= ps3v->FullPlaneMask; 643 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT; 644 645 if(planemask != ps3v->FullPlaneMask) { 646 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 647 WAITFIFO(4); 648 OUTREG(PAT_FG_CLR, planemask); 649 OUTREG(MONO_PAT_0, ~0); 650 OUTREG(MONO_PAT_1, ~0); 651 } 652 else { 653 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 654 WAITFIFO(1); 655 } 656 if(xdir == 1) ps3v->AccelCmd |= CMD_XP; 657 if(ydir == 1) ps3v->AccelCmd |= CMD_YP; 658 659 OUTREG(CMD_SET, ps3v->AccelCmd); 660} 661 662 663static void 664S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 665 int x2, int y2, int w, int h) 666{ 667 S3VPtr ps3v = S3VPTR(pScrn); 668 669 CHECK_SRC_BASE(y1,h); 670 CHECK_DEST_BASE(y2,h); 671 672 w--; 673 674 if(!(ps3v->AccelCmd & CMD_YP)) { 675 y1 += h - 1; y2 += h - 1; 676 } 677 678 if(!(ps3v->AccelCmd & CMD_XP)) { 679 x1 += w; x2 += w; 680 } 681 682 WAITFIFO(3); 683 OUTREG(RWIDTH_HEIGHT, (w << 16) | h); 684 OUTREG(RSRC_XY, (x1 << 16) | y1); 685 WAITCMD(); 686 OUTREG(RDEST_XY, (x2 << 16) | y2); 687} 688 689 690 /*********************\ 691 | 8x8 Pattern fills | 692 \*********************/ 693 694 695static void 696S3VSetupForMono8x8PatternFill( 697 ScrnInfoPtr pScrn, 698 int patx, int paty, 699 int fg, int bg, 700 int rop, unsigned int planemask 701){ 702 S3VPtr ps3v = S3VPTR(pScrn); 703 int mix; 704 705 mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop); 706 707 ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) | 708 CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT; 709 710 if(mix & ROP_SRC) { 711 ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC; 712 ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect = 713 S3VSubsequentMono8x8PatternFillRectPlaneMask; 714 WAITFIFO(6); 715 OUTREG(SRC_FG_CLR, planemask); 716 } else { 717 ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect = 718 S3VSubsequentMono8x8PatternFillRect; 719 WAITFIFO(5); 720 } 721 722 if(mix & ROP_PAT) { 723 ps3v->AccelCmd |= MIX_MONO_PATT; 724 OUTREG(PAT_FG_CLR, fg); 725 OUTREG(PAT_BG_CLR, bg); 726 OUTREG(MONO_PAT_0, patx); 727 OUTREG(MONO_PAT_1, paty); 728 } 729 730 OUTREG(CMD_SET, ps3v->AccelCmd); 731} 732 733 734static void 735S3VSubsequentMono8x8PatternFillRect( 736 ScrnInfoPtr pScrn, 737 int patx, int paty, 738 int x, int y, int w, int h 739){ 740 S3VPtr ps3v = S3VPTR(pScrn); 741 742 CHECK_DEST_BASE(y,h); 743 744 WAITFIFO(2); 745 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 746 WAITCMD(); 747 OUTREG(RDEST_XY, (x << 16) | y); 748} 749 750 751static void 752S3VSubsequentMono8x8PatternFillRectPlaneMask( 753 ScrnInfoPtr pScrn, 754 int patx, int paty, 755 int x, int y, int w, int h 756){ 757 S3VPtr ps3v = S3VPTR(pScrn); 758 int dwords; 759 760 CHECK_DEST_BASE(y,h); 761 762 dwords = ((w + 31) >> 5) * h; 763 764 WAITFIFO(2); 765 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 766 WAITCMD(); 767 OUTREG(RDEST_XY, (x << 16) | y); 768 769 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 770} 771 772 /*********************************\ 773 | CPU to Screen Color Expansion | 774 \*********************************/ 775 776 777static void 778S3VSetupForCPUToScreenColorExpand( 779 ScrnInfoPtr pScrn, 780 int fg, int bg, 781 int rop, 782 unsigned int planemask 783){ 784 S3VPtr ps3v = S3VPTR(pScrn); 785 786 planemask &= ps3v->FullPlaneMask; 787 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT | 788 CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP | 789 MIX_CPUDATA | MIX_MONO_SRC; 790 791 792 if(planemask == ps3v->FullPlaneMask) { 793 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 794 WAITFIFO(3); 795 } else { 796 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 797 WAITFIFO(6); 798 OUTREG(MONO_PAT_0, ~0); 799 OUTREG(MONO_PAT_1, ~0); 800 OUTREG(PAT_FG_CLR, planemask); 801 } 802 803 if(bg == -1) 804 ps3v->AccelCmd |= MIX_MONO_TRANSP; 805 else 806 OUTREG(SRC_BG_CLR, bg); 807 808 OUTREG(SRC_FG_CLR, fg); 809 OUTREG(CMD_SET, ps3v->AccelCmd); 810} 811 812 813void 814S3VSubsequentCPUToScreenColorExpand( 815 ScrnInfoPtr pScrn, 816 int x, int y, 817 int w, int h, 818 int skipleft 819){ 820 S3VPtr ps3v = S3VPTR(pScrn); 821 822 CHECK_DEST_BASE(y,h); 823 WAITFIFO(3); 824 OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff); 825 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 826 WAITCMD(); 827 OUTREG(RDEST_XY, (x << 16) | y); 828} 829 830 831 /****************\ 832 | Image Writes | 833 \****************/ 834 835 836static void 837S3VSetupForImageWrite( 838 ScrnInfoPtr pScrn, 839 int rop, unsigned int planemask, 840 int trans_color, int bpp, int depth 841){ 842 S3VPtr ps3v = S3VPTR(pScrn); 843 844 planemask &= ps3v->FullPlaneMask; 845 ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT | 846 MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP; 847 848 if(planemask != ps3v->FullPlaneMask) { 849 ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT; 850 WAITFIFO(4); 851 OUTREG(PAT_FG_CLR, planemask); 852 OUTREG(MONO_PAT_0, ~0); 853 OUTREG(MONO_PAT_1, ~0); 854 } else { 855 ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17; 856 WAITFIFO(1); 857 } 858 859 OUTREG(CMD_SET, ps3v->AccelCmd); 860} 861 862 863static void 864S3VSubsequentImageWriteRect( 865 ScrnInfoPtr pScrn, 866 int x, int y, 867 int w, int h, 868 int skipleft 869){ 870 S3VPtr ps3v = S3VPTR(pScrn); 871 872 CHECK_DEST_BASE(y,h); 873 874 WAITFIFO(3); 875 OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff); 876 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 877 WAITCMD(); 878 OUTREG(RDEST_XY, (x << 16) | y); 879} 880 881 882 /***********\ 883 | Lines | 884 \***********/ 885 886 887#if 0 /* Some line funcs are disabled at the moment */ 888 889static void 890S3VPolylinesThinSolidWrapper( 891 DrawablePtr pDraw, 892 GCPtr pGC, 893 int mode, 894 int npt, 895 DDXPointPtr pPts 896){ 897 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 898 S3VPtr ps3v = S3VPTR(infoRec->pScrn); 899 ps3v->CurrentGC = pGC; 900 /* fb support */ 901 ps3v->CurrentDrawable = pDraw; 902 if(infoRec->NeedToSync) 903 S3VAccelSync(infoRec->pScrn); 904 XAAPolyLines(pDraw, pGC, mode, npt, pPts); 905} 906 907static void 908S3VPolySegmentThinSolidWrapper( 909 DrawablePtr pDraw, 910 GCPtr pGC, 911 int nseg, 912 xSegment *pSeg 913){ 914 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 915 S3VPtr ps3v = S3VPTR(infoRec->pScrn); 916 ps3v->CurrentGC = pGC; 917 /* fb support */ 918 ps3v->CurrentDrawable = pDraw; 919 if(infoRec->NeedToSync) 920 S3VAccelSync(infoRec->pScrn); 921 XAAPolySegment(pDraw, pGC, nseg, pSeg); 922} 923 924#endif 925 926static void 927S3VSubsequentSolidHorVertLine( 928 ScrnInfoPtr pScrn, 929 int x, int y, 930 int len, int dir 931){ 932 S3VPtr ps3v = S3VPTR(pScrn); 933 int w, h; 934 935 if(dir == DEGREES_0) { 936 w = len; h = 1; 937 } else { 938 w = 1; h = len; 939 } 940 941 CHECK_DEST_BASE(y,h); 942 943 WAITFIFO(2); 944 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 945 WAITCMD(); 946 OUTREG(RDEST_XY, (x << 16) | y); 947} 948 949static void 950S3VSubsequentSolidHorVertLinePlaneMask( 951 ScrnInfoPtr pScrn, 952 int x, int y, 953 int len, int dir 954){ 955 S3VPtr ps3v = S3VPTR(pScrn); 956 int w, h, dwords; 957 958 if(dir == DEGREES_0) { 959 w = len; h = 1; dwords = (len + 31) >> 5; 960 } else { 961 w = 1; h = len; dwords = len; 962 } 963 964 CHECK_DEST_BASE(y,h); 965 966 WAITFIFO(2); 967 OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h); 968 WAITCMD(); 969 OUTREG(RDEST_XY, (x << 16) | y); 970 971 S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords); 972} 973 974#endif 975 976void 977S3VWaitFifoGX2(S3VPtr ps3v, int slots ) 978{ 979 if(ps3v->NoPCIRetry) 980 while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){} 981} 982 983 984 985void 986S3VWaitFifoMain(S3VPtr ps3v, int slots ) 987{ 988 if(ps3v->NoPCIRetry) 989 while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){} 990} 991 992 993void 994S3VWaitCmdGX2(S3VPtr ps3v) 995{ 996 while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){} 997} 998 999 1000void 1001S3VWaitDummy(S3VPtr ps3v) 1002{ 1003 /* do nothing */ 1004} 1005 1006/*EOF*/ 1007 1008