1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2008 Red Hat, Inc
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software
5*4882a593Smuzhiyun * and its documentation for any purpose is hereby granted without
6*4882a593Smuzhiyun * fee, provided that the above copyright notice appear in all copies
7*4882a593Smuzhiyun * and that both that copyright notice and this permission notice
8*4882a593Smuzhiyun * appear in supporting documentation, and that the name of the
9*4882a593Smuzhiyun * copyright holders not be used in advertising or publicity
10*4882a593Smuzhiyun * pertaining to distribution of the software without specific,
11*4882a593Smuzhiyun * written prior permission. The copyright holders make no
12*4882a593Smuzhiyun * representations about the suitability of this software for any
13*4882a593Smuzhiyun * purpose. It is provided "as is" without express or implied
14*4882a593Smuzhiyun * warranty.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17*4882a593Smuzhiyun * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18*4882a593Smuzhiyun * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*4882a593Smuzhiyun * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21*4882a593Smuzhiyun * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22*4882a593Smuzhiyun * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23*4882a593Smuzhiyun * SOFTWARE.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
27*4882a593Smuzhiyun #include <dix-config.h>
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <stdint.h>
31*4882a593Smuzhiyun #include <errno.h>
32*4882a593Smuzhiyun #include <dlfcn.h>
33*4882a593Smuzhiyun #include <sys/time.h>
34*4882a593Smuzhiyun #include <GL/gl.h>
35*4882a593Smuzhiyun #include <GL/glxtokens.h>
36*4882a593Smuzhiyun #include <GL/internal/dri_interface.h>
37*4882a593Smuzhiyun #include <os.h>
38*4882a593Smuzhiyun #include "extinit.h"
39*4882a593Smuzhiyun #include "glxserver.h"
40*4882a593Smuzhiyun #include "glxext.h"
41*4882a593Smuzhiyun #include "glxcontext.h"
42*4882a593Smuzhiyun #include "glxscreens.h"
43*4882a593Smuzhiyun #include "glxdricommon.h"
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define __ATTRIB(attrib, field) \
46*4882a593Smuzhiyun { attrib, offsetof(__GLXconfig, field) }
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun static const struct {
49*4882a593Smuzhiyun unsigned int attrib, offset;
50*4882a593Smuzhiyun } attribMap[] = {
51*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
52*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_LEVEL, level),
53*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
54*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
55*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
56*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
57*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
58*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
59*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
60*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
61*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
62*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
63*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
64*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
65*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
66*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
67*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
68*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
69*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel),
70*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
71*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
72*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
73*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
74*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
75*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
76*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
77*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
78*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
79*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
80*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
81*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
82*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
83*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
84*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
85*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
86*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
87*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
88*4882a593Smuzhiyun __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable),
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun static void
setScalar(__GLXconfig * config,unsigned int attrib,unsigned int value)92*4882a593Smuzhiyun setScalar(__GLXconfig * config, unsigned int attrib, unsigned int value)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int i;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(attribMap); i++)
97*4882a593Smuzhiyun if (attribMap[i].attrib == attrib) {
98*4882a593Smuzhiyun *(unsigned int *) ((char *) config + attribMap[i].offset) = value;
99*4882a593Smuzhiyun return;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun static Bool
render_type_is_pbuffer_only(unsigned renderType)104*4882a593Smuzhiyun render_type_is_pbuffer_only(unsigned renderType)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun /* The GL_ARB_color_buffer_float spec says:
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * "Note that floating point rendering is only supported for
109*4882a593Smuzhiyun * GLXPbuffer drawables. The GLX_DRAWABLE_TYPE attribute of the
110*4882a593Smuzhiyun * GLXFBConfig must have the GLX_PBUFFER_BIT bit set and the
111*4882a593Smuzhiyun * GLX_RENDER_TYPE attribute must have the GLX_RGBA_FLOAT_BIT set."
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun return !!(renderType & (__DRI_ATTRIB_UNSIGNED_FLOAT_BIT
114*4882a593Smuzhiyun | __DRI_ATTRIB_FLOAT_BIT));
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun static __GLXconfig *
createModeFromConfig(const __DRIcoreExtension * core,const __DRIconfig * driConfig,unsigned int visualType,GLboolean duplicateForComp)118*4882a593Smuzhiyun createModeFromConfig(const __DRIcoreExtension * core,
119*4882a593Smuzhiyun const __DRIconfig * driConfig,
120*4882a593Smuzhiyun unsigned int visualType,
121*4882a593Smuzhiyun GLboolean duplicateForComp)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun __GLXDRIconfig *config;
124*4882a593Smuzhiyun GLint renderType = 0;
125*4882a593Smuzhiyun unsigned int attrib, value, drawableType = GLX_PBUFFER_BIT;
126*4882a593Smuzhiyun int i;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun config = calloc(1, sizeof *config);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun config->driConfig = driConfig;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun i = 0;
134*4882a593Smuzhiyun while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
135*4882a593Smuzhiyun switch (attrib) {
136*4882a593Smuzhiyun case __DRI_ATTRIB_RENDER_TYPE:
137*4882a593Smuzhiyun if (value & __DRI_ATTRIB_RGBA_BIT)
138*4882a593Smuzhiyun renderType |= GLX_RGBA_BIT;
139*4882a593Smuzhiyun if (value & __DRI_ATTRIB_COLOR_INDEX_BIT)
140*4882a593Smuzhiyun renderType |= GLX_COLOR_INDEX_BIT;
141*4882a593Smuzhiyun if (value & __DRI_ATTRIB_FLOAT_BIT)
142*4882a593Smuzhiyun renderType |= GLX_RGBA_FLOAT_BIT_ARB;
143*4882a593Smuzhiyun if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT)
144*4882a593Smuzhiyun renderType |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun case __DRI_ATTRIB_CONFIG_CAVEAT:
147*4882a593Smuzhiyun if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
148*4882a593Smuzhiyun config->config.visualRating = GLX_NON_CONFORMANT_CONFIG;
149*4882a593Smuzhiyun else if (value & __DRI_ATTRIB_SLOW_BIT)
150*4882a593Smuzhiyun config->config.visualRating = GLX_SLOW_CONFIG;
151*4882a593Smuzhiyun else
152*4882a593Smuzhiyun config->config.visualRating = GLX_NONE;
153*4882a593Smuzhiyun break;
154*4882a593Smuzhiyun case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
155*4882a593Smuzhiyun config->config.bindToTextureTargets = 0;
156*4882a593Smuzhiyun if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
157*4882a593Smuzhiyun config->config.bindToTextureTargets |= GLX_TEXTURE_1D_BIT_EXT;
158*4882a593Smuzhiyun if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
159*4882a593Smuzhiyun config->config.bindToTextureTargets |= GLX_TEXTURE_2D_BIT_EXT;
160*4882a593Smuzhiyun if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
161*4882a593Smuzhiyun config->config.bindToTextureTargets |=
162*4882a593Smuzhiyun GLX_TEXTURE_RECTANGLE_BIT_EXT;
163*4882a593Smuzhiyun break;
164*4882a593Smuzhiyun case __DRI_ATTRIB_SWAP_METHOD:
165*4882a593Smuzhiyun /* Workaround for broken dri drivers */
166*4882a593Smuzhiyun if (value != GLX_SWAP_UNDEFINED_OML &&
167*4882a593Smuzhiyun value != GLX_SWAP_COPY_OML &&
168*4882a593Smuzhiyun value != GLX_SWAP_EXCHANGE_OML)
169*4882a593Smuzhiyun value = GLX_SWAP_UNDEFINED_OML;
170*4882a593Smuzhiyun /* Fall through. */
171*4882a593Smuzhiyun default:
172*4882a593Smuzhiyun setScalar(&config->config, attrib, value);
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (!render_type_is_pbuffer_only(renderType))
178*4882a593Smuzhiyun drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun config->config.next = NULL;
181*4882a593Smuzhiyun config->config.visualType = visualType;
182*4882a593Smuzhiyun config->config.renderType = renderType;
183*4882a593Smuzhiyun config->config.drawableType = drawableType;
184*4882a593Smuzhiyun config->config.yInverted = GL_TRUE;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun #ifdef COMPOSITE
187*4882a593Smuzhiyun if (!noCompositeExtension) {
188*4882a593Smuzhiyun /*
189*4882a593Smuzhiyun * Here we decide what fbconfigs will be duplicated for compositing.
190*4882a593Smuzhiyun * fgbconfigs marked with duplicatedForConf will be reserved for
191*4882a593Smuzhiyun * compositing visuals.
192*4882a593Smuzhiyun * It might look strange to do this decision this late when translation
193*4882a593Smuzhiyun * from a __DRIConfig is already done, but using the __DRIConfig
194*4882a593Smuzhiyun * accessor function becomes worse both with respect to code complexity
195*4882a593Smuzhiyun * and CPU usage.
196*4882a593Smuzhiyun */
197*4882a593Smuzhiyun if (duplicateForComp &&
198*4882a593Smuzhiyun (render_type_is_pbuffer_only(renderType) ||
199*4882a593Smuzhiyun config->config.rgbBits != 32 ||
200*4882a593Smuzhiyun config->config.redBits != 8 ||
201*4882a593Smuzhiyun config->config.greenBits != 8 ||
202*4882a593Smuzhiyun config->config.blueBits != 8 ||
203*4882a593Smuzhiyun config->config.visualRating != GLX_NONE ||
204*4882a593Smuzhiyun config->config.sampleBuffers != 0)) {
205*4882a593Smuzhiyun free(config);
206*4882a593Smuzhiyun return NULL;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun config->config.duplicatedForComp = duplicateForComp;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun #endif
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun return &config->config;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun __GLXconfig *
glxConvertConfigs(const __DRIcoreExtension * core,const __DRIconfig ** configs)217*4882a593Smuzhiyun glxConvertConfigs(const __DRIcoreExtension * core,
218*4882a593Smuzhiyun const __DRIconfig ** configs)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun __GLXconfig head, *tail;
221*4882a593Smuzhiyun int i;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun tail = &head;
224*4882a593Smuzhiyun head.next = NULL;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun for (i = 0; configs[i]; i++) {
227*4882a593Smuzhiyun tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR,
228*4882a593Smuzhiyun GL_FALSE);
229*4882a593Smuzhiyun if (tail->next == NULL)
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun tail = tail->next;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun for (i = 0; configs[i]; i++) {
235*4882a593Smuzhiyun tail->next = createModeFromConfig(core, configs[i], GLX_DIRECT_COLOR,
236*4882a593Smuzhiyun GL_FALSE);
237*4882a593Smuzhiyun if (tail->next == NULL)
238*4882a593Smuzhiyun break;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun tail = tail->next;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun #ifdef COMPOSITE
244*4882a593Smuzhiyun if (!noCompositeExtension) {
245*4882a593Smuzhiyun /* Duplicate fbconfigs for use with compositing visuals */
246*4882a593Smuzhiyun for (i = 0; configs[i]; i++) {
247*4882a593Smuzhiyun tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR,
248*4882a593Smuzhiyun GL_TRUE);
249*4882a593Smuzhiyun if (tail->next == NULL)
250*4882a593Smuzhiyun continue;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun tail = tail->next;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun #endif
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return head.next;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun static const char dri_driver_path[] = DRI_DRIVER_PATH;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* Temporary define to allow building without a dri_interface.h from
263*4882a593Smuzhiyun * updated Mesa. Some day when we don't care about Mesa that old any
264*4882a593Smuzhiyun * more this can be removed.
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun #ifndef __DRI_DRIVER_GET_EXTENSIONS
267*4882a593Smuzhiyun #define __DRI_DRIVER_GET_EXTENSIONS "__driDriverGetExtensions"
268*4882a593Smuzhiyun #endif
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun void *
glxProbeDriver(const char * driverName,void ** coreExt,const char * coreName,int coreVersion,void ** renderExt,const char * renderName,int renderVersion)271*4882a593Smuzhiyun glxProbeDriver(const char *driverName,
272*4882a593Smuzhiyun void **coreExt, const char *coreName, int coreVersion,
273*4882a593Smuzhiyun void **renderExt, const char *renderName, int renderVersion)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun int i;
276*4882a593Smuzhiyun void *driver;
277*4882a593Smuzhiyun char filename[PATH_MAX];
278*4882a593Smuzhiyun char *get_extensions_name;
279*4882a593Smuzhiyun const __DRIextension **extensions = NULL;
280*4882a593Smuzhiyun const char *path = NULL;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun /* Search in LIBGL_DRIVERS_PATH if we're not setuid. */
283*4882a593Smuzhiyun if (!PrivsElevated())
284*4882a593Smuzhiyun path = getenv("LIBGL_DRIVERS_PATH");
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (!path)
287*4882a593Smuzhiyun path = dri_driver_path;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun do {
290*4882a593Smuzhiyun const char *next;
291*4882a593Smuzhiyun int path_len;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun next = strchr(path, ':');
294*4882a593Smuzhiyun if (next) {
295*4882a593Smuzhiyun path_len = next - path;
296*4882a593Smuzhiyun next++;
297*4882a593Smuzhiyun } else {
298*4882a593Smuzhiyun path_len = strlen(path);
299*4882a593Smuzhiyun next = NULL;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun snprintf(filename, sizeof filename, "%.*s/%s_dri.so", path_len, path,
303*4882a593Smuzhiyun driverName);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
306*4882a593Smuzhiyun if (driver != NULL)
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
310*4882a593Smuzhiyun filename, dlerror());
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun path = next;
313*4882a593Smuzhiyun } while (path);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (driver == NULL) {
316*4882a593Smuzhiyun LogMessage(X_ERROR, "AIGLX error: unable to load driver %s\n",
317*4882a593Smuzhiyun driverName);
318*4882a593Smuzhiyun goto cleanup_failure;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (asprintf(&get_extensions_name, "%s_%s",
322*4882a593Smuzhiyun __DRI_DRIVER_GET_EXTENSIONS, driverName) != -1) {
323*4882a593Smuzhiyun const __DRIextension **(*get_extensions)(void);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun get_extensions = dlsym(driver, get_extensions_name);
326*4882a593Smuzhiyun if (get_extensions)
327*4882a593Smuzhiyun extensions = get_extensions();
328*4882a593Smuzhiyun free(get_extensions_name);
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (!extensions)
332*4882a593Smuzhiyun extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS);
333*4882a593Smuzhiyun if (extensions == NULL) {
334*4882a593Smuzhiyun LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
335*4882a593Smuzhiyun driverName, dlerror());
336*4882a593Smuzhiyun goto cleanup_failure;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun for (i = 0; extensions[i]; i++) {
340*4882a593Smuzhiyun if (strcmp(extensions[i]->name, coreName) == 0 &&
341*4882a593Smuzhiyun extensions[i]->version >= coreVersion) {
342*4882a593Smuzhiyun *coreExt = (void *) extensions[i];
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if (strcmp(extensions[i]->name, renderName) == 0 &&
346*4882a593Smuzhiyun extensions[i]->version >= renderVersion) {
347*4882a593Smuzhiyun *renderExt = (void *) extensions[i];
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun if (*coreExt == NULL || *renderExt == NULL) {
352*4882a593Smuzhiyun LogMessage(X_ERROR,
353*4882a593Smuzhiyun "AIGLX error: %s does not export required DRI extension\n",
354*4882a593Smuzhiyun driverName);
355*4882a593Smuzhiyun goto cleanup_failure;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun return driver;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun cleanup_failure:
360*4882a593Smuzhiyun if (driver)
361*4882a593Smuzhiyun dlclose(driver);
362*4882a593Smuzhiyun *coreExt = *renderExt = NULL;
363*4882a593Smuzhiyun return NULL;
364*4882a593Smuzhiyun }
365