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