trident_dga.c revision 95b296d0
195b296d0Smrg/*
295b296d0Smrg * Copyright 1997-2003 by Alan Hourihane, North Wales, UK.
395b296d0Smrg *
495b296d0Smrg * Permission to use, copy, modify, distribute, and sell this software and its
595b296d0Smrg * documentation for any purpose is hereby granted without fee, provided that
695b296d0Smrg * the above copyright notice appear in all copies and that both that
795b296d0Smrg * copyright notice and this permission notice appear in supporting
895b296d0Smrg * documentation, and that the name of Alan Hourihane not be used in
995b296d0Smrg * advertising or publicity pertaining to distribution of the software without
1095b296d0Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1195b296d0Smrg * about the suitability of this software for any purpose.  It is provided
1295b296d0Smrg * "as is" without express or implied warranty.
1395b296d0Smrg *
1495b296d0Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1595b296d0Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1695b296d0Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1795b296d0Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1895b296d0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1995b296d0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2095b296d0Smrg * PERFORMANCE OF THIS SOFTWARE.
2195b296d0Smrg *
2295b296d0Smrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
2395b296d0Smrg */
2495b296d0Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_dga.c,v 1.4 2002/10/08 22:14:11 tsi Exp $ */
2595b296d0Smrg
2695b296d0Smrg#ifdef HAVE_CONFIG_H
2795b296d0Smrg#include "config.h"
2895b296d0Smrg#endif
2995b296d0Smrg
3095b296d0Smrg#include "xf86.h"
3195b296d0Smrg#include "xf86_OSproc.h"
3295b296d0Smrg#include "xf86Pci.h"
3395b296d0Smrg#include "xf86PciInfo.h"
3495b296d0Smrg#include "xaa.h"
3595b296d0Smrg#include "xaalocal.h"
3695b296d0Smrg#include "trident.h"
3795b296d0Smrg#include "trident_regs.h"
3895b296d0Smrg#include "dgaproc.h"
3995b296d0Smrg
4095b296d0Smrg
4195b296d0Smrgstatic Bool TRIDENT_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
4295b296d0Smrg					int *, int *, int *);
4395b296d0Smrgstatic Bool TRIDENT_SetMode(ScrnInfoPtr, DGAModePtr);
4495b296d0Smrgstatic void TRIDENT_Sync(ScrnInfoPtr);
4595b296d0Smrgstatic int  TRIDENT_GetViewport(ScrnInfoPtr);
4695b296d0Smrgstatic void TRIDENT_SetViewport(ScrnInfoPtr, int, int, int);
4795b296d0Smrgstatic void TRIDENT_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
4895b296d0Smrgstatic void TRIDENT_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
4995b296d0Smrg#if 0
5095b296d0Smrgstatic void TRIDENT_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
5195b296d0Smrg					unsigned long);
5295b296d0Smrg#endif
5395b296d0Smrg
5495b296d0Smrgstatic
5595b296d0SmrgDGAFunctionRec TRIDENTDGAFuncs = {
5695b296d0Smrg   TRIDENT_OpenFramebuffer,
5795b296d0Smrg   NULL,
5895b296d0Smrg   TRIDENT_SetMode,
5995b296d0Smrg   TRIDENT_SetViewport,
6095b296d0Smrg   TRIDENT_GetViewport,
6195b296d0Smrg   TRIDENT_Sync,
6295b296d0Smrg   TRIDENT_FillRect,
6395b296d0Smrg   TRIDENT_BlitRect,
6495b296d0Smrg#if 0
6595b296d0Smrg   TRIDENT_BlitTransRect
6695b296d0Smrg#else
6795b296d0Smrg   NULL
6895b296d0Smrg#endif
6995b296d0Smrg};
7095b296d0Smrg
7195b296d0SmrgBool
7295b296d0SmrgTRIDENTDGAInit(ScreenPtr pScreen)
7395b296d0Smrg{
7495b296d0Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
7595b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
7695b296d0Smrg   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
7795b296d0Smrg   DisplayModePtr pMode, firstMode;
7895b296d0Smrg   int Bpp = pScrn->bitsPerPixel >> 3;
7995b296d0Smrg   int num = 0;
8095b296d0Smrg   Bool oneMore;
8195b296d0Smrg
8295b296d0Smrg   pMode = firstMode = pScrn->modes;
8395b296d0Smrg
8495b296d0Smrg   while(pMode) {
8595b296d0Smrg
8695b296d0Smrg	if(0 /*pScrn->displayWidth != pMode->HDisplay*/) {
8795b296d0Smrg	    newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec));
8895b296d0Smrg	    oneMore = TRUE;
8995b296d0Smrg	} else {
9095b296d0Smrg	    newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
9195b296d0Smrg	    oneMore = FALSE;
9295b296d0Smrg	}
9395b296d0Smrg
9495b296d0Smrg	if(!newmodes) {
9595b296d0Smrg	   xfree(modes);
9695b296d0Smrg	   return FALSE;
9795b296d0Smrg	}
9895b296d0Smrg	modes = newmodes;
9995b296d0Smrg
10095b296d0SmrgSECOND_PASS:
10195b296d0Smrg
10295b296d0Smrg	currentMode = modes + num;
10395b296d0Smrg	num++;
10495b296d0Smrg
10595b296d0Smrg	currentMode->mode = pMode;
10695b296d0Smrg	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
10795b296d0Smrg	if(!pTrident->NoAccel)
10895b296d0Smrg	   currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
10995b296d0Smrg	if(pMode->Flags & V_DBLSCAN)
11095b296d0Smrg	   currentMode->flags |= DGA_DOUBLESCAN;
11195b296d0Smrg	if(pMode->Flags & V_INTERLACE)
11295b296d0Smrg	   currentMode->flags |= DGA_INTERLACED;
11395b296d0Smrg	currentMode->byteOrder = pScrn->imageByteOrder;
11495b296d0Smrg	currentMode->depth = pScrn->depth;
11595b296d0Smrg	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
11695b296d0Smrg	currentMode->red_mask = pScrn->mask.red;
11795b296d0Smrg	currentMode->green_mask = pScrn->mask.green;
11895b296d0Smrg	currentMode->blue_mask = pScrn->mask.blue;
11995b296d0Smrg	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
12095b296d0Smrg	currentMode->viewportWidth = pMode->HDisplay;
12195b296d0Smrg	currentMode->viewportHeight = pMode->VDisplay;
12295b296d0Smrg	currentMode->xViewportStep = 1;
12395b296d0Smrg	currentMode->yViewportStep = 1;
12495b296d0Smrg	currentMode->viewportFlags = DGA_FLIP_RETRACE;
12595b296d0Smrg	currentMode->offset = 0;
12695b296d0Smrg	currentMode->address = pTrident->FbBase;
12795b296d0Smrg
12895b296d0Smrg	if(oneMore) { /* first one is narrow width */
12995b296d0Smrg	    currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L;
13095b296d0Smrg	    currentMode->imageWidth = pMode->HDisplay;
13195b296d0Smrg	    currentMode->imageHeight =  pMode->VDisplay;
13295b296d0Smrg	    currentMode->pixmapWidth = currentMode->imageWidth;
13395b296d0Smrg	    currentMode->pixmapHeight = currentMode->imageHeight;
13495b296d0Smrg	    currentMode->maxViewportX = currentMode->imageWidth -
13595b296d0Smrg					currentMode->viewportWidth;
13695b296d0Smrg	    /* this might need to get clamped to some maximum */
13795b296d0Smrg	    currentMode->maxViewportY = currentMode->imageHeight -
13895b296d0Smrg					currentMode->viewportHeight;
13995b296d0Smrg	    oneMore = FALSE;
14095b296d0Smrg	    goto SECOND_PASS;
14195b296d0Smrg	} else {
14295b296d0Smrg	    currentMode->bytesPerScanline =
14395b296d0Smrg			((pScrn->displayWidth * Bpp) + 3) & ~3L;
14495b296d0Smrg	    currentMode->imageWidth = pScrn->displayWidth;
14595b296d0Smrg	    currentMode->imageHeight =  pMode->VDisplay;
14695b296d0Smrg	    currentMode->pixmapWidth = currentMode->imageWidth;
14795b296d0Smrg	    currentMode->pixmapHeight = currentMode->imageHeight;
14895b296d0Smrg	    currentMode->maxViewportX = currentMode->imageWidth -
14995b296d0Smrg					currentMode->viewportWidth;
15095b296d0Smrg	    /* this might need to get clamped to some maximum */
15195b296d0Smrg	    currentMode->maxViewportY = currentMode->imageHeight -
15295b296d0Smrg					currentMode->viewportHeight;
15395b296d0Smrg	}
15495b296d0Smrg
15595b296d0Smrg	pMode = pMode->next;
15695b296d0Smrg	if(pMode == firstMode)
15795b296d0Smrg	   break;
15895b296d0Smrg   }
15995b296d0Smrg
16095b296d0Smrg   pTrident->numDGAModes = num;
16195b296d0Smrg   pTrident->DGAModes = modes;
16295b296d0Smrg
16395b296d0Smrg   return DGAInit(pScreen, &TRIDENTDGAFuncs, modes, num);
16495b296d0Smrg}
16595b296d0Smrg
16695b296d0Smrg
16795b296d0Smrgstatic Bool
16895b296d0SmrgTRIDENT_SetMode(
16995b296d0Smrg   ScrnInfoPtr pScrn,
17095b296d0Smrg   DGAModePtr pMode
17195b296d0Smrg){
17295b296d0Smrg   static int OldDisplayWidth[MAXSCREENS];
17395b296d0Smrg   int index = pScrn->pScreen->myNum;
17495b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
17595b296d0Smrg
17695b296d0Smrg   if(!pMode) { /* restore the original mode */
17795b296d0Smrg	/* put the ScreenParameters back */
17895b296d0Smrg
17995b296d0Smrg	pScrn->displayWidth = OldDisplayWidth[index];
18095b296d0Smrg
18195b296d0Smrg        TRIDENTSwitchMode(index, pScrn->currentMode, 0);
18295b296d0Smrg	pTrident->DGAactive = FALSE;
18395b296d0Smrg   } else {
18495b296d0Smrg	if(!pTrident->DGAactive) {  /* save the old parameters */
18595b296d0Smrg	    OldDisplayWidth[index] = pScrn->displayWidth;
18695b296d0Smrg
18795b296d0Smrg	    pTrident->DGAactive = TRUE;
18895b296d0Smrg	}
18995b296d0Smrg
19095b296d0Smrg	pScrn->displayWidth = pMode->bytesPerScanline /
19195b296d0Smrg			      (pMode->bitsPerPixel >> 3);
19295b296d0Smrg
19395b296d0Smrg        TRIDENTSwitchMode(index, pMode->mode, 0);
19495b296d0Smrg   }
19595b296d0Smrg
19695b296d0Smrg   return TRUE;
19795b296d0Smrg}
19895b296d0Smrg
19995b296d0Smrg
20095b296d0Smrg
20195b296d0Smrgstatic int
20295b296d0SmrgTRIDENT_GetViewport(
20395b296d0Smrg  ScrnInfoPtr pScrn
20495b296d0Smrg){
20595b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
20695b296d0Smrg
20795b296d0Smrg    return pTrident->DGAViewportStatus;
20895b296d0Smrg}
20995b296d0Smrg
21095b296d0Smrgstatic void
21195b296d0SmrgTRIDENT_SetViewport(
21295b296d0Smrg   ScrnInfoPtr pScrn,
21395b296d0Smrg   int x, int y,
21495b296d0Smrg   int flags
21595b296d0Smrg){
21695b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
21795b296d0Smrg
21895b296d0Smrg   TRIDENTAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
21995b296d0Smrg   pTrident->DGAViewportStatus = 0;  /* TRIDENTAdjustFrame loops until finished */
22095b296d0Smrg}
22195b296d0Smrg
22295b296d0Smrgstatic void
22395b296d0SmrgTRIDENT_FillRect (
22495b296d0Smrg   ScrnInfoPtr pScrn,
22595b296d0Smrg   int x, int y, int w, int h,
22695b296d0Smrg   unsigned long color
22795b296d0Smrg){
22895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
22995b296d0Smrg
23095b296d0Smrg    if(pTrident->AccelInfoRec) {
23195b296d0Smrg	(*pTrident->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
23295b296d0Smrg	(*pTrident->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
23395b296d0Smrg	SET_SYNC_FLAG(pTrident->AccelInfoRec);
23495b296d0Smrg    }
23595b296d0Smrg}
23695b296d0Smrg
23795b296d0Smrgstatic void
23895b296d0SmrgTRIDENT_Sync(
23995b296d0Smrg   ScrnInfoPtr pScrn
24095b296d0Smrg){
24195b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
24295b296d0Smrg
24395b296d0Smrg    if(pTrident->AccelInfoRec) {
24495b296d0Smrg	(*pTrident->AccelInfoRec->Sync)(pScrn);
24595b296d0Smrg    }
24695b296d0Smrg}
24795b296d0Smrg
24895b296d0Smrgstatic void
24995b296d0SmrgTRIDENT_BlitRect(
25095b296d0Smrg   ScrnInfoPtr pScrn,
25195b296d0Smrg   int srcx, int srcy,
25295b296d0Smrg   int w, int h,
25395b296d0Smrg   int dstx, int dsty
25495b296d0Smrg){
25595b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
25695b296d0Smrg
25795b296d0Smrg    if(pTrident->AccelInfoRec) {
25895b296d0Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
25995b296d0Smrg	int ydir = (srcy < dsty) ? -1 : 1;
26095b296d0Smrg
26195b296d0Smrg	(*pTrident->AccelInfoRec->SetupForScreenToScreenCopy)(
26295b296d0Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
26395b296d0Smrg	(*pTrident->AccelInfoRec->SubsequentScreenToScreenCopy)(
26495b296d0Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
26595b296d0Smrg	SET_SYNC_FLAG(pTrident->AccelInfoRec);
26695b296d0Smrg    }
26795b296d0Smrg}
26895b296d0Smrg
26995b296d0Smrg#if 0
27095b296d0Smrgstatic void
27195b296d0SmrgTRIDENT_BlitTransRect(
27295b296d0Smrg   ScrnInfoPtr pScrn,
27395b296d0Smrg   int srcx, int srcy,
27495b296d0Smrg   int w, int h,
27595b296d0Smrg   int dstx, int dsty,
27695b296d0Smrg   unsigned long color
27795b296d0Smrg){
27895b296d0Smrg  /* this one should be separate since the XAA function would
27995b296d0Smrg     prohibit usage of ~0 as the key */
28095b296d0Smrg}
28195b296d0Smrg#endif
28295b296d0Smrg
28395b296d0Smrgstatic Bool
28495b296d0SmrgTRIDENT_OpenFramebuffer(
28595b296d0Smrg   ScrnInfoPtr pScrn,
28695b296d0Smrg   char **name,
28795b296d0Smrg   unsigned char **mem,
28895b296d0Smrg   int *size,
28995b296d0Smrg   int *offset,
29095b296d0Smrg   int *flags
29195b296d0Smrg){
29295b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
29395b296d0Smrg
29495b296d0Smrg    *name = NULL; 		/* no special device */
29595b296d0Smrg    *mem = (unsigned char*)pTrident->FbAddress;
29695b296d0Smrg    *size = pTrident->FbMapSize;
29795b296d0Smrg    *offset = 0;
29895b296d0Smrg    *flags = DGA_NEED_ROOT;
29995b296d0Smrg
30095b296d0Smrg    return TRUE;
30195b296d0Smrg}
302