/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atidga.c,v 1.10 2003/04/23 21:51:27 tsi Exp $ */ /* * Copyright 2000 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of Marc Aurele La France not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. Marc Aurele La France makes no representations * about the suitability of this software for any purpose. It is provided * "as-is" without express or implied warranty. * * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef AVOID_DGA #include #include "ati.h" #include "atiadjust.h" #include "atichip.h" #include "atidac.h" #include "atidga.h" #include "atiident.h" #include "atimode.h" #include "atistruct.h" #include "dgaproc.h" /* * ATIDGAOpenFramebuffer -- * * This function returns various framebuffer attributes to a DGA client. */ static Bool ATIDGAOpenFramebuffer ( ScrnInfoPtr pScreenInfo, char **DeviceName, unsigned char **ApertureBase, int *ApertureSize, int *ApertureOffset, int *flags ) { ATIPtr pATI = ATIPTR(pScreenInfo); *DeviceName = NULL; /* No special device */ *ApertureBase = (unsigned char *)(pATI->LinearBase); *ApertureSize = pScreenInfo->videoRam * 1024; *ApertureOffset = 0; /* Always */ *flags = 0; /* Root premissions OS-dependent */ return TRUE; } static int BitsSet ( unsigned long data ) { unsigned long mask = 1; int set = 0; for (; mask; mask <<= 1) if (data & mask) set++; return set; } /* * ATIDGASetMode -- * * This function sets a graphics mode for a DGA client. */ static Bool ATIDGASetMode ( ScrnInfoPtr pScreenInfo, DGAModePtr pDGAMode ) { ATIPtr pATI = ATIPTR(pScreenInfo); DisplayModePtr pMode; int iScreen = pScreenInfo->scrnIndex; int frameX0, frameY0; if (pDGAMode) { pMode = pDGAMode->mode; pATI->depth = pDGAMode->depth; pATI->bitsPerPixel = pDGAMode->bitsPerPixel; pATI->displayWidth = pDGAMode->bytesPerScanline * 8 / pATI->bitsPerPixel; pATI->weight.red = BitsSet(pDGAMode->red_mask); pATI->weight.green = BitsSet(pDGAMode->green_mask); pATI->weight.blue = BitsSet(pDGAMode->blue_mask); frameX0 = frameY0 = 0; if (!pATI->currentMode) pATI->currentMode = pScreenInfo->currentMode; } else { if (!(pMode = pATI->currentMode)) return TRUE; pATI->depth = pScreenInfo->depth; pATI->bitsPerPixel = pScreenInfo->bitsPerPixel; pATI->displayWidth = pScreenInfo->displayWidth; pATI->weight = pScreenInfo->weight; frameX0 = pScreenInfo->frameX0; frameY0 = pScreenInfo->frameY0; } pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel); ATIAdjustPreInit(pATI); ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW); if (!(*pScreenInfo->SwitchMode)(iScreen, pMode, 0)) return FALSE; if (!pDGAMode) pATI->currentMode = NULL; (*pScreenInfo->AdjustFrame)(iScreen, frameX0, frameY0, 0); return TRUE; } /* * ATIDGASetViewport -- * * This function sets the display start address for a DGA client. */ static void ATIDGASetViewport ( ScrnInfoPtr pScreenInfo, int x, int y, int flags ) { (*pScreenInfo->AdjustFrame)(pScreenInfo->pScreen->myNum, x, y, flags); } /* * ATIDGAGetViewport -- * * This function returns the current status of prior DGA requests to set the * adapter's display start address. */ static int ATIDGAGetViewport ( ScrnInfoPtr pScreenInfo ) { return 0; /* There are never any pending requests */ } /* * ATIDGAFillRect -- * * This function calls XAA solid fill primitives to fill a rectangle. */ static void ATIDGAFillRect ( ScrnInfoPtr pScreenInfo, int x, int y, int w, int h, unsigned long colour ) { ATIPtr pATI = ATIPTR(pScreenInfo); /*FIXME : use EXA if available */ #ifdef USE_XAA XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; (*pXAAInfo->SetupForSolidFill)(pScreenInfo, (int)colour, GXcopy, (CARD32)(~0)); (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, x, y, w, h); if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) SET_SYNC_FLAG(pXAAInfo); #endif } /* * ATIDGABlitRect -- * * This function calls XAA screen-to-screen copy primitives to copy a * rectangle. */ static void ATIDGABlitRect ( ScrnInfoPtr pScreenInfo, int xSrc, int ySrc, int w, int h, int xDst, int yDst ) { ATIPtr pATI = ATIPTR(pScreenInfo); /*FIXME : use EXA if available */ #ifdef USE_XAA XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1; int ydir = (ySrc < yDst) ? -1 : 1; (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy, (CARD32)(~0), -1); (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, xSrc, ySrc, xDst, yDst, w, h); if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) SET_SYNC_FLAG(pXAAInfo); #endif } /* * ATIDGABlitTransRect -- * * This function calls XAA screen-to-screen copy primitives to transparently * copy a rectangle. */ static void ATIDGABlitTransRect ( ScrnInfoPtr pScreenInfo, int xSrc, int ySrc, int w, int h, int xDst, int yDst, unsigned long colour ) { ATIPtr pATI = ATIPTR(pScreenInfo); /*FIXME : use EXA if available */ #ifdef USE_XAA XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo; int xdir = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1; int ydir = (ySrc < yDst) ? -1 : 1; pATI->XAAForceTransBlit = TRUE; (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy, (CARD32)(~0), (int)colour); pATI->XAAForceTransBlit = FALSE; (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo, xSrc, ySrc, xDst, yDst, w, h); if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel) SET_SYNC_FLAG(pXAAInfo); #endif } /* * ATIDGAAddModes -- * * This function translates DisplayModeRec's into DGAModeRec's. */ static void ATIDGAAddModes ( ScrnInfoPtr pScreenInfo, ATIPtr pATI, int flags, int depth, int bitsPerPixel, int redMask, int greenMask, int blueMask, int visualClass ) { DisplayModePtr pMode = pScreenInfo->modes; DGAModePtr pDGAMode; int displayWidth = pScreenInfo->displayWidth; int videoBits = pScreenInfo->videoRam * 1024 * 8; int xViewportStep = 64 / UnitOf(bitsPerPixel); int modePitch, bitsPerScanline, maxViewportY; if (bitsPerPixel != pScreenInfo->bitsPerPixel) displayWidth = 0; while (1) { /* Weed out multiscanned modes */ if ((pMode->VScan <= 1) || ((pMode->VScan == 2) && !(pMode->Flags & V_DBLSCAN))) { /* * For code simplicity, ensure DGA mode pitch is a multiple of 64 * bytes. */ if (!(modePitch = displayWidth)) { modePitch = ((64 * 8) / UnitOf(bitsPerPixel)) - 1; modePitch = (pMode->HDisplay + modePitch) & ~modePitch; } /* Ensure the mode fits in video memory */ if ((modePitch * bitsPerPixel * pMode->VDisplay) <= videoBits) { /* Stop generating modes on out-of-memory conditions */ pDGAMode = xrealloc(pATI->pDGAMode, (pATI->nDGAMode + 1) * SizeOf(DGAModeRec)); if (!pDGAMode) break; pATI->pDGAMode = pDGAMode; pDGAMode += pATI->nDGAMode; pATI->nDGAMode++; (void)memset(pDGAMode, 0, SizeOf(DGAModeRec)); /* Fill in the mode structure */ pDGAMode->mode = pMode; pDGAMode->flags = flags; if (bitsPerPixel == pScreenInfo->bitsPerPixel) { pDGAMode->flags |= DGA_PIXMAP_AVAILABLE; pDGAMode->address = pATI->pMemory; #ifdef USE_XAA if (pATI->pXAAInfo) pDGAMode->flags &= ~DGA_CONCURRENT_ACCESS; #endif } if ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1)) pDGAMode->flags |= DGA_DOUBLESCAN; if (pMode->Flags & V_INTERLACE) pDGAMode->flags |= DGA_INTERLACED; pDGAMode->byteOrder = pScreenInfo->imageByteOrder; pDGAMode->depth = depth; pDGAMode->bitsPerPixel = bitsPerPixel; pDGAMode->red_mask = redMask; pDGAMode->green_mask = greenMask; pDGAMode->blue_mask = blueMask; pDGAMode->visualClass = visualClass; pDGAMode->viewportWidth = pMode->HDisplay; pDGAMode->viewportHeight = pMode->VDisplay; pDGAMode->xViewportStep = xViewportStep; pDGAMode->yViewportStep = 1; bitsPerScanline = modePitch * bitsPerPixel; pDGAMode->bytesPerScanline = bitsPerScanline / 8; pDGAMode->imageWidth = pDGAMode->pixmapWidth = modePitch; pDGAMode->imageHeight = pDGAMode->pixmapHeight = videoBits / bitsPerScanline; pDGAMode->maxViewportX = pDGAMode->imageWidth - pDGAMode->viewportWidth; pDGAMode->maxViewportY = pDGAMode->imageHeight - pDGAMode->viewportHeight; maxViewportY = ((((pATI->AdjustMaxBase * 8) / bitsPerPixel) + xViewportStep) / modePitch) - 1; if (maxViewportY < pDGAMode->maxViewportY) pDGAMode->maxViewportY = maxViewportY; } } if ((pMode = pMode->next) == pScreenInfo->modes) { if (!displayWidth) break; displayWidth = 0; } } } /* * ATIDGAInit -- * * This function initialises the driver's support for the DGA extension. */ Bool ATIDGAInit ( ScreenPtr pScreen, ScrnInfoPtr pScreenInfo, ATIPtr pATI ) { #ifdef USE_XAA XAAInfoRecPtr pXAAInfo; #endif int flags; if (!pATI->nDGAMode) { #ifndef AVOID_CPIO /* * Contrary to previous extension versions, DGA 2 does not support * banked framebuffers. Also, disable DGA when non-DGA server modes * are planar. */ if (pATI->BankInfo.BankSize || (pScreenInfo->depth <= 4)) return FALSE; #endif /* AVOID_CPIO */ /* Set up DGA callbacks */ pATI->ATIDGAFunctions.OpenFramebuffer = ATIDGAOpenFramebuffer; pATI->ATIDGAFunctions.SetMode = ATIDGASetMode; pATI->ATIDGAFunctions.SetViewport = ATIDGASetViewport; pATI->ATIDGAFunctions.GetViewport = ATIDGAGetViewport; flags = 0; #ifdef USE_XAA if ((pXAAInfo = pATI->pXAAInfo)) { pATI->ATIDGAFunctions.Sync = pXAAInfo->Sync; if (pXAAInfo->SetupForSolidFill && pXAAInfo->SubsequentSolidFillRect) { flags |= DGA_FILL_RECT; pATI->ATIDGAFunctions.FillRect = ATIDGAFillRect; } if (pXAAInfo->SetupForScreenToScreenCopy && pXAAInfo->SubsequentScreenToScreenCopy) { flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS; pATI->ATIDGAFunctions.BlitRect = ATIDGABlitRect; pATI->ATIDGAFunctions.BlitTransRect = ATIDGABlitTransRect; } } #endif if (!flags) flags = DGA_CONCURRENT_ACCESS; ATIDGAAddModes(pScreenInfo, pATI, flags, 8, 8, 0, 0, 0, PseudoColor); if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chipset == ATI_CHIPSET_ATI)) { ATIDGAAddModes(pScreenInfo, pATI, flags, 15, 16, 0x7C00U, 0x03E0U, 0x001FU, TrueColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 16, 16, 0xF800U, 0x07E0U, 0x001FU, TrueColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor); if (pATI->DAC != ATI_DAC_INTERNAL) /* Not first revision */ { ATIDGAAddModes(pScreenInfo, pATI, flags, 15, 16, 0x7C00U, 0x03E0U, 0x001FU, DirectColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 16, 16, 0xF800U, 0x07E0U, 0x001FU, DirectColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor); ATIDGAAddModes(pScreenInfo, pATI, flags, 24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor); } } } return DGAInit(pScreen, &pATI->ATIDGAFunctions, pATI->pDGAMode, pATI->nDGAMode); } #endif /* AVOID_DGA */