1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include "riva_local.h"
6#include "riva_include.h"
7#include "riva_type.h"
8#include "riva_proto.h"
9#ifdef HAVE_XAA_H
10#include "xaalocal.h"
11#endif
12#include "dgaproc.h"
13
14static Bool Riva_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
15					int *, int *, int *);
16static Bool Riva_SetMode(ScrnInfoPtr, DGAModePtr);
17static int  Riva_GetViewport(ScrnInfoPtr);
18static void Riva_SetViewport(ScrnInfoPtr, int, int, int);
19#ifdef HAVE_XAA_H
20static void Riva_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
21static void Riva_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
22static void Riva_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
23					unsigned long);
24#endif
25
26static
27DGAFunctionRec Riva_DGAFuncs = {
28   Riva_OpenFramebuffer,
29   NULL,
30   Riva_SetMode,
31   Riva_SetViewport,
32   Riva_GetViewport,
33   RivaSync,
34#ifdef HAVE_XAA_H
35   Riva_FillRect,
36   Riva_BlitRect,
37   Riva_BlitTransRect
38#else
39   NULL, NULL, NULL
40#endif
41};
42
43
44
45static DGAModePtr
46RivaSetupDGAMode(
47   ScrnInfoPtr pScrn,
48   DGAModePtr modes,
49   int *num,
50   int bitsPerPixel,
51   int depth,
52   Bool pixmap,
53   int secondPitch,
54   unsigned long red,
55   unsigned long green,
56   unsigned long blue,
57   short visualClass
58){
59   DisplayModePtr firstMode, pMode;
60   RivaPtr pRiva = RivaPTR(pScrn);
61   DGAModePtr mode, newmodes;
62   int size, pitch, Bpp = bitsPerPixel >> 3;
63
64SECOND_PASS:
65
66   pMode = firstMode = pScrn->modes;
67
68   while(1) {
69
70	pitch = (pMode->HDisplay + 31) & ~31;
71	size = pitch * Bpp * pMode->VDisplay;
72
73	if((!secondPitch || (pitch != secondPitch)) &&
74		(size <= pRiva->FbUsableSize)) {
75
76	    if(secondPitch)
77		pitch = secondPitch;
78
79	    if(!(newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec))))
80		break;
81
82	    modes = newmodes;
83	    mode = modes + *num;
84
85	    mode->mode = pMode;
86	    mode->flags = DGA_CONCURRENT_ACCESS;
87
88	    if(pixmap)
89		mode->flags |= DGA_PIXMAP_AVAILABLE;
90#ifdef HAVE_XAA_H
91	    if(!pRiva->NoAccel)
92		mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
93#endif
94	    if(pMode->Flags & V_DBLSCAN)
95		mode->flags |= DGA_DOUBLESCAN;
96	    if(pMode->Flags & V_INTERLACE)
97		mode->flags |= DGA_INTERLACED;
98	    mode->byteOrder = pScrn->imageByteOrder;
99	    mode->depth = depth;
100	    mode->bitsPerPixel = bitsPerPixel;
101	    mode->red_mask = red;
102	    mode->green_mask = green;
103	    mode->blue_mask = blue;
104	    mode->visualClass = visualClass;
105	    mode->viewportWidth = pMode->HDisplay;
106	    mode->viewportHeight = pMode->VDisplay;
107	    mode->xViewportStep = 4 / Bpp;
108	    mode->yViewportStep = 1;
109	    mode->viewportFlags = DGA_FLIP_RETRACE;
110	    mode->offset = 0;
111	    mode->address = pRiva->FbStart;
112	    mode->bytesPerScanline = pitch * Bpp;
113	    mode->imageWidth = pitch;
114	    mode->imageHeight =  pRiva->FbUsableSize / mode->bytesPerScanline;
115	    mode->pixmapWidth = mode->imageWidth;
116	    mode->pixmapHeight = mode->imageHeight;
117	    mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
118	    mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
119	    (*num)++;
120	}
121
122	pMode = pMode->next;
123	if(pMode == firstMode)
124	   break;
125    }
126
127    if(secondPitch) {
128	secondPitch = 0;
129	goto SECOND_PASS;
130    }
131
132    return modes;
133}
134
135
136Bool
137RivaDGAInit(ScreenPtr pScreen)
138{
139   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
140   RivaPtr pRiva = RivaPTR(pScrn);
141   DGAModePtr modes = NULL;
142   int num = 0;
143
144   /* 8 */
145   modes = RivaSetupDGAMode (pScrn, modes, &num, 8, 8,
146		(pScrn->bitsPerPixel == 8),
147		(pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
148		0, 0, 0, PseudoColor);
149
150   /* 15 */
151   modes = RivaSetupDGAMode (pScrn, modes, &num, 16, 15,
152		(pScrn->bitsPerPixel == 16),
153		(pScrn->depth != 15) ? 0 : pScrn->displayWidth,
154		0x7c00, 0x03e0, 0x001f, TrueColor);
155
156   /* 32 */
157   modes = RivaSetupDGAMode (pScrn, modes, &num, 32, 24,
158		(pScrn->bitsPerPixel == 32),
159		(pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
160		0xff0000, 0x00ff00, 0x0000ff, TrueColor);
161
162   pRiva->numDGAModes = num;
163   pRiva->DGAModes = modes;
164
165   return DGAInit(pScreen, &Riva_DGAFuncs, modes, num);
166}
167
168
169static int
170BitsSet(unsigned long data)
171{
172   unsigned long mask;
173   int set = 0;
174
175   for(mask = 1; mask; mask <<= 1)
176        if(mask & data) set++;
177
178   return set;
179}
180
181static Bool
182Riva_SetMode(
183   ScrnInfoPtr pScrn,
184   DGAModePtr pMode
185){
186   static RivaFBLayout SavedLayouts[MAXSCREENS];
187   int index = pScrn->pScreen->myNum;
188
189   RivaPtr pRiva = RivaPTR(pScrn);
190
191   if(!pMode) { /* restore the original mode */
192      if(pRiva->DGAactive)
193        memcpy(&pRiva->CurrentLayout, &SavedLayouts[index], sizeof(RivaFBLayout));
194
195      pScrn->currentMode = pRiva->CurrentLayout.mode;
196      RivaSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
197      RivaAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
198      pRiva->DGAactive = FALSE;
199   } else {
200      if(!pRiva->DGAactive) {  /* save the old parameters */
201	memcpy(&SavedLayouts[index], &pRiva->CurrentLayout, sizeof(RivaFBLayout));
202	pRiva->DGAactive = TRUE;
203      }
204
205      /* update CurrentLayout */
206      pRiva->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
207      pRiva->CurrentLayout.depth = pMode->depth;
208      pRiva->CurrentLayout.displayWidth = pMode->bytesPerScanline /
209                              (pMode->bitsPerPixel >> 3);
210      pRiva->CurrentLayout.weight.red = BitsSet(pMode->red_mask);
211      pRiva->CurrentLayout.weight.green = BitsSet(pMode->green_mask);
212      pRiva->CurrentLayout.weight.blue = BitsSet(pMode->blue_mask);
213      /* RivaModeInit() will set the mode field */
214      RivaSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
215   }
216
217   return TRUE;
218}
219
220
221
222static int
223Riva_GetViewport(
224  ScrnInfoPtr pScrn
225){
226    RivaPtr pRiva = RivaPTR(pScrn);
227
228    return pRiva->DGAViewportStatus;
229}
230
231static void
232Riva_SetViewport(
233   ScrnInfoPtr pScrn,
234   int x, int y,
235   int flags
236){
237   RivaPtr pRiva = RivaPTR(pScrn);
238
239   RivaAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
240
241   while(VGA_RD08(pRiva->riva.PCIO, 0x3da) & 0x08);
242   while(!(VGA_RD08(pRiva->riva.PCIO, 0x3da) & 0x08));
243
244   pRiva->DGAViewportStatus = 0;
245}
246
247#ifdef HAVE_XAA_H
248static void
249Riva_FillRect (
250   ScrnInfoPtr pScrn,
251   int x, int y, int w, int h,
252   unsigned long color
253){
254    RivaPtr pRiva = RivaPTR(pScrn);
255
256    if(!pRiva->AccelInfoRec) return;
257
258    (*pRiva->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
259    (*pRiva->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
260
261    SET_SYNC_FLAG(pRiva->AccelInfoRec);
262}
263
264static void
265Riva_BlitRect(
266   ScrnInfoPtr pScrn,
267   int srcx, int srcy,
268   int w, int h,
269   int dstx, int dsty
270){
271    RivaPtr pRiva = RivaPTR(pScrn);
272    int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
273    int ydir = (srcy < dsty) ? -1 : 1;
274
275    if(!pRiva->AccelInfoRec) return;
276
277    (*pRiva->AccelInfoRec->SetupForScreenToScreenCopy)(
278		pScrn, xdir, ydir, GXcopy, ~0, -1);
279
280    (*pRiva->AccelInfoRec->SubsequentScreenToScreenCopy)(
281		pScrn, srcx, srcy, dstx, dsty, w, h);
282
283    SET_SYNC_FLAG(pRiva->AccelInfoRec);
284}
285
286
287static void
288Riva_BlitTransRect(
289   ScrnInfoPtr pScrn,
290   int srcx, int srcy,
291   int w, int h,
292   int dstx, int dsty,
293   unsigned long color
294){
295   /* not implemented... yet */
296}
297#endif
298
299static Bool
300Riva_OpenFramebuffer(
301   ScrnInfoPtr pScrn,
302   char **name,
303   unsigned char **mem,
304   int *size,
305   int *offset,
306   int *flags
307){
308    RivaPtr pRiva = RivaPTR(pScrn);
309
310    *name = NULL; 		/* no special device */
311    *mem = (unsigned char*)pRiva->FbAddress;
312    *size = pRiva->FbMapSize;
313    *offset = 0;
314    *flags = DGA_NEED_ROOT;
315
316    return TRUE;
317}
318