dri_common.c revision 6ddf66e9230ee862ac341c4767cf6b3b2dd2552b
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 162static GLboolean 163__driGetMSCRate(__DRIdrawable *draw, 164 int32_t * numerator, int32_t * denominator, 165 void *loaderPrivate) 166{ 167 __GLXDRIdrawable *glxDraw = loaderPrivate; 168 169 return __glxGetMscRate(glxDraw, numerator, denominator); 170} 171 172_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { 173 {__DRI_SYSTEM_TIME, __DRI_SYSTEM_TIME_VERSION}, 174 __glXGetUST, 175 __driGetMSCRate 176}; 177 178#define __ATTRIB(attrib, field) \ 179 { attrib, offsetof(struct glx_config, field) } 180 181static const struct 182{ 183 unsigned int attrib, offset; 184} attribMap[] = { 185 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 186 __ATTRIB(__DRI_ATTRIB_LEVEL, level), 187 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 188 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 189 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 190 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 191 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 192 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 193 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 194 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 195 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 196 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 197 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 198 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 199 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 200 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 201 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 202#if 0 203 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 204 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), 205 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 206 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 207 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 208 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 209 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 210 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 211 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 212 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 213#endif 214 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 215 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 216 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 217 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 218 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 219#if 0 220 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 221#endif 222__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 223 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 224 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, 225 bindToMipmapTexture), 226 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),}; 227 228static int 229scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value) 230{ 231 unsigned int glxValue; 232 int i; 233 234 for (i = 0; i < ARRAY_SIZE(attribMap); i++) 235 if (attribMap[i].attrib == attrib) { 236 glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); 237 return glxValue == GLX_DONT_CARE || glxValue == value; 238 } 239 240 return GL_TRUE; /* Is a non-existing attribute equal to value? */ 241} 242 243static int 244driConfigEqual(const __DRIcoreExtension *core, 245 struct glx_config *config, const __DRIconfig *driConfig) 246{ 247 unsigned int attrib, value, glxValue; 248 int i; 249 250 i = 0; 251 while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 252 switch (attrib) { 253 case __DRI_ATTRIB_RENDER_TYPE: 254 glxValue = 0; 255 if (value & __DRI_ATTRIB_RGBA_BIT) { 256 glxValue |= GLX_RGBA_BIT; 257 } 258 else if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { 259 glxValue |= GLX_COLOR_INDEX_BIT; 260 } 261 if (glxValue != config->renderType) 262 return GL_FALSE; 263 break; 264 265 case __DRI_ATTRIB_CONFIG_CAVEAT: 266 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 267 glxValue = GLX_NON_CONFORMANT_CONFIG; 268 else if (value & __DRI_ATTRIB_SLOW_BIT) 269 glxValue = GLX_SLOW_CONFIG; 270 else 271 glxValue = GLX_NONE; 272 if (glxValue != config->visualRating) 273 return GL_FALSE; 274 break; 275 276 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 277 glxValue = 0; 278 if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 279 glxValue |= GLX_TEXTURE_1D_BIT_EXT; 280 if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 281 glxValue |= GLX_TEXTURE_2D_BIT_EXT; 282 if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 283 glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; 284 if (config->bindToTextureTargets != GLX_DONT_CARE && 285 glxValue != config->bindToTextureTargets) 286 return GL_FALSE; 287 break; 288 289 default: 290 if (!scalarEqual(config, attrib, value)) 291 return GL_FALSE; 292 } 293 } 294 295 return GL_TRUE; 296} 297 298static struct glx_config * 299createDriMode(const __DRIcoreExtension * core, 300 struct glx_config *config, const __DRIconfig **driConfigs) 301{ 302 __GLXDRIconfigPrivate *driConfig; 303 int i; 304 305 for (i = 0; driConfigs[i]; i++) { 306 if (driConfigEqual(core, config, driConfigs[i])) 307 break; 308 } 309 310 if (driConfigs[i] == NULL) 311 return NULL; 312 313 driConfig = Xmalloc(sizeof *driConfig); 314 if (driConfig == NULL) 315 return NULL; 316 317 driConfig->base = *config; 318 driConfig->driConfig = driConfigs[i]; 319 320 return &driConfig->base; 321} 322 323_X_HIDDEN struct glx_config * 324driConvertConfigs(const __DRIcoreExtension * core, 325 struct glx_config *configs, const __DRIconfig **driConfigs) 326{ 327 struct glx_config head, *tail, *m; 328 329 tail = &head; 330 head.next = NULL; 331 for (m = configs; m; m = m->next) { 332 tail->next = createDriMode(core, m, driConfigs); 333 if (tail->next == NULL) { 334 /* no matching dri config for m */ 335 continue; 336 } 337 338 339 tail = tail->next; 340 } 341 342 glx_config_destroy_list(configs); 343 344 return head.next; 345} 346 347_X_HIDDEN void 348driDestroyConfigs(const __DRIconfig **configs) 349{ 350 int i; 351 352 for (i = 0; configs[i]; i++) 353 free((__DRIconfig *) configs[i]); 354 free(configs); 355} 356 357#endif /* GLX_DIRECT_RENDERING */ 358