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