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