s/#define ABC ;/#define ABC do { ; } while(0);/
[nouveau] / src / nv_dri.c
1 #include "nv_include.h"
2
3 #define _XF86DRI_SERVER_
4 #include "GL/glxint.h"
5 #include "GL/glxtokens.h"
6 #include "sarea.h"
7 #include "xf86drm.h"
8 #include "dri.h"
9 #include "nv_dripriv.h"
10 #include "nv_dri.h"
11
12 Bool NVDRMSetParam(NVPtr pNv, unsigned int param, unsigned int value)
13 {
14         struct drm_nouveau_setparam setparam;
15         int ret;
16
17         setparam.param = param;
18         setparam.value = value;
19         ret = drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_SETPARAM, &setparam,
20                         sizeof(setparam));
21         if (ret)
22                 return FALSE;
23         return TRUE;
24 }
25
26 unsigned int NVDRMGetParam(NVPtr pNv, unsigned int param)
27 {
28         struct drm_nouveau_getparam getparam;
29
30         getparam.param = param;
31         drmCommandWriteRead(pNv->drm_fd, DRM_NOUVEAU_GETPARAM, &getparam, sizeof(getparam));
32
33         return getparam.value;
34 }
35
36 static Bool NVCreateContext(ScreenPtr pScreen, VisualPtr visual,
37                 drm_context_t hwContext, void *pVisualConfigPriv,
38                 DRIContextType contextStore)
39 {
40         return TRUE;
41 }
42
43
44 static void NVDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
45                 DRIContextType contextStore)
46 {
47         return;
48 }
49
50 static void NVDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
51                 DRIContextType oldContextType,
52                 void *oldContext,
53                 DRIContextType newContextType,
54                 void *newContext)
55 {
56         /* we really should do something here */
57         return;
58 }
59
60 static void NVDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
61 {   
62         return;
63 }
64
65 static void NVDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
66                 RegionPtr prgnSrc, CARD32 indx)
67 {
68         return;
69 }       
70
71 static void NVDRITransitionTo2d(ScreenPtr pScreen)
72 {
73         return;
74 }
75
76 static void NVDRITransitionTo3d(ScreenPtr pScreen)
77 {
78         return;
79 }
80
81 static void NVDRITransitionSingleToMulti3d(ScreenPtr pScreen)
82 {           
83         return;
84 }           
85         
86 static void NVDRITransitionMultiToSingle3d(ScreenPtr pScreen)
87 {       
88         return;
89 }
90
91 static Bool NVDRIInitVisualConfigs(ScreenPtr pScreen)
92 {
93         ScrnInfoPtr pScrn=xf86Screens[pScreen->myNum];
94         __GLXvisualConfig* pConfigs = NULL;
95         NVConfigPrivPtr pNVConfigs = NULL;
96         NVConfigPrivPtr* pNVConfigPtrs = NULL;
97         int db,depth,alpha,stencil;
98         int depths[]={24,16,0};
99         int num_configs,i;
100
101         switch(pScrn->depth)
102         {
103                 case 8:
104                 case 15:
105                         xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] no DRI at %d bpp ",pScrn->depth);
106                         break;
107                 case 16:
108                 case 24:
109                         num_configs=2*3*((pScrn->depth==24)?2:1)*2; /* db*depth*alpha*stencil */
110                         if (!(pConfigs=(__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),num_configs)))
111                                 return FALSE;
112                         if (!(pNVConfigs=(NVConfigPrivPtr)xcalloc(sizeof(NVConfigPrivRec), num_configs))) {
113                                 xfree(pConfigs);
114                                 return FALSE;
115                         }
116                         if (!(pNVConfigPtrs=(NVConfigPrivPtr *)xcalloc(sizeof(NVConfigPrivPtr),num_configs))) {
117                                 xfree(pConfigs);
118                                 xfree(pNVConfigs);
119                                 return FALSE;
120                         }
121
122                         i = 0;
123                         for(db=1;db>=0;db--)
124                         for(depth=0;depth<3;depth++)
125                         for(alpha=0;alpha<((pScrn->depth==24)?2:1);alpha++)
126                         for(stencil=0;stencil<2;stencil++)
127                         {
128                                 pConfigs[i].vid                = (VisualID)(-1);
129                                 pConfigs[i].class              = -1;
130                                 pConfigs[i].rgba               = TRUE;
131                                 if (pScrn->depth==16)
132                                 {                                       
133                                         pConfigs[i].redSize            = 5;
134                                         pConfigs[i].greenSize          = 6;
135                                         pConfigs[i].blueSize           = 5;
136                                         pConfigs[i].alphaSize          = 0;
137                                         pConfigs[i].redMask            = 0x0000F800;
138                                         pConfigs[i].greenMask          = 0x000007E0;
139                                         pConfigs[i].blueMask           = 0x0000001F;
140                                         pConfigs[i].alphaMask          = 0x00000000;
141                                 } else {
142                                         pConfigs[i].redSize            = 8;
143                                         pConfigs[i].greenSize          = 8;
144                                         pConfigs[i].blueSize           = 8;
145                                         pConfigs[i].redMask            = 0x00FF0000;
146                                         pConfigs[i].greenMask          = 0x0000FF00;
147                                         pConfigs[i].blueMask           = 0x000000FF;
148                                         if (alpha) {
149                                                 pConfigs[i].alphaSize          = 8;
150                                                 pConfigs[i].alphaMask          = 0xFF000000;
151                                         } else {
152                                                 pConfigs[i].alphaSize          = 0;
153                                                 pConfigs[i].alphaMask          = 0x00000000;
154                                         }
155                                 }
156
157                                 pConfigs[i].accumRedSize   = 0;
158                                 pConfigs[i].accumGreenSize = 0;
159                                 pConfigs[i].accumBlueSize  = 0;
160                                 pConfigs[i].accumAlphaSize = 0;
161                                 if (db)
162                                         pConfigs[i].doubleBuffer   = TRUE;
163                                 else
164                                         pConfigs[i].doubleBuffer   = FALSE;
165                                 pConfigs[i].stereo             = FALSE;
166                                 pConfigs[i].bufferSize         = pScrn->depth;
167                                 if (depths[depth] == 24 && stencil) {
168                                         pConfigs[i].depthSize          = depths[depth];
169                                         pConfigs[i].stencilSize        = 8;
170                                 } else {
171                                         pConfigs[i].depthSize          = depths[depth];
172                                         pConfigs[i].stencilSize        = 0;
173                                 }
174                                 pConfigs[i].auxBuffers         = 0;
175                                 pConfigs[i].level              = 0;
176                                 pConfigs[i].visualRating       = GLX_NONE;
177                                 pConfigs[i].transparentPixel   = GLX_NONE;
178                                 pConfigs[i].transparentRed     = 0;
179                                 pConfigs[i].transparentGreen   = 0;
180                                 pConfigs[i].transparentBlue    = 0;
181                                 pConfigs[i].transparentAlpha   = 0;
182                                 pConfigs[i].transparentIndex   = 0;
183                                 i++;
184                         }
185                         break;
186         }
187         GlxSetVisualConfigs(num_configs, pConfigs, (void**)pNVConfigPtrs);
188         return TRUE;
189 }
190
191 Bool NVDRIGetVersion(ScrnInfoPtr pScrn)
192 {
193         NVPtr pNv = NVPTR(pScrn);
194         char *busId;
195         int fd;
196
197         {
198                 pointer ret;
199                 int errmaj, errmin;
200
201                 ret = LoadSubModule(pScrn->module, "dri", NULL, NULL, NULL,
202                                     NULL, &errmaj, &errmin);
203                 if (!ret) {
204                         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205                                         "error %d\n", errmaj);
206                         LoaderErrorMsg(pScrn->name, "dri", errmaj, errmin);
207                 }
208
209                 if (!ret && errmaj != LDR_ONCEONLY)
210                         return FALSE;
211         }
212
213         xf86LoaderReqSymLists(drmSymbols, NULL);
214         xf86LoaderReqSymLists(driSymbols, NULL);
215         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loaded DRI module\n");
216
217         busId = DRICreatePCIBusID(pNv->PciInfo);
218
219         fd = drmOpen("nouveau", busId);
220         xfree(busId);
221         if (fd < 0) {
222                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
223                         "[dri] Failed to open the DRM\n");
224                 return FALSE;
225         }
226
227         /* Check the lib version */
228         if (xf86LoaderCheckSymbol("drmGetLibVersion"))
229                 pNv->pLibDRMVersion = drmGetLibVersion(0);
230         if (pNv->pLibDRMVersion == NULL) {
231                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
232                 "NVDRIGetVersion failed because libDRM is really "
233                 "way to old to even get a version number out of it.\n"
234                 "[dri] Disabling DRI.\n");
235                 return FALSE;
236         }
237
238         pNv->pKernelDRMVersion = drmGetVersion(fd);
239         drmClose(fd);
240         if (pNv->pKernelDRMVersion == NULL) {
241                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
242                         "failed to get DRM version\n");
243                 return FALSE;
244         }
245         
246         /* temporary lock step versioning */
247 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
248 #error nouveau_drm.h doesn\'t match expected patchlevel, update libdrm.
249 #endif
250         if (pNv->pKernelDRMVersion->version_patchlevel !=
251                         NOUVEAU_DRM_HEADER_PATCHLEVEL) {
252                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
253                         "wrong DRM version\n");
254                 return FALSE;
255         }
256
257         return TRUE;
258 }
259
260 Bool NVDRICheckModules(ScrnInfoPtr pScrn)
261 {
262         if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) {
263                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
264                            "[dri] GlxSetVisualConfigs not found.\n");
265                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
266                            "      NVIDIA's glx present, or glx not loaded.\n");
267                 return FALSE;
268         }
269
270         return TRUE;
271 }
272
273 Bool NVDRIScreenInit(ScrnInfoPtr pScrn)
274 {
275         DRIInfoPtr     pDRIInfo;
276         NOUVEAUDRIPtr  pNOUVEAUDRI;
277         NVPtr pNv = NVPTR(pScrn);
278         ScreenPtr pScreen;
279         pScreen = screenInfo.screens[pScrn->scrnIndex];
280         int drm_page_size;
281
282         if (!NVDRICheckModules(pScrn))
283                 return FALSE;
284
285         drm_page_size = getpagesize();
286         if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
287         
288         pNv->pDRIInfo                        = pDRIInfo;
289         pDRIInfo->drmDriverName              = "nouveau";
290         pDRIInfo->clientDriverName           = "nouveau";
291         pDRIInfo->busIdString                = DRICreatePCIBusID(pNv->PciInfo);
292
293         pDRIInfo->ddxDriverMajorVersion      = NV_MAJOR_VERSION;
294         pDRIInfo->ddxDriverMinorVersion      = NV_MINOR_VERSION;
295         pDRIInfo->ddxDriverPatchVersion      = NV_PATCHLEVEL;
296
297         /*
298          * We set the FB to be in the higher half of VRAM. If we don't, any
299          * VRAM allocations before the FB is mapped will change that map
300          * and we fail.
301          * We should detect when the DRM decides to change the FB area
302          * but we currently don't know how to.
303          */
304         pDRIInfo->frameBufferSize            = pNv->VRAMPhysicalSize / 2;
305         pDRIInfo->frameBufferPhysicalAddress = (void *)pNv->VRAMPhysical +
306                                                pDRIInfo->frameBufferSize;
307         pDRIInfo->frameBufferStride          = pScrn->displayWidth * pScrn->bitsPerPixel/8;
308
309         pDRIInfo->ddxDrawableTableEntry      = 1;
310         pDRIInfo->maxDrawableTableEntry      = 1;
311
312         if (!(pNOUVEAUDRI = (NOUVEAUDRIPtr)xcalloc(sizeof(NOUVEAUDRIRec), 1))) {
313                 DRIDestroyInfoRec(pDRIInfo);
314                 pNv->pDRIInfo = NULL;
315                 return FALSE;
316         }
317         pDRIInfo->devPrivate                 = pNOUVEAUDRI; 
318         pDRIInfo->devPrivateSize             = sizeof(NOUVEAUDRIRec);
319         pDRIInfo->contextSize                = sizeof(NVDRIContextRec);
320         pDRIInfo->SAREASize                  = (drm_page_size > SAREA_MAX) ? drm_page_size : SAREA_MAX;
321
322         pDRIInfo->CreateContext              = NVCreateContext;
323         pDRIInfo->DestroyContext             = NVDestroyContext;
324         pDRIInfo->SwapContext                = NVDRISwapContext;
325         pDRIInfo->InitBuffers                = NVDRIInitBuffers;
326         pDRIInfo->MoveBuffers                = NVDRIMoveBuffers;
327         pDRIInfo->bufferRequests             = DRI_ALL_WINDOWS;
328         pDRIInfo->TransitionTo2d             = NVDRITransitionTo2d;
329         pDRIInfo->TransitionTo3d             = NVDRITransitionTo3d;
330         pDRIInfo->TransitionSingleToMulti3D  = NVDRITransitionSingleToMulti3d;
331         pDRIInfo->TransitionMultiToSingle3D  = NVDRITransitionMultiToSingle3d;
332
333         pDRIInfo->createDummyCtx     = FALSE;
334         pDRIInfo->createDummyCtxPriv = FALSE;
335
336         if (!DRIScreenInit(pScreen, pDRIInfo, &pNv->drm_fd)) {
337                 xf86DrvMsg(pScreen->myNum, X_ERROR,
338                                 "[dri] DRIScreenInit failed.  Disabling DRI.\n");
339                 xfree(pDRIInfo->devPrivate);
340                 pDRIInfo->devPrivate = NULL;
341                 DRIDestroyInfoRec(pDRIInfo);
342                 pDRIInfo = NULL;
343                 return FALSE;
344         }
345         if (!NVDRIInitVisualConfigs(pScreen)) {
346                 xf86DrvMsg(pScreen->myNum, X_ERROR,
347                                 "[dri] NVDRIInitVisualConfigs failed.  Disabling DRI.\n");
348                 xfree(pDRIInfo->devPrivate);
349                 pDRIInfo->devPrivate = NULL;
350                 DRIDestroyInfoRec(pDRIInfo);
351                 pDRIInfo = NULL;
352                 return FALSE;
353         }
354
355         return TRUE;
356 }
357
358 Bool NVDRIFinishScreenInit(ScrnInfoPtr pScrn)
359 {
360         ScreenPtr      pScreen = screenInfo.screens[pScrn->scrnIndex];
361         NVPtr          pNv = NVPTR(pScrn);
362         NOUVEAUDRIPtr  pNOUVEAUDRI;
363
364         if (!DRIFinishScreenInit(pScreen)) {
365                 return FALSE;
366         }
367
368         pNOUVEAUDRI                     = (NOUVEAUDRIPtr)pNv->pDRIInfo->devPrivate;
369
370         pNOUVEAUDRI->device_id          = pNv->Chipset;
371
372         pNOUVEAUDRI->width              = pScrn->virtualX;
373         pNOUVEAUDRI->height             = pScrn->virtualY;
374         pNOUVEAUDRI->depth              = pScrn->depth;
375         pNOUVEAUDRI->bpp                = pScrn->bitsPerPixel;
376
377         pNOUVEAUDRI->front_offset       = pNv->FB->offset;
378         pNOUVEAUDRI->front_pitch        = pScrn->virtualX;
379         /* back/depth buffers will likely be allocated on a per-drawable
380          * basis, but these may be useful if we want to support shared back
381          * buffers at some point.
382          */
383         pNOUVEAUDRI->back_offset        = 0;
384         pNOUVEAUDRI->back_pitch         = 0;
385         pNOUVEAUDRI->depth_offset       = 0;
386         pNOUVEAUDRI->depth_pitch        = 0;
387
388         return TRUE;
389 }
390