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 */
253
if (pNv->pKernelDRMVersion == NULL) {
254
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
255
"failed to get DRM version\n");
259
/* temporary lock step versioning */
260
#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 10
261
#error nouveau_drm.h does not match expected patchlevel, update libdrm.
263
if (pNv->pKernelDRMVersion->version_patchlevel !=
264
NOUVEAU_DRM_HEADER_PATCHLEVEL) {
265
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
266
"wrong DRM version\n");
273
Bool NVDRICheckModules(ScrnInfoPtr pScrn)
275
if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) {
276
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
277
"[dri] GlxSetVisualConfigs not found.\n");
278
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
279
" NVIDIA's glx present, or glx not loaded.\n");
286
Bool NVDRIScreenInit(ScrnInfoPtr pScrn)
289
NOUVEAUDRIPtr pNOUVEAUDRI;
290
NVPtr pNv = NVPTR(pScrn);
292
pScreen = screenInfo.screens[pScrn->scrnIndex];
297
/* drm already open, reuse it */
299
drmmode_ptr drmmode = pNv->drmmode;
300
drm_fd = drmmode->fd;
304
if (!NVDRICheckModules(pScrn))
307
drm_page_size = getpagesize();
308
if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
310
pNv->pDRIInfo = pDRIInfo;
311
pDRIInfo->drmDriverName = "nouveau";
312
pDRIInfo->clientDriverName = "nouveau";
313
pDRIInfo->busIdString = DRICreatePCIBusID(pNv->PciInfo);
315
pDRIInfo->ddxDriverMajorVersion = NV_MAJOR_VERSION;
316
pDRIInfo->ddxDriverMinorVersion = NV_MINOR_VERSION;
317
pDRIInfo->ddxDriverPatchVersion = NV_PATCHLEVEL;
320
* We set the FB to be in the higher half of VRAM. If we don't, any
321
* VRAM allocations before the FB is mapped will change that map
323
* We should detect when the DRM decides to change the FB area
324
* but we currently don't know how to.
326
pDRIInfo->frameBufferSize = pNv->VRAMPhysicalSize / 2;
327
pDRIInfo->frameBufferPhysicalAddress = (void *)pNv->VRAMPhysical;
328
pDRIInfo->frameBufferStride = pScrn->displayWidth * pScrn->bitsPerPixel/8;
330
pDRIInfo->ddxDrawableTableEntry = 1;
331
pDRIInfo->maxDrawableTableEntry = 1;
333
if (!(pNOUVEAUDRI = (NOUVEAUDRIPtr)xcalloc(sizeof(NOUVEAUDRIRec), 1))) {
334
DRIDestroyInfoRec(pDRIInfo);
335
pNv->pDRIInfo = NULL;
338
pDRIInfo->devPrivate = pNOUVEAUDRI;
339
pDRIInfo->devPrivateSize = sizeof(NOUVEAUDRIRec);
340
pDRIInfo->contextSize = sizeof(NVDRIContextRec);
341
pDRIInfo->SAREASize = (drm_page_size > SAREA_MAX) ? drm_page_size : SAREA_MAX;
343
pDRIInfo->CreateContext = NVCreateContext;
344
pDRIInfo->DestroyContext = NVDestroyContext;
345
pDRIInfo->SwapContext = NVDRISwapContext;
346
pDRIInfo->InitBuffers = NVDRIInitBuffers;
347
pDRIInfo->MoveBuffers = NVDRIMoveBuffers;
348
pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
349
pDRIInfo->TransitionTo2d = NVDRITransitionTo2d;
350
pDRIInfo->TransitionTo3d = NVDRITransitionTo3d;
351
pDRIInfo->TransitionSingleToMulti3D = NVDRITransitionSingleToMulti3d;
352
pDRIInfo->TransitionMultiToSingle3D = NVDRITransitionMultiToSingle3d;
354
pDRIInfo->createDummyCtx = FALSE;
355
pDRIInfo->createDummyCtxPriv = FALSE;
357
if (!DRIScreenInit(pScreen, pDRIInfo, &drm_fd)) {
358
xf86DrvMsg(pScreen->myNum, X_ERROR,
359
"[dri] DRIScreenInit failed. Disabling DRI.\n");
360
xfree(pDRIInfo->devPrivate);
361
pDRIInfo->devPrivate = NULL;
362
DRIDestroyInfoRec(pDRIInfo);
367
if (!NVDRIInitVisualConfigs(pScreen)) {
368
xf86DrvMsg(pScreen->myNum, X_ERROR,
369
"[dri] NVDRIInitVisualConfigs failed. Disabling DRI.\n");
370
xfree(pDRIInfo->devPrivate);
371
pDRIInfo->devPrivate = NULL;
372
DRIDestroyInfoRec(pDRIInfo);
377
/* turn on need_close, so we explictly drmClose() on exit */
378
if (nouveau_device_open_existing(&pNv->dev, 1, drm_fd, 0)) {
379
xf86DrvMsg(pScreen->myNum, X_ERROR, "Error creating device\n");
380
xfree(pDRIInfo->devPrivate);
381
pDRIInfo->devPrivate = NULL;
382
DRIDestroyInfoRec(pDRIInfo);
390
Bool NVDRIFinishScreenInit(ScrnInfoPtr pScrn)
392
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
393
NVPtr pNv = NVPTR(pScrn);
394
NOUVEAUDRIPtr pNOUVEAUDRI;
396
if (!DRIFinishScreenInit(pScreen)) {
400
pNOUVEAUDRI = (NOUVEAUDRIPtr)pNv->pDRIInfo->devPrivate;
402
pNOUVEAUDRI->device_id = pNv->Chipset;
404
pNOUVEAUDRI->width = pScrn->virtualX;
405
pNOUVEAUDRI->height = pScrn->virtualY;
406
pNOUVEAUDRI->depth = pScrn->depth;
407
pNOUVEAUDRI->bpp = pScrn->bitsPerPixel;
409
pNOUVEAUDRI->front_offset = pNv->FB->offset;
410
pNOUVEAUDRI->front_pitch = pScrn->displayWidth;
411
/* back/depth buffers will likely be allocated on a per-drawable
412
* basis, but these may be useful if we want to support shared back
413
* buffers at some point.
415
pNOUVEAUDRI->back_offset = 0;
416
pNOUVEAUDRI->back_pitch = 0;
417
pNOUVEAUDRI->depth_offset = 0;
418
pNOUVEAUDRI->depth_pitch = 0;
423
void NVDRICloseScreen(ScrnInfoPtr pScrn)
425
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
426
NVPtr pNv = NVPTR(pScrn);
428
DRICloseScreen(pScreen);
429
nouveau_device_close(&pNv->dev);