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