neo_dga.c revision 3f6d0e1d
1/*
2 * Copyright 2000 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 "xf86PciInfo.h"
33#include "neo.h"
34#include "neo_reg.h"
35#include "dgaproc.h"
36#include "vgaHW.h"
37
38static Bool NEO_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
39					int *, int *, int *);
40static Bool NEO_SetMode(ScrnInfoPtr, DGAModePtr);
41static void NEO_Sync(ScrnInfoPtr);
42static int  NEO_GetViewport(ScrnInfoPtr);
43static void NEO_SetViewport(ScrnInfoPtr, int, int, int);
44#ifdef HAVE_XAA_H
45static void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
46static void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
47#if 0
48static void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
49					unsigned long);
50#endif
51#endif
52
53static
54DGAFunctionRec NEODGAFuncs = {
55   NEO_OpenFramebuffer,
56   NULL,
57   NEO_SetMode,
58   NEO_SetViewport,
59   NEO_GetViewport,
60   NEO_Sync,
61#ifdef HAVE_XAA_H
62   NEO_FillRect,
63   NEO_BlitRect,
64#if 0
65   NEO_BlitTransRect
66#else
67   NULL
68#endif
69#else
70   NULL, NULL, NULL
71#endif
72};
73
74Bool
75NEODGAInit(ScreenPtr pScreen)
76{
77   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
78   NEOPtr pNEO = NEOPTR(pScrn);
79   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
80   DisplayModePtr pMode, firstMode;
81   int Bpp = pScrn->bitsPerPixel >> 3;
82   int num = 0, imlines, pixlines;
83
84   imlines =  (pScrn->videoRam * 1024) /
85      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
86
87   pixlines =  (imlines > 1024 && !pNEO->noAccel)  ? 1024 : imlines;
88
89   pMode = firstMode = pScrn->modes;
90
91   while(pMode) {
92
93	newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
94
95	if(!newmodes) {
96	   free(modes);
97	   return FALSE;
98	}
99	modes = newmodes;
100
101	currentMode = modes + num;
102	num++;
103
104	currentMode->mode = pMode;
105	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
106#ifdef HAVE_XAA_H
107	if (!pNEO->noAccel)
108	    currentMode->flags |= (DGA_FILL_RECT | DGA_BLIT_RECT);
109#endif
110	if(pMode->Flags & V_DBLSCAN)
111	   currentMode->flags |= DGA_DOUBLESCAN;
112	if(pMode->Flags & V_INTERLACE)
113	   currentMode->flags |= DGA_INTERLACED;
114	currentMode->byteOrder = pScrn->imageByteOrder;
115	currentMode->depth = pScrn->depth;
116	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
117	currentMode->red_mask = pScrn->mask.red;
118	currentMode->green_mask = pScrn->mask.green;
119	currentMode->blue_mask = pScrn->mask.blue;
120	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
121	currentMode->viewportWidth = pMode->HDisplay;
122	currentMode->viewportHeight = pMode->VDisplay;
123	currentMode->xViewportStep = 1;
124	currentMode->yViewportStep = 1;
125	currentMode->viewportFlags = DGA_FLIP_RETRACE;
126	currentMode->offset = 0;
127	currentMode->address = pNEO->NeoFbBase;
128
129	currentMode->bytesPerScanline =
130			((pScrn->displayWidth * Bpp) + 3) & ~3L;
131	currentMode->imageWidth = pScrn->displayWidth;
132	currentMode->imageHeight =  imlines;
133	currentMode->pixmapWidth = currentMode->imageWidth;
134	currentMode->pixmapHeight = pixlines;
135	currentMode->maxViewportX = currentMode->imageWidth -
136					currentMode->viewportWidth;
137	currentMode->maxViewportY = currentMode->imageHeight -
138					currentMode->viewportHeight;
139
140	pMode = pMode->next;
141	if(pMode == firstMode)
142	   break;
143   }
144
145   pNEO->numDGAModes = num;
146   pNEO->DGAModes = modes;
147
148   return DGAInit(pScreen, &NEODGAFuncs, modes, num);
149}
150
151static DisplayModePtr NEOSavedDGAModes[MAXSCREENS];
152
153static Bool
154NEO_SetMode(
155   ScrnInfoPtr pScrn,
156   DGAModePtr pMode
157){
158   int index = pScrn->pScreen->myNum;
159   NEOPtr pNEO = NEOPTR(pScrn);
160
161   if(!pMode) { /* restore the original mode */
162 	if(pNEO->DGAactive) {
163	    pScrn->currentMode = NEOSavedDGAModes[index];
164            NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
165	    NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
166 	    pNEO->DGAactive = FALSE;
167	}
168   } else {
169	if(!pNEO->DGAactive) {  /* save the old parameters */
170	    NEOSavedDGAModes[index] = pScrn->currentMode;
171	    pNEO->DGAactive = TRUE;
172	}
173
174        NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
175   }
176
177   return TRUE;
178}
179
180static int
181NEO_GetViewport(
182  ScrnInfoPtr pScrn
183){
184    NEOPtr pNEO = NEOPTR(pScrn);
185
186    return pNEO->DGAViewportStatus;
187}
188
189static void
190NEO_SetViewport(
191   ScrnInfoPtr pScrn,
192   int x, int y,
193   int flags
194){
195   NEOPtr pNEO = NEOPTR(pScrn);
196   vgaHWPtr hwp = VGAHWPTR(pScrn);
197
198   NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
199   /* wait for retrace */
200   while((hwp->readST01(hwp) & 0x08));
201   while(!(hwp->readST01(hwp) & 0x08));
202
203   pNEO->DGAViewportStatus = 0;
204}
205
206#ifdef HAVE_XAA_H
207static void
208NEO_FillRect (
209   ScrnInfoPtr pScrn,
210   int x, int y, int w, int h,
211   unsigned long color
212){
213    NEOPtr pNEO = NEOPTR(pScrn);
214
215    if(pNEO->AccelInfoRec) {
216	(*pNEO->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
217	(*pNEO->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
218	SET_SYNC_FLAG(pNEO->AccelInfoRec);
219    }
220}
221
222
223static void
224NEO_Sync(
225   ScrnInfoPtr pScrn
226){
227    NEOPtr pNEO = NEOPTR(pScrn);
228#ifdef HAVE_XAA_H
229    if(pNEO->AccelInfoRec) {
230	(*pNEO->AccelInfoRec->Sync)(pScrn);
231    }
232#endif
233}
234
235static void
236NEO_BlitRect(
237   ScrnInfoPtr pScrn,
238   int srcx, int srcy,
239   int w, int h,
240   int dstx, int dsty
241){
242    NEOPtr pNEO = NEOPTR(pScrn);
243
244    if(pNEO->AccelInfoRec) {
245	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
246	int ydir = (srcy < dsty) ? -1 : 1;
247
248	(*pNEO->AccelInfoRec->SetupForScreenToScreenCopy)(
249		pScrn, xdir, ydir, GXcopy, ~0, -1);
250	(*pNEO->AccelInfoRec->SubsequentScreenToScreenCopy)(
251		pScrn, srcx, srcy, dstx, dsty, w, h);
252	SET_SYNC_FLAG(pNEO->AccelInfoRec);
253    }
254}
255
256#if 0
257static void
258NEO_BlitTransRect(
259   ScrnInfoPtr pScrn,
260   int srcx, int srcy,
261   int w, int h,
262   int dstx, int dsty,
263   unsigned long color
264){
265  /* this one should be separate since the XAA function would
266     prohibit usage of ~0 as the key */
267}
268#endif
269#endif
270static Bool
271NEO_OpenFramebuffer(
272   ScrnInfoPtr pScrn,
273   char **name,
274   unsigned char **mem,
275   int *size,
276   int *offset,
277   int *flags
278){
279    NEOPtr pNEO = NEOPTR(pScrn);
280
281    *name = NULL; 		/* no special device */
282    *mem = (unsigned char*)pNEO->NeoLinearAddr;
283    *size = pNEO->NeoFbMapSize;
284    *offset = 0;
285    *flags = DGA_NEED_ROOT;
286
287    return TRUE;
288}
289
290