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