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