i740_accel.c revision 301ea0f4
1 2/************************************************************************** 3 4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i740/i740_accel.c,v 1.6 2002/01/25 21:56:02 tsi Exp $ */ 29 30/* 31 * Authors: 32 * Daryll Strauss <daryll@precisioninsight.com> 33 * 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include "xf86.h" 41#include "xf86_OSproc.h" 42 43#include "compiler.h" 44 45#include "xf86Pci.h" 46#include "xf86PciInfo.h" 47 48#include "xaa.h" 49#include "vgaHW.h" 50 51#include "xf86xv.h" 52#include "i740.h" 53 54static unsigned int i740Rop[16] = { 55 0x00, /* GXclear */ 56 0x88, /* GXand */ 57 0x44, /* GXandReverse */ 58 0xCC, /* GXcopy */ 59 0x22, /* GXandInvert */ 60 0xAA, /* GXnoop */ 61 0x66, /* GXxor */ 62 0xEE, /* GXor */ 63 0x11, /* GXnor */ 64 0x99, /* GXequiv */ 65 0x55, /* GXinvert */ 66 0xDD, /* GXorReverse */ 67 0x33, /* GXcopyInvert */ 68 0xBB, /* GXorInverted */ 69 0x77, /* GXnand */ 70 0xFF /* GXset */ 71}; 72 73static unsigned int i740PatternRop[16] = { 74 0x00, /* GXclear */ 75 0xA0, /* GXand */ 76 0x50, /* GXandReverse */ 77 0xF0, /* GXcopy */ 78 0x0A, /* GXandInvert */ 79 0xAA, /* GXnoop */ 80 0x5A, /* GXxor */ 81 0xFA, /* GXor */ 82 0x05, /* GXnor */ 83 0xA5, /* GXequiv */ 84 0x55, /* GXinvert */ 85 0xF5, /* GXorReverse */ 86 0x0F, /* GXcopyInvert */ 87 0xAF, /* GXorInverted */ 88 0x5F, /* GXnand */ 89 0xFF /* GXset */ 90}; 91 92static void I740SyncPIO(ScrnInfoPtr pScrn); 93static void I740SyncMMIO(ScrnInfoPtr pScrn); 94static void I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 95 unsigned int planemask); 96static void I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, 97 int w, int h); 98static void I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 99 int ydir, int rop, 100 unsigned int planemask, 101 int transparency_color); 102static void I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 103 int x2, int y2, int w, int h); 104static void I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, 105 int pattx, int patty, 106 int fg, int bg, int rop, 107 unsigned int planemask); 108static void I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, 109 int pattx, int patty, 110 int x, int y, int w, int h); 111#if 0 112static void I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 113 int bg, int fg, int rop, 114 unsigned int planemask); 115static void I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, 116 int x, int y, int w, int h, 117 int skipleft); 118#endif 119/* 120 * The following function sets up the supported acceleration. Call it 121 * from the FbInit() function in the SVGA driver, or before ScreenInit 122 * in a monolithic server. 123 */ 124Bool 125I740AccelInit(ScreenPtr pScreen) { 126 XAAInfoRecPtr infoPtr; 127 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 128 I740Ptr pI740 = I740PTR(pScrn); 129 130 pI740->AccelInfoRec = infoPtr = XAACreateInfoRec(); 131 if (!infoPtr) return FALSE; 132 133 if (pScrn->bitsPerPixel == 32) { 134 infoPtr->Flags = 0; /* Disables all acceleration */ 135 return TRUE;; 136 } 137 138 infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER; 139 140 /* Sync */ 141 if (pI740->usePIO) 142 infoPtr->Sync = I740SyncPIO; 143 else 144 infoPtr->Sync = I740SyncMMIO; 145 146 infoPtr->CachePixelGranularity=8/pI740->cpp; 147 148 /* Solid filled rectangles */ 149 infoPtr->SolidFillFlags = NO_PLANEMASK; 150 infoPtr->SetupForSolidFill = I740SetupForSolidFill; 151 infoPtr->SubsequentSolidFillRect = I740SubsequentSolidFillRect; 152 153 /* Screen to screen copy */ 154 infoPtr->ScreenToScreenCopyFlags = (NO_PLANEMASK | NO_TRANSPARENCY); 155 infoPtr->SetupForScreenToScreenCopy = I740SetupForScreenToScreenCopy; 156 infoPtr->SubsequentScreenToScreenCopy = I740SubsequentScreenToScreenCopy; 157 158 /* 8x8 pattern fills */ 159 infoPtr->SetupForMono8x8PatternFill = I740SetupForMono8x8PatternFill; 160 infoPtr->SubsequentMono8x8PatternFillRect = I740SubsequentMono8x8PatternFillRect; 161 infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN | 162 BIT_ORDER_IN_BYTE_MSBFIRST; 163 164 /* CPU to screen color expansion */ 165 /* Currently XAA is limited to only DWORD padding. The 3.3 driver 166 * uses NO_PAD scanlines b/c of problems with using the chip in 167 * DWORD mode. Once other padding modes are available in XAA this 168 * Code can be turned back on. 169 */ 170#if 0 171#ifndef ALLOW_PCI_COLOR_EXP 172 if (pI740->Chipset != PCI_CHIP_I740_PCI) { 173#endif 174 /* 175 * Currently, we are not properly able to read the bitblt engine 176 * busy bit on the PCI i740 card. When we are able to do so, we 177 * can re-enable color expansion. 178 */ 179 infoPtr->CPUToScreenColorExpandFillFlags = 180 NO_PLANEMASK | 181#ifdef USE_DWORD_COLOR_EXP 182 SCANLINE_PAD_DWORD | 183#endif 184 CPU_TRANSFER_PAD_QWORD | 185 SYNC_AFTER_COLOR_EXPAND | 186 BIT_ORDER_IN_BYTE_MSBFIRST; 187 infoPtr->ColorExpandBase = (unsigned char *)(pI740->MMIOBase + BLTDATA); 188 infoPtr->ColorExpandRange = 0x10000; 189 infoPtr->SetupForCPUToScreenColorExpandFill = I740SetupForCPUToScreenColorExpandFill; 190 infoPtr->SubsequentCPUToScreenColorExpandFill = I740SubsequentCPUToScreenColorExpandFill; 191#ifndef ALLOW_PCI_COLOR_EXP 192 } 193#endif 194#endif 195 return XAAInit(pScreen, infoPtr); 196} 197 198static void 199I740SyncPIO(ScrnInfoPtr pScrn) { 200 WAIT_ENGINE_IDLE_PIO(); 201} 202 203static void 204I740SyncMMIO(ScrnInfoPtr pScrn) { 205 I740Ptr pI740; 206 207 pI740 = I740PTR(pScrn); 208 WAIT_ENGINE_IDLE_MMIO(); 209} 210 211static void 212I740SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 213 unsigned int planemask) { 214 I740Ptr pI740; 215 216 pI740 = I740PTR(pScrn); 217 218 pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) | 219 (pScrn->displayWidth * pI740->cpp); 220 pI740->bltcmd.BR01 = color; 221 pI740->bltcmd.BR04 = SOLID_PAT_SELECT | PAT_IS_MONO | i740PatternRop[rop]; 222} 223 224static void 225I740SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) { 226 I740Ptr pI740; 227 228 pI740 = I740PTR(pScrn); 229 WAIT_LP_FIFO(12); 230 OUTREG(LP_FIFO, 0x6000000A); 231 OUTREG(LP_FIFO, pI740->bltcmd.BR00); 232 OUTREG(LP_FIFO, pI740->bltcmd.BR01); 233 OUTREG(LP_FIFO, 0x00000000); 234 OUTREG(LP_FIFO, 0x00000000); 235 OUTREG(LP_FIFO, pI740->bltcmd.BR04); 236 OUTREG(LP_FIFO, 0x00000000); 237 OUTREG(LP_FIFO, 0x00000000); 238 OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp); 239 OUTREG(LP_FIFO, 0x00000000); 240 OUTREG(LP_FIFO, 0x00000000); 241 OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp)); 242} 243 244static void 245I740SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, 246 unsigned int planemask, int transparency_color) 247{ 248 I740Ptr pI740; 249 250 pI740 = I740PTR(pScrn); 251 pI740->bltcmd.BR00 = (((pScrn->displayWidth * pI740->cpp) << 16) | 252 (pScrn->displayWidth * pI740->cpp)); 253 254 pI740->bltcmd.BR04 = SRC_IS_IN_COLOR | SRC_USE_SRC_ADDR | i740Rop[rop]; 255 if (xdir == -1) 256 pI740->bltcmd.BR04 |= BLT_RIGHT_TO_LEFT; 257 else 258 pI740->bltcmd.BR04 |= BLT_LEFT_TO_RIGHT; 259 260 if (ydir == -1) 261 pI740->bltcmd.BR04 |= BLT_BOT_TO_TOP; 262 else 263 pI740->bltcmd.BR04 |= BLT_TOP_TO_BOT; 264 265 pI740->bltcmd.BR01 = 0x00000000; 266 267} 268 269static void 270I740SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 271 int x2, int y2, int w, int h) { 272 I740Ptr pI740; 273 274 pI740 = I740PTR(pScrn); 275 if (pI740->bltcmd.BR04 & BLT_BOT_TO_TOP) { 276 pI740->bltcmd.BR06 = (y1 + h - 1) * 277 pScrn->displayWidth * pI740->cpp; 278 pI740->bltcmd.BR07 = (y2 + h - 1) * 279 pScrn->displayWidth * pI740->cpp; 280 } else { 281 pI740->bltcmd.BR06 = y1 * pScrn->displayWidth * pI740->cpp; 282 pI740->bltcmd.BR07 = y2 * pScrn->displayWidth * pI740->cpp; 283 } 284 285 if (pI740->bltcmd.BR04 & BLT_RIGHT_TO_LEFT) { 286 pI740->bltcmd.BR06 += (x1 + w - 1) * pI740->cpp + pI740->cpp - 1; 287 pI740->bltcmd.BR07 += (x2 + w - 1) * pI740->cpp + pI740->cpp - 1; 288 } else { 289 pI740->bltcmd.BR06 += x1 * pI740->cpp; 290 pI740->bltcmd.BR07 += x2 * pI740->cpp; 291 } 292 293 WAIT_LP_FIFO(12); 294 OUTREG(LP_FIFO, 0x6000000A); 295 OUTREG(LP_FIFO, pI740->bltcmd.BR00); 296 OUTREG(LP_FIFO, pI740->bltcmd.BR01); 297 OUTREG(LP_FIFO, 0x00000000); 298 OUTREG(LP_FIFO, 0x00000000); 299 OUTREG(LP_FIFO, pI740->bltcmd.BR04); 300 OUTREG(LP_FIFO, 0x00000000); 301 OUTREG(LP_FIFO, pI740->bltcmd.BR06); 302 OUTREG(LP_FIFO, pI740->bltcmd.BR07); 303 OUTREG(LP_FIFO, 0x00000000); 304 OUTREG(LP_FIFO, 0x00000000); 305 OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp)); 306} 307 308static void 309I740SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, 310 int fg, int bg, int rop, 311 unsigned int planemask) { 312 I740Ptr pI740; 313 314 pI740 = I740PTR(pScrn); 315 pI740->bltcmd.BR00 = ((pScrn->displayWidth * pI740->cpp) << 16) | 316 (pScrn->displayWidth * pI740->cpp); 317 318 pI740->bltcmd.BR01 = bg; 319 pI740->bltcmd.BR02 = fg; 320 321 pI740->bltcmd.BR04 = PAT_IS_MONO | i740PatternRop[rop]; 322 if (bg == -1) pI740->bltcmd.BR04 |= MONO_PAT_TRANSP; 323 324 pI740->bltcmd.BR05 = (pattx + patty * pScrn->displayWidth) * pI740->cpp; 325} 326 327static void 328I740SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, 329 int x, int y, int w, int h) { 330 I740Ptr pI740; 331 332 pI740 = I740PTR(pScrn); 333 WAIT_LP_FIFO(12); 334 OUTREG(LP_FIFO, 0x6000000A); 335 OUTREG(LP_FIFO, pI740->bltcmd.BR00); 336 OUTREG(LP_FIFO, pI740->bltcmd.BR01); 337 OUTREG(LP_FIFO, pI740->bltcmd.BR02); 338 OUTREG(LP_FIFO, 0x00000000); 339 OUTREG(LP_FIFO, pI740->bltcmd.BR04 | ((y<<20) & PAT_VERT_ALIGN)); 340 OUTREG(LP_FIFO, pI740->bltcmd.BR05); 341 OUTREG(LP_FIFO, 0x00000000); 342 OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp); 343 OUTREG(LP_FIFO, 0x00000000); 344 OUTREG(LP_FIFO, 0x00000000); 345 OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp)); 346} 347#if 0 348static void 349I740SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int bg, int fg, 350 int rop, unsigned int planemask) { 351 I740Ptr pI740; 352 353 pI740 = I740PTR(pScrn); 354 pI740->bltcmd.BR00 = (pScrn->displayWidth * pI740->cpp) << 16; 355 pI740->bltcmd.BR01 = bg; 356 pI740->bltcmd.BR02 = fg; 357#ifdef USE_DWORD_COLOR_EXP 358 pI740->bltcmd.BR03 = MONO_DWORD_ALIGN | MONO_USE_COLEXP; 359#else 360 pI740->bltcmd.BR03 = MONO_BIT_ALIGN | MONO_USE_COLEXP; 361#endif 362 pI740->bltcmd.BR04 = SRC_IS_MONO | SRC_USE_BLTDATA | i740Rop[rop]; 363 if (bg == -1) pI740->bltcmd.BR04 |= MONO_SRC_TRANSP; 364} 365 366static void 367I740SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, 368 int w, int h, int skipleft) { 369 I740Ptr pI740; 370 371 pI740 = I740PTR(pScrn); 372 pI740->AccelInfoRec->Sync(pScrn); 373 OUTREG(LP_FIFO, 0x6000000A); 374 OUTREG(LP_FIFO, pI740->bltcmd.BR00); 375 OUTREG(LP_FIFO, pI740->bltcmd.BR01); 376 OUTREG(LP_FIFO, pI740->bltcmd.BR02); 377 OUTREG(LP_FIFO, pI740->bltcmd.BR03 | (skipleft & MONO_SRC_LEFT_CLIP)); 378 OUTREG(LP_FIFO, pI740->bltcmd.BR04); 379 OUTREG(LP_FIFO, 0x00000000); 380 OUTREG(LP_FIFO, 0x00000000); 381 OUTREG(LP_FIFO, (y * pScrn->displayWidth + x) * pI740->cpp); 382 OUTREG(LP_FIFO, 0x00000000); 383 OUTREG(LP_FIFO, 0x00000000); 384#ifdef USE_DWORD_COLOR_EXP 385 /* 386 * This extra wait is necessary to keep the bitblt engine from 387 * locking up, but I am not sure why it is needed. If we take it 388 * out, "x11perf -copyplane10" will lock the bitblt engine. When 389 * the bitblt engine is locked, it is waiting for mono data to be 390 * written to the BLTDATA region, which seems to imply that some of 391 * the data that was written was lost. This might be fixed by 392 * BLT_SKEW changes. Update: The engine still locks up with this 393 * extra wait. More investigation (and time) is needed. 394 */ 395 WAIT_BLT_IDLE(); 396#endif 397 OUTREG(LP_FIFO, (h << 16) | (w * pI740->cpp)); 398} 399#endif 400