atidga.c revision e35d4d8e
1/* 2 * Copyright 2000 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of Marc Aurele La France not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. Marc Aurele La France makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as-is" without express or implied warranty. 13 * 14 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 16 * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include "config.h" 25#endif 26#ifndef AVOID_DGA 27 28#include <string.h> 29 30#include "ati.h" 31#include "atichip.h" 32#include "atidac.h" 33#include "atidga.h" 34#include "atimode.h" 35#include "atistruct.h" 36#include "atiadjust.h" 37 38#include "dgaproc.h" 39 40/* 41 * ATIDGAOpenFramebuffer -- 42 * 43 * This function returns various framebuffer attributes to a DGA client. 44 */ 45static Bool 46ATIDGAOpenFramebuffer 47( 48 ScrnInfoPtr pScreenInfo, 49 char **DeviceName, 50 unsigned char **ApertureBase, 51 int *ApertureSize, 52 int *ApertureOffset, 53 int *flags 54) 55{ 56 ATIPtr pATI = ATIPTR(pScreenInfo); 57 58 *DeviceName = NULL; /* No special device */ 59 *ApertureBase = (unsigned char *)(pATI->LinearBase); 60 *ApertureSize = pScreenInfo->videoRam * 1024; 61 *ApertureOffset = 0; /* Always */ 62 *flags = 0; /* Root premissions OS-dependent */ 63 64 return TRUE; 65} 66 67static int 68BitsSet 69( 70 unsigned long data 71) 72{ 73 unsigned long mask = 1; 74 int set = 0; 75 76 for (; mask; mask <<= 1) 77 if (data & mask) 78 set++; 79 80 return set; 81} 82 83/* 84 * ATIDGASetMode -- 85 * 86 * This function sets a graphics mode for a DGA client. 87 */ 88static Bool 89ATIDGASetMode 90( 91 ScrnInfoPtr pScreenInfo, 92 DGAModePtr pDGAMode 93) 94{ 95 ATIPtr pATI = ATIPTR(pScreenInfo); 96 DisplayModePtr pMode; 97 int frameX0, frameY0; 98 99 if (pDGAMode) 100 { 101 pMode = pDGAMode->mode; 102 pATI->depth = pDGAMode->depth; 103 pATI->bitsPerPixel = pDGAMode->bitsPerPixel; 104 pATI->displayWidth = 105 pDGAMode->bytesPerScanline * 8 / pATI->bitsPerPixel; 106 pATI->weight.red = BitsSet(pDGAMode->red_mask); 107 pATI->weight.green = BitsSet(pDGAMode->green_mask); 108 pATI->weight.blue = BitsSet(pDGAMode->blue_mask); 109 frameX0 = frameY0 = 0; 110 if (!pATI->currentMode) 111 pATI->currentMode = pScreenInfo->currentMode; 112 } 113 else 114 { 115 if (!(pMode = pATI->currentMode)) 116 return TRUE; 117 118 pATI->depth = pScreenInfo->depth; 119 pATI->bitsPerPixel = pScreenInfo->bitsPerPixel; 120 pATI->displayWidth = pScreenInfo->displayWidth; 121 pATI->weight = pScreenInfo->weight; 122 frameX0 = pScreenInfo->frameX0; 123 frameY0 = pScreenInfo->frameY0; 124 } 125 126 pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel); 127 ATIAdjustPreInit(pATI); 128 ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW); 129 130 if (!(*pScreenInfo->SwitchMode)(SWITCH_MODE_ARGS(pScreenInfo, pMode))) 131 return FALSE; 132 if (!pDGAMode) 133 pATI->currentMode = NULL; 134 (*pScreenInfo->AdjustFrame)(ADJUST_FRAME_ARGS(pScreenInfo, frameX0, frameY0)); 135 136 return TRUE; 137} 138 139/* 140 * ATIDGASetViewport -- 141 * 142 * This function sets the display start address for a DGA client. 143 */ 144static void 145ATIDGASetViewport 146( 147 ScrnInfoPtr pScreenInfo, 148 int x, 149 int y, 150 int flags 151) 152{ 153 (*pScreenInfo->AdjustFrame)(ADJUST_FRAME_ARGS(pScreenInfo, x, y)); 154} 155 156/* 157 * ATIDGAGetViewport -- 158 * 159 * This function returns the current status of prior DGA requests to set the 160 * adapter's display start address. 161 */ 162static int 163ATIDGAGetViewport 164( 165 ScrnInfoPtr pScreenInfo 166) 167{ 168 return 0; /* There are never any pending requests */ 169} 170 171/* 172 * ATIDGAFillRect -- 173 * 174 * This function calls XAA solid fill primitives to fill a rectangle. 175 */ 176static void 177ATIDGAFillRect 178( 179 ScrnInfoPtr pScreenInfo, 180 int x, 181 int y, 182 int w, 183 int h, 184 unsigned long colour 185) 186{ 187 ATIPtr pATI = ATIPTR(pScreenInfo); 188/*FIXME : use EXA if available */ 189#ifdef USE_XAA 190 XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 191 192 (*pXAAInfo->SetupForSolidFill)(pScreenInfo, (int)colour, GXcopy, 193 (CARD32)(~0)); 194 (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, x, y, w, h); 195 196 if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) 197 SET_SYNC_FLAG(pXAAInfo); 198#endif 199} 200 201/* 202 * ATIDGABlitRect -- 203 * 204 * This function calls XAA screen-to-screen copy primitives to copy a 205 * rectangle. 206 */ 207static void 208ATIDGABlitRect 209( 210 ScrnInfoPtr pScreenInfo, 211 int xSrc, 212 int ySrc, 213 int w, 214 int h, 215 int xDst, 216 int yDst 217) 218{ 219 ATIPtr pATI = ATIPTR(pScreenInfo); 220/*FIXME : use EXA if available */ 221#ifdef USE_XAA 222 XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 223 int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1; 224 int ydir = (ySrc < yDst) ? -1 : 1; 225 226 (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, 227 xdir, ydir, GXcopy, (CARD32)(~0), -1); 228 (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, 229 xSrc, ySrc, xDst, yDst, w, h); 230 231 if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) 232 SET_SYNC_FLAG(pXAAInfo); 233#endif 234} 235 236/* 237 * ATIDGABlitTransRect -- 238 * 239 * This function calls XAA screen-to-screen copy primitives to transparently 240 * copy a rectangle. 241 */ 242static void 243ATIDGABlitTransRect 244( 245 ScrnInfoPtr pScreenInfo, 246 int xSrc, 247 int ySrc, 248 int w, 249 int h, 250 int xDst, 251 int yDst, 252 unsigned long colour 253) 254{ 255 ATIPtr pATI = ATIPTR(pScreenInfo); 256/*FIXME : use EXA if available */ 257#ifdef USE_XAA 258 XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; 259 int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1; 260 int ydir = (ySrc < yDst) ? -1 : 1; 261 262 pATI->XAAForceTransBlit = TRUE; 263 264 (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, 265 xdir, ydir, GXcopy, (CARD32)(~0), (int)colour); 266 267 pATI->XAAForceTransBlit = FALSE; 268 269 (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, 270 xSrc, ySrc, xDst, yDst, w, h); 271 272 if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) 273 SET_SYNC_FLAG(pXAAInfo); 274#endif 275} 276 277/* 278 * ATIDGAAddModes -- 279 * 280 * This function translates DisplayModeRec's into DGAModeRec's. 281 */ 282static void 283ATIDGAAddModes 284( 285 ScrnInfoPtr pScreenInfo, 286 ATIPtr pATI, 287 int flags, 288 int depth, 289 int bitsPerPixel, 290 int redMask, 291 int greenMask, 292 int blueMask, 293 int visualClass 294) 295{ 296 DisplayModePtr pMode = pScreenInfo->modes; 297 DGAModePtr pDGAMode; 298 int displayWidth = pScreenInfo->displayWidth; 299 int videoBits = pScreenInfo->videoRam * 1024 * 8; 300 int xViewportStep = 64 / UnitOf(bitsPerPixel); 301 int modePitch, bitsPerScanline, maxViewportY; 302 303 if (bitsPerPixel != pScreenInfo->bitsPerPixel) 304 displayWidth = 0; 305 306 while (1) 307 { 308 /* Weed out multiscanned modes */ 309 if ((pMode->VScan <= 1) || 310 ((pMode->VScan == 2) && !(pMode->Flags & V_DBLSCAN))) 311 { 312 /* 313 * For code simplicity, ensure DGA mode pitch is a multiple of 64 314 * bytes. 315 */ 316 if (!(modePitch = displayWidth)) 317 { 318 modePitch = ((64 * 8) / UnitOf(bitsPerPixel)) - 1; 319 modePitch = (pMode->HDisplay + modePitch) & ~modePitch; 320 } 321 322 /* Ensure the mode fits in video memory */ 323 if ((modePitch * bitsPerPixel * pMode->VDisplay) <= videoBits) 324 { 325 /* Stop generating modes on out-of-memory conditions */ 326 pDGAMode = realloc(pATI->pDGAMode, 327 (pATI->nDGAMode + 1) * SizeOf(DGAModeRec)); 328 if (!pDGAMode) 329 break; 330 331 pATI->pDGAMode = pDGAMode; 332 pDGAMode += pATI->nDGAMode; 333 pATI->nDGAMode++; 334 (void)memset(pDGAMode, 0, SizeOf(DGAModeRec)); 335 336 /* Fill in the mode structure */ 337 pDGAMode->mode = pMode; 338 pDGAMode->flags = flags; 339 if (bitsPerPixel == pScreenInfo->bitsPerPixel) 340 { 341 pDGAMode->flags |= DGA_PIXMAP_AVAILABLE; 342 pDGAMode->address = pATI->pMemory; 343 344#ifdef USE_XAA 345 if (pATI->pXAAInfo) 346 pDGAMode->flags &= ~DGA_CONCURRENT_ACCESS; 347#endif 348 } 349 if ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1)) 350 pDGAMode->flags |= DGA_DOUBLESCAN; 351 if (pMode->Flags & V_INTERLACE) 352 pDGAMode->flags |= DGA_INTERLACED; 353 354 pDGAMode->byteOrder = pScreenInfo->imageByteOrder; 355 pDGAMode->depth = depth; 356 pDGAMode->bitsPerPixel = bitsPerPixel; 357 pDGAMode->red_mask = redMask; 358 pDGAMode->green_mask = greenMask; 359 pDGAMode->blue_mask = blueMask; 360 pDGAMode->visualClass = visualClass; 361 362 pDGAMode->viewportWidth = pMode->HDisplay; 363 pDGAMode->viewportHeight = pMode->VDisplay; 364 pDGAMode->xViewportStep = xViewportStep; 365 pDGAMode->yViewportStep = 1; 366 367 bitsPerScanline = modePitch * bitsPerPixel; 368 pDGAMode->bytesPerScanline = bitsPerScanline / 8; 369 pDGAMode->imageWidth = pDGAMode->pixmapWidth = modePitch; 370 pDGAMode->imageHeight = pDGAMode->pixmapHeight = 371 videoBits / bitsPerScanline; 372 373 pDGAMode->maxViewportX = 374 pDGAMode->imageWidth - pDGAMode->viewportWidth; 375 pDGAMode->maxViewportY = 376 pDGAMode->imageHeight - pDGAMode->viewportHeight; 377 maxViewportY = 378 ((((pATI->AdjustMaxBase * 8) / bitsPerPixel) + 379 xViewportStep) / modePitch) - 1; 380 if (maxViewportY < pDGAMode->maxViewportY) 381 pDGAMode->maxViewportY = maxViewportY; 382 } 383 } 384 385 if ((pMode = pMode->next) == pScreenInfo->modes) 386 { 387 if (!displayWidth) 388 break; 389 390 displayWidth = 0; 391 } 392 } 393} 394 395/* 396 * ATIDGAInit -- 397 * 398 * This function initialises the driver's support for the DGA extension. 399 */ 400Bool 401ATIDGAInit 402( 403 ScreenPtr pScreen, 404 ScrnInfoPtr pScreenInfo, 405 ATIPtr pATI 406) 407{ 408#ifdef USE_XAA 409 XAAInfoRecPtr pXAAInfo; 410#endif 411 int flags; 412 413 if (!pATI->nDGAMode) 414 { 415 /* Set up DGA callbacks */ 416 pATI->ATIDGAFunctions.OpenFramebuffer = ATIDGAOpenFramebuffer; 417 pATI->ATIDGAFunctions.SetMode = ATIDGASetMode; 418 pATI->ATIDGAFunctions.SetViewport = ATIDGASetViewport; 419 pATI->ATIDGAFunctions.GetViewport = ATIDGAGetViewport; 420 421 flags = 0; 422#ifdef USE_XAA 423 if ((pXAAInfo = pATI->pXAAInfo)) 424 { 425 pATI->ATIDGAFunctions.Sync = pXAAInfo->Sync; 426 if (pXAAInfo->SetupForSolidFill && 427 pXAAInfo->SubsequentSolidFillRect) 428 { 429 flags |= DGA_FILL_RECT; 430 pATI->ATIDGAFunctions.FillRect = ATIDGAFillRect; 431 } 432 if (pXAAInfo->SetupForScreenToScreenCopy && 433 pXAAInfo->SubsequentScreenToScreenCopy) 434 { 435 flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS; 436 pATI->ATIDGAFunctions.BlitRect = ATIDGABlitRect; 437 pATI->ATIDGAFunctions.BlitTransRect = ATIDGABlitTransRect; 438 } 439 } 440#endif 441 if (!flags) 442 flags = DGA_CONCURRENT_ACCESS; 443 444 ATIDGAAddModes(pScreenInfo, pATI, flags, 445 8, 8, 0, 0, 0, PseudoColor); 446 447 if ((pATI->Chip >= ATI_CHIP_264CT)) 448 { 449 ATIDGAAddModes(pScreenInfo, pATI, flags, 450 15, 16, 0x7C00U, 0x03E0U, 0x001FU, TrueColor); 451 452 ATIDGAAddModes(pScreenInfo, pATI, flags, 453 16, 16, 0xF800U, 0x07E0U, 0x001FU, TrueColor); 454 455 ATIDGAAddModes(pScreenInfo, pATI, flags, 456 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor); 457 458 ATIDGAAddModes(pScreenInfo, pATI, flags, 459 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor); 460 461 if (pATI->DAC != ATI_DAC_INTERNAL) /* Not first revision */ 462 { 463 ATIDGAAddModes(pScreenInfo, pATI, flags, 464 15, 16, 0x7C00U, 0x03E0U, 0x001FU, DirectColor); 465 466 ATIDGAAddModes(pScreenInfo, pATI, flags, 467 16, 16, 0xF800U, 0x07E0U, 0x001FU, DirectColor); 468 469 ATIDGAAddModes(pScreenInfo, pATI, flags, 470 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor); 471 472 ATIDGAAddModes(pScreenInfo, pATI, flags, 473 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor); 474 } 475 } 476 } 477 478 return DGAInit(pScreen, &pATI->ATIDGAFunctions, pATI->pDGAMode, 479 pATI->nDGAMode); 480} 481 482#endif /* AVOID_DGA */ 483