1 /* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
3 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 * Copyright © 2008 Red Hat, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Soft-
8 * ware"), to deal in the Software without restriction, including without
9 * limitation the rights to use, copy, modify, merge, publish, distribute,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, provided that the above copyright
12 * notice(s) and this permission notice appear in all copies of the Soft-
13 * ware and that both the above copyright notice(s) and this permission
14 * notice appear in supporting documentation.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
19 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
20 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
21 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
24 * MANCE OF THIS SOFTWARE.
26 * Except as contained in this notice, the name of a copyright holder shall
27 * not be used in advertising or otherwise to promote the sale, use or
28 * other dealings in this Software without prior written authorization of
29 * the copyright holder.
32 * Kevin E. Martin <kevin@precisioninsight.com>
33 * Brian Paul <brian@precisioninsight.com>
34 * Kristian Høgsberg (krh@redhat.com)
37 #ifdef GLX_DIRECT_RENDERING
42 #include "glxclient.h"
43 #include "glcontextmodes.h"
44 #include "dri_common.h"
53 _X_HIDDEN
void InfoMessageF(const char *f
, ...)
58 if ((env
= getenv("LIBGL_DEBUG")) && strstr(env
, "verbose")) {
59 fprintf(stderr
, "libGL: ");
61 vfprintf(stderr
, f
, args
);
67 * Print error to stderr, unless LIBGL_DEBUG=="quiet".
69 _X_HIDDEN
void ErrorMessageF(const char *f
, ...)
74 if ((env
= getenv("LIBGL_DEBUG")) && !strstr(env
, "quiet")) {
75 fprintf(stderr
, "libGL error: ");
77 vfprintf(stderr
, f
, args
);
82 #ifndef DEFAULT_DRIVER_DIR
83 /* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
84 #define DEFAULT_DRIVER_DIR "/usr/local/lib/dri"
88 * Try to \c dlopen the named driver.
90 * This function adds the "_dri.so" suffix to the driver name and searches the
91 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
92 * order to find the driver.
94 * \param driverName - a name like "tdfx", "i810", "mga", etc.
97 * A handle from \c dlopen, or \c NULL if driver file not found.
99 _X_HIDDEN
void *driOpenDriver(const char *driverName
)
101 void *glhandle
, *handle
;
102 const char *libPaths
, *p
, *next
;
103 char realDriverName
[200];
106 /* Attempt to make sure libGL symbols will be visible to the driver */
107 glhandle
= dlopen("libGL.so.1", RTLD_NOW
| RTLD_GLOBAL
);
110 if (geteuid() == getuid()) {
111 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
112 libPaths
= getenv("LIBGL_DRIVERS_PATH");
114 libPaths
= getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
116 if (libPaths
== NULL
)
117 libPaths
= DEFAULT_DRIVER_DIR
;
120 for (p
= libPaths
; *p
; p
= next
) {
121 next
= strchr(p
, ':');
131 snprintf(realDriverName
, sizeof realDriverName
,
132 "%.*s/tls/%s_dri.so", len
, p
, driverName
);
133 InfoMessageF("OpenDriver: trying %s\n", realDriverName
);
134 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
137 if ( handle
== NULL
) {
138 snprintf(realDriverName
, sizeof realDriverName
,
139 "%.*s/%s_dri.so", len
, p
, driverName
);
140 InfoMessageF("OpenDriver: trying %s\n", realDriverName
);
141 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
144 if ( handle
!= NULL
)
147 ErrorMessageF("dlopen %s failed (%s)\n", realDriverName
, dlerror());
151 ErrorMessageF("unable to load driver: %s_dri.so\n", driverName
);
159 _X_HIDDEN
const __DRIsystemTimeExtension systemTimeExtension
= {
160 { __DRI_SYSTEM_TIME
, __DRI_SYSTEM_TIME_VERSION
},
165 #define __ATTRIB(attrib, field) \
166 { attrib, offsetof(__GLcontextModes, field) }
168 static const struct { unsigned int attrib
, offset
; } attribMap
[] = {
169 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE
, rgbBits
),
170 __ATTRIB(__DRI_ATTRIB_LEVEL
, level
),
171 __ATTRIB(__DRI_ATTRIB_RED_SIZE
, redBits
),
172 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE
, greenBits
),
173 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE
, blueBits
),
174 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE
, alphaBits
),
175 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE
, depthBits
),
176 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE
, stencilBits
),
177 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE
, accumRedBits
),
178 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE
, accumGreenBits
),
179 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE
, accumBlueBits
),
180 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
181 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS
, sampleBuffers
),
182 __ATTRIB(__DRI_ATTRIB_SAMPLES
, samples
),
183 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER
, doubleBufferMode
),
184 __ATTRIB(__DRI_ATTRIB_STEREO
, stereoMode
),
185 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS
, numAuxBuffers
),
187 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE
, transparentPixel
),
188 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE
, transparentIndex
),
189 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE
, transparentRed
),
190 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE
, transparentGreen
),
191 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE
, transparentBlue
),
192 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE
, transparentAlpha
),
193 __ATTRIB(__DRI_ATTRIB_RED_MASK
, redMask
),
194 __ATTRIB(__DRI_ATTRIB_GREEN_MASK
, greenMask
),
195 __ATTRIB(__DRI_ATTRIB_BLUE_MASK
, blueMask
),
196 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK
, alphaMask
),
198 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH
, maxPbufferWidth
),
199 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT
, maxPbufferHeight
),
200 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS
, maxPbufferPixels
),
201 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH
, optimalPbufferWidth
),
202 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT
, optimalPbufferHeight
),
204 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD
, swapMethod
),
206 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB
, bindToTextureRgb
),
207 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA
, bindToTextureRgba
),
208 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE
, bindToMipmapTexture
),
209 __ATTRIB(__DRI_ATTRIB_YINVERTED
, yInverted
),
212 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
215 scalarEqual(__GLcontextModes
*mode
, unsigned int attrib
, unsigned int value
)
217 unsigned int glxValue
;
220 for (i
= 0; i
< ARRAY_SIZE(attribMap
); i
++)
221 if (attribMap
[i
].attrib
== attrib
) {
222 glxValue
= *(unsigned int *) ((char *) mode
+ attribMap
[i
].offset
);
223 return glxValue
== GLX_DONT_CARE
|| glxValue
== value
;
226 return GL_TRUE
; /* Is a non-existing attribute equal to value? */
230 driConfigEqual(const __DRIcoreExtension
*core
,
231 __GLcontextModes
*modes
, const __DRIconfig
*driConfig
)
233 unsigned int attrib
, value
, glxValue
;
237 while (core
->indexConfigAttrib(driConfig
, i
++, &attrib
, &value
)) {
239 case __DRI_ATTRIB_RENDER_TYPE
:
241 if (value
& __DRI_ATTRIB_RGBA_BIT
) {
242 glxValue
|= GLX_RGBA_BIT
;
243 } else if (value
& __DRI_ATTRIB_COLOR_INDEX_BIT
) {
244 glxValue
|= GLX_COLOR_INDEX_BIT
;
246 if (glxValue
!= modes
->renderType
)
250 case __DRI_ATTRIB_CONFIG_CAVEAT
:
251 if (value
& __DRI_ATTRIB_NON_CONFORMANT_CONFIG
)
252 glxValue
= GLX_NON_CONFORMANT_CONFIG
;
253 else if (value
& __DRI_ATTRIB_SLOW_BIT
)
254 glxValue
= GLX_SLOW_CONFIG
;
257 if (glxValue
!= modes
->visualRating
)
261 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS
:
263 if (value
& __DRI_ATTRIB_TEXTURE_1D_BIT
)
264 glxValue
|= GLX_TEXTURE_1D_BIT_EXT
;
265 if (value
& __DRI_ATTRIB_TEXTURE_2D_BIT
)
266 glxValue
|= GLX_TEXTURE_2D_BIT_EXT
;
267 if (value
& __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT
)
268 glxValue
|= GLX_TEXTURE_RECTANGLE_BIT_EXT
;
269 if (modes
->bindToTextureTargets
!= GLX_DONT_CARE
&&
270 glxValue
!= modes
->bindToTextureTargets
)
275 if (!scalarEqual(modes
, attrib
, value
))
283 static __GLcontextModes
*
284 createDriMode(const __DRIcoreExtension
*core
,
285 __GLcontextModes
*modes
, const __DRIconfig
**driConfigs
)
287 __GLXDRIconfigPrivate
*config
;
290 for (i
= 0; driConfigs
[i
]; i
++) {
291 if (driConfigEqual(core
, modes
, driConfigs
[i
]))
295 if (driConfigs
[i
] == NULL
)
298 config
= Xmalloc(sizeof *config
);
302 config
->modes
= *modes
;
303 config
->driConfig
= driConfigs
[i
];
305 return &config
->modes
;
308 _X_HIDDEN __GLcontextModes
*
309 driConvertConfigs(const __DRIcoreExtension
*core
,
310 __GLcontextModes
*modes
, const __DRIconfig
**configs
)
312 __GLcontextModes head
, *tail
, *m
;
316 for (m
= modes
; m
; m
= m
->next
) {
317 tail
->next
= createDriMode(core
, m
, configs
);
318 if (tail
->next
== NULL
) {
319 /* no matching dri config for m */
327 _gl_context_modes_destroy(modes
);
333 driBindExtensions(__GLXscreenConfigs
*psc
, int dri2
)
335 const __DRIextension
**extensions
;
338 extensions
= psc
->core
->getExtensions(psc
->__driScreen
);
340 for (i
= 0; extensions
[i
]; i
++) {
341 #ifdef __DRI_COPY_SUB_BUFFER
342 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
343 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
344 __glXEnableDirectExtension(psc
, "GLX_MESA_copy_sub_buffer_bit");
348 #ifdef __DRI_SWAP_CONTROL
349 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
350 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
351 __glXEnableDirectExtension(psc
, "GLX_SGI_swap_control");
352 __glXEnableDirectExtension(psc
, "GLX_MESA_swap_control");
356 #ifdef __DRI_ALLOCATE
357 if (strcmp(extensions
[i
]->name
, __DRI_ALLOCATE
) == 0) {
358 psc
->allocate
= (__DRIallocateExtension
*) extensions
[i
];
359 __glXEnableDirectExtension(psc
, "GLX_MESA_allocate_memory");
363 #ifdef __DRI_FRAME_TRACKING
364 if (strcmp(extensions
[i
]->name
, __DRI_FRAME_TRACKING
) == 0) {
365 psc
->frameTracking
= (__DRIframeTrackingExtension
*) extensions
[i
];
366 __glXEnableDirectExtension(psc
, "GLX_MESA_swap_frame_usage");
370 #ifdef __DRI_MEDIA_STREAM_COUNTER
371 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
372 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
373 __glXEnableDirectExtension(psc
, "GLX_SGI_video_sync");
377 #ifdef __DRI_SWAP_BUFFER_COUNTER
378 /* No driver supports this at this time and the extension is
379 * not defined in dri_interface.h. Will enable
380 * GLX_OML_sync_control if implemented. */
383 #ifdef __DRI_READ_DRAWABLE
384 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
385 __glXEnableDirectExtension(psc
, "GLX_SGI_make_current_read");
389 #ifdef __DRI_TEX_BUFFER
390 if ((strcmp(extensions
[i
]->name
, __DRI_TEX_BUFFER
) == 0) && dri2
) {
391 psc
->texBuffer
= (__DRItexBufferExtension
*) extensions
[i
];
392 __glXEnableDirectExtension(psc
, "GLX_EXT_texture_from_pixmap");
396 /* Ignore unknown extensions */
400 #endif /* GLX_DIRECT_RENDERING */