dri_common.c revision cb2a66fd0c095fe03be5aaf88c8d48f5867425d3
1/* 2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 3 * Copyright © 2008 Red Hat, Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Soft- 7 * ware"), to deal in the Software without restriction, including without 8 * limitation the rights to use, copy, modify, merge, publish, distribute, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, provided that the above copyright 11 * notice(s) and this permission notice appear in all copies of the Soft- 12 * ware and that both the above copyright notice(s) and this permission 13 * notice appear in supporting documentation. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 17 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 18 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 19 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 20 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 23 * MANCE OF THIS SOFTWARE. 24 * 25 * Except as contained in this notice, the name of a copyright holder shall 26 * not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization of 28 * the copyright holder. 29 * 30 * Authors: 31 * Kevin E. Martin <kevin@precisioninsight.com> 32 * Brian Paul <brian@precisioninsight.com> 33 * Kristian Høgsberg (krh@redhat.com) 34 */ 35 36#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 37 38#include <unistd.h> 39#include <dlfcn.h> 40#include <stdarg.h> 41#include "glxclient.h" 42#include "glcontextmodes.h" 43#include "dri_common.h" 44 45#ifndef RTLD_NOW 46#define RTLD_NOW 0 47#endif 48#ifndef RTLD_GLOBAL 49#define RTLD_GLOBAL 0 50#endif 51 52_X_HIDDEN void 53InfoMessageF(const char *f, ...) 54{ 55 va_list args; 56 const char *env; 57 58 if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) { 59 fprintf(stderr, "libGL: "); 60 va_start(args, f); 61 vfprintf(stderr, f, args); 62 va_end(args); 63 } 64} 65 66/** 67 * Print error to stderr, unless LIBGL_DEBUG=="quiet". 68 */ 69_X_HIDDEN void 70ErrorMessageF(const char *f, ...) 71{ 72 va_list args; 73 const char *env; 74 75 if ((env = getenv("LIBGL_DEBUG")) && !strstr(env, "quiet")) { 76 fprintf(stderr, "libGL error: "); 77 va_start(args, f); 78 vfprintf(stderr, f, args); 79 va_end(args); 80 } 81} 82 83#ifndef DEFAULT_DRIVER_DIR 84/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */ 85#define DEFAULT_DRIVER_DIR "/usr/local/lib/dri" 86#endif 87 88/** 89 * Try to \c dlopen the named driver. 90 * 91 * This function adds the "_dri.so" suffix to the driver name and searches the 92 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in 93 * order to find the driver. 94 * 95 * \param driverName - a name like "tdfx", "i810", "mga", etc. 96 * 97 * \returns 98 * A handle from \c dlopen, or \c NULL if driver file not found. 99 */ 100_X_HIDDEN void * 101driOpenDriver(const char *driverName) 102{ 103 void *glhandle, *handle; 104 const char *libPaths, *p, *next; 105 char realDriverName[200]; 106 int len; 107 108 /* Attempt to make sure libGL symbols will be visible to the driver */ 109 glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); 110 111 libPaths = NULL; 112 if (geteuid() == getuid()) { 113 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 114 libPaths = getenv("LIBGL_DRIVERS_PATH"); 115 if (!libPaths) 116 libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ 117 } 118 if (libPaths == NULL) 119 libPaths = DEFAULT_DRIVER_DIR; 120 121 handle = NULL; 122 for (p = libPaths; *p; p = next) { 123 next = strchr(p, ':'); 124 if (next == NULL) { 125 len = strlen(p); 126 next = p + len; 127 } 128 else { 129 len = next - p; 130 next++; 131 } 132 133#ifdef GLX_USE_TLS 134 snprintf(realDriverName, sizeof realDriverName, 135 "%.*s/tls/%s_dri.so", len, p, driverName); 136 InfoMessageF("OpenDriver: trying %s\n", realDriverName); 137 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 138#endif 139 140 if (handle == NULL) { 141 snprintf(realDriverName, sizeof realDriverName, 142 "%.*s/%s_dri.so", len, p, driverName); 143 InfoMessageF("OpenDriver: trying %s\n", realDriverName); 144 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 145 } 146 147 if (handle != NULL) 148 break; 149 else 150 ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); 151 } 152 153 if (!handle) 154 ErrorMessageF("unable to load driver: %s_dri.so\n", driverName); 155 156 if (glhandle) 157 dlclose(glhandle); 158 159 return handle; 160} 161 162_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { 163 {__DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION}, 164 __glXGetUST, 165 __driGetMscRateOML 166}; 167 168#define __ATTRIB(attrib, field) \ 169 { attrib, offsetof(__GLcontextModes, field) } 170 171static const struct 172{ 173 unsigned int attrib, offset; 174} attribMap[] = { 175 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 176 __ATTRIB(__DRI_ATTRIB_LEVEL, level), 177 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 178 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 179 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 180 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 181 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 182 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 183 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 184 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 185 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 186 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 187 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 188 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 189 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 190 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 191 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 192#if 0 193 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 194 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), 195 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 196 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 197 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 198 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 199 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 200 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 201 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 202 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 203#endif 204 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 205 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 206 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 207 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 208 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 209#if 0 210 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 211#endif 212__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 213 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 214 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, 215 bindToMipmapTexture), 216 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),}; 217 218#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) 219 220static int 221scalarEqual(__GLcontextModes * mode, unsigned int attrib, unsigned int value) 222{ 223 unsigned int glxValue; 224 int i; 225 226 for (i = 0; i < ARRAY_SIZE(attribMap); i++) 227 if (attribMap[i].attrib == attrib) { 228 glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); 229 return glxValue == GLX_DONT_CARE || glxValue == value; 230 } 231 232 return GL_TRUE; /* Is a non-existing attribute equal to value? */ 233} 234 235static int 236driConfigEqual(const __DRIcoreExtension * core, 237 __GLcontextModes * modes, const __DRIconfig * driConfig) 238{ 239 unsigned int attrib, value, glxValue; 240 int i; 241 242 i = 0; 243 while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 244 switch (attrib) { 245 case __DRI_ATTRIB_RENDER_TYPE: 246 glxValue = 0; 247 if (value & __DRI_ATTRIB_RGBA_BIT) { 248 glxValue |= GLX_RGBA_BIT; 249 } 250 else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { 251 glxValue |= GLX_COLOR_INDEX_BIT; 252 } 253 if (glxValue != modes->renderType) 254 return GL_FALSE; 255 break; 256 257 case __DRI_ATTRIB_CONFIG_CAVEAT: 258 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 259 glxValue = GLX_NON_CONFORMANT_CONFIG; 260 else if (value & __DRI_ATTRIB_SLOW_BIT) 261 glxValue = GLX_SLOW_CONFIG; 262 else 263 glxValue = GLX_NONE; 264 if (glxValue != modes->visualRating) 265 return GL_FALSE; 266 break; 267 268 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 269 glxValue = 0; 270 if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 271 glxValue |= GLX_TEXTURE_1D_BIT_EXT; 272 if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 273 glxValue |= GLX_TEXTURE_2D_BIT_EXT; 274 if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 275 glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; 276 if (modes->bindToTextureTargets != GLX_DONT_CARE && 277 glxValue != modes->bindToTextureTargets) 278 return GL_FALSE; 279 break; 280 281 default: 282 if (!scalarEqual(modes, attrib, value)) 283 return GL_FALSE; 284 } 285 } 286 287 return GL_TRUE; 288} 289 290static __GLcontextModes * 291createDriMode(const __DRIcoreExtension * core, 292 __GLcontextModes * modes, const __DRIconfig ** driConfigs) 293{ 294 __GLXDRIconfigPrivate *config; 295 int i; 296 297 for (i = 0; driConfigs[i]; i++) { 298 if (driConfigEqual(core, modes, driConfigs[i])) 299 break; 300 } 301 302 if (driConfigs[i] == NULL) 303 return NULL; 304 305 config = Xmalloc(sizeof *config); 306 if (config == NULL) 307 return NULL; 308 309 config->modes = *modes; 310 config->driConfig = driConfigs[i]; 311 312 return &config->modes; 313} 314 315_X_HIDDEN __GLcontextModes * 316driConvertConfigs(const __DRIcoreExtension * core, 317 __GLcontextModes * modes, const __DRIconfig ** configs) 318{ 319 __GLcontextModes head, *tail, *m; 320 321 tail = &head; 322 head.next = NULL; 323 for (m = modes; m; m = m->next) { 324 tail->next = createDriMode(core, m, configs); 325 if (tail->next == NULL) { 326 /* no matching dri config for m */ 327 continue; 328 } 329 330 331 tail = tail->next; 332 } 333 334 _gl_context_modes_destroy(modes); 335 336 return head.next; 337} 338 339/* Bind DRI1 specific extensions */ 340_X_HIDDEN void 341driBindExtensions(__GLXscreenConfigs *psc, const __DRIextension **extensions) 342{ 343 int i; 344 345 for (i = 0; extensions[i]; i++) { 346#ifdef __DRI_SWAP_CONTROL 347 /* No DRI2 support for swap_control at the moment, since SwapBuffers 348 * is done by the X server */ 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"); 353 } 354#endif 355 356#ifdef __DRI_MEDIA_STREAM_COUNTER 357 if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) { 358 psc->msc = (__DRImediaStreamCounterExtension *) extensions[i]; 359 __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); 360 } 361#endif 362 363#ifdef __DRI_SWAP_BUFFER_COUNTER 364 /* No driver supports this at this time and the extension is 365 * not defined in dri_interface.h. Will enable 366 * GLX_OML_sync_control if implemented. */ 367#endif 368 369 /* Ignore unknown extensions */ 370 } 371} 372 373/* Bind DRI2 specific extensions */ 374_X_HIDDEN void 375dri2BindExtensions(__GLXscreenConfigs *psc, 376 const __DRIextension **extensions) 377{ 378 int i; 379 380 for (i = 0; extensions[i]; i++) { 381#ifdef __DRI_TEX_BUFFER 382 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) { 383 psc->texBuffer = (__DRItexBufferExtension *) extensions[i]; 384 __glXEnableDirectExtension(psc, "GLX_EXT_texture_from_pixmap"); 385 } 386#endif 387 388 __glXEnableDirectExtension(psc, "GLX_SGI_video_sync"); 389 __glXEnableDirectExtension(psc, "GLX_SGI_swap_control"); 390 __glXEnableDirectExtension(psc, "GLX_MESA_swap_control"); 391 392 /* FIXME: if DRI2 version supports it... */ 393 __glXEnableDirectExtension(psc, "INTEL_swap_event"); 394 395#ifdef __DRI2_FLUSH 396 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) { 397 psc->f = (__DRI2flushExtension *) extensions[i]; 398 /* internal driver extension, no GL extension exposed */ 399 } 400#endif 401 402#ifdef __DRI2_CONFIG_QUERY 403 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) 404 psc->config = (__DRI2configQueryExtension *) extensions[i]; 405#endif 406 } 407} 408 409/* Bind extensions common to DRI1 and DRI2 */ 410_X_HIDDEN void 411driBindCommonExtensions(__GLXscreenConfigs *psc, 412 const __DRIextension **extensions) 413{ 414 int i; 415 416 for (i = 0; extensions[i]; i++) { 417#ifdef __DRI_COPY_SUB_BUFFER 418 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) { 419 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i]; 420 __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer"); 421 } 422#endif 423 424#ifdef __DRI_FRAME_TRACKING 425 if (strcmp(extensions[i]->name, __DRI_FRAME_TRACKING) == 0) { 426 psc->frameTracking = (__DRIframeTrackingExtension *) extensions[i]; 427 __glXEnableDirectExtension(psc, "GLX_MESA_swap_frame_usage"); 428 } 429#endif 430 431#ifdef __DRI_READ_DRAWABLE 432 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) { 433 __glXEnableDirectExtension(psc, "GLX_SGI_make_current_read"); 434 } 435#endif 436 437 /* Ignore unknown extensions */ 438 } 439} 440 441#endif /* GLX_DIRECT_RENDERING */ 442