1/********************************************************************** 2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, distribute, and sell this software and 7its documentation for any purpose is hereby granted without fee, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Precision Insight not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. Precision Insight 13and its suppliers make no representations about the suitability of this 14software for any purpose. It is provided "as is" without express or 15implied warranty. 16 17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24**********************************************************************/ 25 26/* 27 * The original Precision Insight driver for 28 * XFree86 v.3.3 has been sponsored by Red Hat. 29 * 30 * Authors: 31 * Jens Owen (jens@tungstengraphics.com) 32 * Kevin E. Martin (kevin@precisioninsight.com) 33 * 34 * Port to Xfree86 v.4.0 35 * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 36 */ 37 38/* 39 * This module supports acceleration for 2097 and 2160. 40 */ 41 42#ifdef HAVE_CONFIG_H 43#include "config.h" 44#endif 45 46#include "xf86.h" 47#include "xf86_OSproc.h" 48#include "compiler.h" 49 50/* Drivers that use XAA need this */ 51#include "xf86fbman.h" 52 53#include "miline.h" 54 55#include "neo.h" 56#include "neo_reg.h" 57#include "neo_macros.h" 58 59#ifdef HAVE_XAA_H 60static void Neo2097Sync(ScrnInfoPtr pScrn); 61static void Neo2097SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 62 int ydir, int rop, 63 unsigned int planemask, 64 int trans_color); 65static void Neo2097SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, 66 int srcY, int dstX, int dstY, 67 int w, int h); 68static void Neo2097SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 69 unsigned int planemask); 70static void Neo2097SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 71 int w, int h); 72static void Neo2097SetupScanlineForCPUToScreenColorExpandFill( 73 ScrnInfoPtr pScrn, 74 int fg, int bg, 75 int rop, 76 unsigned int planemask); 77static void Neo2097SubsequentScanlineCPUToScreenColorExpandFill( 78 ScrnInfoPtr pScrn, 79 int x, int y, 80 int w, int h, 81 int skipleft); 82static void Neo2097SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); 83#if 0 84static void Neo2097SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, 85 int patternx, 86 int patterny, 87 int fg, int bg, 88 int rop, unsigned int planemask); 89static void Neo2097SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn, 90 int patternx, 91 int patterny, 92 int x, int y, 93 int w, int h); 94#endif 95static void Neo2097SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, 96 unsigned int planemask, 97 int transparency_color, int bpp, int depth); 98static void Neo2097SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, 99 int x, int y, int w, int h, int skipleft); 100static void Neo2097SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int num); 101 102 103 104static unsigned int neo2097Rop[16] = { 105 0x000000, /* 0x0000 - GXclear */ 106 0x080000, /* 0x1000 - GXand */ 107 0x040000, /* 0x0100 - GXandReverse */ 108 0x0c0000, /* 0x1100 - GXcopy */ 109 0x020000, /* 0x0010 - GXandInvert */ 110 0x0a0000, /* 0x1010 - GXnoop */ 111 0x060000, /* 0x0110 - GXxor */ 112 0x0e0000, /* 0x1110 - GXor */ 113 0x010000, /* 0x0001 - GXnor */ 114 0x090000, /* 0x1001 - GXequiv */ 115 0x050000, /* 0x0101 - GXinvert */ 116 0x0d0000, /* 0x1101 - GXorReverse */ 117 0x030000, /* 0x0011 - GXcopyInvert */ 118 0x0b0000, /* 0x1011 - GXorInverted */ 119 0x070000, /* 0x0111 - GXnand */ 120 0x0f0000 /* 0x1111 - GXset */ 121}; 122#endif 123 124Bool 125Neo2097AccelInit(ScreenPtr pScreen) 126{ 127#ifdef HAVE_XAA_H 128 XAAInfoRecPtr infoPtr; 129 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 130 NEOPtr nPtr = NEOPTR(pScrn); 131 NEOACLPtr nAcl = NEOACLPTR(pScrn); 132 133 nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec(); 134 if(!infoPtr) return FALSE; 135 136 /* 137 * Set up the main acceleration flags. 138 */ 139 infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; 140 if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE; 141 142 infoPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES; 143 144 /* sync */ 145 infoPtr->Sync = Neo2097Sync; 146 147 /* screen to screen copy */ 148 infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK); 149 infoPtr->SetupForScreenToScreenCopy = 150 Neo2097SetupForScreenToScreenCopy; 151 infoPtr->SubsequentScreenToScreenCopy = 152 Neo2097SubsequentScreenToScreenCopy; 153 154 /* solid filled rectangles */ 155 infoPtr->SolidFillFlags = NO_PLANEMASK; 156 infoPtr->SetupForSolidFill = 157 Neo2097SetupForSolidFillRect; 158 infoPtr->SubsequentSolidFillRect = 159 Neo2097SubsequentSolidFillRect; 160 161 if (!nPtr->strangeLockups) { 162 /* cpu to screen color expansion */ 163 /* 164 * We do CPUToScreenColorExpand (ab)using the Scanline functions: 165 * the neo chipsets need byte padding however we can only do dword 166 * padding. Fortunately the graphics engine doesn't choke if we 167 * transfer up to 3 bytes more than it wants. 168 */ 169 infoPtr->ScanlineColorExpandBuffers = 170 (unsigned char **)xnfalloc(sizeof(char*)); 171 infoPtr->ScanlineColorExpandBuffers[0] = (unsigned char *)(nPtr->NeoMMIOBase + 0x100000); 172 infoPtr->NumScanlineColorExpandBuffers = 1; 173 infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK | 174#ifdef NEO_DO_CLIPPING 175 LEFT_EDGE_CLIPPING | 176#endif 177 CPU_TRANSFER_PAD_DWORD | 178 BIT_ORDER_IN_BYTE_MSBFIRST ); 179 infoPtr->SetupForScanlineCPUToScreenColorExpandFill = 180 Neo2097SetupScanlineForCPUToScreenColorExpandFill; 181 infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = 182 Neo2097SubsequentScanlineCPUToScreenColorExpandFill; 183 infoPtr->SubsequentColorExpandScanline = 184 Neo2097SubsequentColorExpandScanline; 185 } 186 187#if 0 188 /* 8x8 pattern fills */ 189 infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK 190 | HARDWARE_PATTERN_PROGRAMMED_ORIGIN 191 | BIT_ORDER_IN_BYTE_MSBFIRST; 192 193 infoPtr->SetupForMono8x8PatternFill = 194 Neo2097SetupForMono8x8PatternFill; 195 infoPtr->SubsequentMono8x8PatternFillRect = 196 Neo2097SubsequentMono8x8PatternFill; 197#endif 198 199 if (!nPtr->strangeLockups) { 200 /* image writes */ 201 infoPtr->ScanlineImageWriteFlags = ( CPU_TRANSFER_PAD_DWORD | 202 SCANLINE_PAD_DWORD | 203 NO_TRANSPARENCY | 204 NO_PLANEMASK ); 205 206 infoPtr->SetupForScanlineImageWrite = 207 Neo2097SetupForScanlineImageWrite; 208 infoPtr->SubsequentScanlineImageWriteRect = 209 Neo2097SubsequentScanlineImageWriteRect; 210 infoPtr->SubsequentImageWriteScanline = 211 Neo2097SubsequentImageWriteScanline; 212 infoPtr->NumScanlineImageWriteBuffers = 1; 213 infoPtr->ScanlineImageWriteBuffers = 214 infoPtr->ScanlineColorExpandBuffers; 215 } 216 217 /* 218 * Setup some global variables 219 */ 220 nAcl->ColorShiftAmt = 0; 221 222 /* Initialize for 8bpp or 15/16bpp support accelerated */ 223 switch (pScrn->bitsPerPixel) { 224 case 8: 225 nAcl->BltCntlFlags = NEO_BC1_DEPTH8; 226 nAcl->ColorShiftAmt = 8; 227 break; 228 case 15: 229 case 16: 230 nAcl->BltCntlFlags = NEO_BC1_DEPTH16; 231 nAcl->ColorShiftAmt = 0; 232 break; 233 case 24: 234 default: 235 return FALSE; 236 } 237 238 /* Initialize for widths */ 239 switch (pScrn->displayWidth) { 240 case 640: 241 nAcl->BltCntlFlags |= NEO_BC1_X_640; 242 break; 243 case 800: 244 nAcl->BltCntlFlags |= NEO_BC1_X_800; 245 break; 246 case 1024: 247 nAcl->BltCntlFlags |= NEO_BC1_X_1024; 248 break; 249 default: 250 return FALSE; 251 } 252 253 return(XAAInit(pScreen, infoPtr)); 254#else 255 return FALSE; 256#endif 257} 258 259#ifdef HAVE_XAA_H 260static void 261Neo2097Sync(ScrnInfoPtr pScrn) 262{ 263 NEOPtr nPtr = NEOPTR(pScrn); 264 265 WAIT_ENGINE_IDLE(); 266} 267 268static void 269Neo2097SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 270 int rop, 271 unsigned int planemask, 272 int trans_color) 273{ 274 NEOACLPtr nAcl = NEOACLPTR(pScrn); 275 276 nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags | 277 NEO_BC3_SKIP_MAPPING | 278 NEO_BC3_DST_XY_ADDR | 279 NEO_BC3_SRC_XY_ADDR | neo2097Rop[rop]); 280} 281 282static void 283Neo2097SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, 284 int srcX, int srcY, 285 int dstX, int dstY, 286 int w, int h) 287{ 288 NEOPtr nPtr = NEOPTR(pScrn); 289 NEOACLPtr nAcl = NEOACLPTR(pScrn); 290 291 if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) { 292 /* start with upper left corner */ 293 WAIT_ENGINE_IDLE(); 294 OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 295 OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff)); 296 OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff)); 297 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 298 } 299 else { 300 /* start with lower right corner */ 301 WAIT_ENGINE_IDLE(); 302 OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC 303 | NEO_BC0_DST_Y_DEC 304 | NEO_BC0_SRC_Y_DEC)); 305 OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff)); 306 OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff)); 307 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 308 } 309} 310 311 312static void 313Neo2097SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop, 314 unsigned int planemask) 315{ 316 NEOPtr nPtr = NEOPTR(pScrn); 317 NEOACLPtr nAcl = NEOACLPTR(pScrn); 318 319 WAIT_ENGINE_IDLE(); 320 321 /* set blt control */ 322 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 323 NEO_BC0_SRC_IS_FG | 324 NEO_BC3_SKIP_MAPPING | 325 NEO_BC3_DST_XY_ADDR | 326 NEO_BC3_SRC_XY_ADDR | neo2097Rop[rop]); 327 328 /* set foreground color */ 329 OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt)); 330} 331 332 333static void 334Neo2097SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 335{ 336 NEOPtr nPtr = NEOPTR(pScrn); 337 338 WAIT_ENGINE_IDLE(); 339 OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 340 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 341} 342 343static void 344Neo2097SetupScanlineForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 345 int fg, int bg, 346 int rop, 347 unsigned int planemask) 348{ 349 NEOPtr nPtr = NEOPTR(pScrn); 350 NEOACLPtr nAcl = NEOACLPTR(pScrn); 351 352 if (bg == -1) { 353 /* transparent setup */ 354 WAIT_ENGINE_IDLE(); 355#ifdef NEO_DO_CLIPPING 356 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 357 NEO_BC0_SYS_TO_VID | 358 NEO_BC0_SRC_MONO | 359 NEO_BC0_SRC_TRANS | 360 NEO_BC3_SKIP_MAPPING | 361 NEO_BC3_CLIP_ON | 362 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 363#else 364 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 365 NEO_BC0_SYS_TO_VID | 366 NEO_BC0_SRC_MONO | 367 NEO_BC0_SRC_TRANS | 368 NEO_BC3_SKIP_MAPPING | 369 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 370#endif 371 372 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 373 } 374 else { 375 /* opaque setup */ 376 WAIT_ENGINE_IDLE(); 377#ifdef NEO_DO_CLIPPING 378 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 379 NEO_BC0_SYS_TO_VID | 380 NEO_BC0_SRC_MONO | 381 NEO_BC3_SKIP_MAPPING | 382 NEO_BC3_CLIP_ON | 383 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 384#else 385 OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags | 386 NEO_BC0_SYS_TO_VID | 387 NEO_BC0_SRC_MONO | 388 NEO_BC3_SKIP_MAPPING | 389 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 390#endif 391 392 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 393 OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt)); 394 } 395} 396 397static void 398Neo2097SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 399 int x, int y, 400 int w, int h, 401 int skipleft) 402{ 403 NEOPtr nPtr = NEOPTR(pScrn); 404 NEOACLPtr nAcl = NEOACLPTR(pScrn); 405 406#ifdef NEO_DO_CLIPPING 407 w = (w + 31) & ~31; 408#else 409 nAcl->CPUToScreenColorExpandFill_x = x; 410 nAcl->CPUToScreenColorExpandFill_y = y; 411 nAcl->CPUToScreenColorExpandFill_w = w; 412 nAcl->CPUToScreenColorExpandFill_h = h; 413#endif 414 WAIT_ENGINE_IDLE(); 415#ifdef NEO_DO_CLIPPING 416 OUTREG(NEOREG_CLIPLT, (y << 16) | (x + skipleft)); 417 OUTREG(NEOREG_CLIPRB, ((y + h) << 16) | (x + w)); 418 WAIT_ENGINE_IDLE(); 419#endif 420 OUTREG(NEOREG_SRCSTARTOFF, 0); 421 OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 422#ifdef NEO_DO_CLIPPING 423 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 424#else 425 OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff)); 426#endif 427} 428 429static void 430Neo2097SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) 431{ 432#ifdef NEO_DO_CLIPPING 433 /* Should I be waiting for fifo slots to prevent retries ? 434 How do I do that on this engine ? */ 435#else 436 NEOPtr nPtr = NEOPTR(pScrn); 437 NEOACLPtr nAcl = NEOACLPTR(pScrn); 438 439 if (!(--nAcl->CPUToScreenColorExpandFill_h)) 440 return; 441 442 WAIT_ENGINE_IDLE(); 443 OUTREG(NEOREG_SRCSTARTOFF, 0); 444 OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16) 445 | (nAcl->CPUToScreenColorExpandFill_x & 0xffff)); 446 OUTREG(NEOREG_XYEXT, (1<<16) 447 | (nAcl->CPUToScreenColorExpandFill_w & 0xffff)); 448#endif 449} 450 451#if 0 452static void 453Neo2097SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, 454 int patternx, 455 int patterny, 456 int fg, int bg, 457 int rop, unsigned int planemask) 458{ 459 NEOPtr nPtr = NEOPTR(pScrn); 460 NEOACLPtr nAcl = NEOACLPTR(pScrn); 461 462 if (bg == -1) { 463 /* transparent setup */ 464 nAcl->tmpBltCntlFlags = ( nAcl->BltCntlFlags | 465 NEO_BC0_SRC_MONO | 466 NEO_BC0_FILL_PAT | 467 NEO_BC0_SRC_TRANS | 468 NEO_BC3_SKIP_MAPPING | 469 NEO_BC3_SRC_XY_ADDR | 470 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 471 472 WAIT_ENGINE_IDLE(); 473 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 474 OUTREG(NEOREG_SRCSTARTOFF, (patterny << 16) | patternx); 475 } 476 else { 477 /* opaque setup */ 478 nAcl->tmpBltCntlFlags = ( nAcl->BltCntlFlags | 479 NEO_BC0_SRC_MONO | 480 NEO_BC0_FILL_PAT | 481 NEO_BC3_SKIP_MAPPING | 482 NEO_BC3_SRC_XY_ADDR | 483 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 484 485 WAIT_ENGINE_IDLE(); 486 OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt)); 487 OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt)); 488 OUTREG(NEOREG_SRCSTARTOFF, (patterny << 16) | patternx); 489 } 490} 491 492 493static void 494Neo2097SubsequentMono8x8PatternFill(ScrnInfoPtr pScrn, 495 int patternx, 496 int patterny, 497 int x, int y, 498 int w, int h) 499{ 500 NEOPtr nPtr = NEOPTR(pScrn); 501 NEOACLPtr nAcl = NEOACLPTR(pScrn); 502 503 patterny &= 0x7; 504 505 WAIT_ENGINE_IDLE(); 506 OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags | (patterny << 20)); 507/* OUTREG(NEOREG_SRCBITOFF, patternx); Bad Register */ 508 OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff)); 509 OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff)); 510} 511#endif 512 513static void 514Neo2097SetupForScanlineImageWrite( 515 ScrnInfoPtr pScrn, 516 int rop, 517 unsigned int planemask, 518 int transparency_color, 519 int bpp, int depth 520){ 521 NEOACLPtr nAcl = NEOACLPTR(pScrn); 522 523 nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags | 524 NEO_BC0_SYS_TO_VID | 525 NEO_BC3_SKIP_MAPPING | 526 NEO_BC3_DST_XY_ADDR | neo2097Rop[rop]); 527} 528 529 530static void 531Neo2097SubsequentScanlineImageWriteRect( 532 ScrnInfoPtr pScrn, 533 int x, int y, int w, int h, 534 int skipleft 535){ 536 NEOPtr nPtr = NEOPTR(pScrn); 537 NEOACLPtr nAcl = NEOACLPTR(pScrn); 538 539 WAIT_ENGINE_IDLE(); 540 OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags); 541 OUTREG(NEOREG_SRCSTARTOFF, 0); 542 OUTREG(NEOREG_DSTSTARTOFF, (y << 16) | (x & 0xffff)); 543 OUTREG(NEOREG_XYEXT, (h << 16) | w); 544} 545 546static void 547Neo2097SubsequentImageWriteScanline( 548 ScrnInfoPtr pScrn, 549 int bufno 550){ 551 /* should I be checking for fifo slots here ? */ 552} 553#endif 554