glxdricommon.c (13768B)
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 <ctype.h> 31 #include <stdint.h> 32 #include <errno.h> 33 #include <dlfcn.h> 34 #include <sys/time.h> 35 #include <GL/gl.h> 36 #include <GL/glxtokens.h> 37 #include <GL/internal/dri_interface.h> 38 #include <os.h> 39 #include "extinit.h" 40 #include "glxserver.h" 41 #include "glxext.h" 42 #include "glxcontext.h" 43 #include "glxscreens.h" 44 #include "glxdricommon.h" 45 46 #define __ATTRIB(attrib, field) \ 47 { attrib, offsetof(__GLXconfig, field) } 48 49 static const struct { 50 unsigned int attrib, offset; 51 } attribMap[] = { 52 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 53 __ATTRIB(__DRI_ATTRIB_LEVEL, level), 54 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 55 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 56 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 57 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 58 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 59 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 60 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 61 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 62 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 63 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 64 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 65 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 66 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 67 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 68 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 69 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 70 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), 71 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 72 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 73 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 74 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 75 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 76 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 77 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 78 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 79 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 80 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 81 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 82 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 83 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 84 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 85 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 86 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 87 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), 88 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), 89 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), 90 }; 91 92 static void 93 setScalar(__GLXconfig * config, unsigned int attrib, unsigned int value) 94 { 95 int i; 96 97 for (i = 0; i < ARRAY_SIZE(attribMap); i++) 98 if (attribMap[i].attrib == attrib) { 99 *(unsigned int *) ((char *) config + attribMap[i].offset) = value; 100 return; 101 } 102 } 103 104 static Bool 105 render_type_is_pbuffer_only(unsigned renderType) 106 { 107 /* The GL_ARB_color_buffer_float spec says: 108 * 109 * "Note that floating point rendering is only supported for 110 * GLXPbuffer drawables. The GLX_DRAWABLE_TYPE attribute of the 111 * GLXFBConfig must have the GLX_PBUFFER_BIT bit set and the 112 * GLX_RENDER_TYPE attribute must have the GLX_RGBA_FLOAT_BIT set." 113 */ 114 return !!(renderType & (__DRI_ATTRIB_UNSIGNED_FLOAT_BIT 115 | __DRI_ATTRIB_FLOAT_BIT)); 116 } 117 118 static int 119 server_has_depth(int depth) 120 { 121 int i; 122 for (i = 0; i < screenInfo.numPixmapFormats; i++) 123 if (screenInfo.formats[i].depth == depth) 124 return 1; 125 return 0; 126 } 127 128 static __GLXconfig * 129 createModeFromConfig(const __DRIcoreExtension * core, 130 const __DRIconfig * driConfig, 131 unsigned int visualType, 132 GLboolean duplicateForComp) 133 { 134 __GLXDRIconfig *config; 135 GLint renderType = 0; 136 unsigned int attrib, value, drawableType = GLX_PBUFFER_BIT; 137 int i; 138 139 140 config = calloc(1, sizeof *config); 141 142 config->driConfig = driConfig; 143 144 i = 0; 145 while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 146 switch (attrib) { 147 case __DRI_ATTRIB_RENDER_TYPE: 148 if (value & __DRI_ATTRIB_RGBA_BIT) 149 renderType |= GLX_RGBA_BIT; 150 if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) 151 renderType |= GLX_COLOR_INDEX_BIT; 152 if (value & __DRI_ATTRIB_FLOAT_BIT) 153 renderType |= GLX_RGBA_FLOAT_BIT_ARB; 154 if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) 155 renderType |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; 156 break; 157 case __DRI_ATTRIB_CONFIG_CAVEAT: 158 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 159 config->config.visualRating = GLX_NON_CONFORMANT_CONFIG; 160 else if (value & __DRI_ATTRIB_SLOW_BIT) 161 config->config.visualRating = GLX_SLOW_CONFIG; 162 else 163 config->config.visualRating = GLX_NONE; 164 break; 165 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 166 config->config.bindToTextureTargets = 0; 167 if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 168 config->config.bindToTextureTargets |= GLX_TEXTURE_1D_BIT_EXT; 169 if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 170 config->config.bindToTextureTargets |= GLX_TEXTURE_2D_BIT_EXT; 171 if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 172 config->config.bindToTextureTargets |= 173 GLX_TEXTURE_RECTANGLE_BIT_EXT; 174 break; 175 case __DRI_ATTRIB_SWAP_METHOD: 176 /* Workaround for broken dri drivers */ 177 if (value != GLX_SWAP_UNDEFINED_OML && 178 value != GLX_SWAP_COPY_OML && 179 value != GLX_SWAP_EXCHANGE_OML) 180 value = GLX_SWAP_UNDEFINED_OML; 181 /* Fall through. */ 182 default: 183 setScalar(&config->config, attrib, value); 184 break; 185 } 186 } 187 188 if (!render_type_is_pbuffer_only(renderType)) 189 drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT; 190 191 /* Make sure we don't advertise things the server isn't configured for */ 192 if ((drawableType & (GLX_PBUFFER_BIT | GLX_PIXMAP_BIT)) && 193 !server_has_depth(config->config.rgbBits)) { 194 drawableType &= ~(GLX_PBUFFER_BIT | GLX_PIXMAP_BIT); 195 if (!drawableType) { 196 free(config); 197 return NULL; 198 } 199 } 200 201 config->config.next = NULL; 202 config->config.visualType = visualType; 203 config->config.renderType = renderType; 204 config->config.drawableType = drawableType; 205 config->config.yInverted = GL_TRUE; 206 207 #ifdef COMPOSITE 208 if (!noCompositeExtension) { 209 /* 210 * Here we decide what fbconfigs will be duplicated for compositing. 211 * fgbconfigs marked with duplicatedForConf will be reserved for 212 * compositing visuals. 213 * It might look strange to do this decision this late when translation 214 * from a __DRIConfig is already done, but using the __DRIConfig 215 * accessor function becomes worse both with respect to code complexity 216 * and CPU usage. 217 */ 218 if (duplicateForComp && 219 (render_type_is_pbuffer_only(renderType) || 220 config->config.rgbBits != 32 || 221 config->config.redBits != 8 || 222 config->config.greenBits != 8 || 223 config->config.blueBits != 8 || 224 config->config.visualRating != GLX_NONE || 225 config->config.sampleBuffers != 0)) { 226 free(config); 227 return NULL; 228 } 229 230 config->config.duplicatedForComp = duplicateForComp; 231 } 232 #endif 233 234 return &config->config; 235 } 236 237 __GLXconfig * 238 glxConvertConfigs(const __DRIcoreExtension * core, 239 const __DRIconfig ** configs) 240 { 241 __GLXconfig head, *tail; 242 int i; 243 244 tail = &head; 245 head.next = NULL; 246 247 for (i = 0; configs[i]; i++) { 248 tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR, 249 GL_FALSE); 250 if (tail->next == NULL) 251 break; 252 tail = tail->next; 253 } 254 255 for (i = 0; configs[i]; i++) { 256 tail->next = createModeFromConfig(core, configs[i], GLX_DIRECT_COLOR, 257 GL_FALSE); 258 if (tail->next == NULL) 259 break; 260 261 tail = tail->next; 262 } 263 264 #ifdef COMPOSITE 265 if (!noCompositeExtension) { 266 /* Duplicate fbconfigs for use with compositing visuals */ 267 for (i = 0; configs[i]; i++) { 268 tail->next = createModeFromConfig(core, configs[i], GLX_TRUE_COLOR, 269 GL_TRUE); 270 if (tail->next == NULL) 271 continue; 272 273 tail = tail->next; 274 } 275 } 276 #endif 277 278 return head.next; 279 } 280 281 static const char dri_driver_path[] = DRI_DRIVER_PATH; 282 283 /* Temporary define to allow building without a dri_interface.h from 284 * updated Mesa. Some day when we don't care about Mesa that old any 285 * more this can be removed. 286 */ 287 #ifndef __DRI_DRIVER_GET_EXTENSIONS 288 #define __DRI_DRIVER_GET_EXTENSIONS "__driDriverGetExtensions" 289 #endif 290 291 void * 292 glxProbeDriver(const char *driverName, 293 void **coreExt, const char *coreName, int coreVersion, 294 void **renderExt, const char *renderName, int renderVersion) 295 { 296 int i; 297 void *driver; 298 char filename[PATH_MAX]; 299 char *get_extensions_name; 300 const __DRIextension **extensions = NULL; 301 const char *path = NULL; 302 303 /* Search in LIBGL_DRIVERS_PATH if we're not setuid. */ 304 if (!PrivsElevated()) 305 path = getenv("LIBGL_DRIVERS_PATH"); 306 307 if (!path) 308 path = dri_driver_path; 309 310 do { 311 const char *next; 312 int path_len; 313 314 next = strchr(path, ':'); 315 if (next) { 316 path_len = next - path; 317 next++; 318 } else { 319 path_len = strlen(path); 320 next = NULL; 321 } 322 323 snprintf(filename, sizeof filename, "%.*s/%s_dri.so", path_len, path, 324 driverName); 325 326 driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); 327 if (driver != NULL) 328 break; 329 330 LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", 331 filename, dlerror()); 332 333 path = next; 334 } while (path); 335 336 if (driver == NULL) { 337 LogMessage(X_ERROR, "AIGLX error: unable to load driver %s\n", 338 driverName); 339 goto cleanup_failure; 340 } 341 342 if (asprintf(&get_extensions_name, "%s_%s", 343 __DRI_DRIVER_GET_EXTENSIONS, driverName) != -1) { 344 const __DRIextension **(*get_extensions)(void); 345 346 for (i = 0; i < strlen(get_extensions_name); i++) { 347 /* Replace all non-alphanumeric characters with underscore, 348 * since they are not allowed in C symbol names. That fixes up 349 * symbol name for drivers with '-drm' suffix 350 */ 351 if (!isalnum(get_extensions_name[i])) 352 get_extensions_name[i] = '_'; 353 } 354 355 get_extensions = dlsym(driver, get_extensions_name); 356 if (get_extensions) 357 extensions = get_extensions(); 358 free(get_extensions_name); 359 } 360 361 if (!extensions) 362 extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS); 363 if (extensions == NULL) { 364 LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", 365 driverName, dlerror()); 366 goto cleanup_failure; 367 } 368 369 for (i = 0; extensions[i]; i++) { 370 if (strcmp(extensions[i]->name, coreName) == 0 && 371 extensions[i]->version >= coreVersion) { 372 *coreExt = (void *) extensions[i]; 373 } 374 375 if (strcmp(extensions[i]->name, renderName) == 0 && 376 extensions[i]->version >= renderVersion) { 377 *renderExt = (void *) extensions[i]; 378 } 379 } 380 381 if (*coreExt == NULL || *renderExt == NULL) { 382 LogMessage(X_ERROR, 383 "AIGLX error: %s does not export required DRI extension\n", 384 driverName); 385 goto cleanup_failure; 386 } 387 return driver; 388 389 cleanup_failure: 390 if (driver) 391 dlclose(driver); 392 *coreExt = *renderExt = NULL; 393 return NULL; 394 }