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