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
2595b296d0Smrg#ifdef HAVE_CONFIG_H
2695b296d0Smrg#include "config.h"
2795b296d0Smrg#endif
2895b296d0Smrg
2995b296d0Smrg#include "xf86.h"
3095b296d0Smrg#include "xf86_OSproc.h"
3195b296d0Smrg#include "xf86Pci.h"
3295b296d0Smrg#include "trident.h"
3395b296d0Smrg#include "trident_regs.h"
3495b296d0Smrg#include "dgaproc.h"
3595b296d0Smrg
3695b296d0Smrg
3795b296d0Smrgstatic Bool TRIDENT_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
3895b296d0Smrg					int *, int *, int *);
3995b296d0Smrgstatic Bool TRIDENT_SetMode(ScrnInfoPtr, DGAModePtr);
4095b296d0Smrgstatic int  TRIDENT_GetViewport(ScrnInfoPtr);
4195b296d0Smrgstatic void TRIDENT_SetViewport(ScrnInfoPtr, int, int, int);
42eca46af7Smrg#ifdef HAVE_XAA_H
43eca46af7Smrgstatic void TRIDENT_Sync(ScrnInfoPtr);
4495b296d0Smrgstatic void TRIDENT_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
4595b296d0Smrgstatic void TRIDENT_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
4695b296d0Smrg#if 0
4795b296d0Smrgstatic void TRIDENT_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
4895b296d0Smrg					unsigned long);
4995b296d0Smrg#endif
50eca46af7Smrg#endif
5195b296d0Smrg
5295b296d0Smrgstatic
5395b296d0SmrgDGAFunctionRec TRIDENTDGAFuncs = {
5495b296d0Smrg   TRIDENT_OpenFramebuffer,
5595b296d0Smrg   NULL,
5695b296d0Smrg   TRIDENT_SetMode,
5795b296d0Smrg   TRIDENT_SetViewport,
5895b296d0Smrg   TRIDENT_GetViewport,
59eca46af7Smrg#ifdef HAVE_XAA_H
6095b296d0Smrg   TRIDENT_Sync,
6195b296d0Smrg   TRIDENT_FillRect,
6295b296d0Smrg   TRIDENT_BlitRect,
6395b296d0Smrg#if 0
6495b296d0Smrg   TRIDENT_BlitTransRect
6595b296d0Smrg#else
6695b296d0Smrg   NULL
6795b296d0Smrg#endif
68eca46af7Smrg#else
69eca46af7Smrg   NULL, NULL, NULL
70eca46af7Smrg#endif
7195b296d0Smrg};
7295b296d0Smrg
7395b296d0SmrgBool
7495b296d0SmrgTRIDENTDGAInit(ScreenPtr pScreen)
7595b296d0Smrg{
76eca46af7Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
7795b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
7895b296d0Smrg   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
7995b296d0Smrg   DisplayModePtr pMode, firstMode;
8095b296d0Smrg   int Bpp = pScrn->bitsPerPixel >> 3;
8195b296d0Smrg   int num = 0;
8295b296d0Smrg   Bool oneMore;
8395b296d0Smrg
8495b296d0Smrg   pMode = firstMode = pScrn->modes;
8595b296d0Smrg
8695b296d0Smrg   while(pMode) {
8795b296d0Smrg
8895b296d0Smrg	if(0 /*pScrn->displayWidth != pMode->HDisplay*/) {
8914330f12Smrg	    newmodes = realloc(modes, (num + 2) * sizeof(DGAModeRec));
9095b296d0Smrg	    oneMore = TRUE;
9195b296d0Smrg	} else {
9214330f12Smrg	    newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
9395b296d0Smrg	    oneMore = FALSE;
9495b296d0Smrg	}
9595b296d0Smrg
9695b296d0Smrg	if(!newmodes) {
9714330f12Smrg	   free(modes);
9895b296d0Smrg	   return FALSE;
9995b296d0Smrg	}
10095b296d0Smrg	modes = newmodes;
10195b296d0Smrg
10295b296d0SmrgSECOND_PASS:
10395b296d0Smrg
10495b296d0Smrg	currentMode = modes + num;
10595b296d0Smrg	num++;
10695b296d0Smrg
10795b296d0Smrg	currentMode->mode = pMode;
10895b296d0Smrg	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
109eca46af7Smrg#ifdef HAVE_XAA_H
11095b296d0Smrg	if(!pTrident->NoAccel)
11195b296d0Smrg	   currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
112eca46af7Smrg#endif
11395b296d0Smrg	if(pMode->Flags & V_DBLSCAN)
11495b296d0Smrg	   currentMode->flags |= DGA_DOUBLESCAN;
11595b296d0Smrg	if(pMode->Flags & V_INTERLACE)
11695b296d0Smrg	   currentMode->flags |= DGA_INTERLACED;
11795b296d0Smrg	currentMode->byteOrder = pScrn->imageByteOrder;
11895b296d0Smrg	currentMode->depth = pScrn->depth;
11995b296d0Smrg	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
12095b296d0Smrg	currentMode->red_mask = pScrn->mask.red;
12195b296d0Smrg	currentMode->green_mask = pScrn->mask.green;
12295b296d0Smrg	currentMode->blue_mask = pScrn->mask.blue;
12395b296d0Smrg	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
12495b296d0Smrg	currentMode->viewportWidth = pMode->HDisplay;
12595b296d0Smrg	currentMode->viewportHeight = pMode->VDisplay;
12695b296d0Smrg	currentMode->xViewportStep = 1;
12795b296d0Smrg	currentMode->yViewportStep = 1;
12895b296d0Smrg	currentMode->viewportFlags = DGA_FLIP_RETRACE;
12995b296d0Smrg	currentMode->offset = 0;
13095b296d0Smrg	currentMode->address = pTrident->FbBase;
13195b296d0Smrg
13295b296d0Smrg	if(oneMore) { /* first one is narrow width */
13395b296d0Smrg	    currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L;
13495b296d0Smrg	    currentMode->imageWidth = pMode->HDisplay;
13595b296d0Smrg	    currentMode->imageHeight =  pMode->VDisplay;
13695b296d0Smrg	    currentMode->pixmapWidth = currentMode->imageWidth;
13795b296d0Smrg	    currentMode->pixmapHeight = currentMode->imageHeight;
13895b296d0Smrg	    currentMode->maxViewportX = currentMode->imageWidth -
13995b296d0Smrg					currentMode->viewportWidth;
14095b296d0Smrg	    /* this might need to get clamped to some maximum */
14195b296d0Smrg	    currentMode->maxViewportY = currentMode->imageHeight -
14295b296d0Smrg					currentMode->viewportHeight;
14395b296d0Smrg	    oneMore = FALSE;
14495b296d0Smrg	    goto SECOND_PASS;
14595b296d0Smrg	} else {
14695b296d0Smrg	    currentMode->bytesPerScanline =
14795b296d0Smrg			((pScrn->displayWidth * Bpp) + 3) & ~3L;
14895b296d0Smrg	    currentMode->imageWidth = pScrn->displayWidth;
14995b296d0Smrg	    currentMode->imageHeight =  pMode->VDisplay;
15095b296d0Smrg	    currentMode->pixmapWidth = currentMode->imageWidth;
15195b296d0Smrg	    currentMode->pixmapHeight = currentMode->imageHeight;
15295b296d0Smrg	    currentMode->maxViewportX = currentMode->imageWidth -
15395b296d0Smrg					currentMode->viewportWidth;
15495b296d0Smrg	    /* this might need to get clamped to some maximum */
15595b296d0Smrg	    currentMode->maxViewportY = currentMode->imageHeight -
15695b296d0Smrg					currentMode->viewportHeight;
15795b296d0Smrg	}
15895b296d0Smrg
15995b296d0Smrg	pMode = pMode->next;
16095b296d0Smrg	if(pMode == firstMode)
16195b296d0Smrg	   break;
16295b296d0Smrg   }
16395b296d0Smrg
16495b296d0Smrg   pTrident->numDGAModes = num;
16595b296d0Smrg   pTrident->DGAModes = modes;
16695b296d0Smrg
16795b296d0Smrg   return DGAInit(pScreen, &TRIDENTDGAFuncs, modes, num);
16895b296d0Smrg}
16995b296d0Smrg
17095b296d0Smrg
17195b296d0Smrgstatic Bool
17295b296d0SmrgTRIDENT_SetMode(
17395b296d0Smrg   ScrnInfoPtr pScrn,
17495b296d0Smrg   DGAModePtr pMode
17595b296d0Smrg){
17695b296d0Smrg   static int OldDisplayWidth[MAXSCREENS];
17795b296d0Smrg   int index = pScrn->pScreen->myNum;
17895b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
17995b296d0Smrg
18095b296d0Smrg   if(!pMode) { /* restore the original mode */
18195b296d0Smrg	/* put the ScreenParameters back */
18295b296d0Smrg
18395b296d0Smrg	pScrn->displayWidth = OldDisplayWidth[index];
18495b296d0Smrg
185eca46af7Smrg        TRIDENTSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
18695b296d0Smrg	pTrident->DGAactive = FALSE;
18795b296d0Smrg   } else {
18895b296d0Smrg	if(!pTrident->DGAactive) {  /* save the old parameters */
18995b296d0Smrg	    OldDisplayWidth[index] = pScrn->displayWidth;
19095b296d0Smrg
19195b296d0Smrg	    pTrident->DGAactive = TRUE;
19295b296d0Smrg	}
19395b296d0Smrg
19495b296d0Smrg	pScrn->displayWidth = pMode->bytesPerScanline /
19595b296d0Smrg			      (pMode->bitsPerPixel >> 3);
19695b296d0Smrg
197eca46af7Smrg        TRIDENTSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
19895b296d0Smrg   }
19995b296d0Smrg
20095b296d0Smrg   return TRUE;
20195b296d0Smrg}
20295b296d0Smrg
20395b296d0Smrg
20495b296d0Smrg
20595b296d0Smrgstatic int
20695b296d0SmrgTRIDENT_GetViewport(
20795b296d0Smrg  ScrnInfoPtr pScrn
20895b296d0Smrg){
20995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
21095b296d0Smrg
21195b296d0Smrg    return pTrident->DGAViewportStatus;
21295b296d0Smrg}
21395b296d0Smrg
21495b296d0Smrgstatic void
21595b296d0SmrgTRIDENT_SetViewport(
21695b296d0Smrg   ScrnInfoPtr pScrn,
21795b296d0Smrg   int x, int y,
21895b296d0Smrg   int flags
21995b296d0Smrg){
22095b296d0Smrg   TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
22195b296d0Smrg
222eca46af7Smrg   TRIDENTAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
22395b296d0Smrg   pTrident->DGAViewportStatus = 0;  /* TRIDENTAdjustFrame loops until finished */
22495b296d0Smrg}
22595b296d0Smrg
226eca46af7Smrg#ifdef HAVE_XAA_H
22795b296d0Smrgstatic void
22895b296d0SmrgTRIDENT_FillRect (
22995b296d0Smrg   ScrnInfoPtr pScrn,
23095b296d0Smrg   int x, int y, int w, int h,
23195b296d0Smrg   unsigned long color
23295b296d0Smrg){
23395b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
23495b296d0Smrg
23595b296d0Smrg    if(pTrident->AccelInfoRec) {
23695b296d0Smrg	(*pTrident->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
23795b296d0Smrg	(*pTrident->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
23895b296d0Smrg	SET_SYNC_FLAG(pTrident->AccelInfoRec);
23995b296d0Smrg    }
24095b296d0Smrg}
24195b296d0Smrg
24295b296d0Smrgstatic void
24395b296d0SmrgTRIDENT_Sync(
24495b296d0Smrg   ScrnInfoPtr pScrn
24595b296d0Smrg){
24695b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
24795b296d0Smrg
24895b296d0Smrg    if(pTrident->AccelInfoRec) {
24995b296d0Smrg	(*pTrident->AccelInfoRec->Sync)(pScrn);
25095b296d0Smrg    }
25195b296d0Smrg}
25295b296d0Smrg
25395b296d0Smrgstatic void
25495b296d0SmrgTRIDENT_BlitRect(
25595b296d0Smrg   ScrnInfoPtr pScrn,
25695b296d0Smrg   int srcx, int srcy,
25795b296d0Smrg   int w, int h,
25895b296d0Smrg   int dstx, int dsty
25995b296d0Smrg){
26095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
26195b296d0Smrg
26295b296d0Smrg    if(pTrident->AccelInfoRec) {
26395b296d0Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
26495b296d0Smrg	int ydir = (srcy < dsty) ? -1 : 1;
26595b296d0Smrg
26695b296d0Smrg	(*pTrident->AccelInfoRec->SetupForScreenToScreenCopy)(
26795b296d0Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
26895b296d0Smrg	(*pTrident->AccelInfoRec->SubsequentScreenToScreenCopy)(
26995b296d0Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
27095b296d0Smrg	SET_SYNC_FLAG(pTrident->AccelInfoRec);
27195b296d0Smrg    }
27295b296d0Smrg}
27395b296d0Smrg
27495b296d0Smrg#if 0
27595b296d0Smrgstatic void
27695b296d0SmrgTRIDENT_BlitTransRect(
27795b296d0Smrg   ScrnInfoPtr pScrn,
27895b296d0Smrg   int srcx, int srcy,
27995b296d0Smrg   int w, int h,
28095b296d0Smrg   int dstx, int dsty,
28195b296d0Smrg   unsigned long color
28295b296d0Smrg){
28395b296d0Smrg  /* this one should be separate since the XAA function would
28495b296d0Smrg     prohibit usage of ~0 as the key */
28595b296d0Smrg}
28695b296d0Smrg#endif
287eca46af7Smrg#endif
28895b296d0Smrg
28995b296d0Smrgstatic Bool
29095b296d0SmrgTRIDENT_OpenFramebuffer(
29195b296d0Smrg   ScrnInfoPtr pScrn,
29295b296d0Smrg   char **name,
29395b296d0Smrg   unsigned char **mem,
29495b296d0Smrg   int *size,
29595b296d0Smrg   int *offset,
29695b296d0Smrg   int *flags
29795b296d0Smrg){
29895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
29995b296d0Smrg
30095b296d0Smrg    *name = NULL; 		/* no special device */
30195b296d0Smrg    *mem = (unsigned char*)pTrident->FbAddress;
30295b296d0Smrg    *size = pTrident->FbMapSize;
30395b296d0Smrg    *offset = 0;
30495b296d0Smrg    *flags = DGA_NEED_ROOT;
30595b296d0Smrg
30695b296d0Smrg    return TRUE;
30795b296d0Smrg}
308