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