atiscreen.c revision 1b12faf6
132b578d3Smrg/*
232b578d3Smrg * Copyright 1999 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
332b578d3Smrg *
432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that
632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright
732b578d3Smrg * notice and this permission notice appear in supporting documentation, and
832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or
932b578d3Smrg * publicity pertaining to distribution of the software without specific,
1032b578d3Smrg * written prior permission.  Marc Aurele La France makes no representations
1132b578d3Smrg * about the suitability of this software for any purpose.  It is provided
1232b578d3Smrg * "as-is" without express or implied warranty.
1332b578d3Smrg *
1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE.
2132b578d3Smrg *
2232b578d3Smrg * DRI support by:
2332b578d3Smrg *    Gareth Hughes <gareth@valinux.com>
2432b578d3Smrg *    José Fonseca <j_r_fonseca@yahoo.co.uk>
2532b578d3Smrg *    Leif Delgass <ldelgass@retinalburn.net>
2632b578d3Smrg */
2732b578d3Smrg
2832b578d3Smrg#ifdef HAVE_CONFIG_H
2932b578d3Smrg#include "config.h"
3032b578d3Smrg#endif
3132b578d3Smrg
3232b578d3Smrg#include <string.h>
3332b578d3Smrg
3432b578d3Smrg#include "ati.h"
3532b578d3Smrg#include "atibus.h"
3632b578d3Smrg#include "atichip.h"
3732b578d3Smrg#include "aticonsole.h"
3832b578d3Smrg#include "aticursor.h"
3932b578d3Smrg#include "atidac.h"
4032b578d3Smrg#include "atidga.h"
4132b578d3Smrg#include "atidri.h"
4232b578d3Smrg#include "atimach64.h"
4332b578d3Smrg#include "atimode.h"
4432b578d3Smrg#include "atiscreen.h"
4532b578d3Smrg#include "atistruct.h"
4632b578d3Smrg#include "atixv.h"
4732b578d3Smrg#include "atimach64accel.h"
4832b578d3Smrg
4932b578d3Smrg#ifdef XF86DRI_DEVEL
5032b578d3Smrg#include "mach64_dri.h"
5132b578d3Smrg#include "mach64_sarea.h"
5232b578d3Smrg#endif
5332b578d3Smrg
5432b578d3Smrg#ifdef TV_OUT
5532b578d3Smrg
5632b578d3Smrg#include "atichip.h"
5732b578d3Smrg
5832b578d3Smrg#endif /* TV_OUT */
5932b578d3Smrg
6032b578d3Smrg#include "shadowfb.h"
6132b578d3Smrg#include "xf86cmap.h"
6232b578d3Smrg
6332b578d3Smrg#include "fb.h"
6432b578d3Smrg
6532b578d3Smrg#include "micmap.h"
6632b578d3Smrg#include "mipointer.h"
6732b578d3Smrg
6832b578d3Smrg/*
6932b578d3Smrg * ATIRefreshArea --
7032b578d3Smrg *
7132b578d3Smrg * This function is called by the shadow frame buffer code to refresh the
7232b578d3Smrg * hardware frame buffer.
7332b578d3Smrg */
7432b578d3Smrgstatic void
7532b578d3SmrgATIRefreshArea
7632b578d3Smrg(
7732b578d3Smrg    ScrnInfoPtr pScreenInfo,
7832b578d3Smrg    int         nBox,
7932b578d3Smrg    BoxPtr      pBox
8032b578d3Smrg)
8132b578d3Smrg{
8232b578d3Smrg    ATIPtr  pATI = ATIPTR(pScreenInfo);
8332b578d3Smrg    pointer pSrc, pDst;
8432b578d3Smrg    int     offset, w, h;
8532b578d3Smrg
8632b578d3Smrg    while (nBox-- > 0)
8732b578d3Smrg    {
8832b578d3Smrg        w = (pBox->x2 - pBox->x1) * pATI->AdjustDepth;
8932b578d3Smrg        h = pBox->y2 - pBox->y1;
9032b578d3Smrg        offset = (pBox->y1 * pATI->FBPitch) + (pBox->x1 * pATI->AdjustDepth);
9132b578d3Smrg        pSrc = (char *)pATI->pShadow + offset;
9232b578d3Smrg        pDst = (char *)pATI->pMemory + offset;
9332b578d3Smrg
9432b578d3Smrg        while (h-- > 0)
9532b578d3Smrg        {
9632b578d3Smrg            (void)memcpy(pDst, pSrc, w);
9732b578d3Smrg            pSrc = (char *)pSrc + pATI->FBPitch;
9832b578d3Smrg            pDst = (char *)pDst + pATI->FBPitch;
9932b578d3Smrg        }
10032b578d3Smrg
10132b578d3Smrg        pBox++;
10232b578d3Smrg    }
10332b578d3Smrg}
10432b578d3Smrg
10532b578d3Smrg/*
10632b578d3Smrg * ATIMinBits --
10732b578d3Smrg *
10832b578d3Smrg * Compute log base 2 of val.
10932b578d3Smrg */
11032b578d3Smrgstatic int
11132b578d3SmrgATIMinBits
11232b578d3Smrg(
11332b578d3Smrg    int val
11432b578d3Smrg)
11532b578d3Smrg{
11632b578d3Smrg    int bits;
11732b578d3Smrg
11832b578d3Smrg    if (!val) return 1;
11932b578d3Smrg    for (bits = 0; val; val >>= 1, ++bits);
12032b578d3Smrg    return bits;
12132b578d3Smrg}
12232b578d3Smrg
12332b578d3Smrg#ifdef USE_XAA
12432b578d3Smrgstatic Bool
12532b578d3SmrgATIMach64SetupMemXAA_NoDRI
12632b578d3Smrg(
12732b578d3Smrg    int       iScreen,
12832b578d3Smrg    ScreenPtr pScreen
12932b578d3Smrg)
13032b578d3Smrg{
13132b578d3Smrg    ScrnInfoPtr  pScreenInfo = xf86Screens[iScreen];
13232b578d3Smrg    ATIPtr       pATI        = ATIPTR(pScreenInfo);
13332b578d3Smrg
13432b578d3Smrg    int maxScanlines = ATIMach64MaxY;
13532b578d3Smrg    int maxPixelArea, PixelArea;
13632b578d3Smrg
13732b578d3Smrg    {
13832b578d3Smrg        /*
13932b578d3Smrg         * Note:  If PixelArea exceeds the engine's maximum, the excess is
14032b578d3Smrg         *        never used, even though it would be useful for such things
14132b578d3Smrg         *        as XVideo buffers.
14232b578d3Smrg         */
14332b578d3Smrg        maxPixelArea = maxScanlines * pScreenInfo->displayWidth;
14432b578d3Smrg        PixelArea = pScreenInfo->videoRam * 1024 * 8 / pATI->bitsPerPixel;
14532b578d3Smrg        if (PixelArea > maxPixelArea)
14632b578d3Smrg            PixelArea = maxPixelArea;
14732b578d3Smrg        xf86InitFBManagerArea(pScreen, PixelArea, 2);
14832b578d3Smrg    }
14932b578d3Smrg
15032b578d3Smrg    return TRUE;
15132b578d3Smrg}
15232b578d3Smrg
15332b578d3Smrg#ifdef XF86DRI_DEVEL
15432b578d3Smrg/*
15532b578d3Smrg * Memory layour for XAA with DRI (no local_textures):
15632b578d3Smrg * | front  | pixmaps, xv | back   | depth  | textures | c |
15732b578d3Smrg *
15832b578d3Smrg * 1024x768@16bpp with 8 MB:
15932b578d3Smrg * | 1.5 MB | ~3.5 MB     | 1.5 MB | 1.5 MB | 0        | c |
16032b578d3Smrg *
16132b578d3Smrg * 1024x768@32bpp with 8 MB:
16232b578d3Smrg * | 3.0 MB | ~0.5 MB     | 3.0 MB | 1.5 MB | 0        | c |
16332b578d3Smrg *
16432b578d3Smrg * "c" is the hw cursor which occupies 1KB
16532b578d3Smrg */
16632b578d3Smrgstatic Bool
16732b578d3SmrgATIMach64SetupMemXAA
16832b578d3Smrg(
16932b578d3Smrg    int       iScreen,
17032b578d3Smrg    ScreenPtr pScreen
17132b578d3Smrg)
17232b578d3Smrg{
17332b578d3Smrg	ScrnInfoPtr  pScreenInfo = xf86Screens[iScreen];
17432b578d3Smrg	ATIPtr       pATI        = ATIPTR(pScreenInfo);
17532b578d3Smrg
17632b578d3Smrg	ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
17732b578d3Smrg	int cpp = pATI->bitsPerPixel >> 3;
17832b578d3Smrg	int widthBytes = pScreenInfo->displayWidth * cpp;
17932b578d3Smrg	int zWidthBytes = pScreenInfo->displayWidth * 2; /* always 16-bit z-buffer */
18032b578d3Smrg	int fbSize = pScreenInfo->videoRam * 1024;
18132b578d3Smrg	int bufferSize = pScreenInfo->virtualY * widthBytes;
18232b578d3Smrg	int zBufferSize = pScreenInfo->virtualY * zWidthBytes;
18332b578d3Smrg	int offscreenBytes, total, scanlines;
18432b578d3Smrg
18532b578d3Smrg	pATIDRIServer->fbX = 0;
18632b578d3Smrg	pATIDRIServer->fbY = 0;
18732b578d3Smrg	pATIDRIServer->frontOffset = 0;
18832b578d3Smrg	pATIDRIServer->frontPitch = pScreenInfo->displayWidth;
18932b578d3Smrg
19032b578d3Smrg	/* Calculate memory remaining for pixcache and textures after
19132b578d3Smrg	 * front, back, and depth buffers
19232b578d3Smrg	 */
19332b578d3Smrg	offscreenBytes = fbSize - ( 2 * bufferSize + zBufferSize );
19432b578d3Smrg
19532b578d3Smrg	if ( !pATIDRIServer->IsPCI && !pATI->OptionLocalTextures ) {
19632b578d3Smrg	    /* Don't allocate a local texture heap for AGP unless requested */
19732b578d3Smrg	    pATIDRIServer->textureSize = 0;
19832b578d3Smrg	} else {
19932b578d3Smrg	    int l, maxPixcache;
20032b578d3Smrg
20132b578d3Smrg#ifdef XvExtension
20232b578d3Smrg
20332b578d3Smrg	    int xvBytes;
20432b578d3Smrg
20532b578d3Smrg	    /* Try for enough pixmap cache for DVD and a full viewport
20632b578d3Smrg	     */
20732b578d3Smrg	    xvBytes = 720*480*cpp; /* enough for single-buffered DVD */
20832b578d3Smrg	    maxPixcache = xvBytes > bufferSize ? xvBytes : bufferSize;
20932b578d3Smrg
21032b578d3Smrg#else /* XvExtension */
21132b578d3Smrg
21232b578d3Smrg	    /* Try for one viewport */
21332b578d3Smrg	    maxPixcache = bufferSize;
21432b578d3Smrg
21532b578d3Smrg#endif /* XvExtension */
21632b578d3Smrg
21732b578d3Smrg	    pATIDRIServer->textureSize = offscreenBytes - maxPixcache;
21832b578d3Smrg
21932b578d3Smrg	    /* If that gives us less than half the offscreen mem available for textures, split
22032b578d3Smrg	     * the available mem between textures and pixmap cache
22132b578d3Smrg	     */
22232b578d3Smrg	    if (pATIDRIServer->textureSize < (offscreenBytes/2)) {
22332b578d3Smrg		pATIDRIServer->textureSize = offscreenBytes/2;
22432b578d3Smrg	    }
22532b578d3Smrg
22632b578d3Smrg	    if (pATIDRIServer->textureSize <= 0)
22732b578d3Smrg		pATIDRIServer->textureSize = 0;
22832b578d3Smrg
22932b578d3Smrg	    l = ATIMinBits((pATIDRIServer->textureSize-1) / MACH64_NR_TEX_REGIONS);
23032b578d3Smrg	    if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
23132b578d3Smrg
23232b578d3Smrg	    /* Round the texture size up to the nearest whole number of
23332b578d3Smrg	     * texture regions.  Again, be greedy about this, don't round
23432b578d3Smrg	     * down.
23532b578d3Smrg	     */
23632b578d3Smrg	    pATIDRIServer->logTextureGranularity = l;
23732b578d3Smrg	    pATIDRIServer->textureSize =
23832b578d3Smrg		(pATIDRIServer->textureSize >> l) << l;
23932b578d3Smrg	}
24032b578d3Smrg
24132b578d3Smrg	total = fbSize - pATIDRIServer->textureSize;
24232b578d3Smrg	scanlines = total / widthBytes;
24332b578d3Smrg	if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;
24432b578d3Smrg
24532b578d3Smrg	/* Recalculate the texture offset and size to accomodate any
24632b578d3Smrg	 * rounding to a whole number of scanlines.
24732b578d3Smrg	 * FIXME: Is this actually needed?
24832b578d3Smrg	 */
24932b578d3Smrg	pATIDRIServer->textureOffset = scanlines * widthBytes;
25032b578d3Smrg	pATIDRIServer->textureSize = fbSize - pATIDRIServer->textureOffset;
25132b578d3Smrg
25232b578d3Smrg	/* Set a minimum usable local texture heap size.  This will fit
25332b578d3Smrg	 * two 256x256 textures.  We check this after any rounding of
25432b578d3Smrg	 * the texture area.
25532b578d3Smrg	 */
25632b578d3Smrg	if (pATIDRIServer->textureSize < 256*256 * cpp * 2) {
25732b578d3Smrg	    pATIDRIServer->textureOffset = 0;
25832b578d3Smrg	    pATIDRIServer->textureSize = 0;
25932b578d3Smrg	    scanlines = fbSize / widthBytes;
26032b578d3Smrg	    if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;
26132b578d3Smrg	}
26232b578d3Smrg
26332b578d3Smrg	pATIDRIServer->depthOffset = scanlines * widthBytes - zBufferSize;
26432b578d3Smrg	pATIDRIServer->depthPitch = pScreenInfo->displayWidth;
26532b578d3Smrg	pATIDRIServer->depthY = pATIDRIServer->depthOffset/widthBytes;
26632b578d3Smrg	pATIDRIServer->depthX =  (pATIDRIServer->depthOffset -
26732b578d3Smrg				  (pATIDRIServer->depthY * widthBytes)) / cpp;
26832b578d3Smrg
26932b578d3Smrg	pATIDRIServer->backOffset = pATIDRIServer->depthOffset - bufferSize;
27032b578d3Smrg	pATIDRIServer->backPitch = pScreenInfo->displayWidth;
27132b578d3Smrg	pATIDRIServer->backY = pATIDRIServer->backOffset/widthBytes;
27232b578d3Smrg	pATIDRIServer->backX =  (pATIDRIServer->backOffset -
27332b578d3Smrg				  (pATIDRIServer->backY * widthBytes)) / cpp;
27432b578d3Smrg
27532b578d3Smrg	scanlines = fbSize / widthBytes;
27632b578d3Smrg	if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY;
27732b578d3Smrg
27832b578d3Smrg	if ( pATIDRIServer->IsPCI && pATIDRIServer->textureSize == 0 ) {
27932b578d3Smrg	    xf86DrvMsg(iScreen, X_WARNING,
28032b578d3Smrg		       "Not enough memory for local textures, disabling DRI\n");
28132b578d3Smrg	    ATIDRICloseScreen(pScreen);
28232b578d3Smrg	    pATI->directRenderingEnabled = FALSE;
28332b578d3Smrg	} else {
28432b578d3Smrg	    BoxRec ScreenArea;
28532b578d3Smrg
28632b578d3Smrg	    ScreenArea.x1 = 0;
28732b578d3Smrg	    ScreenArea.y1 = 0;
28832b578d3Smrg	    ScreenArea.x2 = pATI->displayWidth;
28932b578d3Smrg	    ScreenArea.y2 = scanlines;
29032b578d3Smrg
29132b578d3Smrg	    if (!xf86InitFBManager(pScreen, &ScreenArea)) {
29232b578d3Smrg		xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
29332b578d3Smrg			   "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
29432b578d3Smrg			   ScreenArea.x1, ScreenArea.y1,
29532b578d3Smrg			   ScreenArea.x2, ScreenArea.y2);
29632b578d3Smrg		return FALSE;
29732b578d3Smrg	    } else {
29832b578d3Smrg		int width, height;
29932b578d3Smrg
30032b578d3Smrg		xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
30132b578d3Smrg			   "Memory manager initialized to (%d,%d) (%d,%d)\n",
30232b578d3Smrg			   ScreenArea.x1, ScreenArea.y1, ScreenArea.x2, ScreenArea.y2);
30332b578d3Smrg
30432b578d3Smrg		if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) {
30532b578d3Smrg		    xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
30632b578d3Smrg			       "Largest offscreen area available: %d x %d\n",
30732b578d3Smrg			       width, height);
30832b578d3Smrg
30932b578d3Smrg		    /* lines in offscreen area needed for depth buffer and textures */
31032b578d3Smrg		    pATI->depthTexLines = scanlines
31132b578d3Smrg			- pATIDRIServer->depthOffset / widthBytes;
31232b578d3Smrg		    pATI->backLines     = scanlines
31332b578d3Smrg			- pATIDRIServer->backOffset / widthBytes
31432b578d3Smrg			- pATI->depthTexLines;
31532b578d3Smrg		    pATI->depthTexArea  = NULL;
31632b578d3Smrg		    pATI->backArea      = NULL;
31732b578d3Smrg		} else {
31832b578d3Smrg		    xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
31932b578d3Smrg			       "Unable to determine largest offscreen area available\n");
32032b578d3Smrg		    return FALSE;
32132b578d3Smrg		}
32232b578d3Smrg
32332b578d3Smrg	    }
32432b578d3Smrg
32532b578d3Smrg	    xf86DrvMsg(iScreen, X_INFO, "Will use %d kB of offscreen memory for XAA\n",
32632b578d3Smrg		       (offscreenBytes - pATIDRIServer->textureSize)/1024);
32732b578d3Smrg
32832b578d3Smrg	    xf86DrvMsg(iScreen, X_INFO, "Will use back buffer at offset 0x%x\n",
32932b578d3Smrg		       pATIDRIServer->backOffset);
33032b578d3Smrg
33132b578d3Smrg	    xf86DrvMsg(iScreen, X_INFO, "Will use depth buffer at offset 0x%x\n",
33232b578d3Smrg		       pATIDRIServer->depthOffset);
33332b578d3Smrg
33432b578d3Smrg	    if (pATIDRIServer->textureSize > 0) {
33532b578d3Smrg		xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
33632b578d3Smrg			   "Will use %d kB for local textures at offset 0x%x\n",
33732b578d3Smrg			   pATIDRIServer->textureSize/1024,
33832b578d3Smrg			   pATIDRIServer->textureOffset);
33932b578d3Smrg	    }
34032b578d3Smrg	}
34132b578d3Smrg
34232b578d3Smrg	return TRUE;
34332b578d3Smrg}
34432b578d3Smrg#endif /* XF86DRI_DEVEL */
34532b578d3Smrg#endif /* USE_XAA */
34632b578d3Smrg
34732b578d3Smrg/*
34832b578d3Smrg * ATIScreenInit --
34932b578d3Smrg *
35032b578d3Smrg * This function is called by DIX to initialise the screen.
35132b578d3Smrg */
35232b578d3SmrgBool
35332b578d3SmrgATIScreenInit
35432b578d3Smrg(
35532b578d3Smrg    int       iScreen,
35632b578d3Smrg    ScreenPtr pScreen,
35732b578d3Smrg    int       argc,
35832b578d3Smrg    char      **argv
35932b578d3Smrg)
36032b578d3Smrg{
36132b578d3Smrg    ScrnInfoPtr  pScreenInfo = xf86Screens[iScreen];
36232b578d3Smrg    ATIPtr       pATI        = ATIPTR(pScreenInfo);
36332b578d3Smrg    pointer      pFB;
36432b578d3Smrg    int          VisualMask;
36532b578d3Smrg
36632b578d3Smrg    /* Set video hardware state */
36732b578d3Smrg    if (!ATIEnterGraphics(pScreen, pScreenInfo, pATI))
36832b578d3Smrg        return FALSE;
36932b578d3Smrg
37032b578d3Smrg    /* Re-initialise mi's visual list */
37132b578d3Smrg    miClearVisualTypes();
37232b578d3Smrg
37332b578d3Smrg    if ((pATI->depth > 8) && (pATI->DAC == ATI_DAC_INTERNAL))
37432b578d3Smrg        VisualMask = TrueColorMask;
37532b578d3Smrg    else
37632b578d3Smrg        VisualMask = miGetDefaultVisualMask(pATI->depth);
37732b578d3Smrg
37832b578d3Smrg    if (!miSetVisualTypes(pATI->depth, VisualMask, pATI->rgbBits,
37932b578d3Smrg                          pScreenInfo->defaultVisual))
38032b578d3Smrg        return FALSE;
38132b578d3Smrg
38232b578d3Smrg    if (!miSetPixmapDepths())
38332b578d3Smrg        return FALSE;
38432b578d3Smrg
38532b578d3Smrg    pFB = pATI->pMemory;
38632b578d3Smrg    pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth);
38732b578d3Smrg    if (pATI->OptionShadowFB)
38832b578d3Smrg    {
38932b578d3Smrg        pATI->FBBytesPerPixel = pATI->bitsPerPixel >> 3;
39032b578d3Smrg        pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth);
3911b12faf6Smrg        if ((pATI->pShadow = malloc(pATI->FBPitch * pScreenInfo->virtualY)))
39232b578d3Smrg        {
39332b578d3Smrg            pFB = pATI->pShadow;
39432b578d3Smrg        }
39532b578d3Smrg        else
39632b578d3Smrg        {
39732b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
39832b578d3Smrg                "Insufficient virtual memory for shadow frame buffer.\n");
39932b578d3Smrg            pATI->OptionShadowFB = FALSE;
40032b578d3Smrg        }
40132b578d3Smrg    }
40232b578d3Smrg
40332b578d3Smrg#ifdef XF86DRI_DEVEL
40432b578d3Smrg
40532b578d3Smrg    /* Setup DRI after visuals have been established, but before
40632b578d3Smrg     * fbScreenInit is called.  fbScreenInit will eventually call the
40732b578d3Smrg     * driver's InitGLXVisuals call back.
40832b578d3Smrg     */
40932b578d3Smrg
41032b578d3Smrg    /* According to atiregs.h, GTPro (3D Rage Pro) is the first chip type with
41132b578d3Smrg     * 3D triangle setup (the VERTEX_* registers)
41232b578d3Smrg     */
41332b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO) {
41432b578d3Smrg	xf86DrvMsg(iScreen, X_WARNING,
41532b578d3Smrg		   "Direct rendering is not supported for ATI chips earlier than "
41632b578d3Smrg		   "the ATI 3D Rage Pro.\n");
41732b578d3Smrg	pATI->directRenderingEnabled = FALSE;
41832b578d3Smrg    } else {
41932b578d3Smrg	/* FIXME: When we move to dynamic allocation of back and depth
42032b578d3Smrg	 * buffers, we will want to revisit the following check for 3
42132b578d3Smrg	 * times the virtual size (or 2.5 times for 24-bit depth) of the screen below.
42232b578d3Smrg	 */
42332b578d3Smrg	int cpp = pATI->bitsPerPixel >> 3;
42432b578d3Smrg	int maxY = pScreenInfo->videoRam * 1024 / (pATI->displayWidth * cpp);
42532b578d3Smrg	int requiredY;
42632b578d3Smrg
42732b578d3Smrg	requiredY = pScreenInfo->virtualY * 2     /* front, back buffers */
42832b578d3Smrg	    + (pScreenInfo->virtualY * 2 / cpp);  /* depth buffer (always 16-bit) */
42932b578d3Smrg
43032b578d3Smrg	if (!pATI->OptionAccel) {
43132b578d3Smrg	    xf86DrvMsg(iScreen, X_WARNING,
43232b578d3Smrg		       "Acceleration disabled, not initializing the DRI\n");
43332b578d3Smrg	    pATI->directRenderingEnabled = FALSE;
43432b578d3Smrg	} else if ( maxY > requiredY ) {
43532b578d3Smrg	    pATI->directRenderingEnabled = ATIDRIScreenInit(pScreen);
43632b578d3Smrg	} else {
43732b578d3Smrg	    xf86DrvMsg(iScreen, X_WARNING,
43832b578d3Smrg		       "DRI static buffer allocation failed -- "
43932b578d3Smrg		       "need at least %d kB video memory\n",
44032b578d3Smrg		       (pScreenInfo->displayWidth * requiredY * cpp ) / 1024);
44132b578d3Smrg	    pATI->directRenderingEnabled = FALSE;
44232b578d3Smrg	}
44332b578d3Smrg    }
44432b578d3Smrg
44532b578d3Smrg#endif /* XF86DRI_DEVEL */
44632b578d3Smrg
44732b578d3Smrg    /* Initialise framebuffer layer */
44832b578d3Smrg    switch (pATI->bitsPerPixel)
44932b578d3Smrg    {
45032b578d3Smrg        case 8:
45132b578d3Smrg        case 16:
45232b578d3Smrg        case 24:
45332b578d3Smrg        case 32:
45432b578d3Smrg            pATI->Closeable = fbScreenInit(pScreen, pFB,
45532b578d3Smrg                pScreenInfo->virtualX, pScreenInfo->virtualY,
45632b578d3Smrg                pScreenInfo->xDpi, pScreenInfo->yDpi, pATI->displayWidth,
45732b578d3Smrg                pATI->bitsPerPixel);
45832b578d3Smrg            break;
45932b578d3Smrg
46032b578d3Smrg        default:
46132b578d3Smrg            return FALSE;
46232b578d3Smrg    }
46332b578d3Smrg
46432b578d3Smrg    if (!pATI->Closeable)
46532b578d3Smrg        return FALSE;
46632b578d3Smrg
46732b578d3Smrg    /* Fixup RGB ordering */
46832b578d3Smrg    if (pATI->depth > 8)
46932b578d3Smrg    {
47032b578d3Smrg        VisualPtr pVisual = pScreen->visuals + pScreen->numVisuals;
47132b578d3Smrg
47232b578d3Smrg        while (--pVisual >= pScreen->visuals)
47332b578d3Smrg        {
47432b578d3Smrg            if ((pVisual->class | DynamicClass) != DirectColor)
47532b578d3Smrg                continue;
47632b578d3Smrg
47732b578d3Smrg            pVisual->offsetRed = pScreenInfo->offset.red;
47832b578d3Smrg            pVisual->offsetGreen = pScreenInfo->offset.green;
47932b578d3Smrg            pVisual->offsetBlue = pScreenInfo->offset.blue;
48032b578d3Smrg
48132b578d3Smrg            pVisual->redMask = pScreenInfo->mask.red;
48232b578d3Smrg            pVisual->greenMask = pScreenInfo->mask.green;
48332b578d3Smrg            pVisual->blueMask = pScreenInfo->mask.blue;
48432b578d3Smrg        }
48532b578d3Smrg    }
48632b578d3Smrg
48732b578d3Smrg    /* If applicable, initialise RENDER extension */
48832b578d3Smrg    {
48932b578d3Smrg        if (pATI->OptionShadowFB)
49032b578d3Smrg        {
49132b578d3Smrg            if (serverGeneration == 1)
49232b578d3Smrg                xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
49332b578d3Smrg                    "RENDER extension not supported with a shadowed"
49432b578d3Smrg                    " framebuffer.\n");
49532b578d3Smrg        }
49632b578d3Smrg        else if (!fbPictureInit(pScreen, NULL, 0) &&
49732b578d3Smrg                 (serverGeneration == 1))
49832b578d3Smrg        {
49932b578d3Smrg            xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
50032b578d3Smrg                "RENDER extension initialisation failed.\n");
50132b578d3Smrg        }
50232b578d3Smrg    }
50332b578d3Smrg
50432b578d3Smrg    xf86SetBlackWhitePixels(pScreen);
50532b578d3Smrg
50632b578d3Smrg#ifdef USE_XAA
50732b578d3Smrg
50832b578d3Smrg    if (!pATI->useEXA) {
50932b578d3Smrg
51032b578d3Smrg    /* Memory manager setup */
51132b578d3Smrg
51232b578d3Smrg#ifdef XF86DRI_DEVEL
51332b578d3Smrg    if (pATI->directRenderingEnabled)
51432b578d3Smrg    {
51532b578d3Smrg        if (!ATIMach64SetupMemXAA(iScreen, pScreen))
51632b578d3Smrg            return FALSE;
51732b578d3Smrg    }
51832b578d3Smrg    else
51932b578d3Smrg#endif /* XF86DRI_DEVEL */
52032b578d3Smrg    {
52132b578d3Smrg        if (!ATIMach64SetupMemXAA_NoDRI(iScreen, pScreen))
52232b578d3Smrg            return FALSE;
52332b578d3Smrg    }
52432b578d3Smrg
52532b578d3Smrg    /* Setup acceleration */
52632b578d3Smrg
52732b578d3Smrg    if (pATI->OptionAccel && !ATIMach64AccelInit(pScreen))
52832b578d3Smrg        return FALSE;
52932b578d3Smrg
53032b578d3Smrg    }
53132b578d3Smrg
53232b578d3Smrg#endif /* USE_XAA */
53332b578d3Smrg
53432b578d3Smrg#ifdef USE_EXA
53532b578d3Smrg
53632b578d3Smrg    if (pATI->useEXA) {
53732b578d3Smrg        /* EXA setups both memory manager and acceleration here */
53832b578d3Smrg
53932b578d3Smrg        if (pATI->OptionAccel && !ATIMach64ExaInit(pScreen))
54032b578d3Smrg            return FALSE;
54132b578d3Smrg    }
54232b578d3Smrg
54332b578d3Smrg#endif /* USE_EXA */
54432b578d3Smrg
54532b578d3Smrg#ifndef AVOID_DGA
54632b578d3Smrg
54732b578d3Smrg    /* Initialise DGA support */
54832b578d3Smrg    (void)ATIDGAInit(pScreen, pScreenInfo, pATI);
54932b578d3Smrg
55032b578d3Smrg#endif /* AVOID_DGA */
55132b578d3Smrg
55232b578d3Smrg    /* Initialise backing store */
55332b578d3Smrg    miInitializeBackingStore(pScreen);
55432b578d3Smrg    xf86SetBackingStore(pScreen);
55532b578d3Smrg
55632b578d3Smrg    /* Initialise cursor */
55732b578d3Smrg    if (!ATIMach64CursorInit(pScreen))
55832b578d3Smrg        return FALSE;
55932b578d3Smrg
56032b578d3Smrg    /* Create default colourmap */
56132b578d3Smrg    if (!miCreateDefColormap(pScreen))
56232b578d3Smrg        return FALSE;
56332b578d3Smrg
56432b578d3Smrg    if (!xf86HandleColormaps(pScreen, 256, pATI->rgbBits, ATILoadPalette, NULL,
56532b578d3Smrg                             CMAP_PALETTED_TRUECOLOR |
56632b578d3Smrg                             CMAP_LOAD_EVEN_IF_OFFSCREEN))
56732b578d3Smrg            return FALSE;
56832b578d3Smrg
56932b578d3Smrg    /* Initialise shadow framebuffer */
57032b578d3Smrg    if (pATI->OptionShadowFB &&
57132b578d3Smrg        !ShadowFBInit(pScreen, ATIRefreshArea))
57232b578d3Smrg        return FALSE;
57332b578d3Smrg
57432b578d3Smrg    /* Initialise DPMS support */
57532b578d3Smrg    (void)xf86DPMSInit(pScreen, ATISetDPMSMode, 0);
57632b578d3Smrg
57732b578d3Smrg    /* Initialise XVideo support */
57832b578d3Smrg    (void)ATIInitializeXVideo(pScreen, pScreenInfo, pATI);
57932b578d3Smrg
58032b578d3Smrg    /* Set pScreen->SaveScreen and wrap CloseScreen vector */
58132b578d3Smrg    pScreen->SaveScreen = ATISaveScreen;
58232b578d3Smrg    pATI->CloseScreen = pScreen->CloseScreen;
58332b578d3Smrg    pScreen->CloseScreen = ATICloseScreen;
58432b578d3Smrg
58532b578d3Smrg    if (serverGeneration == 1)
58632b578d3Smrg        xf86ShowUnusedOptions(pScreenInfo->scrnIndex, pScreenInfo->options);
58732b578d3Smrg
58832b578d3Smrg#ifdef TV_OUT
58932b578d3Smrg    /* Fix-up TV out after ImpacTV probe */
59032b578d3Smrg    if (pATI->OptionTvOut && pATI->Chip < ATI_CHIP_264GTPRO)
59132b578d3Smrg        ATISwitchMode(0, pScreenInfo->currentMode, 0);
59232b578d3Smrg#endif /* TV_OUT */
59332b578d3Smrg
59432b578d3Smrg#ifdef XF86DRI_DEVEL
59532b578d3Smrg
59632b578d3Smrg    /* DRI finalization */
59732b578d3Smrg    if (pATI->directRenderingEnabled) {
59832b578d3Smrg	/* Now that mi, fb, drm and others have done their thing,
59932b578d3Smrg	 * complete the DRI setup.
60032b578d3Smrg	 */
60132b578d3Smrg	pATI->directRenderingEnabled = ATIDRIFinishScreenInit(pScreen);
60232b578d3Smrg    }
60332b578d3Smrg    if (pATI->directRenderingEnabled) {
60432b578d3Smrg	xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
60532b578d3Smrg		   "Direct rendering enabled\n");
60632b578d3Smrg    } else {
60732b578d3Smrg        /* FIXME: Release unused offscreen mem here? */
60832b578d3Smrg	xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
60932b578d3Smrg		   "Direct rendering disabled\n");
61032b578d3Smrg    }
61132b578d3Smrg
61232b578d3Smrg#endif /* XF86DRI_DEVEL */
61332b578d3Smrg
61432b578d3Smrg    return TRUE;
61532b578d3Smrg}
61632b578d3Smrg
61732b578d3Smrg/*
61832b578d3Smrg * ATICloseScreen --
61932b578d3Smrg *
62032b578d3Smrg * This function is called by DIX to close the screen.
62132b578d3Smrg */
62232b578d3SmrgBool
62332b578d3SmrgATICloseScreen
62432b578d3Smrg(
62532b578d3Smrg    int       iScreen,
62632b578d3Smrg    ScreenPtr pScreen
62732b578d3Smrg)
62832b578d3Smrg{
62932b578d3Smrg    ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
63032b578d3Smrg    ATIPtr      pATI        = ATIPTR(pScreenInfo);
63132b578d3Smrg
63232b578d3Smrg#ifdef XF86DRI_DEVEL
63332b578d3Smrg
63432b578d3Smrg    /* Disable direct rendering */
63532b578d3Smrg    if (pATI->directRenderingEnabled)
63632b578d3Smrg    {
63732b578d3Smrg	ATIDRICloseScreen(pScreen);
63832b578d3Smrg	pATI->directRenderingEnabled = FALSE;
63932b578d3Smrg    }
64032b578d3Smrg
64132b578d3Smrg#endif /* XF86DRI_DEVEL */
64232b578d3Smrg
64332b578d3Smrg    ATICloseXVideo(pScreen, pScreenInfo, pATI);
64432b578d3Smrg
64532b578d3Smrg#ifdef USE_EXA
64632b578d3Smrg    if (pATI->pExa)
64732b578d3Smrg    {
64832b578d3Smrg        exaDriverFini(pScreen);
6491b12faf6Smrg        free(pATI->pExa);
65032b578d3Smrg        pATI->pExa = NULL;
65132b578d3Smrg    }
65232b578d3Smrg#endif
65332b578d3Smrg#ifdef USE_XAA
65432b578d3Smrg    if (pATI->pXAAInfo)
65532b578d3Smrg    {
65632b578d3Smrg        XAADestroyInfoRec(pATI->pXAAInfo);
65732b578d3Smrg        pATI->pXAAInfo = NULL;
65832b578d3Smrg    }
65932b578d3Smrg#endif
66032b578d3Smrg    if (pATI->pCursorInfo)
66132b578d3Smrg    {
66232b578d3Smrg        xf86DestroyCursorInfoRec(pATI->pCursorInfo);
66332b578d3Smrg        pATI->pCursorInfo = NULL;
66432b578d3Smrg    }
66532b578d3Smrg
6661b12faf6Smrg    pATI->Closeable = FALSE;
66732b578d3Smrg    ATILeaveGraphics(pScreenInfo, pATI);
66832b578d3Smrg
66932b578d3Smrg#ifdef USE_XAA
67032b578d3Smrg    if (!pATI->useEXA)
67132b578d3Smrg    {
6721b12faf6Smrg        free(pATI->ExpansionBitmapScanlinePtr[1]);
67332b578d3Smrg        pATI->ExpansionBitmapScanlinePtr[0] = NULL;
67432b578d3Smrg        pATI->ExpansionBitmapScanlinePtr[1] = NULL;
67532b578d3Smrg    }
67632b578d3Smrg#endif
67732b578d3Smrg
6781b12faf6Smrg    free(pATI->pShadow);
67932b578d3Smrg    pATI->pShadow = NULL;
68032b578d3Smrg    pScreenInfo->pScreen = NULL;
68132b578d3Smrg
6821b12faf6Smrg    pScreen->CloseScreen = pATI->CloseScreen;
6831b12faf6Smrg    return (*pScreen->CloseScreen)(iScreen, pScreen);
68432b578d3Smrg}
685