1
/**************************************************************************
3
Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
6
Permission is hereby granted, free of charge, to any person obtaining a
7
copy of this software and associated documentation files (the
8
"Software"), to deal in the Software without restriction, including
9
without limitation the rights to use, copy, modify, merge, publish,
10
distribute, sub license, and/or sell copies of the Software, and to
11
permit persons to whom the Software is furnished to do so, subject to
12
the following conditions:
14
The above copyright notice and this permission notice (including the
15
next paragraph) shall be included in all copies or substantial portions
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
**************************************************************************/
27
/* $XFree86: xc/lib/GL/dri/dri_glx.c,v 1.12 2003/02/06 12:42:10 alanh Exp $ */
31
* Kevin E. Martin <kevin@precisioninsight.com>
32
* Brian Paul <brian@precisioninsight.com>
36
#ifdef GLX_DIRECT_RENDERING
39
#include <X11/Xlibint.h>
40
#include <X11/extensions/Xext.h>
42
#include "glxclient.h"
48
#include <sys/types.h>
52
typedef void *(*CreateScreenFunc)(Display *dpy, int scrn, __DRIscreen *psc,
53
int numConfigs, __GLXvisualConfig *config);
55
typedef void *(*RegisterExtensionsFunc)(void);
58
#ifdef BUILT_IN_DRI_DRIVER
60
extern void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
61
int numConfigs, __GLXvisualConfig *config);
64
#else /* BUILT_IN_DRI_DRIVER */
67
#ifndef DEFAULT_DRIVER_DIR
68
/* this is normally defined in the Imakefile */
69
#define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
73
* We keep a linked list of these structures, one per DRI device driver.
75
typedef struct __DRIdriverRec {
78
CreateScreenFunc createScreenFunc;
79
RegisterExtensionsFunc registerExtensionsFunc;
80
struct __DRIdriverRec *next;
83
static __DRIdriver *Drivers = NULL;
90
static void InfoMessageF(const char *f, ...)
95
if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
96
fprintf(stderr, "libGL: ");
98
vfprintf(stderr, f, args);
103
static void ErrorMessageF(const char *f, ...)
107
if (getenv("LIBGL_DEBUG")) {
108
fprintf(stderr, "libGL error: ");
110
vfprintf(stderr, f, args);
117
* We'll save a pointer to this function when we couldn't find a
118
* direct rendering driver for a given screen.
120
static void *DummyCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
121
int numConfigs, __GLXvisualConfig *config)
134
* Extract the ith directory path out of a colon-separated list of
137
* index - index of path to extract (starting at zero)
138
* paths - the colon-separated list of paths
139
* dirLen - max length of result to store in <dir>
141
* dir - the extracted directory path, dir[0] will be zero when
144
static void ExtractDir(int index, const char *paths, int dirLen, char *dir)
147
const char *start, *end;
157
else if (*start == 0) {
158
/* end of string and couldn't find ith colon */
167
while (*start == ':')
170
/* find next colon, or end of string */
172
while (*end != ':' && *end != 0) {
176
/* copy string between <start> and <end> into result string */
178
if (len > dirLen - 1)
180
strncpy(dir, start, len);
186
* Try to dlopen() the named driver. This function adds the
187
* "_dri.so" suffix to the driver name and searches the
188
* directories specified by the LIBGL_DRIVERS_PATH env var
189
* in order to find the driver.
191
* driverName - a name like "tdfx", "i810", "mga", etc.
193
* handle from dlopen, or NULL if driver file not found.
195
static __DRIdriver *OpenDriver(const char *driverName)
197
char *libPaths = NULL;
201
/* First, search Drivers list to see if we've already opened this driver */
202
for (driver = Drivers; driver; driver = driver->next) {
203
if (strcmp(driver->name, driverName) == 0) {
209
if (geteuid() == getuid()) {
210
/* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
211
libPaths = getenv("LIBGL_DRIVERS_PATH");
213
libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
216
libPaths = DEFAULT_DRIVER_DIR;
219
char libDir[1000], realDriverName[200];
221
ExtractDir(i, libPaths, 1000, libDir);
223
break; /* ran out of paths to search */
224
snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
225
InfoMessageF("OpenDriver: trying %s\n", realDriverName);
226
handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
228
/* allocate __DRIdriver struct */
229
driver = (__DRIdriver *) Xmalloc(sizeof(__DRIdriver));
231
return NULL; /* out of memory! */
232
/* init the struct */
233
driver->name = __glXstrdup(driverName);
236
return NULL; /* out of memory! */
238
driver->createScreenFunc = (CreateScreenFunc)
239
dlsym(handle, "__driCreateScreen");
240
if (!driver->createScreenFunc) {
241
/* If the driver doesn't have this symbol then something's
242
* really, really wrong.
244
ErrorMessageF("__driCreateScreen() not defined in %s_dri.so!\n",
250
driver->registerExtensionsFunc = (RegisterExtensionsFunc)
251
dlsym(handle, "__driRegisterExtensions");
252
driver->handle = handle;
253
/* put at head of linked list */
254
driver->next = Drivers;
259
ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
263
ErrorMessageF("unable to find driver: %s_dri.so\n", driverName);
269
* Given a display pointer and screen number, determine the name of
270
* the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
271
* Return True for success, False for failure.
273
static Bool GetDriverName(Display *dpy, int scrNum, char **driverName)
277
int driverMajor, driverMinor, driverPatch;
281
if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
282
ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed");
285
if (!directCapable) {
286
ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false");
290
b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
291
&driverPatch, driverName);
293
ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
297
InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
298
driverMajor, driverMinor, driverPatch, *driverName, scrNum);
305
* Given a display pointer and screen number, return a __DRIdriver handle.
306
* Return NULL if anything goes wrong.
308
static __DRIdriver *GetDriver(Display *dpy, int scrNum)
313
if (GetDriverName(dpy, scrNum, &driverName)) {
314
ret = OpenDriver(driverName);
324
#endif /* BUILT_IN_DRI_DRIVER */
327
/* This function isn't currently used.
329
static void driDestroyDisplay(Display *dpy, void *private)
331
__DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
334
const int numScreens = ScreenCount(dpy);
336
for (i = 0; i < numScreens; i++) {
337
if (pdpyp->libraryHandles[i])
338
dlclose(pdpyp->libraryHandles[i]);
340
Xfree(pdpyp->libraryHandles);
347
* Allocate, initialize and return a __DRIdisplayPrivate object.
348
* This is called from __glXInitialize() when we are given a new
351
void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
353
const int numScreens = ScreenCount(dpy);
354
__DRIdisplayPrivate *pdpyp;
355
int eventBase, errorBase;
356
int major, minor, patch;
359
/* Initialize these fields to NULL in case we fail.
360
* If we don't do this we may later get segfaults trying to free random
361
* addresses when the display is closed.
363
pdisp->private = NULL;
364
pdisp->destroyDisplay = NULL;
365
pdisp->createScreen = NULL;
367
if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
371
if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
375
pdpyp = (__DRIdisplayPrivate *)Xmalloc(sizeof(__DRIdisplayPrivate));
380
pdpyp->driMajor = major;
381
pdpyp->driMinor = minor;
382
pdpyp->driPatch = patch;
384
pdisp->destroyDisplay = driDestroyDisplay;
386
/* allocate array of pointers to createScreen funcs */
387
pdisp->createScreen = (CreateScreenFunc *) Xmalloc(numScreens * sizeof(void *));
388
if (!pdisp->createScreen) {
393
/* allocate array of library handles */
394
pdpyp->libraryHandles = (void **) Xmalloc(numScreens * sizeof(void*));
395
if (!pdpyp->libraryHandles) {
396
Xfree(pdisp->createScreen);
401
#ifdef BUILT_IN_DRI_DRIVER
402
/* we'll statically bind to the built-in __driCreateScreen function */
403
for (scrn = 0; scrn < numScreens; scrn++) {
404
pdisp->createScreen[scrn] = __driCreateScreen;
405
pdpyp->libraryHandles[scrn] = NULL;
409
/* dynamically discover DRI drivers for all screens, saving each
410
* driver's "__driCreateScreen" function pointer. That's the bootstrap
411
* entrypoint for all DRI drivers.
413
__glXRegisterExtensions();
414
for (scrn = 0; scrn < numScreens; scrn++) {
415
__DRIdriver *driver = GetDriver(dpy, scrn);
417
pdisp->createScreen[scrn] = driver->createScreenFunc;
418
pdpyp->libraryHandles[scrn] = driver->handle;
421
pdisp->createScreen[scrn] = DummyCreateScreen;
422
pdpyp->libraryHandles[scrn] = NULL;
427
return (void *)pdpyp;
433
** Here we'll query the DRI driver for each screen and let each
434
** driver register its GL extension functions. We only have to
435
** do this once. But it MUST be done before we create any contexts
436
** (i.e. before any dispatch tables are created) and before
437
** glXGetProcAddressARB() returns.
439
** Currently called by glXGetProcAddress(), __glXInitialize(), and
440
** __glXNewIndirectAPI().
443
__glXRegisterExtensions(void)
445
#ifndef BUILT_IN_DRI_DRIVER
446
static GLboolean alreadyCalled = GL_FALSE;
447
int displayNum, maxDisplays;
451
alreadyCalled = GL_TRUE;
453
if (getenv("LIBGL_MULTIHEAD")) {
454
/* we'd like to always take this path but doing so causes a second
455
* or more of delay while the XOpenDisplay() function times out.
457
maxDisplays = 10; /* infinity, really */
460
/* just open the :0 display */
464
for (displayNum = 0; displayNum < maxDisplays; displayNum++) {
465
char displayName[200];
467
snprintf(displayName, 199, ":%d.0", displayNum);
468
dpy = XOpenDisplay(displayName);
470
const int numScreens = ScreenCount(dpy);
472
for (screenNum = 0; screenNum < numScreens; screenNum++) {
473
__DRIdriver *driver = GetDriver(dpy, screenNum);
474
if (driver && driver->registerExtensionsFunc) {
475
(*driver->registerExtensionsFunc)();
488
#endif /* GLX_DIRECT_RENDERING */