SiS_DDC2Delay: initialize variable before adding to it
[xf86-video-sis.git] / src / sis_dga.c
blobad37d66f5926b798c4a83c46ef0bd807f84048fb
1 /*
2 * SiS DGA handling
4 * Copyright (C) 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
5 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
7 * Portions from radeon_dga.c which is
8 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
9 * VA Linux Systems Inc., Fremont, California.
11 * Licensed under the following terms:
13 * Permission to use, copy, modify, distribute, and sell this software and its
14 * documentation for any purpose is hereby granted without fee, provided that
15 * the above copyright notice appear in all copies and that both that
16 * copyright notice and this permission notice appear in supporting
17 * documentation, and that the name of the providers not be used in
18 * advertising or publicity pertaining to distribution of the software without
19 * specific, written prior permission. The providers make no representations
20 * about the suitability of this software for any purpose. It is provided
21 * "as is" without express or implied warranty.
23 * THE PROVIDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
25 * EVENT SHALL THE PROVIDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
27 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
28 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
29 * PERFORMANCE OF THIS SOFTWARE.
31 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
32 * Thomas Winischhofer <thomas@winischhofer.net>
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
39 #include "sis.h"
40 #include "dgaproc.h"
42 #include "sis_regs.h"
44 #ifndef NEW_DGAOPENFRAMEBUFFER
45 static Bool SIS_OpenFramebuffer(ScrnInfoPtr, char **, UChar **,
46 int *, int *, int *);
47 #else
48 static Bool SIS_OpenFramebuffer(ScrnInfoPtr, char **, unsigned int *,
49 unsigned int *, unsigned int *, unsigned int *);
50 #endif
51 static Bool SIS_SetMode(ScrnInfoPtr, DGAModePtr);
52 static void SIS_Sync(ScrnInfoPtr);
53 static int SIS_GetViewport(ScrnInfoPtr);
54 static void SIS_SetViewport(ScrnInfoPtr, int, int, int);
55 static void SIS_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
56 static void SIS_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
57 static void SIS_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long);
59 static
60 DGAFunctionRec SISDGAFuncs = {
61 SIS_OpenFramebuffer,
62 NULL,
63 SIS_SetMode,
64 SIS_SetViewport,
65 SIS_GetViewport,
66 SIS_Sync,
67 SIS_FillRect,
68 SIS_BlitRect,
69 NULL
72 static
73 DGAFunctionRec SISDGAFuncs3xx = {
74 SIS_OpenFramebuffer,
75 NULL,
76 SIS_SetMode,
77 SIS_SetViewport,
78 SIS_GetViewport,
79 SIS_Sync,
80 SIS_FillRect,
81 SIS_BlitRect,
82 SIS_BlitTransRect
85 static DGAModePtr
86 SISSetupDGAMode(
87 ScrnInfoPtr pScrn,
88 DGAModePtr modes,
89 int *num,
90 int bitsPerPixel,
91 int depth,
92 Bool pixmap,
93 int secondPitch,
94 ULong red,
95 ULong green,
96 ULong blue,
97 short visualClass
99 SISPtr pSiS = SISPTR(pScrn);
100 DGAModePtr newmodes = NULL, currentMode;
101 DisplayModePtr pMode, firstMode;
102 int otherPitch, Bpp = bitsPerPixel >> 3;
103 Bool oneMore;
105 pMode = firstMode = pScrn->modes;
107 while(pMode) {
109 #ifdef SISMERGED
110 if(pSiS->MergedFB) {
111 Bool nogood = FALSE;
112 /* Filter out all meta modes that would require driver-side panning */
113 switch(((SiSMergedDisplayModePtr)pMode->Private)->CRT2Position) {
114 case sisClone:
115 if( (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->HDisplay !=
116 ((SiSMergedDisplayModePtr)pMode->Private)->CRT2->HDisplay) ||
117 (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->VDisplay !=
118 ((SiSMergedDisplayModePtr)pMode->Private)->CRT2->VDisplay) ||
119 (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->HDisplay !=
120 pMode->HDisplay) ||
121 (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->VDisplay !=
122 pMode->VDisplay) )
123 nogood = TRUE;
124 break;
125 case sisRightOf:
126 case sisLeftOf:
127 if( (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->VDisplay !=
128 ((SiSMergedDisplayModePtr)pMode->Private)->CRT2->VDisplay) ||
129 (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->VDisplay != pMode->VDisplay) )
130 nogood = TRUE;
131 break;
132 default:
133 if( (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->HDisplay !=
134 ((SiSMergedDisplayModePtr)pMode->Private)->CRT2->HDisplay) ||
135 (((SiSMergedDisplayModePtr)pMode->Private)->CRT1->HDisplay != pMode->HDisplay) )
136 nogood = TRUE;
138 if(nogood) {
139 if(depth == 16) { /* Print this only the first time */
140 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
141 "DGA: MetaMode %dx%d not suitable for DGA, skipping\n",
142 pMode->HDisplay, pMode->VDisplay);
144 goto mode_nogood;
147 #endif
149 otherPitch = secondPitch ? secondPitch : pMode->HDisplay;
151 if(pMode->HDisplay != otherPitch) {
153 newmodes = realloc(modes, (*num + 2) * sizeof(DGAModeRec));
154 oneMore = TRUE;
156 } else {
158 newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec));
159 oneMore = FALSE;
163 if(!newmodes) {
164 free(modes);
165 return NULL;
167 modes = newmodes;
169 SECOND_PASS:
171 currentMode = modes + *num;
172 (*num)++;
174 currentMode->mode = pMode;
175 currentMode->flags = DGA_CONCURRENT_ACCESS;
176 if(pixmap)
177 currentMode->flags |= DGA_PIXMAP_AVAILABLE;
178 if(!pSiS->NoAccel) {
179 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
180 if((pSiS->VGAEngine == SIS_300_VGA) ||
181 (pSiS->VGAEngine == SIS_315_VGA) ||
182 (pSiS->VGAEngine == SIS_530_VGA)) {
183 currentMode->flags |= DGA_BLIT_RECT_TRANS;
186 if(pMode->Flags & V_DBLSCAN)
187 currentMode->flags |= DGA_DOUBLESCAN;
188 if(pMode->Flags & V_INTERLACE)
189 currentMode->flags |= DGA_INTERLACED;
190 currentMode->byteOrder = pScrn->imageByteOrder;
191 currentMode->depth = depth;
192 currentMode->bitsPerPixel = bitsPerPixel;
193 currentMode->red_mask = red;
194 currentMode->green_mask = green;
195 currentMode->blue_mask = blue;
196 currentMode->visualClass = visualClass;
197 currentMode->viewportWidth = pMode->HDisplay;
198 currentMode->viewportHeight = pMode->VDisplay;
199 currentMode->xViewportStep = 1;
200 currentMode->yViewportStep = 1;
201 currentMode->viewportFlags = DGA_FLIP_RETRACE;
202 currentMode->offset = 0;
203 currentMode->address = pSiS->FbBase;
205 if(oneMore) {
207 /* first one is narrow width */
208 currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L);
209 currentMode->imageWidth = pMode->HDisplay;
210 currentMode->imageHeight = pMode->VDisplay;
211 currentMode->pixmapWidth = currentMode->imageWidth;
212 currentMode->pixmapHeight = currentMode->imageHeight;
213 currentMode->maxViewportX = currentMode->imageWidth -
214 currentMode->viewportWidth;
215 /* this might need to get clamped to some maximum */
216 currentMode->maxViewportY = (currentMode->imageHeight -
217 currentMode->viewportHeight);
218 oneMore = FALSE;
219 goto SECOND_PASS;
221 } else {
223 currentMode->bytesPerScanline = ((otherPitch * Bpp) + 3) & ~3L;
224 currentMode->imageWidth = otherPitch;
225 currentMode->imageHeight = pMode->VDisplay;
226 currentMode->pixmapWidth = currentMode->imageWidth;
227 currentMode->pixmapHeight = currentMode->imageHeight;
228 currentMode->maxViewportX = (currentMode->imageWidth -
229 currentMode->viewportWidth);
230 /* this might need to get clamped to some maximum */
231 currentMode->maxViewportY = (currentMode->imageHeight -
232 currentMode->viewportHeight);
235 #ifdef SISMERGED
236 mode_nogood:
237 #endif
239 pMode = pMode->next;
240 if(pMode == firstMode)
241 break;
244 return modes;
247 Bool
248 SISDGAInit(ScreenPtr pScreen)
250 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
251 SISPtr pSiS = SISPTR(pScrn);
252 DGAModePtr modes = NULL;
253 int num = 0;
255 /* 8 */
256 /* We don't support 8bpp modes in dual head or MergedFB mode,
257 * so don't offer them to DGA either.
259 #ifdef SISDUALHEAD
260 if(!pSiS->DualHeadMode) {
261 #endif
262 #ifdef SISMERGED
263 if(!(pSiS->MergedFB)) {
264 #endif
265 modes = SISSetupDGAMode(pScrn, modes, &num, 8, 8,
266 (pScrn->bitsPerPixel == 8),
267 ((pScrn->bitsPerPixel != 8)
268 ? 0 : pScrn->displayWidth),
269 0, 0, 0, PseudoColor);
270 #ifdef SISMERGED
272 #endif
273 #ifdef SISDUALHEAD
275 #endif
277 /* 16 */
278 modes = SISSetupDGAMode(pScrn, modes, &num, 16, 16,
279 (pScrn->bitsPerPixel == 16),
280 ((pScrn->depth != 16)
281 ? 0 : pScrn->displayWidth),
282 0xf800, 0x07e0, 0x001f, TrueColor);
284 if((pSiS->VGAEngine == SIS_530_VGA) || (pSiS->VGAEngine == SIS_OLD_VGA)) {
285 /* 24 */
286 modes = SISSetupDGAMode(pScrn, modes, &num, 24, 24,
287 (pScrn->bitsPerPixel == 24),
288 ((pScrn->bitsPerPixel != 24)
289 ? 0 : pScrn->displayWidth),
290 0xff0000, 0x00ff00, 0x0000ff, TrueColor);
293 if(pSiS->VGAEngine != SIS_OLD_VGA) {
294 /* 32 */
295 modes = SISSetupDGAMode(pScrn, modes, &num, 32, 24,
296 (pScrn->bitsPerPixel == 32),
297 ((pScrn->bitsPerPixel != 32)
298 ? 0 : pScrn->displayWidth),
299 0xff0000, 0x00ff00, 0x0000ff, TrueColor);
302 pSiS->numDGAModes = num;
303 pSiS->DGAModes = modes;
305 if(num) {
306 if((pSiS->VGAEngine == SIS_300_VGA) ||
307 (pSiS->VGAEngine == SIS_315_VGA) ||
308 (pSiS->VGAEngine == SIS_530_VGA)) {
309 return DGAInit(pScreen, &SISDGAFuncs3xx, modes, num);
310 } else {
311 return DGAInit(pScreen, &SISDGAFuncs, modes, num);
313 } else {
314 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
315 "No DGA-suitable modes found, disabling DGA\n");
316 return TRUE;
320 static Bool
321 SIS_OpenFramebuffer(
322 ScrnInfoPtr pScrn,
323 char **name,
324 #ifndef NEW_DGAOPENFRAMEBUFFER
325 UChar **mem,
326 int *size,
327 int *offset,
328 int *flags
329 #else
330 unsigned int *mem,
331 unsigned int *size,
332 unsigned int *offset,
333 unsigned int *flags
334 #endif
336 SISPtr pSiS = SISPTR(pScrn);
338 *name = NULL; /* no special device */
339 #ifndef NEW_DGAOPENFRAMEBUFFER
340 *mem = (UChar *)pSiS->FbAddress;
341 #else
342 *mem = pSiS->FbAddress;
343 #endif
344 *size = pSiS->maxxfbmem;
345 *offset = 0;
346 #ifndef NEW_DGAOPENFRAMEBUFFER
347 *flags = DGA_NEED_ROOT;
348 #else
349 *flags = 0;
350 #endif
352 return TRUE;
355 static Bool
356 SIS_SetMode(
357 ScrnInfoPtr pScrn,
358 DGAModePtr pMode
360 static SISFBLayout BackupLayouts[MAXSCREENS];
361 int index = pScrn->pScreen->myNum;
362 SISPtr pSiS = SISPTR(pScrn);
364 if(!pMode) { /* restore the original mode */
366 if(pSiS->DGAactive) {
367 /* put the ScreenParameters back */
368 memcpy(&pSiS->CurrentLayout, &BackupLayouts[index], sizeof(SISFBLayout));
371 pScrn->currentMode = pSiS->CurrentLayout.mode;
372 pSiS->DGAactive = FALSE;
374 (*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
375 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
377 } else { /* set new mode */
379 if(!pSiS->DGAactive) {
380 /* save the old parameters */
381 memcpy(&BackupLayouts[index], &pSiS->CurrentLayout, sizeof(SISFBLayout));
382 pSiS->DGAactive = TRUE;
385 pSiS->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
386 pSiS->CurrentLayout.depth = pMode->depth;
387 pSiS->CurrentLayout.displayWidth = pMode->bytesPerScanline / (pMode->bitsPerPixel >> 3);
388 pSiS->CurrentLayout.displayHeight = pMode->imageHeight;
390 (*pScrn->SwitchMode)(SWITCH_MODE_ARGS(pScrn, pMode->mode));
391 /* Adjust viewport to 0/0 after mode switch */
392 /* This fixes the vmware-in-dualhead problems */
393 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, 0, 0));
394 pSiS->CurrentLayout.DGAViewportX = pSiS->CurrentLayout.DGAViewportY = 0;
397 return TRUE;
400 static int
401 SIS_GetViewport(
402 ScrnInfoPtr pScrn
404 SISPtr pSiS = SISPTR(pScrn);
406 return pSiS->DGAViewportStatus;
409 static void
410 SIS_SetViewport(
411 ScrnInfoPtr pScrn,
412 int x, int y,
413 int flags
415 SISPtr pSiS = SISPTR(pScrn);
417 (*pScrn->AdjustFrame)(ADJUST_FRAME_ARGS(pScrn, x, y));
418 pSiS->DGAViewportStatus = 0; /* There are never pending Adjusts */
419 pSiS->CurrentLayout.DGAViewportX = x;
420 pSiS->CurrentLayout.DGAViewportY = y;
423 static void
424 SIS_Sync(
425 ScrnInfoPtr pScrn
427 SISPtr pSiS = SISPTR(pScrn);
429 (*pSiS->SyncAccel)(pScrn);
432 static void
433 SIS_FillRect(
434 ScrnInfoPtr pScrn,
435 int x, int y, int w, int h,
436 unsigned long color
438 SISPtr pSiS = SISPTR(pScrn);
440 if(pSiS->FillRect) {
441 (*pSiS->FillRect)(pScrn, x, y, w, h, (int)color);
442 #ifdef SIS_USE_XAA
443 if(!pSiS->useEXA && pSiS->AccelInfoPtr) {
444 SET_SYNC_FLAG(pSiS->AccelInfoPtr);
446 #endif
450 static void
451 SIS_BlitRect(
452 ScrnInfoPtr pScrn,
453 int srcx, int srcy,
454 int w, int h,
455 int dstx, int dsty
457 SISPtr pSiS = SISPTR(pScrn);
459 if(pSiS->BlitRect) {
460 (*pSiS->BlitRect)(pScrn, srcx, srcy, dstx, dsty, w, h, -1);
461 #ifdef SIS_USE_XAA
462 if(!pSiS->useEXA && pSiS->AccelInfoPtr) {
463 SET_SYNC_FLAG(pSiS->AccelInfoPtr);
465 #endif
469 static void
470 SIS_BlitTransRect(
471 ScrnInfoPtr pScrn,
472 int srcx, int srcy,
473 int w, int h,
474 int dstx, int dsty,
475 ULong color
477 SISPtr pSiS = SISPTR(pScrn);
479 if(pSiS->BlitRect) {
480 (*pSiS->BlitRect)(pScrn, srcx, srcy, dstx, dsty, w, h, (int)color);
481 #ifdef SIS_USE_XAA
482 if(!pSiS->useEXA && pSiS->AccelInfoPtr) {
483 SET_SYNC_FLAG(pSiS->AccelInfoPtr);
485 #endif