Add two aliases for some PointParameters entrypoints for libglx compatibility.
[mesa.git] / src / glx / x11 / dri_glx.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
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:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
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.
25
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/dri/dri_glx.c,v 1.14 2003/07/16 00:54:00 dawes Exp $ */
28
29 /*
30 * Authors:
31 * Kevin E. Martin <kevin@precisioninsight.com>
32 * Brian Paul <brian@precisioninsight.com>
33 *
34 */
35
36 #ifdef GLX_DIRECT_RENDERING
37
38 #include <unistd.h>
39 #include <X11/Xlibint.h>
40 #include <X11/extensions/Xext.h>
41 #include "extutil.h"
42 #include "glxclient.h"
43 #include "xf86dri.h"
44 #include "sarea.h"
45 #include <stdio.h>
46 #include <dlfcn.h>
47 #include "dri_glx.h"
48 #include <sys/types.h>
49 #include <stdarg.h>
50
51 #ifndef RTLD_NOW
52 #define RTLD_NOW 0
53 #endif
54 #ifndef RTLD_GLOBAL
55 #define RTLD_GLOBAL 0
56 #endif
57
58 #ifdef BUILT_IN_DRI_DRIVER
59
60 extern void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
61 int numConfigs, __GLXvisualConfig *config);
62
63
64 #else /* BUILT_IN_DRI_DRIVER */
65
66
67 #ifndef DEFAULT_DRIVER_DIR
68 /* this is normally defined in the Imakefile */
69 #define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
70 #endif
71
72 static __DRIdriver *Drivers = NULL;
73
74
75 /*
76 * printf wrappers
77 */
78
79 static void InfoMessageF(const char *f, ...)
80 {
81 va_list args;
82 const char *env;
83
84 if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) {
85 fprintf(stderr, "libGL: ");
86 va_start(args, f);
87 vfprintf(stderr, f, args);
88 va_end(args);
89 }
90 }
91
92 static void ErrorMessageF(const char *f, ...)
93 {
94 va_list args;
95
96 if (getenv("LIBGL_DEBUG")) {
97 fprintf(stderr, "libGL error: ");
98 va_start(args, f);
99 vfprintf(stderr, f, args);
100 va_end(args);
101 }
102 }
103
104
105 /*
106 * We'll save a pointer to this function when we couldn't find a
107 * direct rendering driver for a given screen.
108 */
109 static void *DummyCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
110 int numConfigs, __GLXvisualConfig *config)
111 {
112 (void) dpy;
113 (void) scrn;
114 (void) psc;
115 (void) numConfigs;
116 (void) config;
117 return NULL;
118 }
119
120
121
122 /**
123 * Extract the ith directory path out of a colon-separated list of paths. No
124 * more than \c dirLen characters, including the terminating \c NUL, will be
125 * written to \c dir.
126 *
127 * \param index Index of path to extract (starting at zero)
128 * \param paths The colon-separated list of paths
129 * \param dirLen Maximum length of result to store in \c dir
130 * \param dir Buffer to hold the extracted directory path
131 *
132 * \returns
133 * The number of characters that would have been written to \c dir had there
134 * been enough room. This does not include the terminating \c NUL. When
135 * extraction fails, zero will be returned.
136 *
137 * \todo
138 * It seems like this function could be rewritten to use \c strchr.
139 */
140 static size_t
141 ExtractDir(int index, const char *paths, int dirLen, char *dir)
142 {
143 int i, len;
144 const char *start, *end;
145
146 /* find ith colon */
147 start = paths;
148 i = 0;
149 while (i < index) {
150 if (*start == ':') {
151 i++;
152 start++;
153 }
154 else if (*start == 0) {
155 /* end of string and couldn't find ith colon */
156 dir[0] = 0;
157 return 0;
158 }
159 else {
160 start++;
161 }
162 }
163
164 while (*start == ':')
165 start++;
166
167 /* find next colon, or end of string */
168 end = start + 1;
169 while (*end != ':' && *end != 0) {
170 end++;
171 }
172
173 /* copy string between <start> and <end> into result string */
174 len = end - start;
175 if (len > dirLen - 1)
176 len = dirLen - 1;
177 strncpy(dir, start, len);
178 dir[len] = 0;
179
180 return( end - start );
181 }
182
183
184 /**
185 * Try to \c dlopen the named driver.
186 *
187 * This function adds the "_dri.so" suffix to the driver name and searches the
188 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
189 * order to find the driver.
190 *
191 * \param driverName - a name like "tdfx", "i810", "mga", etc.
192 *
193 * \returns
194 * A handle from \c dlopen, or \c NULL if driver file not found.
195 */
196 static __DRIdriver *OpenDriver(const char *driverName)
197 {
198 char *libPaths = NULL;
199 char libDir[1000];
200 int i;
201 __DRIdriver *driver;
202
203 /* First, search Drivers list to see if we've already opened this driver */
204 for (driver = Drivers; driver; driver = driver->next) {
205 if (strcmp(driver->name, driverName) == 0) {
206 /* found it */
207 return driver;
208 }
209 }
210
211 if (geteuid() == getuid()) {
212 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
213 libPaths = getenv("LIBGL_DRIVERS_PATH");
214 if (!libPaths)
215 libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
216 }
217 if (!libPaths)
218 libPaths = DEFAULT_DRIVER_DIR;
219
220 for ( i = 0 ; ExtractDir(i, libPaths, 1000, libDir) != 0 ; i++ ) {
221 char realDriverName[200];
222 void *handle = NULL;
223
224
225 /* If TLS support is enabled, try to open the TLS version of the driver
226 * binary first. If that fails, try the non-TLS version.
227 */
228 #ifdef GLX_USE_TLS
229 snprintf(realDriverName, 200, "%s/tls/%s_dri.so", libDir, driverName);
230 InfoMessageF("OpenDriver: trying %s\n", realDriverName);
231 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
232 #endif
233
234 if ( handle == NULL ) {
235 snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
236 InfoMessageF("OpenDriver: trying %s\n", realDriverName);
237 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
238 }
239
240 if ( handle != NULL ) {
241 /* allocate __DRIdriver struct */
242 driver = (__DRIdriver *) Xmalloc(sizeof(__DRIdriver));
243 if (!driver)
244 return NULL; /* out of memory! */
245 /* init the struct */
246 driver->name = __glXstrdup(driverName);
247 if (!driver->name) {
248 Xfree(driver);
249 return NULL; /* out of memory! */
250 }
251
252 driver->createScreenFunc = (CreateScreenFunc)
253 dlsym(handle, "__driCreateScreen");
254 driver->createNewScreenFunc = (CreateNewScreenFunc)
255 dlsym(handle, "__driCreateNewScreen");
256
257 if ( (driver->createScreenFunc == NULL)
258 && (driver->createNewScreenFunc == NULL) ) {
259 /* If the driver doesn't have this symbol then something's
260 * really, really wrong.
261 */
262 ErrorMessageF("Neither __driCreateScreen or __driCreateNewScreen "
263 "are defined in %s_dri.so!\n", driverName);
264 Xfree(driver);
265 dlclose(handle);
266 continue;
267 }
268 driver->handle = handle;
269 /* put at head of linked list */
270 driver->next = Drivers;
271 Drivers = driver;
272 return driver;
273 }
274 else {
275 ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
276 }
277 }
278
279 ErrorMessageF("unable to find driver: %s_dri.so\n", driverName);
280 return NULL;
281 }
282
283
284 /*
285 * Given a display pointer and screen number, determine the name of
286 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
287 * Return True for success, False for failure.
288 */
289 static Bool GetDriverName(Display *dpy, int scrNum, char **driverName)
290 {
291 int directCapable;
292 Bool b;
293 int driverMajor, driverMinor, driverPatch;
294
295 *driverName = NULL;
296
297 if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
298 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
299 return False;
300 }
301 if (!directCapable) {
302 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
303 return False;
304 }
305
306 b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
307 &driverPatch, driverName);
308 if (!b) {
309 ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
310 return False;
311 }
312
313 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
314 driverMajor, driverMinor, driverPatch, *driverName, scrNum);
315
316 return True;
317 }
318
319
320 /*
321 * Given a display pointer and screen number, return a __DRIdriver handle.
322 * Return NULL if anything goes wrong.
323 */
324 __DRIdriver *driGetDriver(Display *dpy, int scrNum)
325 {
326 char *driverName;
327 if (GetDriverName(dpy, scrNum, &driverName)) {
328 __DRIdriver *ret;
329 ret = OpenDriver(driverName);
330 if (driverName)
331 Xfree(driverName);
332 return ret;
333 }
334 return NULL;
335 }
336
337
338 /*
339 * Exported function for querying the DRI driver for a given screen.
340 *
341 * The returned char pointer points to a static array that will be
342 * overwritten by subsequent calls.
343 */
344 const char *glXGetScreenDriver (Display *dpy, int scrNum) {
345 static char ret[32];
346 char *driverName;
347 if (GetDriverName(dpy, scrNum, &driverName)) {
348 int len;
349 if (!driverName)
350 return NULL;
351 len = strlen (driverName);
352 if (len >= 31)
353 return NULL;
354 memcpy (ret, driverName, len+1);
355 Xfree(driverName);
356 return ret;
357 }
358 return NULL;
359 }
360
361
362 /*
363 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
364 *
365 * The returned char pointer points directly into the driver. Therefore
366 * it should be treated as a constant.
367 *
368 * If the driver was not found or does not support configuration NULL is
369 * returned.
370 *
371 * Note: The driver remains opened after this function returns.
372 */
373 const char *glXGetDriverConfig (const char *driverName) {
374 __DRIdriver *driver = OpenDriver (driverName);
375 if (driver)
376 return dlsym (driver->handle, "__driConfigOptions");
377 else
378 return NULL;
379 }
380
381
382 #endif /* BUILT_IN_DRI_DRIVER */
383
384
385 /* This function isn't currently used.
386 */
387 static void driDestroyDisplay(Display *dpy, void *private)
388 {
389 __DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
390
391 if (pdpyp) {
392 const int numScreens = ScreenCount(dpy);
393 int i;
394 for (i = 0; i < numScreens; i++) {
395 if (pdpyp->libraryHandles[i])
396 dlclose(pdpyp->libraryHandles[i]);
397 }
398 Xfree(pdpyp->libraryHandles);
399 Xfree(pdpyp);
400 }
401 }
402
403
404 /*
405 * Allocate, initialize and return a __DRIdisplayPrivate object.
406 * This is called from __glXInitialize() when we are given a new
407 * display pointer.
408 */
409 void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
410 {
411 const int numScreens = ScreenCount(dpy);
412 __DRIdisplayPrivate *pdpyp;
413 int eventBase, errorBase;
414 int major, minor, patch;
415 int scrn;
416
417 /* Initialize these fields to NULL in case we fail.
418 * If we don't do this we may later get segfaults trying to free random
419 * addresses when the display is closed.
420 */
421 pdisp->private = NULL;
422 pdisp->destroyDisplay = NULL;
423 pdisp->createScreen = NULL;
424
425 if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
426 return NULL;
427 }
428
429 if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
430 return NULL;
431 }
432
433 pdpyp = (__DRIdisplayPrivate *)Xmalloc(sizeof(__DRIdisplayPrivate));
434 if (!pdpyp) {
435 return NULL;
436 }
437
438 pdpyp->driMajor = major;
439 pdpyp->driMinor = minor;
440 pdpyp->driPatch = patch;
441
442 pdisp->destroyDisplay = driDestroyDisplay;
443
444 /* allocate array of pointers to createScreen funcs */
445 pdisp->createScreen = (CreateScreenFunc *) Xmalloc(numScreens * sizeof(void *));
446 if (!pdisp->createScreen) {
447 Xfree(pdpyp);
448 return NULL;
449 }
450
451 /* allocate array of pointers to createScreen funcs */
452 pdisp->createNewScreen = (CreateNewScreenFunc *) Xmalloc(numScreens * sizeof(void *));
453 if (!pdisp->createNewScreen) {
454 Xfree(pdisp->createScreen);
455 Xfree(pdpyp);
456 return NULL;
457 }
458
459 /* allocate array of library handles */
460 pdpyp->libraryHandles = (void **) Xmalloc(numScreens * sizeof(void*));
461 if (!pdpyp->libraryHandles) {
462 Xfree(pdisp->createNewScreen);
463 Xfree(pdisp->createScreen);
464 Xfree(pdpyp);
465 return NULL;
466 }
467
468 #ifdef BUILT_IN_DRI_DRIVER
469 /* we'll statically bind to the built-in __driCreateScreen function */
470 for (scrn = 0; scrn < numScreens; scrn++) {
471 pdisp->createScreen[scrn] = __driCreateScreen;
472 pdisp->createNewScreen[scrn] = NULL;
473 pdpyp->libraryHandles[scrn] = NULL;
474 }
475
476 #else
477 /* dynamically discover DRI drivers for all screens, saving each
478 * driver's "__driCreateScreen" function pointer. That's the bootstrap
479 * entrypoint for all DRI drivers.
480 */
481 for (scrn = 0; scrn < numScreens; scrn++) {
482 __DRIdriver *driver = driGetDriver(dpy, scrn);
483 if (driver) {
484 pdisp->createScreen[scrn] = driver->createScreenFunc;
485 pdisp->createNewScreen[scrn] = driver->createNewScreenFunc;
486 pdpyp->libraryHandles[scrn] = driver->handle;
487 }
488 else {
489 pdisp->createScreen[scrn] = DummyCreateScreen;
490 pdisp->createNewScreen[scrn] = NULL;
491 pdpyp->libraryHandles[scrn] = NULL;
492 }
493 }
494 #endif
495
496 return (void *)pdpyp;
497 }
498
499 #endif /* GLX_DIRECT_RENDERING */