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