2 * Copyright 2006 Stephane Marchesin
3 * Copyright 2006 Ben Skeggs
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include "nv_include.h"
26 #define _XF86DRI_SERVER_
27 #include "GL/glxint.h"
28 #include "GL/glxtokens.h"
32 #include "nv_dripriv.h"
34 #include "drmmode_display.h"
36 static Bool NVCreateContext(ScreenPtr pScreen, VisualPtr visual,
37 drm_context_t hwContext, void *pVisualConfigPriv,
38 DRIContextType contextStore)
44 static void NVDestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
45 DRIContextType contextStore)
50 static void NVDRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
51 DRIContextType oldContextType,
53 DRIContextType newContextType,
56 /* we really should do something here */
60 static void NVDRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 indx)
65 static void NVDRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
66 RegionPtr prgnSrc, CARD32 indx)
71 static void NVDRITransitionTo2d(ScreenPtr pScreen)
76 static void NVDRITransitionTo3d(ScreenPtr pScreen)
81 static void NVDRITransitionSingleToMulti3d(ScreenPtr pScreen)
86 static void NVDRITransitionMultiToSingle3d(ScreenPtr pScreen)
91 static Bool NVDRIInitVisualConfigs(ScreenPtr pScreen)
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};
105 num_configs=2*3*((pScrn->depth==24)?2:1)*2; /* db*depth*alpha*stencil */
106 if (!(pConfigs=(__GLXvisualConfig*)xcalloc(sizeof(__GLXvisualConfig),num_configs)))
108 if (!(pNVConfigs=(NVConfigPrivPtr)xcalloc(sizeof(NVConfigPrivRec), num_configs))) {
112 if (!(pNVConfigPtrs=(NVConfigPrivPtr *)xcalloc(sizeof(NVConfigPrivPtr),num_configs))) {
120 for(depth=0;depth<3;depth++)
121 for(alpha=0;alpha<((pScrn->depth==24)?2:1);alpha++)
122 for(stencil=0;stencil<2;stencil++)
124 pConfigs[i].vid = (VisualID)(-1);
125 pConfigs[i].class = -1;
126 pConfigs[i].rgba = TRUE;
127 if (pScrn->depth==16)
129 pConfigs[i].redSize = 5;
130 pConfigs[i].greenSize = 6;
131 pConfigs[i].blueSize = 5;
132 pConfigs[i].alphaSize = 0;
133 pConfigs[i].redMask = 0x0000F800;
134 pConfigs[i].greenMask = 0x000007E0;
135 pConfigs[i].blueMask = 0x0000001F;
136 pConfigs[i].alphaMask = 0x00000000;
138 pConfigs[i].redSize = 8;
139 pConfigs[i].greenSize = 8;
140 pConfigs[i].blueSize = 8;
141 pConfigs[i].redMask = 0x00FF0000;
142 pConfigs[i].greenMask = 0x0000FF00;
143 pConfigs[i].blueMask = 0x000000FF;
145 pConfigs[i].alphaSize = 8;
146 pConfigs[i].alphaMask = 0xFF000000;
148 pConfigs[i].alphaSize = 0;
149 pConfigs[i].alphaMask = 0x00000000;
153 pConfigs[i].accumRedSize = 0;
154 pConfigs[i].accumGreenSize = 0;
155 pConfigs[i].accumBlueSize = 0;
156 pConfigs[i].accumAlphaSize = 0;
158 pConfigs[i].doubleBuffer = TRUE;
160 pConfigs[i].doubleBuffer = FALSE;
161 pConfigs[i].stereo = FALSE;
162 pConfigs[i].bufferSize = pScrn->depth;
163 if (depths[depth] == 24 && stencil) {
164 pConfigs[i].depthSize = depths[depth];
165 pConfigs[i].stencilSize = 8;
167 pConfigs[i].depthSize = depths[depth];
168 pConfigs[i].stencilSize = 0;
170 pConfigs[i].auxBuffers = 0;
171 pConfigs[i].level = 0;
172 pConfigs[i].visualRating = GLX_NONE;
173 pConfigs[i].transparentPixel = GLX_NONE;
174 pConfigs[i].transparentRed = 0;
175 pConfigs[i].transparentGreen = 0;
176 pConfigs[i].transparentBlue = 0;
177 pConfigs[i].transparentAlpha = 0;
178 pConfigs[i].transparentIndex = 0;
183 xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] no DRI at %d bpp ",pScrn->depth);
186 GlxSetVisualConfigs(num_configs, pConfigs, (void**)pNVConfigPtrs);
190 Bool NVDRIGetVersion(ScrnInfoPtr pScrn)
192 NVPtr pNv = NVPTR(pScrn);
197 /* drm already open */
199 drmmode_ptr drmmode = pNv->drmmode;
208 ret = LoadSubModule(pScrn->module, "dri", NULL, NULL, NULL,
209 NULL, &errmaj, &errmin);
211 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
212 "error %d\n", errmaj);
213 LoaderErrorMsg(pScrn->name, "dri", errmaj, errmin);
216 if (!ret && errmaj != LDR_ONCEONLY)
220 xf86LoaderReqSymLists(drmSymbols, NULL);
221 xf86LoaderReqSymLists(driSymbols, NULL);
222 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loaded DRI module\n");
225 busId = DRICreatePCIBusID(pNv->PciInfo);
227 fd = drmOpen("nouveau", busId);
231 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
232 "[dri] Failed to open the DRM\n");
236 /* Check the lib version */
237 if (xf86LoaderCheckSymbol("drmGetLibVersion"))
238 pNv->pLibDRMVersion = drmGetLibVersion(0);
239 if (pNv->pLibDRMVersion == NULL) {
240 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
241 "NVDRIGetVersion failed because libDRM is really "
242 "way to old to even get a version number out of it.\n"
243 "[dri] Disabling DRI.\n");
247 pNv->pKernelDRMVersion = drmGetVersion(fd);
249 if (!pNv->drmmode) /* drmmode still needs the file descriptor */
255 if (pNv->pKernelDRMVersion == NULL) {
256 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
257 "failed to get DRM version\n");
261 /* temporary lock step versioning */
262 #if NOUVEAU_DRM_HEADER_PATCHLEVEL != 11
263 #error nouveau_drm.h does not match expected patchlevel, update libdrm.
265 if (pNv->pKernelDRMVersion->version_patchlevel !=
266 NOUVEAU_DRM_HEADER_PATCHLEVEL) {
267 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
268 "wrong DRM version\n");
275 Bool NVDRICheckModules(ScrnInfoPtr pScrn)
277 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) {
278 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
279 "[dri] GlxSetVisualConfigs not found.\n");
280 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
281 " NVIDIA's glx present, or glx not loaded.\n");
288 Bool NVDRIScreenInit(ScrnInfoPtr pScrn)
291 NOUVEAUDRIPtr pNOUVEAUDRI;
292 NVPtr pNv = NVPTR(pScrn);
294 pScreen = screenInfo.screens[pScrn->scrnIndex];
299 /* drm already open, reuse it */
301 drmmode_ptr drmmode = pNv->drmmode;
302 drm_fd = drmmode->fd;
306 if (!NVDRICheckModules(pScrn))
309 drm_page_size = getpagesize();
310 if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
312 pNv->pDRIInfo = pDRIInfo;
313 pDRIInfo->drmDriverName = "nouveau";
314 pDRIInfo->clientDriverName = "nouveau";
315 pDRIInfo->busIdString = DRICreatePCIBusID(pNv->PciInfo);
317 pDRIInfo->ddxDriverMajorVersion = NV_MAJOR_VERSION;
318 pDRIInfo->ddxDriverMinorVersion = NV_MINOR_VERSION;
319 pDRIInfo->ddxDriverPatchVersion = NV_PATCHLEVEL;
322 * We set the FB to be in the higher half of VRAM. If we don't, any
323 * VRAM allocations before the FB is mapped will change that map
325 * We should detect when the DRM decides to change the FB area
326 * but we currently don't know how to.
328 pDRIInfo->frameBufferSize = pNv->VRAMPhysicalSize / 2;
329 pDRIInfo->frameBufferPhysicalAddress = (void *)pNv->VRAMPhysical;
330 pDRIInfo->frameBufferStride = pScrn->displayWidth * pScrn->bitsPerPixel/8;
332 pDRIInfo->ddxDrawableTableEntry = 1;
333 pDRIInfo->maxDrawableTableEntry = 1;
335 if (!(pNOUVEAUDRI = (NOUVEAUDRIPtr)xcalloc(sizeof(NOUVEAUDRIRec), 1))) {
336 DRIDestroyInfoRec(pDRIInfo);
337 pNv->pDRIInfo = NULL;
340 pDRIInfo->devPrivate = pNOUVEAUDRI;
341 pDRIInfo->devPrivateSize = sizeof(NOUVEAUDRIRec);
342 pDRIInfo->contextSize = sizeof(NVDRIContextRec);
343 pDRIInfo->SAREASize = (drm_page_size > SAREA_MAX) ? drm_page_size : SAREA_MAX;
345 pDRIInfo->CreateContext = NVCreateContext;
346 pDRIInfo->DestroyContext = NVDestroyContext;
347 pDRIInfo->SwapContext = NVDRISwapContext;
348 pDRIInfo->InitBuffers = NVDRIInitBuffers;
349 pDRIInfo->MoveBuffers = NVDRIMoveBuffers;
350 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
351 pDRIInfo->TransitionTo2d = NVDRITransitionTo2d;
352 pDRIInfo->TransitionTo3d = NVDRITransitionTo3d;
353 pDRIInfo->TransitionSingleToMulti3D = NVDRITransitionSingleToMulti3d;
354 pDRIInfo->TransitionMultiToSingle3D = NVDRITransitionMultiToSingle3d;
356 pDRIInfo->createDummyCtx = FALSE;
357 pDRIInfo->createDummyCtxPriv = FALSE;
359 if (!DRIScreenInit(pScreen, pDRIInfo, &drm_fd)) {
360 xf86DrvMsg(pScreen->myNum, X_ERROR,
361 "[dri] DRIScreenInit failed. Disabling DRI.\n");
362 xfree(pDRIInfo->devPrivate);
363 pDRIInfo->devPrivate = NULL;
364 DRIDestroyInfoRec(pDRIInfo);
369 if (!NVDRIInitVisualConfigs(pScreen)) {
370 xf86DrvMsg(pScreen->myNum, X_ERROR,
371 "[dri] NVDRIInitVisualConfigs failed. Disabling DRI.\n");
372 xfree(pDRIInfo->devPrivate);
373 pDRIInfo->devPrivate = NULL;
374 DRIDestroyInfoRec(pDRIInfo);
379 /* need_close = 0, because DRICloseScreen() will handle the closing. */
380 if (nouveau_device_open_existing(&pNv->dev, 0, drm_fd, 0)) {
381 xf86DrvMsg(pScreen->myNum, X_ERROR, "Error creating device\n");
382 xfree(pDRIInfo->devPrivate);
383 pDRIInfo->devPrivate = NULL;
384 DRIDestroyInfoRec(pDRIInfo);
392 Bool NVDRIFinishScreenInit(ScrnInfoPtr pScrn)
394 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
395 NVPtr pNv = NVPTR(pScrn);
396 NOUVEAUDRIPtr pNOUVEAUDRI;
398 if (!DRIFinishScreenInit(pScreen)) {
402 pNOUVEAUDRI = (NOUVEAUDRIPtr)pNv->pDRIInfo->devPrivate;
404 pNOUVEAUDRI->device_id = pNv->Chipset;
406 pNOUVEAUDRI->width = pScrn->virtualX;
407 pNOUVEAUDRI->height = pScrn->virtualY;
408 pNOUVEAUDRI->depth = pScrn->depth;
409 pNOUVEAUDRI->bpp = pScrn->bitsPerPixel;
411 pNOUVEAUDRI->front_offset = pNv->FB->offset;
412 pNOUVEAUDRI->front_pitch = pScrn->displayWidth;
413 /* back/depth buffers will likely be allocated on a per-drawable
414 * basis, but these may be useful if we want to support shared back
415 * buffers at some point.
417 pNOUVEAUDRI->back_offset = 0;
418 pNOUVEAUDRI->back_pitch = 0;
419 pNOUVEAUDRI->depth_offset = 0;
420 pNOUVEAUDRI->depth_pitch = 0;
425 void NVDRICloseScreen(ScrnInfoPtr pScrn)
427 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
428 NVPtr pNv = NVPTR(pScrn);
430 /* close fifo channel so it won't fail on open for next server generation. */
431 nouveau_channel_free(&pNv->chan);
433 /* this may not work for kernel modesetting, so i'm leaving a note. */
434 nouveau_device_close(&pNv->dev);
436 DRICloseScreen(pScreen);
439 if (pNv->pDRIInfo->devPrivate) {
440 xfree(pNv->pDRIInfo->devPrivate);
441 pNv->pDRIInfo->devPrivate = NULL;
443 DRIDestroyInfoRec(pNv->pDRIInfo);
444 pNv->pDRIInfo = NULL;