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