riva_xaa.c revision fc5a983d
1/* 2 * Copyright (c) 1993-1999 NVIDIA, Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24/* Hacked together from mga driver and 3.3.4 NVIDIA driver by 25 Jarno Paananen <jpaana@s2.org> */ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include "riva_include.h" 32#include "xaalocal.h" 33#include "xaarop.h" 34 35#include "miline.h" 36 37static void 38RivaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) 39{ 40 int height = y2-y1 + 1; 41 int width = x2-x1 + 1; 42 RivaPtr pRiva = RivaPTR(pScrn); 43 44 RIVA_FIFO_FREE(pRiva->riva, Clip, 2); 45 pRiva->riva.Clip->TopLeft = (y1 << 16) | (x1 & 0xffff); 46 pRiva->riva.Clip->WidthHeight = (height << 16) | width; 47} 48 49 50static void 51RivaDisableClipping(ScrnInfoPtr pScrn) 52{ 53 RivaSetClippingRectangle(pScrn, 0, 0, 0x7fff, 0x7fff); 54} 55 56/* 57 * Set pattern. Internal routine. The upper bits of the colors 58 * are the ALPHA bits. 0 == transparency. 59 */ 60static void 61RivaSetPattern(RivaPtr pRiva, int clr0, int clr1, int pat0, int pat1) 62{ 63 RIVA_FIFO_FREE(pRiva->riva, Patt, 4); 64 pRiva->riva.Patt->Color0 = clr0; 65 pRiva->riva.Patt->Color1 = clr1; 66 pRiva->riva.Patt->Monochrome[0] = pat0; 67 pRiva->riva.Patt->Monochrome[1] = pat1; 68} 69 70/* 71 * Set ROP. Translate X rop into ROP3. Internal routine. 72 */ 73static void 74RivaSetRopSolid(RivaPtr pRiva, int rop) 75{ 76 if (pRiva->currentRop != rop) { 77 if (pRiva->currentRop >= 16) 78 RivaSetPattern(pRiva, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 79 pRiva->currentRop = rop; 80 RIVA_FIFO_FREE(pRiva->riva, Rop, 1); 81 pRiva->riva.Rop->Rop3 = XAAGetCopyROP(rop); 82 } 83} 84 85static void 86RivaSetRopPattern(RivaPtr pRiva, int rop) 87{ 88 if (pRiva->currentRop != (rop + 16)) { 89 pRiva->currentRop = rop + 16; /* +16 is important */ 90 RIVA_FIFO_FREE(pRiva->riva, Rop, 1); 91 pRiva->riva.Rop->Rop3 = XAAGetPatternROP(rop); 92 } 93} 94 95/* 96 * Fill solid rectangles. 97 */ 98static 99void RivaSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 100 unsigned planemask) 101{ 102 RivaPtr pRiva = RivaPTR(pScrn); 103 104 RivaSetRopSolid(pRiva, rop); 105 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1); 106 pRiva->riva.Bitmap->Color1A = color; 107} 108 109static void 110RivaSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 111{ 112 RivaPtr pRiva = RivaPTR(pScrn); 113 114 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2); 115 pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; 116 write_mem_barrier(); 117 pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; 118 write_mem_barrier(); 119} 120 121/* 122 * Screen to screen BLTs. 123 */ 124static void 125RivaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, 126 unsigned planemask, int transparency_color) 127{ 128 RivaSetRopSolid(RivaPTR(pScrn), rop); 129} 130 131static void 132RivaSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 133 int x2, int y2, int w, int h) 134{ 135 RivaPtr pRiva = RivaPTR(pScrn); 136 137 RIVA_FIFO_FREE(pRiva->riva, Blt, 3); 138 pRiva->riva.Blt->TopLeftSrc = (y1 << 16) | x1; 139 pRiva->riva.Blt->TopLeftDst = (y2 << 16) | x2; 140 write_mem_barrier(); 141 pRiva->riva.Blt->WidthHeight = (h << 16) | w; 142 write_mem_barrier(); 143} 144 145 146/* 147 * Fill 8x8 monochrome pattern rectangles. patternx and patterny are 148 * the overloaded pattern bits themselves. The pattern colors don't 149 * support 565, only 555. Hack around it. 150 */ 151static void 152RivaSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, 153 int fg, int bg, int rop, unsigned planemask) 154{ 155 RivaPtr pRiva = RivaPTR(pScrn); 156 157 RivaSetRopPattern(pRiva, rop); 158 if (pScrn->depth == 16) 159 { 160 fg = ((fg & 0x0000F800) << 8) 161 | ((fg & 0x000007E0) << 5) 162 | ((fg & 0x0000001F) << 3) 163 | 0xFF000000; 164 if (bg != -1) 165 bg = ((bg & 0x0000F800) << 8) 166 | ((bg & 0x000007E0) << 5) 167 | ((bg & 0x0000001F) << 3) 168 | 0xFF000000; 169 else 170 bg = 0; 171 } 172 else 173 { 174 fg |= pRiva->opaqueMonochrome; 175 bg = (bg == -1) ? 0 : bg | pRiva->opaqueMonochrome; 176 }; 177 RivaSetPattern(pRiva, bg, fg, patternx, patterny); 178 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1); 179 pRiva->riva.Bitmap->Color1A = fg; 180} 181 182static void 183RivaSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, 184 int patternx, int patterny, 185 int x, int y, int w, int h) 186{ 187 RivaPtr pRiva = RivaPTR(pScrn); 188 189 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2); 190 pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft = (x << 16) | y; 191 write_mem_barrier(); 192 pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h; 193 write_mem_barrier(); 194} 195 196 197void 198RivaResetGraphics(ScrnInfoPtr pScrn) 199{ 200 RivaPtr pRiva = RivaPTR(pScrn); 201 202 if(pRiva->NoAccel) return; 203 204 RIVA_FIFO_FREE(pRiva->riva, Patt, 1); 205 pRiva->riva.Patt->Shape = 0; 206 RivaDisableClipping(pScrn); 207 pRiva->currentRop = 16; /* to force RivaSetRopSolid to reset the pattern */ 208 RivaSetRopSolid(pRiva, GXcopy); 209} 210 211 212 213/* 214 * Synchronise with graphics engine. Make sure it is idle before returning. 215 * Should attempt to yield CPU if busy for awhile. 216 */ 217void RivaSync(ScrnInfoPtr pScrn) 218{ 219 RivaPtr pRiva = RivaPTR(pScrn); 220 RIVA_BUSY(pRiva->riva); 221} 222 223/* Color expansion */ 224static void 225RivaSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 226 int fg, int bg, int rop, 227 unsigned int planemask) 228{ 229 RivaPtr pRiva = RivaPTR(pScrn); 230 231 RivaSetRopSolid(pRiva, rop); 232 233 if ( bg == -1 ) 234 { 235 /* Transparent case */ 236 bg = 0x80000000; 237 pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData1C; 238 } 239 else 240 { 241 pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E; 242 if (pScrn->depth == 16) 243 { 244 bg = ((bg & 0x0000F800) << 8) 245 | ((bg & 0x000007E0) << 5) 246 | ((bg & 0x0000001F) << 3) 247 | 0xFF000000; 248 } 249 else 250 { 251 bg |= pRiva->opaqueMonochrome; 252 }; 253 } 254 pRiva->FgColor = fg; 255 pRiva->BgColor = bg; 256} 257 258static void 259RivaSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) 260{ 261 RivaPtr pRiva = RivaPTR(pScrn); 262 263 int t = pRiva->expandWidth; 264 CARD32 *pbits = (CARD32*)pRiva->expandBuffer; 265 CARD32 *d = (CARD32*)pRiva->expandFifo; 266 267 while(t >= 16) 268 { 269 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 16); 270 d[0] = pbits[0]; 271 d[1] = pbits[1]; 272 d[2] = pbits[2]; 273 d[3] = pbits[3]; 274 d[4] = pbits[4]; 275 d[5] = pbits[5]; 276 d[6] = pbits[6]; 277 d[7] = pbits[7]; 278 d[8] = pbits[8]; 279 d[9] = pbits[9]; 280 d[10] = pbits[10]; 281 d[11] = pbits[11]; 282 d[12] = pbits[12]; 283 d[13] = pbits[13]; 284 d[14] = pbits[14]; 285 d[15] = pbits[15]; 286 t -= 16; pbits += 16; 287 } 288 if(t) { 289 RIVA_FIFO_FREE(pRiva->riva, Bitmap, t); 290 while(t >= 4) 291 { 292 d[0] = pbits[0]; 293 d[1] = pbits[1]; 294 d[2] = pbits[2]; 295 d[3] = pbits[3]; 296 t -= 4; pbits += 4; 297 } 298 while(t--) 299 *(d++) = *(pbits++); 300 } 301 302 if (!(--pRiva->expandRows)) { /* hardware bug workaround */ 303 RIVA_FIFO_FREE(pRiva->riva, Blt, 1); 304 write_mem_barrier(); 305 pRiva->riva.Blt->TopLeftSrc = 0; 306 } 307 write_mem_barrier(); 308} 309 310static void 311RivaSubsequentColorExpandScanlineFifo(ScrnInfoPtr pScrn, int bufno) 312{ 313 RivaPtr pRiva = RivaPTR(pScrn); 314 315 if ( --pRiva->expandRows ) { 316 RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth); 317 } else { /* hardware bug workaround */ 318 RIVA_FIFO_FREE(pRiva->riva, Blt, 1); 319 write_mem_barrier(); 320 pRiva->riva.Blt->TopLeftSrc = 0; 321 } 322 write_mem_barrier(); 323} 324 325static void 326RivaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, 327 int y, int w, int h, 328 int skipleft) 329{ 330 int bw; 331 RivaPtr pRiva = RivaPTR(pScrn); 332 333 bw = (w + 31) & ~31; 334 pRiva->expandWidth = bw >> 5; 335 336 if ( pRiva->BgColor == 0x80000000 ) 337 { 338 /* Use faster transparent method */ 339 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 5); 340 pRiva->riva.Bitmap->ClipC.TopLeft = (y << 16) | ((x+skipleft) 341 & 0xFFFF); 342 pRiva->riva.Bitmap->ClipC.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); 343 pRiva->riva.Bitmap->Color1C = pRiva->FgColor; 344 pRiva->riva.Bitmap->WidthHeightC = (h << 16) | bw; 345 write_mem_barrier(); 346 pRiva->riva.Bitmap->PointC = (y << 16) | (x & 0xFFFF); 347 write_mem_barrier(); 348 } 349 else 350 { 351 /* Opaque */ 352 RIVA_FIFO_FREE(pRiva->riva, Bitmap, 7); 353 pRiva->riva.Bitmap->ClipE.TopLeft = (y << 16) | ((x+skipleft) 354 & 0xFFFF); 355 pRiva->riva.Bitmap->ClipE.BottomRight = ((y+h) << 16) | ((x+w)&0xffff); 356 pRiva->riva.Bitmap->Color0E = pRiva->BgColor; 357 pRiva->riva.Bitmap->Color1E = pRiva->FgColor; 358 pRiva->riva.Bitmap->WidthHeightInE = (h << 16) | bw; 359 pRiva->riva.Bitmap->WidthHeightOutE = (h << 16) | bw; 360 write_mem_barrier(); 361 pRiva->riva.Bitmap->PointE = (y << 16) | (x & 0xFFFF); 362 write_mem_barrier(); 363 } 364 365 pRiva->expandRows = h; 366 367 if(pRiva->expandWidth > (pRiva->riva.FifoEmptyCount >> 2)) { 368 pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandBuffer; 369 pRiva->AccelInfoRec->SubsequentColorExpandScanline = 370 RivaSubsequentColorExpandScanline; 371 } else { 372 pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandFifo; 373 pRiva->AccelInfoRec->SubsequentColorExpandScanline = 374 RivaSubsequentColorExpandScanlineFifo; 375 RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth); 376 } 377} 378 379static void 380RivaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask) 381{ 382 RivaPtr pRiva = RivaPTR(pScrn); 383 384 RivaSetRopSolid(pRiva, rop); 385 pRiva->FgColor = color; 386} 387 388static void 389RivaSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir) 390{ 391 RivaPtr pRiva = RivaPTR(pScrn); 392 393 RIVA_FIFO_FREE(pRiva->riva, Line, 3); 394 pRiva->riva.Line->Color = pRiva->FgColor; 395 pRiva->riva.Line->Lin[0].point0 = ((y << 16) | ( x & 0xffff)); 396 write_mem_barrier(); 397 if ( dir ==DEGREES_0 ) 398 pRiva->riva.Line->Lin[0].point1 = ((y << 16) | (( x + len ) & 0xffff)); 399 else 400 pRiva->riva.Line->Lin[0].point1 = (((y + len) << 16) | ( x & 0xffff)); 401 write_mem_barrier(); 402} 403 404static void 405RivaSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, 406 int x2, int y2, int flags) 407{ 408 RivaPtr pRiva = RivaPTR(pScrn); 409 Bool lastPoint = !(flags & OMIT_LAST); 410 411 RIVA_FIFO_FREE(pRiva->riva, Line, lastPoint ? 5 : 3); 412 pRiva->riva.Line->Color = pRiva->FgColor; 413 pRiva->riva.Line->Lin[0].point0 = ((y1 << 16) | (x1 & 0xffff)); 414 write_mem_barrier(); 415 pRiva->riva.Line->Lin[0].point1 = ((y2 << 16) | (x2 & 0xffff)); 416 write_mem_barrier(); 417 if (lastPoint) 418 { 419 pRiva->riva.Line->Lin[1].point0 = ((y2 << 16) | (x2 & 0xffff)); 420 write_mem_barrier(); 421 pRiva->riva.Line->Lin[1].point1 = (((y2 + 1) << 16) | (x2 & 0xffff)); 422 write_mem_barrier(); 423 } 424} 425 426static void 427RivaValidatePolyArc( 428 GCPtr pGC, 429 unsigned long changes, 430 DrawablePtr pDraw 431){ 432 if(pGC->planemask != ~0) return; 433 434 if(!pGC->lineWidth && 435 ((pGC->alu != GXcopy) || (pGC->lineStyle != LineSolid))) 436 { 437 pGC->ops->PolyArc = miZeroPolyArc; 438 } 439} 440 441static void 442RivaValidatePolyPoint( 443 GCPtr pGC, 444 unsigned long changes, 445 DrawablePtr pDraw 446){ 447 pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint; 448 449 if(pGC->planemask != ~0) return; 450 451 if(pGC->alu != GXcopy) 452 pGC->ops->PolyPoint = miPolyPoint; 453} 454 455/* Initialize XAA acceleration info */ 456Bool 457RivaAccelInit(ScreenPtr pScreen) 458{ 459 XAAInfoRecPtr infoPtr; 460 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 461 RivaPtr pRiva = RivaPTR(pScrn); 462 463 pRiva->AccelInfoRec = infoPtr = XAACreateInfoRec(); 464 if(!infoPtr) return FALSE; 465 466 /* fill out infoPtr here */ 467 infoPtr->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS; 468 469 /* sync */ 470 infoPtr->Sync = RivaSync; 471 472 /* solid fills */ 473 infoPtr->SolidFillFlags = NO_PLANEMASK; 474 infoPtr->SetupForSolidFill = RivaSetupForSolidFill; 475 infoPtr->SubsequentSolidFillRect = RivaSubsequentSolidFillRect; 476 477 /* screen to screen copy */ 478 infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK; 479 infoPtr->SetupForScreenToScreenCopy = RivaSetupForScreenToScreenCopy; 480 infoPtr->SubsequentScreenToScreenCopy = RivaSubsequentScreenToScreenCopy; 481 482 /* 8x8 mono patterns */ 483 /* 484 * Set pattern opaque bits based on pixel format. 485 */ 486 pRiva->opaqueMonochrome = ~((1 << pScrn->depth) - 1); 487 488 infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN | 489 HARDWARE_PATTERN_PROGRAMMED_BITS | 490 NO_PLANEMASK; 491 infoPtr->SetupForMono8x8PatternFill = RivaSetupForMono8x8PatternFill; 492 infoPtr->SubsequentMono8x8PatternFillRect = 493 RivaSubsequentMono8x8PatternFillRect; 494 495 /* Color expansion */ 496 infoPtr->ScanlineCPUToScreenColorExpandFillFlags = 497 BIT_ORDER_IN_BYTE_LSBFIRST | 498 NO_PLANEMASK | 499 CPU_TRANSFER_PAD_DWORD | 500 LEFT_EDGE_CLIPPING | 501 LEFT_EDGE_CLIPPING_NEGATIVE_X; 502 503 infoPtr->NumScanlineColorExpandBuffers = 1; 504 505 infoPtr->SetupForScanlineCPUToScreenColorExpandFill = 506 RivaSetupForScanlineCPUToScreenColorExpandFill; 507 infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = 508 RivaSubsequentScanlineCPUToScreenColorExpandFill; 509 510 pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E; 511 512 /* Allocate buffer for color expansion and also image writes in the 513 future */ 514 pRiva->expandBuffer = xnfalloc(((pScrn->virtualX*pScrn->bitsPerPixel)/8) + 8); 515 516 517 infoPtr->ScanlineColorExpandBuffers = &pRiva->expandBuffer; 518 infoPtr->SubsequentColorExpandScanline = RivaSubsequentColorExpandScanline; 519 520 infoPtr->SolidLineFlags = infoPtr->SolidFillFlags; 521 infoPtr->SetupForSolidLine = RivaSetupForSolidLine; 522 infoPtr->SubsequentSolidHorVertLine = 523 RivaSubsequentSolidHorVertLine; 524 infoPtr->SubsequentSolidTwoPointLine = 525 RivaSubsequentSolidTwoPointLine; 526 infoPtr->SetClippingRectangle = RivaSetClippingRectangle; 527 infoPtr->DisableClipping = RivaDisableClipping; 528 infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE; 529 miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6); 530 531 infoPtr->ValidatePolyArc = RivaValidatePolyArc; 532 infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask; 533 infoPtr->ValidatePolyPoint = RivaValidatePolyPoint; 534 infoPtr->PolyPointMask = GCFunction | GCPlaneMask; 535 536 RivaResetGraphics(pScrn); 537 538 return(XAAInit(pScreen, infoPtr)); 539} 540