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