cir_dga.c revision 76888252
176888252Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_dga.c,v 1.5 2001/02/15 17:39:27 eich Exp $ */
276888252Smrg/*
376888252Smrg * Copyright 2000 by Egbert Eich
476888252Smrg *
576888252Smrg * Permission to use, copy, modify, distribute, and sell this software and its
676888252Smrg * documentation for any purpose is hereby granted without fee, provided that
776888252Smrg * the above copyright notice appear in all copies and that both that
876888252Smrg * copyright notice and this permission notice appear in supporting
976888252Smrg * documentation, and that the name of Alan Hourihane not be used in
1076888252Smrg * advertising or publicity pertaining to distribution of the software without
1176888252Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1276888252Smrg * about the suitability of this software for any purpose.  It is provided
1376888252Smrg * "as is" without express or implied warranty.
1476888252Smrg *
1576888252Smrg * EGBERT EICH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1676888252Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1776888252Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1876888252Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1976888252Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2076888252Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2176888252Smrg * PERFORMANCE OF THIS SOFTWARE.
2276888252Smrg *
2376888252Smrg * Authors:  Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
2476888252Smrg *           by: Egbert Eich
2576888252Smrg */
2676888252Smrg
2776888252Smrg#ifdef HAVE_CONFIG_H
2876888252Smrg#include "config.h"
2976888252Smrg#endif
3076888252Smrg
3176888252Smrg#include "xf86.h"
3276888252Smrg#include "xf86_OSproc.h"
3376888252Smrg#include "xf86Pci.h"
3476888252Smrg#include "xf86PciInfo.h"
3576888252Smrg#include "xaa.h"
3676888252Smrg#include "xaalocal.h"
3776888252Smrg#include "vgaHW.h"
3876888252Smrg#include "cir.h"
3976888252Smrg#include "dgaproc.h"
4076888252Smrg
4176888252Smrgstatic Bool Cir_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
4276888252Smrg				  int *, int *, int *);
4376888252Smrgstatic Bool Cir_SetMode(ScrnInfoPtr, DGAModePtr);
4476888252Smrgstatic void Cir_Sync(ScrnInfoPtr);
4576888252Smrgstatic int  Cir_GetViewport(ScrnInfoPtr);
4676888252Smrgstatic void Cir_SetViewport(ScrnInfoPtr, int, int, int);
4776888252Smrgstatic void Cir_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
4876888252Smrgstatic void Cir_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
4976888252Smrg/*
5076888252Smrgstatic void Cir_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
5176888252Smrg                                unsigned long);
5276888252Smrg*/
5376888252Smrg
5476888252Smrgstatic
5576888252SmrgDGAFunctionRec CirDGAFuncs = {
5676888252Smrg   Cir_OpenFramebuffer,
5776888252Smrg   NULL, /* Cir_CloseFramebuffer */
5876888252Smrg   Cir_SetMode,
5976888252Smrg   Cir_SetViewport,
6076888252Smrg   Cir_GetViewport,
6176888252Smrg   Cir_Sync,
6276888252Smrg   Cir_FillRect,
6376888252Smrg   Cir_BlitRect,
6476888252Smrg   NULL  /* Cir_BlitTransRect */
6576888252Smrg};
6676888252Smrg
6776888252Smrg
6876888252Smrg
6976888252Smrg
7076888252SmrgBool
7176888252SmrgCirDGAInit(ScreenPtr pScreen)
7276888252Smrg{
7376888252Smrg  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
7476888252Smrg  CirPtr pCir = CIRPTR(pScrn);
7576888252Smrg  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
7676888252Smrg  DisplayModePtr pMode, firstMode;
7776888252Smrg  int Bpp = pScrn->bitsPerPixel >> 3;
7876888252Smrg  int num = 0;
7976888252Smrg  int imlines =  (pScrn->videoRam * 1024) /
8076888252Smrg       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
8176888252Smrg
8276888252Smrg
8376888252Smrg  if (!pCir->DGAnumModes) {
8476888252Smrg    pMode = firstMode = pScrn->modes;
8576888252Smrg    while (pMode) {
8676888252Smrg      newmodes = xrealloc(modes, (num + 1) * sizeof (DGAModeRec));
8776888252Smrg      if (!newmodes) {
8876888252Smrg	xfree(modes);
8976888252Smrg	return FALSE;
9076888252Smrg      }
9176888252Smrg      modes = newmodes;
9276888252Smrg      currentMode = modes + num;
9376888252Smrg      num++;
9476888252Smrg      (void)memset(currentMode, 1, sizeof(DGAModeRec));
9576888252Smrg      currentMode->mode = pMode;
9676888252Smrg      currentMode->flags = DGA_PIXMAP_AVAILABLE
9776888252Smrg	  | ((!pCir->NoAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
9876888252Smrg      if (pMode->Flags & V_DBLSCAN)
9976888252Smrg	currentMode->flags |= DGA_DOUBLESCAN;
10076888252Smrg      if(pMode->Flags & V_INTERLACE)
10176888252Smrg	currentMode->flags |= DGA_INTERLACED;
10276888252Smrg      currentMode->byteOrder        = pScrn->imageByteOrder;
10376888252Smrg      currentMode->depth            = pScrn->depth;
10476888252Smrg      currentMode->bitsPerPixel     = pScrn->bitsPerPixel;
10576888252Smrg      currentMode->red_mask         = pScrn->mask.red;
10676888252Smrg      currentMode->green_mask       = pScrn->mask.green;
10776888252Smrg      currentMode->blue_mask        = pScrn->mask.blue;
10876888252Smrg      currentMode->visualClass      = (Bpp == 1) ? PseudoColor : TrueColor;
10976888252Smrg      currentMode->viewportWidth    = pMode->HDisplay;
11076888252Smrg      currentMode->viewportHeight   = pMode->VDisplay;
11176888252Smrg      currentMode->xViewportStep    = 1; /*  The granularity of x and y pos. */
11276888252Smrg      currentMode->yViewportStep    = 1;
11376888252Smrg      currentMode->viewportFlags    = 0 /*DGA_FLIP_RETRACE*/;
11476888252Smrg      currentMode->offset           = 0;
11576888252Smrg      currentMode->address          = pCir->FbBase;
11676888252Smrg      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
11776888252Smrg      currentMode->pixmapWidth      = currentMode->imageWidth
11876888252Smrg	                               = pScrn->displayWidth;
11976888252Smrg      currentMode->pixmapHeight     = currentMode->imageHeight = imlines;
12076888252Smrg      currentMode->maxViewportX     = currentMode->imageWidth -
12176888252Smrg                                      currentMode->viewportWidth;
12276888252Smrg      /* this might need to get clamped to some maximum */
12376888252Smrg      currentMode->maxViewportY     = currentMode->imageHeight -
12476888252Smrg                                      currentMode->viewportHeight;
12576888252Smrg
12676888252Smrg      pMode = pMode->next;
12776888252Smrg      if(pMode == firstMode)
12876888252Smrg	break;
12976888252Smrg    }
13076888252Smrg    pCir->DGAnumModes = num;
13176888252Smrg    pCir->DGAModes = modes;
13276888252Smrg  }
13376888252Smrg  return DGAInit(pScreen, &CirDGAFuncs, pCir->DGAModes, pCir->DGAnumModes);
13476888252Smrg}
13576888252Smrg
13676888252Smrgstatic Bool
13776888252SmrgCir_OpenFramebuffer(
13876888252Smrg   ScrnInfoPtr pScrn,
13976888252Smrg   char **name,
14076888252Smrg   unsigned char **mem,
14176888252Smrg   int *size,
14276888252Smrg   int *offset,
14376888252Smrg   int *flags
14476888252Smrg){
14576888252Smrg    CirPtr pCir = CIRPTR(pScrn);
14676888252Smrg
14776888252Smrg    *name = NULL; 		/* no special device */
14876888252Smrg    *mem = (unsigned char*)(long)pCir->FbAddress;
14976888252Smrg    *size = pCir->FbMapSize;
15076888252Smrg    *offset = 0;                /* Always */
15176888252Smrg    *flags = 0;                 /* Root permissions OS-dependent */
15276888252Smrg
15376888252Smrg    return TRUE;
15476888252Smrg}
15576888252Smrg
15676888252Smrg
15776888252Smrgstatic Bool
15876888252SmrgCir_SetMode(
15976888252Smrg   ScrnInfoPtr pScrn,
16076888252Smrg   DGAModePtr pMode
16176888252Smrg){
16276888252Smrg   CirPtr pCir = CIRPTR(pScrn);
16376888252Smrg   static int OldDisplayWidth[MAXSCREENS];
16476888252Smrg   int index = pScrn->pScreen->myNum;
16576888252Smrg   Bool ret = FALSE;
16676888252Smrg
16776888252Smrg   if(!pMode) { /* restore the original mode */
16876888252Smrg	/* put the ScreenParameters back */
16976888252Smrg	pScrn->displayWidth = OldDisplayWidth[index];
17076888252Smrg	ret = pCir->DGAModeInit(xf86Screens[index], pScrn->currentMode);
17176888252Smrg	pCir->DGAactive = FALSE;
17276888252Smrg   } else {
17376888252Smrg	if(!pCir->DGAactive) {  /* save the old parameters */
17476888252Smrg	    OldDisplayWidth[index] = pScrn->displayWidth;
17576888252Smrg
17676888252Smrg	    pCir->DGAactive = TRUE;
17776888252Smrg	}
17876888252Smrg	pScrn->displayWidth = pMode->bytesPerScanline /
17976888252Smrg			      (pMode->bitsPerPixel >> 3);
18076888252Smrg
18176888252Smrg	ret = pCir->DGAModeInit(xf86Screens[index], pMode->mode);
18276888252Smrg   }
18376888252Smrg   return ret;
18476888252Smrg}
18576888252Smrg
18676888252Smrgstatic void
18776888252SmrgCir_SetViewport(
18876888252Smrg   ScrnInfoPtr pScrn,
18976888252Smrg   int x, int y,
19076888252Smrg   int flags
19176888252Smrg){
19276888252Smrg   CirPtr pCir = CIRPTR(pScrn);
19376888252Smrg   vgaHWPtr hwp = VGAHWPTR(pScrn);
19476888252Smrg
19576888252Smrg   pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
19676888252Smrg
19776888252Smrg   while((hwp->readST01(hwp) & 0x08));
19876888252Smrg   while(!(hwp->readST01(hwp) & 0x08));
19976888252Smrg
20076888252Smrg   pCir->DGAViewportStatus = 0;  /* AdjustFrame loops until finished */
20176888252Smrg}
20276888252Smrg
20376888252Smrgstatic int
20476888252SmrgCir_GetViewport(
20576888252Smrg  ScrnInfoPtr pScrn
20676888252Smrg){
20776888252Smrg    CirPtr pCir = CIRPTR(pScrn);
20876888252Smrg
20976888252Smrg    return pCir->DGAViewportStatus;
21076888252Smrg}
21176888252Smrg
21276888252Smrg
21376888252Smrg
21476888252Smrgstatic void
21576888252SmrgCir_Sync(
21676888252Smrg   ScrnInfoPtr pScrn
21776888252Smrg){
21876888252Smrg    CirPtr pCir = CIRPTR(pScrn);
21976888252Smrg
22076888252Smrg    if(pCir->AccelInfoRec) {
22176888252Smrg	(*pCir->AccelInfoRec->Sync)(pScrn);
22276888252Smrg    }
22376888252Smrg}
22476888252Smrg
22576888252Smrgstatic void
22676888252SmrgCir_FillRect (
22776888252Smrg   ScrnInfoPtr pScrn,
22876888252Smrg   int x, int y, int w, int h,
22976888252Smrg   unsigned long color
23076888252Smrg){
23176888252Smrg    CirPtr pCir = CIRPTR(pScrn);
23276888252Smrg
23376888252Smrg    if(pCir->AccelInfoRec) {
23476888252Smrg	(*pCir->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
23576888252Smrg	(*pCir->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
23676888252Smrg	SET_SYNC_FLAG(pCir->AccelInfoRec);
23776888252Smrg    }
23876888252Smrg}
23976888252Smrg
24076888252Smrgstatic void
24176888252SmrgCir_BlitRect(
24276888252Smrg   ScrnInfoPtr pScrn,
24376888252Smrg   int srcx, int srcy,
24476888252Smrg   int w, int h,
24576888252Smrg   int dstx, int dsty
24676888252Smrg){
24776888252Smrg    CirPtr pCir = CIRPTR(pScrn);
24876888252Smrg
24976888252Smrg    if(pCir->AccelInfoRec) {
25076888252Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
25176888252Smrg	int ydir = (srcy < dsty) ? -1 : 1;
25276888252Smrg
25376888252Smrg	(*pCir->AccelInfoRec->SetupForScreenToScreenCopy)(
25476888252Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
25576888252Smrg	(*pCir->AccelInfoRec->SubsequentScreenToScreenCopy)(
25676888252Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
25776888252Smrg	SET_SYNC_FLAG(pCir->AccelInfoRec);
25876888252Smrg    }
25976888252Smrg}
260