1
2/*
3Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the XFree86 Project shall not
23be used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the XFree86 Project.
25*/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31/*
32 * file: savage_dga.c
33 * ported from s3v, which was ported from mga
34 *
35 */
36
37#ifdef HAVE_XAA_H
38#include "xaalocal.h"
39#endif
40#include "savage_driver.h"
41#include "dgaproc.h"
42
43
44Bool SavageDGAInit(ScreenPtr pScreen);
45static Bool Savage_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
46		int *, int *, int *);
47static Bool Savage_SetMode(ScrnInfoPtr, DGAModePtr);
48static int  Savage_GetViewport(ScrnInfoPtr);
49static void Savage_SetViewport(ScrnInfoPtr, int, int, int);
50#ifdef HAVE_XAA_H
51static void Savage_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
52static void Savage_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
53#endif
54
55static
56DGAFunctionRec Savage_DGAFuncs = {
57    Savage_OpenFramebuffer,
58    NULL,	/* CloseFrameBuffer */
59    Savage_SetMode,
60    Savage_SetViewport,
61    Savage_GetViewport,
62    SavageAccelSync,
63#ifdef HAVE_XAA_H
64    Savage_FillRect,
65    Savage_BlitRect,
66#else
67    NULL, NULL,
68#endif
69    NULL			 /* BlitTransRect */
70};
71
72#define DGATRACE	4
73
74/*
75 * I don't understand the thinking here.  As near as I can tell, we are
76 * never asked to change into a depth other than the frame buffer depth.
77 * So why create modes to do so?
78 */
79
80static DGAModePtr
81SavageSetupDGAMode(
82    ScrnInfoPtr pScrn,
83    DGAModePtr modes,
84    int *num,
85    int bitsPerPixel,
86    int depth,
87    Bool pixmap,
88    int secondPitch,
89    unsigned long red,
90    unsigned long green,
91    unsigned long blue,
92    short visualClass
93)
94{
95    SavagePtr psav = SAVPTR(pScrn);
96    DGAModePtr mode, newmodes = NULL;
97    DisplayModePtr pMode, firstMode;
98    int otherPitch, Bpp = bitsPerPixel >> 3;
99    Bool oneMore;
100
101    xf86ErrorFVerb(DGATRACE, "		SavageSetupDGAMode\n");
102
103    pMode = firstMode = pScrn->modes;
104
105    /*
106     * DGA 1.0 would only provide modes where the depth and stride
107     * matched the current desktop.  Some DGA apps might still expect
108     * this, so we provide them, too.
109     */
110
111    while(pMode) {
112
113	otherPitch = secondPitch ? secondPitch : pMode->HDisplay;
114
115	if(pMode->HDisplay != otherPitch) {
116	    newmodes = realloc(modes, (*num + 2) * sizeof(DGAModeRec));
117	    oneMore = TRUE;
118	} else {
119	    newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec));
120	    oneMore = FALSE;
121	}
122
123	if(!newmodes) {
124	   free(modes);
125	   return NULL;
126	}
127	modes = newmodes;
128
129SECOND_PASS:
130
131	mode = modes + *num;
132	(*num)++;
133
134	mode->mode = pMode;
135	mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
136#ifdef HAVE_XAA_H
137	if(!psav->NoAccel)
138	    mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
139#endif
140	if(pMode->Flags & V_DBLSCAN)
141	    mode->flags |= DGA_DOUBLESCAN;
142	if(pMode->Flags & V_INTERLACE)
143	    mode->flags |= DGA_INTERLACED;
144	mode->byteOrder = pScrn->imageByteOrder;
145	mode->depth = depth;
146	mode->bitsPerPixel = bitsPerPixel;
147	mode->red_mask = red;
148	mode->green_mask = green;
149	mode->blue_mask = blue;
150	mode->visualClass = visualClass;
151	mode->viewportWidth = pMode->HDisplay;
152	mode->viewportHeight = pMode->VDisplay;
153	mode->xViewportStep = 2;
154	mode->yViewportStep = 1;
155	mode->viewportFlags = DGA_FLIP_RETRACE;
156	mode->offset = 0;
157	mode->address = psav->FBBase;
158
159	xf86ErrorFVerb(DGATRACE,
160	    "SavageDGAInit vpWid=%d, vpHgt=%d, Bpp=%d, mdbitsPP=%d\n",
161	    mode->viewportWidth,
162	    mode->viewportHeight,
163	    Bpp,
164	    mode->bitsPerPixel
165	);
166
167	if(oneMore) { /* first one is narrow width */
168	    /* Force stride to multiple of 16 pixels. */
169	    mode->bytesPerScanline = ((pMode->HDisplay + 15) & ~15) * Bpp;
170	    mode->imageWidth = pMode->HDisplay;
171	    mode->imageHeight =  pMode->VDisplay;
172	    mode->pixmapWidth = mode->imageWidth;
173	    mode->pixmapHeight = mode->imageHeight;
174	    mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
175	    /* this might need to get clamped to some maximum */
176	    mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
177	    oneMore = FALSE;
178
179	    xf86ErrorFVerb(DGATRACE,
180		"SavageDGAInit 1 imgHgt=%d, stride=%d\n",
181		mode->imageHeight,
182		mode->bytesPerScanline );
183
184	    goto SECOND_PASS;
185	} else {
186	    mode->bytesPerScanline = ((pScrn->displayWidth + 15) & ~15) * Bpp;
187	    mode->imageWidth = pScrn->displayWidth;
188	    mode->imageHeight = psav->videoRambytes / mode->bytesPerScanline;
189	    mode->pixmapWidth = mode->imageWidth;
190	    mode->pixmapHeight = mode->imageHeight;
191	    mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
192	    /* this might need to get clamped to some maximum */
193	    mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
194
195	    xf86ErrorFVerb(DGATRACE,
196		"SavageDGAInit 2 imgHgt=%d, stride=%d\n",
197		mode->imageHeight,
198		mode->bytesPerScanline );
199	}
200
201	pMode = pMode->next;
202	if(pMode == firstMode)
203	    break;
204    }
205
206    return modes;
207}
208
209
210Bool
211SavageDGAInit(ScreenPtr pScreen)
212{
213    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
214    SavagePtr psav = SAVPTR(pScrn);
215    DGAModePtr modes = NULL;
216    int num = 0;
217
218    xf86ErrorFVerb(DGATRACE, "		SavageDGAInit\n");
219
220    /* 8 */
221    modes = SavageSetupDGAMode (pScrn, modes, &num, 8, 8,
222		(pScrn->bitsPerPixel == 8),
223		(pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
224		0, 0, 0, PseudoColor);
225
226    /* 15 */
227    modes = SavageSetupDGAMode (pScrn, modes, &num, 16, 15,
228		(pScrn->bitsPerPixel == 16),
229		(pScrn->depth != 15) ? 0 : pScrn->displayWidth,
230		0x7c00, 0x03e0, 0x001f, TrueColor);
231
232    modes = SavageSetupDGAMode (pScrn, modes, &num, 16, 15,
233		(pScrn->bitsPerPixel == 16),
234		(pScrn->depth != 15) ? 0 : pScrn->displayWidth,
235		0x7c00, 0x03e0, 0x001f, DirectColor);
236
237    /* 16 */
238    modes = SavageSetupDGAMode (pScrn, modes, &num, 16, 16,
239		(pScrn->bitsPerPixel == 16),
240		(pScrn->depth != 16) ? 0 : pScrn->displayWidth,
241		0xf800, 0x07e0, 0x001f, TrueColor);
242
243    modes = SavageSetupDGAMode (pScrn, modes, &num, 16, 16,
244		(pScrn->bitsPerPixel == 16),
245		(pScrn->depth != 16) ? 0 : pScrn->displayWidth,
246		0xf800, 0x07e0, 0x001f, DirectColor);
247
248    /* 24-in-32 */
249    modes = SavageSetupDGAMode (pScrn, modes, &num, 32, 24,
250		(pScrn->bitsPerPixel == 32),
251		(pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
252		0xff0000, 0x00ff00, 0x0000ff, TrueColor);
253
254    modes = SavageSetupDGAMode (pScrn, modes, &num, 32, 24,
255		(pScrn->bitsPerPixel == 32),
256		(pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
257		0xff0000, 0x00ff00, 0x0000ff, DirectColor);
258
259    psav->numDGAModes = num;
260    psav->DGAModes = modes;
261
262    return DGAInit(pScreen, &Savage_DGAFuncs, modes, num);
263}
264
265
266static Bool
267Savage_SetMode(
268    ScrnInfoPtr pScrn,
269    DGAModePtr pMode
270){
271    static int OldDisplayWidth[MAXSCREENS];
272    static int OldBitsPerPixel[MAXSCREENS];
273    static int OldDepth[MAXSCREENS];
274    static DisplayModePtr OldMode[MAXSCREENS];
275    int index = pScrn->pScreen->myNum;
276    SavagePtr psav = SAVPTR(pScrn);
277
278    if(!pMode) { /* restore the original mode */
279	/* put the ScreenParameters back */
280
281	pScrn->displayWidth = OldDisplayWidth[index];
282	pScrn->bitsPerPixel = OldBitsPerPixel[index];
283	pScrn->depth = OldDepth[index];
284	pScrn->currentMode = OldMode[index];
285
286	psav->DGAactive = FALSE;
287	SavageSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
288	if( psav->hwcursor && psav->hwc_on )
289	    SavageShowCursor(pScrn);
290    } else {
291	Bool holdBIOS = psav->UseBIOS;
292
293#if 0
294	ErrorF(
295	    "pScrn->bitsPerPixel %d, pScrn->depth %d\n",
296	    pScrn->bitsPerPixel, pScrn->depth);
297	ErrorF(
298	    " want  bitsPerPixel %d,  want  depth %d\n",
299	    pMode->bitsPerPixel, pMode->depth);
300#endif
301
302	if( psav->hwcursor && psav->hwc_on) {
303	    SavageHideCursor(pScrn);
304	    psav->hwc_on = TRUE;    /* save for later restoration */
305	}
306
307
308	if(!psav->DGAactive) {  /* save the old parameters */
309	    OldDisplayWidth[index] = pScrn->displayWidth;
310	    OldBitsPerPixel[index] = pScrn->bitsPerPixel;
311	    OldDepth[index] = pScrn->depth;
312	    OldMode[index] = pScrn->currentMode;
313
314	    psav->DGAactive = TRUE;
315	}
316
317	pScrn->bitsPerPixel = pMode->bitsPerPixel;
318	pScrn->depth = pMode->depth;
319	pScrn->displayWidth = pMode->bytesPerScanline /
320	    (pMode->bitsPerPixel >> 3);
321
322/*	psav->UseBIOS = FALSE; */
323	SavageSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
324	psav->UseBIOS = holdBIOS;
325    }
326
327    return TRUE;
328}
329
330
331static int
332Savage_GetViewport(
333    ScrnInfoPtr pScrn
334){
335    SavagePtr psav = SAVPTR(pScrn);
336    return psav->DGAViewportStatus;
337}
338
339
340static void
341Savage_SetViewport(
342   ScrnInfoPtr pScrn,
343   int x, int y,
344   int flags
345){
346    SavagePtr psav = SAVPTR(pScrn);
347
348    SavageAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
349    psav->DGAViewportStatus = 0;  /* MGAAdjustFrame loops until finished */
350}
351
352#ifdef HAVE_XAA_H
353static void
354Savage_FillRect (
355    ScrnInfoPtr pScrn,
356    int x, int y, int w, int h,
357    unsigned long color
358){
359    SavagePtr psav = SAVPTR(pScrn);
360
361    if(psav->AccelInfoRec) {
362	(*psav->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
363	(*psav->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
364	SET_SYNC_FLAG(psav->AccelInfoRec);
365    }
366}
367
368static void
369Savage_BlitRect(
370    ScrnInfoPtr pScrn,
371    int srcx, int srcy,
372    int w, int h,
373    int dstx, int dsty
374){
375    SavagePtr psav = SAVPTR(pScrn);
376
377    if(psav->AccelInfoRec) {
378    int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
379    int ydir = (srcy < dsty) ? -1 : 1;
380
381    (*psav->AccelInfoRec->SetupForScreenToScreenCopy)(
382	pScrn, xdir, ydir, GXcopy, ~0, -1);
383    (*psav->AccelInfoRec->SubsequentScreenToScreenCopy)(
384	pScrn, srcx, srcy, dstx, dsty, w, h);
385    SET_SYNC_FLAG(psav->AccelInfoRec);
386    }
387}
388#endif
389
390static Bool
391Savage_OpenFramebuffer(
392    ScrnInfoPtr pScrn,
393    char **name,
394    unsigned char **mem,
395    int *size,
396    int *offset,
397    int *flags
398){
399    SavagePtr psav = SAVPTR(pScrn);
400
401    *name = NULL;	 /* no special device */
402    *mem = (unsigned char*)(uintptr_t) psav->FbRegion.base;
403    *size = psav->videoRambytes;
404    *offset = 0;
405    *flags = DGA_NEED_ROOT;
406
407    return TRUE;
408}
409