cir_dga.c revision 1ae1b5e8
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_dga.c,v 1.5 2001/02/15 17:39:27 eich Exp $ */
2/*
3 * Copyright 2000 by Egbert Eich
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Alan Hourihane not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission.  Alan Hourihane makes no representations
12 * about the suitability of this software for any purpose.  It is provided
13 * "as is" without express or implied warranty.
14 *
15 * EGBERT EICH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Authors:  Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
24 *           by: Egbert Eich
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "xf86.h"
32#include "xf86_OSproc.h"
33#include "xf86Pci.h"
34#include "xf86PciInfo.h"
35#include "xaa.h"
36#include "xaalocal.h"
37#include "vgaHW.h"
38#include "cir.h"
39#include "dgaproc.h"
40
41static Bool Cir_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
42				  int *, int *, int *);
43static Bool Cir_SetMode(ScrnInfoPtr, DGAModePtr);
44static void Cir_Sync(ScrnInfoPtr);
45static int  Cir_GetViewport(ScrnInfoPtr);
46static void Cir_SetViewport(ScrnInfoPtr, int, int, int);
47static void Cir_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
48static void Cir_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
49/*
50static void Cir_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
51                                unsigned long);
52*/
53
54static
55DGAFunctionRec CirDGAFuncs = {
56   Cir_OpenFramebuffer,
57   NULL, /* Cir_CloseFramebuffer */
58   Cir_SetMode,
59   Cir_SetViewport,
60   Cir_GetViewport,
61   Cir_Sync,
62   Cir_FillRect,
63   Cir_BlitRect,
64   NULL  /* Cir_BlitTransRect */
65};
66
67
68
69
70_X_EXPORT Bool
71CirDGAInit(ScreenPtr pScreen)
72{
73  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
74  CirPtr pCir = CIRPTR(pScrn);
75  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
76  DisplayModePtr pMode, firstMode;
77  int Bpp = pScrn->bitsPerPixel >> 3;
78  int num = 0;
79  int imlines =  (pScrn->videoRam * 1024) /
80       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
81
82
83  if (!pCir->DGAnumModes) {
84    pMode = firstMode = pScrn->modes;
85    while (pMode) {
86      newmodes = xrealloc(modes, (num + 1) * sizeof (DGAModeRec));
87      if (!newmodes) {
88	xfree(modes);
89	return FALSE;
90      }
91      modes = newmodes;
92      currentMode = modes + num;
93      num++;
94      (void)memset(currentMode, 1, sizeof(DGAModeRec));
95      currentMode->mode = pMode;
96      currentMode->flags = DGA_PIXMAP_AVAILABLE
97	  | ((!pCir->NoAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
98      if (pMode->Flags & V_DBLSCAN)
99	currentMode->flags |= DGA_DOUBLESCAN;
100      if(pMode->Flags & V_INTERLACE)
101	currentMode->flags |= DGA_INTERLACED;
102      currentMode->byteOrder        = pScrn->imageByteOrder;
103      currentMode->depth            = pScrn->depth;
104      currentMode->bitsPerPixel     = pScrn->bitsPerPixel;
105      currentMode->red_mask         = pScrn->mask.red;
106      currentMode->green_mask       = pScrn->mask.green;
107      currentMode->blue_mask        = pScrn->mask.blue;
108      currentMode->visualClass      = (Bpp == 1) ? PseudoColor : TrueColor;
109      currentMode->viewportWidth    = pMode->HDisplay;
110      currentMode->viewportHeight   = pMode->VDisplay;
111      currentMode->xViewportStep    = 1; /*  The granularity of x and y pos. */
112      currentMode->yViewportStep    = 1;
113      currentMode->viewportFlags    = 0 /*DGA_FLIP_RETRACE*/;
114      currentMode->offset           = 0;
115      currentMode->address          = pCir->FbBase;
116      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
117      currentMode->pixmapWidth      = currentMode->imageWidth
118	                               = pScrn->displayWidth;
119      currentMode->pixmapHeight     = currentMode->imageHeight = imlines;
120      currentMode->maxViewportX     = currentMode->imageWidth -
121                                      currentMode->viewportWidth;
122      /* this might need to get clamped to some maximum */
123      currentMode->maxViewportY     = currentMode->imageHeight -
124                                      currentMode->viewportHeight;
125
126      pMode = pMode->next;
127      if(pMode == firstMode)
128	break;
129    }
130    pCir->DGAnumModes = num;
131    pCir->DGAModes = modes;
132  }
133  return DGAInit(pScreen, &CirDGAFuncs, pCir->DGAModes, pCir->DGAnumModes);
134}
135
136static Bool
137Cir_OpenFramebuffer(
138   ScrnInfoPtr pScrn,
139   char **name,
140   unsigned char **mem,
141   int *size,
142   int *offset,
143   int *flags
144){
145    CirPtr pCir = CIRPTR(pScrn);
146
147    *name = NULL; 		/* no special device */
148    *mem = (unsigned char*)(long)pCir->FbAddress;
149    *size = pCir->FbMapSize;
150    *offset = 0;                /* Always */
151    *flags = 0;                 /* Root permissions OS-dependent */
152
153    return TRUE;
154}
155
156
157static Bool
158Cir_SetMode(
159   ScrnInfoPtr pScrn,
160   DGAModePtr pMode
161){
162   CirPtr pCir = CIRPTR(pScrn);
163   static int OldDisplayWidth[MAXSCREENS];
164   int index = pScrn->pScreen->myNum;
165   Bool ret = FALSE;
166
167   if(!pMode) { /* restore the original mode */
168	/* put the ScreenParameters back */
169	pScrn->displayWidth = OldDisplayWidth[index];
170	ret = pCir->DGAModeInit(xf86Screens[index], pScrn->currentMode);
171	pCir->DGAactive = FALSE;
172   } else {
173	if(!pCir->DGAactive) {  /* save the old parameters */
174	    OldDisplayWidth[index] = pScrn->displayWidth;
175
176	    pCir->DGAactive = TRUE;
177	}
178	pScrn->displayWidth = pMode->bytesPerScanline /
179			      (pMode->bitsPerPixel >> 3);
180
181	ret = pCir->DGAModeInit(xf86Screens[index], pMode->mode);
182   }
183   return ret;
184}
185
186static void
187Cir_SetViewport(
188   ScrnInfoPtr pScrn,
189   int x, int y,
190   int flags
191){
192   CirPtr pCir = CIRPTR(pScrn);
193   vgaHWPtr hwp = VGAHWPTR(pScrn);
194
195   pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
196
197   while((hwp->readST01(hwp) & 0x08));
198   while(!(hwp->readST01(hwp) & 0x08));
199
200   pCir->DGAViewportStatus = 0;  /* AdjustFrame loops until finished */
201}
202
203static int
204Cir_GetViewport(
205  ScrnInfoPtr pScrn
206){
207    CirPtr pCir = CIRPTR(pScrn);
208
209    return pCir->DGAViewportStatus;
210}
211
212
213
214static void
215Cir_Sync(
216   ScrnInfoPtr pScrn
217){
218    CirPtr pCir = CIRPTR(pScrn);
219
220    if(pCir->AccelInfoRec) {
221	(*pCir->AccelInfoRec->Sync)(pScrn);
222    }
223}
224
225static void
226Cir_FillRect (
227   ScrnInfoPtr pScrn,
228   int x, int y, int w, int h,
229   unsigned long color
230){
231    CirPtr pCir = CIRPTR(pScrn);
232
233    if(pCir->AccelInfoRec) {
234	(*pCir->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
235	(*pCir->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
236	SET_SYNC_FLAG(pCir->AccelInfoRec);
237    }
238}
239
240static void
241Cir_BlitRect(
242   ScrnInfoPtr pScrn,
243   int srcx, int srcy,
244   int w, int h,
245   int dstx, int dsty
246){
247    CirPtr pCir = CIRPTR(pScrn);
248
249    if(pCir->AccelInfoRec) {
250	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
251	int ydir = (srcy < dsty) ? -1 : 1;
252
253	(*pCir->AccelInfoRec->SetupForScreenToScreenCopy)(
254		pScrn, xdir, ydir, GXcopy, ~0, -1);
255	(*pCir->AccelInfoRec->SubsequentScreenToScreenCopy)(
256		pScrn, srcx, srcy, dstx, dsty, w, h);
257	SET_SYNC_FLAG(pCir->AccelInfoRec);
258    }
259}
260