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