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