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