s3_dga.c revision bd35f0db
1/*
2 *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
3 *
4 *      XFree86 4.x driver for S3 chipsets
5 *
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation and
11 * that the name of Ani Joshi not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  Ani Joshi makes no representations
14 * about the suitability of this software for any purpose.  It is provided
15 * "as-is" without express or implied warranty.
16 *
17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "xf86.h"
33#include "xf86_OSproc.h"
34
35#include "dgaproc.h"
36
37#include "s3.h"
38#include "s3_reg.h"
39
40
41static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode);
42static int S3_GetViewport(ScrnInfoPtr pScrn);
43static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags);
44static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
45		        unsigned long color);
46static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h,
47		       int dstx, int dsty);
48static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name,
49			       unsigned char **mem, int *size, int *offset,
50			       int *flags);
51static void S3_Sync(ScrnInfoPtr pScrn);
52
53
54static DGAFunctionRec S3_DGAFuncs = {
55	S3_OpenFramebuffer,
56	NULL,
57	S3_SetMode,
58	S3_SetViewport,
59	S3_GetViewport,
60	S3_Sync,
61	S3_FillRect,
62	S3_BltRect,
63	NULL
64};
65
66
67static DGAModePtr S3SetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes,
68				 int *num, int bitsPerPixel, int depth,
69				 Bool pixmap, int secondPitch,
70				 unsigned long red, unsigned long green,
71				 unsigned long blue, short visualClass)
72{
73	S3Ptr pS3 = S3PTR(pScrn);
74	DGAModePtr newmodes = NULL, currentMode;
75	DisplayModePtr pMode, firstMode;
76	int otherPitch, Bpp = bitsPerPixel >> 3;
77	Bool oneMore;
78
79	pMode = firstMode = pScrn->modes;
80
81	while (pMode) {
82		otherPitch = secondPitch ? secondPitch : pMode->HDisplay;
83
84		if (pMode->HDisplay != otherPitch) {
85			newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec));
86			oneMore = TRUE;
87		} else {
88			newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec));
89			oneMore = FALSE;
90		}
91
92		if (!newmodes) {
93			xfree(modes);
94			return NULL;
95		}
96
97		modes = newmodes;
98
99SECOND_PASS:
100
101		currentMode = modes + *num;
102		(*num)++;
103
104		currentMode->mode = pMode;
105		currentMode->flags = DGA_CONCURRENT_ACCESS;
106		if (pixmap)
107			currentMode->flags |= DGA_PIXMAP_AVAILABLE;
108		if (pS3->pXAA)
109			currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
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 = depth;
116		currentMode->bitsPerPixel = bitsPerPixel;
117		currentMode->red_mask = red;
118		currentMode->green_mask = green;
119		currentMode->blue_mask = blue;
120		currentMode->visualClass = visualClass;
121		currentMode->viewportWidth = pMode->HDisplay;
122		currentMode->viewportHeight = pMode->VDisplay;
123		currentMode->xViewportStep = 8;
124		currentMode->yViewportStep = 1;
125		currentMode->viewportFlags = DGA_FLIP_RETRACE;
126		currentMode->offset = 0;
127		currentMode->address = (unsigned char*)pS3->FBAddress;
128
129		if (oneMore) {
130			currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L);
131
132			currentMode->imageWidth = pMode->HDisplay;
133			currentMode->imageHeight = pMode->VDisplay;
134			currentMode->pixmapWidth = currentMode->imageWidth;
135			currentMode->pixmapHeight = currentMode->imageHeight;
136			currentMode->maxViewportX = currentMode->imageWidth -
137						    currentMode->viewportWidth;
138			currentMode->maxViewportY = currentMode->imageHeight -
139						    currentMode->viewportHeight;
140
141			oneMore = FALSE;
142			goto SECOND_PASS;
143		} else {
144			currentMode->bytesPerScanline = (((otherPitch * Bpp) + 3) & ~3L);
145
146			currentMode->imageWidth = otherPitch;
147			currentMode->imageHeight = pMode->VDisplay;
148			currentMode->pixmapWidth = currentMode->imageWidth;
149			currentMode->pixmapHeight = currentMode->imageHeight;
150			currentMode->maxViewportX = currentMode->imageWidth -
151						    currentMode->viewportWidth;
152			currentMode->maxViewportY = currentMode->imageHeight -
153						    currentMode->viewportHeight;
154
155		}
156
157		pMode = pMode->next;
158
159		if (pMode == firstMode)
160			break;
161
162	}
163
164	return modes;
165}
166
167
168
169Bool S3DGAInit(ScreenPtr pScreen)
170{
171	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
172	S3Ptr pS3 = S3PTR(pScrn);
173	DGAModePtr modes = NULL;
174	int num = 0;
175
176	modes = S3SetupDGAMode(pScrn, modes, &num, 8, 8,
177			       (pScrn->bitsPerPixel == 8),
178			       ((pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth),
179			       0, 0, 0, PseudoColor);
180
181	modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15,
182			       (pScrn->bitsPerPixel == 16),
183			       ((pScrn->depth != 15)
184			       ? 0 : pScrn->displayWidth),
185			       0x7c00, 0x03e0, 0x001f, TrueColor);
186
187	modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15,
188			       (pScrn->bitsPerPixel == 16),
189			       ((pScrn->depth != 15)
190			       ? 0 : pScrn->displayWidth),
191			       0x7c00, 0x03e0, 0x001f, DirectColor);
192
193	modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16,
194			       (pScrn->bitsPerPixel == 16),
195			       ((pScrn->depth != 16)
196			       ? 0 : pScrn->displayWidth),
197			       0xf800, 0x07e0, 0x001f, TrueColor);
198
199	modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16,
200			       (pScrn->bitsPerPixel == 16),
201			       ((pScrn->depth != 16)
202			       ? 0 : pScrn->displayWidth),
203			       0xf800, 0x07e0, 0x001f, DirectColor);
204
205	modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24,
206			       (pScrn->bitsPerPixel == 32),
207			       ((pScrn->bitsPerPixel != 32)
208			       ? 0 : pScrn->displayWidth),
209			       0xff0000, 0x00ff00, 0x0000ff, TrueColor);
210
211	modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24,
212			       (pScrn->bitsPerPixel == 32),
213			       ((pScrn->bitsPerPixel != 32)
214			       ? 0 : pScrn->displayWidth),
215			       0xff0000, 0x00ff00, 0x0000ff, DirectColor);
216
217	pS3->numDGAModes = num;
218	pS3->DGAModes = modes;
219
220	return DGAInit(pScreen, &S3_DGAFuncs, modes, num);
221}
222
223
224static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
225{
226	S3Ptr pS3 = S3PTR(pScrn);
227	static S3FBLayout SavedLayouts[MAXSCREENS];
228	int indx = pScrn->pScreen->myNum;
229
230	if (!pMode) {
231		if (pS3->DGAactive) {
232			memcpy(&pS3->CurrentLayout, &SavedLayouts[indx],
233			       sizeof(S3FBLayout));
234			pS3->DGAactive = TRUE;
235		}
236
237		pS3->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
238		pS3->CurrentLayout.depth = pMode->depth;
239		pS3->CurrentLayout.displayWidth = (pMode->bytesPerScanline /
240						   (pMode->bitsPerPixel >> 3));
241		pS3->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8;
242		pS3->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16 ?
243						 pMode->bitsPerPixel :
244						 pMode->depth);
245
246		S3SwitchMode(indx, pMode->mode, 0);
247	}
248
249	return TRUE;
250}
251
252
253static int S3_GetViewport(ScrnInfoPtr pScrn)
254{
255	S3Ptr pS3 = S3PTR(pScrn);
256
257	return pS3->DGAViewportStatus;
258}
259
260
261static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
262{
263	S3Ptr pS3 = S3PTR(pScrn);
264
265	pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags);
266	pS3->DGAViewportStatus = 0;
267}
268
269
270static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
271		        unsigned long color)
272{
273	S3Ptr pS3 = S3PTR(pScrn);
274
275	if (pS3->pXAA) {
276		(*pS3->pXAA->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0));
277		(*pS3->pXAA->SubsequentSolidFillRect)(pScrn, x, y, w, h);
278		SET_SYNC_FLAG(pS3->pXAA);
279	}
280}
281
282
283static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h,
284		       int dstx, int dsty)
285{
286	S3Ptr pS3 = S3PTR(pScrn);
287
288	if (pS3->pXAA) {
289		int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
290		int ydir = (srcy < dsty) ? -1 : 1;
291
292		(*pS3->pXAA->SetupForScreenToScreenCopy)(pScrn, xdir, ydir,
293							 GXcopy, (CARD32)(~0), -1);
294		(*pS3->pXAA->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy,
295							   dstx, dsty, w, h);
296		SET_SYNC_FLAG(pS3->pXAA);
297	}
298}
299
300
301static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name,
302			       unsigned char **mem, int *size, int *offset,
303			       int *flags)
304{
305	S3Ptr pS3 = S3PTR(pScrn);
306
307	*name = NULL;
308	*mem = (unsigned char*)pS3->FBAddress;
309	*size = (pScrn->videoRam * 1024);
310	*offset = 0;
311	*flags = 0;
312
313	return TRUE;
314}
315
316
317static void S3_Sync(ScrnInfoPtr pScrn)
318{
319	WaitIdle();
320}
321