1/* 2 * DGA handling 3 * 4 * Copyright (C) 2000 by Alan Hourihane, Sychdyn, North Wales, UK. 5 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria 6 * 7 * Portions from radeon_dga.c which is 8 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 9 * VA Linux Systems Inc., Fremont, California. 10 * 11 * Licensed under the following terms: 12 * 13 * Permission to use, copy, modify, distribute, and sell this software and its 14 * documentation for any purpose is hereby granted without fee, provided that 15 * the above copyright notice appear in all copies and that both that 16 * copyright notice and this permission notice appear in supporting 17 * documentation, and that the name of the providers not be used in 18 * advertising or publicity pertaining to distribution of the software without 19 * specific, written prior permission. The providers make no representations 20 * about the suitability of this software for any purpose. It is provided 21 * "as is" without express or implied warranty. 22 * 23 * THE PROVIDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 25 * EVENT SHALL THE PROVIDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 27 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 28 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29 * PERFORMANCE OF THIS SOFTWARE. 30 * 31 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 32 * Thomas Winischhofer <thomas@winischhofer.net> 33 */ 34 35#ifdef HAVE_CONFIG_H 36#include "config.h" 37#endif 38 39#include "xf86.h" 40#include "xf86_OSproc.h" 41#include "xf86Pci.h" 42#include "xf86PciInfo.h" 43#include "xaa.h" 44#include "xaalocal.h" 45#include "xgi.h" 46#include "xgi_regs.h" 47#include "dgaproc.h" 48 49#ifndef NEW_DGAOPENFRAMEBUFFER 50static Bool XGI_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 51 int *, int *, int *); 52#else 53static Bool XGI_OpenFramebuffer(ScrnInfoPtr, char **, unsigned int *, 54 unsigned int *, unsigned int *, unsigned int *); 55#endif 56 57static Bool XGI_SetMode(ScrnInfoPtr, DGAModePtr); 58static void XGI_Sync(ScrnInfoPtr); 59static int XGI_GetViewport(ScrnInfoPtr); 60static void XGI_SetViewport(ScrnInfoPtr, int, int, int); 61static void XGI_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 62static void XGI_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); 63 64static 65DGAFunctionRec XGIDGAFuncs = { 66 XGI_OpenFramebuffer, 67 NULL, 68 XGI_SetMode, 69 XGI_SetViewport, 70 XGI_GetViewport, 71 XGI_Sync, 72 XGI_FillRect, 73 XGI_BlitRect, 74 NULL 75}; 76 77 78static DGAModePtr 79XGISetupDGAMode( 80 ScrnInfoPtr pScrn, 81 DGAModePtr modes, 82 int *num, 83 int bitsPerPixel, 84 int depth, 85 Bool pixmap, 86 int secondPitch, 87 unsigned long red, 88 unsigned long green, 89 unsigned long blue, 90 short visualClass 91){ 92 XGIPtr pXGI = XGIPTR(pScrn); 93 DGAModePtr newmodes = NULL, currentMode; 94 DisplayModePtr pMode, firstMode; 95 int otherPitch, Bpp = bitsPerPixel >> 3; 96 Bool oneMore; 97 98 pMode = firstMode = pScrn->modes; 99 100 while(pMode) { 101 102 otherPitch = secondPitch ? secondPitch : pMode->HDisplay; 103 104 if(pMode->HDisplay != otherPitch) { 105 106 newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec)); 107 oneMore = TRUE; 108 109 } else { 110 111 newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)); 112 oneMore = FALSE; 113 114 } 115 116 if(!newmodes) { 117 xfree(modes); 118 return NULL; 119 } 120 modes = newmodes; 121 122SECOND_PASS: 123 124 currentMode = modes + *num; 125 (*num)++; 126 127 currentMode->mode = pMode; 128 currentMode->flags = DGA_CONCURRENT_ACCESS; 129 if(pixmap) 130 currentMode->flags |= DGA_PIXMAP_AVAILABLE; 131 if(!pXGI->NoAccel) { 132 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; 133 } 134 if(pMode->Flags & V_DBLSCAN) 135 currentMode->flags |= DGA_DOUBLESCAN; 136 if(pMode->Flags & V_INTERLACE) 137 currentMode->flags |= DGA_INTERLACED; 138 currentMode->byteOrder = pScrn->imageByteOrder; 139 currentMode->depth = depth; 140 currentMode->bitsPerPixel = bitsPerPixel; 141 currentMode->red_mask = red; 142 currentMode->green_mask = green; 143 currentMode->blue_mask = blue; 144 currentMode->visualClass = visualClass; 145 currentMode->viewportWidth = pMode->HDisplay; 146 currentMode->viewportHeight = pMode->VDisplay; 147 currentMode->xViewportStep = 1; 148 currentMode->yViewportStep = 1; 149 currentMode->viewportFlags = DGA_FLIP_RETRACE; 150 currentMode->offset = 0; 151 currentMode->address = pXGI->FbBase; 152 153 if(oneMore) { 154 155 /* first one is narrow width */ 156 currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L); 157 currentMode->imageWidth = pMode->HDisplay; 158 currentMode->imageHeight = pMode->VDisplay; 159 currentMode->pixmapWidth = currentMode->imageWidth; 160 currentMode->pixmapHeight = currentMode->imageHeight; 161 currentMode->maxViewportX = currentMode->imageWidth - 162 currentMode->viewportWidth; 163 /* this might need to get clamped to some maximum */ 164 currentMode->maxViewportY = (currentMode->imageHeight - 165 currentMode->viewportHeight); 166 oneMore = FALSE; 167 goto SECOND_PASS; 168 169 } else { 170 171 currentMode->bytesPerScanline = ((otherPitch * Bpp) + 3) & ~3L; 172 currentMode->imageWidth = otherPitch; 173 currentMode->imageHeight = pMode->VDisplay; 174 currentMode->pixmapWidth = currentMode->imageWidth; 175 currentMode->pixmapHeight = currentMode->imageHeight; 176 currentMode->maxViewportX = (currentMode->imageWidth - 177 currentMode->viewportWidth); 178 /* this might need to get clamped to some maximum */ 179 currentMode->maxViewportY = (currentMode->imageHeight - 180 currentMode->viewportHeight); 181 } 182 183 pMode = pMode->next; 184 if(pMode == firstMode) 185 break; 186 } 187 188 return modes; 189} 190 191 192Bool 193XGIDGAInit(ScreenPtr pScreen) 194{ 195 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 196 XGIPtr pXGI = XGIPTR(pScrn); 197 DGAModePtr modes = NULL; 198 int num = 0; 199 200 /* 8 */ 201 /* We don't support 8bpp modes in dual head or MergedFB mode, 202 * so don't offer them to DGA either. 203 */ 204 if (!IS_DUAL_HEAD(pXGI) 205#ifdef XGIMERGED 206 && !(pXGI->MergedFB) 207#endif 208 ) { 209 modes = XGISetupDGAMode(pScrn, modes, &num, 8, 8, 210 (pScrn->bitsPerPixel == 8), 211 ((pScrn->bitsPerPixel != 8) 212 ? 0 : pScrn->displayWidth), 213 0, 0, 0, PseudoColor); 214 } 215 216 /* 16 */ 217 modes = XGISetupDGAMode(pScrn, modes, &num, 16, 16, 218 (pScrn->bitsPerPixel == 16), 219 ((pScrn->depth != 16) 220 ? 0 : pScrn->displayWidth), 221 0xf800, 0x07e0, 0x001f, TrueColor); 222 223 /* 32 */ 224 modes = XGISetupDGAMode(pScrn, modes, &num, 32, 24, 225 (pScrn->bitsPerPixel == 32), 226 ((pScrn->bitsPerPixel != 32) 227 ? 0 : pScrn->displayWidth), 228 0xff0000, 0x00ff00, 0x0000ff, TrueColor); 229 230 pXGI->numDGAModes = num; 231 pXGI->DGAModes = modes; 232 233 if (num) { 234 return DGAInit(pScreen, &XGIDGAFuncs, modes, num); 235 } 236 else { 237 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 238 "No DGA-suitable modes found, disabling DGA\n"); 239 return TRUE; 240 } 241} 242 243 244static Bool 245XGI_SetMode( 246 ScrnInfoPtr pScrn, 247 DGAModePtr pMode 248){ 249 static XGIFBLayout BackupLayouts[MAXSCREENS]; 250 int index = pScrn->pScreen->myNum; 251 XGIPtr pXGI = XGIPTR(pScrn); 252 253 if(!pMode) { /* restore the original mode */ 254 255 if(pXGI->DGAactive) { 256 /* put the ScreenParameters back */ 257 memcpy(&pXGI->CurrentLayout, &BackupLayouts[index], sizeof(XGIFBLayout)); 258 } 259 260 pScrn->currentMode = pXGI->CurrentLayout.mode; 261 262 (*pScrn->SwitchMode)(index, pScrn->currentMode, 0); 263 (*pScrn->AdjustFrame)(index, pScrn->frameX0, pScrn->frameY0, 0); 264 pXGI->DGAactive = FALSE; 265 266 } else { /* set new mode */ 267 268 if(!pXGI->DGAactive) { 269 /* save the old parameters */ 270 memcpy(&BackupLayouts[index], &pXGI->CurrentLayout, sizeof(XGIFBLayout)); 271 pXGI->DGAactive = TRUE; 272 } 273 274 pXGI->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; 275 pXGI->CurrentLayout.depth = pMode->depth; 276 pXGI->CurrentLayout.displayWidth = pMode->bytesPerScanline / (pMode->bitsPerPixel >> 3); 277 278 (*pScrn->SwitchMode)(index, pMode->mode, 0); 279 /* TW: Adjust viewport to 0/0 after mode switch */ 280 /* This should fix the vmware-in-dualhead problems */ 281 (*pScrn->AdjustFrame)(index, 0, 0, 0); 282 } 283 284 return TRUE; 285} 286 287static int 288XGI_GetViewport(ScrnInfoPtr pScrn) 289{ 290 (void) pScrn; 291 292 /* There are never pending Adjusts */ 293 return 0; 294} 295 296static void 297XGI_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 298{ 299 (*pScrn->AdjustFrame)(pScrn->pScreen->myNum, x, y, flags); 300} 301 302static void 303XGI_FillRect ( 304 ScrnInfoPtr pScrn, 305 int x, int y, int w, int h, 306 unsigned long color 307){ 308 XGIPtr pXGI = XGIPTR(pScrn); 309 310#ifdef XGI_USE_XAA 311 if(pXGI->AccelInfoPtr) { 312 (*pXGI->AccelInfoPtr->SetupForSolidFill)(pScrn, color, GXcopy, ~0); 313 (*pXGI->AccelInfoPtr->SubsequentSolidFillRect)(pScrn, x, y, w, h); 314 SET_SYNC_FLAG(pXGI->AccelInfoPtr); 315 } 316#endif 317} 318 319static void 320XGI_Sync( 321 ScrnInfoPtr pScrn 322){ 323 XGIPtr pXGI = XGIPTR(pScrn); 324 325#ifdef XGI_USE_XAA 326 if(pXGI->AccelInfoPtr) { 327 (*pXGI->AccelInfoPtr->Sync)(pScrn); 328 } 329#endif 330} 331 332static void 333XGI_BlitRect( 334 ScrnInfoPtr pScrn, 335 int srcx, int srcy, 336 int w, int h, 337 int dstx, int dsty 338){ 339 XGIPtr pXGI = XGIPTR(pScrn); 340 341#ifdef XGI_USE_XAA 342 if(pXGI->AccelInfoPtr) { 343 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 344 int ydir = (srcy < dsty) ? -1 : 1; 345 346 (*pXGI->AccelInfoPtr->SetupForScreenToScreenCopy)( 347 pScrn, xdir, ydir, GXcopy, (CARD32)~0, -1); 348 (*pXGI->AccelInfoPtr->SubsequentScreenToScreenCopy)( 349 pScrn, srcx, srcy, dstx, dsty, w, h); 350 SET_SYNC_FLAG(pXGI->AccelInfoPtr); 351 } 352#endif 353} 354 355static Bool 356XGI_OpenFramebuffer( 357 ScrnInfoPtr pScrn, 358 char **name, 359#ifndef NEW_DGAOPENFRAMEBUFFER 360 unsigned char **mem, 361 int *size, 362 int *offset, 363 int *flags 364#else 365 unsigned int *mem, 366 unsigned int *size, 367 unsigned int *offset, 368 unsigned int *flags 369#endif 370){ 371 XGIPtr pXGI = XGIPTR(pScrn); 372 373 *name = NULL; /* no special device */ 374#ifndef NEW_DGAOPENFRAMEBUFFER 375 *mem = (unsigned char*)pXGI->FbAddress; 376#else 377 *mem = pXGI->FbAddress; 378#endif 379 *size = pXGI->maxxfbmem; 380 *offset = 0; 381 *flags = DGA_NEED_ROOT; 382 383 return TRUE; 384} 385