dri_common.c revision 848b8605
1848b8605Smrg/* 2848b8605Smrg * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 3848b8605Smrg * Copyright © 2008 Red Hat, Inc. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Soft- 7848b8605Smrg * ware"), to deal in the Software without restriction, including without 8848b8605Smrg * limitation the rights to use, copy, modify, merge, publish, distribute, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, provided that the above copyright 11848b8605Smrg * notice(s) and this permission notice appear in all copies of the Soft- 12848b8605Smrg * ware and that both the above copyright notice(s) and this permission 13848b8605Smrg * notice appear in supporting documentation. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 17848b8605Smrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 18848b8605Smrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 19848b8605Smrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 20848b8605Smrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21848b8605Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22848b8605Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 23848b8605Smrg * MANCE OF THIS SOFTWARE. 24848b8605Smrg * 25848b8605Smrg * Except as contained in this notice, the name of a copyright holder shall 26848b8605Smrg * not be used in advertising or otherwise to promote the sale, use or 27848b8605Smrg * other dealings in this Software without prior written authorization of 28848b8605Smrg * the copyright holder. 29848b8605Smrg * 30848b8605Smrg * Authors: 31848b8605Smrg * Kevin E. Martin <kevin@precisioninsight.com> 32848b8605Smrg * Brian Paul <brian@precisioninsight.com> 33848b8605Smrg * Kristian Høgsberg (krh@redhat.com) 34848b8605Smrg */ 35848b8605Smrg 36848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 37848b8605Smrg 38848b8605Smrg#include <unistd.h> 39848b8605Smrg#include <dlfcn.h> 40848b8605Smrg#include <stdarg.h> 41848b8605Smrg#include "glxclient.h" 42848b8605Smrg#include "dri_common.h" 43848b8605Smrg#include "loader.h" 44848b8605Smrg 45848b8605Smrg#ifndef RTLD_NOW 46848b8605Smrg#define RTLD_NOW 0 47848b8605Smrg#endif 48848b8605Smrg#ifndef RTLD_GLOBAL 49848b8605Smrg#define RTLD_GLOBAL 0 50848b8605Smrg#endif 51848b8605Smrg 52848b8605Smrg_X_HIDDEN void 53848b8605Smrgdri_message(int level, const char *f, ...) 54848b8605Smrg{ 55848b8605Smrg va_list args; 56848b8605Smrg int threshold = _LOADER_WARNING; 57848b8605Smrg const char *libgl_debug; 58848b8605Smrg 59848b8605Smrg libgl_debug = getenv("LIBGL_DEBUG"); 60848b8605Smrg if (libgl_debug) { 61848b8605Smrg if (strstr(libgl_debug, "quiet")) 62848b8605Smrg threshold = _LOADER_FATAL; 63848b8605Smrg else if (strstr(libgl_debug, "verbose")) 64848b8605Smrg threshold = _LOADER_DEBUG; 65848b8605Smrg } 66848b8605Smrg 67848b8605Smrg /* Note that the _LOADER_* levels are lower numbers for more severe. */ 68848b8605Smrg if (level <= threshold) { 69848b8605Smrg fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : ""); 70848b8605Smrg va_start(args, f); 71848b8605Smrg vfprintf(stderr, f, args); 72848b8605Smrg va_end(args); 73848b8605Smrg } 74848b8605Smrg} 75848b8605Smrg 76848b8605Smrg#ifndef DEFAULT_DRIVER_DIR 77848b8605Smrg/* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */ 78848b8605Smrg#define DEFAULT_DRIVER_DIR "/usr/local/lib/dri" 79848b8605Smrg#endif 80848b8605Smrg 81848b8605Smrg/** 82848b8605Smrg * Try to \c dlopen the named driver. 83848b8605Smrg * 84848b8605Smrg * This function adds the "_dri.so" suffix to the driver name and searches the 85848b8605Smrg * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in 86848b8605Smrg * order to find the driver. 87848b8605Smrg * 88848b8605Smrg * \param driverName - a name like "i965", "radeon", "nouveau", etc. 89848b8605Smrg * 90848b8605Smrg * \returns 91848b8605Smrg * A handle from \c dlopen, or \c NULL if driver file not found. 92848b8605Smrg */ 93848b8605Smrg_X_HIDDEN void * 94848b8605SmrgdriOpenDriver(const char *driverName) 95848b8605Smrg{ 96848b8605Smrg void *glhandle, *handle; 97848b8605Smrg const char *libPaths, *p, *next; 98848b8605Smrg char realDriverName[200]; 99848b8605Smrg int len; 100848b8605Smrg 101848b8605Smrg /* Attempt to make sure libGL symbols will be visible to the driver */ 102848b8605Smrg#ifdef __NetBSD__ // base only, pkgsrc didn't get bumped for time_t 103848b8605Smrg glhandle = dlopen("libGL.so.2", RTLD_NOW | RTLD_GLOBAL); 104848b8605Smrg#else 105848b8605Smrg glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); 106848b8605Smrg#endif 107848b8605Smrg 108848b8605Smrg libPaths = NULL; 109848b8605Smrg if (geteuid() == getuid()) { 110848b8605Smrg /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 111848b8605Smrg libPaths = getenv("LIBGL_DRIVERS_PATH"); 112848b8605Smrg if (!libPaths) 113848b8605Smrg libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */ 114848b8605Smrg } 115848b8605Smrg if (libPaths == NULL) 116848b8605Smrg libPaths = DEFAULT_DRIVER_DIR; 117848b8605Smrg 118848b8605Smrg handle = NULL; 119848b8605Smrg for (p = libPaths; *p; p = next) { 120848b8605Smrg next = strchr(p, ':'); 121848b8605Smrg if (next == NULL) { 122848b8605Smrg len = strlen(p); 123848b8605Smrg next = p + len; 124848b8605Smrg } 125848b8605Smrg else { 126848b8605Smrg len = next - p; 127848b8605Smrg next++; 128848b8605Smrg } 129848b8605Smrg 130848b8605Smrg#ifdef GLX_USE_TLS 131848b8605Smrg snprintf(realDriverName, sizeof realDriverName, 132848b8605Smrg "%.*s/tls/%s_dri.so", len, p, driverName); 133848b8605Smrg InfoMessageF("OpenDriver: trying %s\n", realDriverName); 134848b8605Smrg handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 135848b8605Smrg#endif 136848b8605Smrg 137848b8605Smrg if (handle == NULL) { 138848b8605Smrg snprintf(realDriverName, sizeof realDriverName, 139848b8605Smrg "%.*s/%s_dri.so", len, p, driverName); 140848b8605Smrg InfoMessageF("OpenDriver: trying %s\n", realDriverName); 141848b8605Smrg handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL); 142848b8605Smrg } 143848b8605Smrg 144848b8605Smrg if (handle != NULL) 145848b8605Smrg break; 146848b8605Smrg else 147848b8605Smrg InfoMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror()); 148848b8605Smrg } 149848b8605Smrg 150848b8605Smrg if (!handle) 151848b8605Smrg ErrorMessageF("unable to load driver: %s_dri.so\n", driverName); 152848b8605Smrg 153848b8605Smrg if (glhandle) 154848b8605Smrg dlclose(glhandle); 155848b8605Smrg 156848b8605Smrg return handle; 157848b8605Smrg} 158848b8605Smrg 159848b8605Smrg_X_HIDDEN const __DRIextension ** 160848b8605SmrgdriGetDriverExtensions(void *handle, const char *driver_name) 161848b8605Smrg{ 162848b8605Smrg const __DRIextension **extensions = NULL; 163848b8605Smrg const __DRIextension **(*get_extensions)(void); 164848b8605Smrg char *get_extensions_name; 165848b8605Smrg 166848b8605Smrg if (asprintf(&get_extensions_name, "%s_%s", 167848b8605Smrg __DRI_DRIVER_GET_EXTENSIONS, driver_name) != -1) { 168848b8605Smrg get_extensions = dlsym(handle, get_extensions_name); 169848b8605Smrg if (get_extensions) { 170848b8605Smrg free(get_extensions_name); 171848b8605Smrg return get_extensions(); 172848b8605Smrg } else { 173848b8605Smrg InfoMessageF("driver does not expose %s(): %s\n", 174848b8605Smrg get_extensions_name, dlerror()); 175848b8605Smrg free(get_extensions_name); 176848b8605Smrg } 177848b8605Smrg } 178848b8605Smrg 179848b8605Smrg extensions = dlsym(handle, __DRI_DRIVER_EXTENSIONS); 180848b8605Smrg if (extensions == NULL) { 181848b8605Smrg ErrorMessageF("driver exports no extensions (%s)\n", dlerror()); 182848b8605Smrg return NULL; 183848b8605Smrg } 184848b8605Smrg 185848b8605Smrg return extensions; 186848b8605Smrg} 187848b8605Smrg 188848b8605Smrgstatic GLboolean 189848b8605Smrg__driGetMSCRate(__DRIdrawable *draw, 190848b8605Smrg int32_t * numerator, int32_t * denominator, 191848b8605Smrg void *loaderPrivate) 192848b8605Smrg{ 193848b8605Smrg __GLXDRIdrawable *glxDraw = loaderPrivate; 194848b8605Smrg 195848b8605Smrg return __glxGetMscRate(glxDraw->psc, numerator, denominator); 196848b8605Smrg} 197848b8605Smrg 198848b8605Smrg_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { 199848b8605Smrg .base = {__DRI_SYSTEM_TIME, 1 }, 200848b8605Smrg 201848b8605Smrg .getUST = __glXGetUST, 202848b8605Smrg .getMSCRate = __driGetMSCRate 203848b8605Smrg}; 204848b8605Smrg 205848b8605Smrg#define __ATTRIB(attrib, field) \ 206848b8605Smrg { attrib, offsetof(struct glx_config, field) } 207848b8605Smrg 208848b8605Smrgstatic const struct 209848b8605Smrg{ 210848b8605Smrg unsigned int attrib, offset; 211848b8605Smrg} attribMap[] = { 212848b8605Smrg __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 213848b8605Smrg __ATTRIB(__DRI_ATTRIB_LEVEL, level), 214848b8605Smrg __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 215848b8605Smrg __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 216848b8605Smrg __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 217848b8605Smrg __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 218848b8605Smrg __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 219848b8605Smrg __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 220848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 221848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 222848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 223848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 224848b8605Smrg __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 225848b8605Smrg __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 226848b8605Smrg __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 227848b8605Smrg __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 228848b8605Smrg __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 229848b8605Smrg#if 0 230848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 231848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), 232848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 233848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 234848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 235848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 236848b8605Smrg __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 237848b8605Smrg __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 238848b8605Smrg __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 239848b8605Smrg __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 240848b8605Smrg#endif 241848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 242848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 243848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 244848b8605Smrg __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 245848b8605Smrg __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 246848b8605Smrg#if 0 247848b8605Smrg __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 248848b8605Smrg#endif 249848b8605Smrg__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 250848b8605Smrg __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 251848b8605Smrg __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, 252848b8605Smrg bindToMipmapTexture), 253848b8605Smrg __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), 254848b8605Smrg __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable) 255848b8605Smrg}; 256848b8605Smrg 257848b8605Smrgstatic int 258848b8605SmrgscalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value) 259848b8605Smrg{ 260848b8605Smrg unsigned int glxValue; 261848b8605Smrg int i; 262848b8605Smrg 263848b8605Smrg for (i = 0; i < ARRAY_SIZE(attribMap); i++) 264848b8605Smrg if (attribMap[i].attrib == attrib) { 265848b8605Smrg glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); 266848b8605Smrg return glxValue == GLX_DONT_CARE || glxValue == value; 267848b8605Smrg } 268848b8605Smrg 269848b8605Smrg return GL_TRUE; /* Is a non-existing attribute equal to value? */ 270848b8605Smrg} 271848b8605Smrg 272848b8605Smrgstatic int 273848b8605SmrgdriConfigEqual(const __DRIcoreExtension *core, 274848b8605Smrg struct glx_config *config, const __DRIconfig *driConfig) 275848b8605Smrg{ 276848b8605Smrg unsigned int attrib, value, glxValue; 277848b8605Smrg int i; 278848b8605Smrg 279848b8605Smrg i = 0; 280848b8605Smrg while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 281848b8605Smrg switch (attrib) { 282848b8605Smrg case __DRI_ATTRIB_RENDER_TYPE: 283848b8605Smrg glxValue = 0; 284848b8605Smrg if (value & __DRI_ATTRIB_RGBA_BIT) { 285848b8605Smrg glxValue |= GLX_RGBA_BIT; 286848b8605Smrg } 287848b8605Smrg if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { 288848b8605Smrg glxValue |= GLX_COLOR_INDEX_BIT; 289848b8605Smrg } 290848b8605Smrg if (value & __DRI_ATTRIB_FLOAT_BIT) { 291848b8605Smrg glxValue |= GLX_RGBA_FLOAT_BIT_ARB; 292848b8605Smrg } 293848b8605Smrg if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) { 294848b8605Smrg glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; 295848b8605Smrg } 296848b8605Smrg if (glxValue != config->renderType) 297848b8605Smrg return GL_FALSE; 298848b8605Smrg break; 299848b8605Smrg 300848b8605Smrg case __DRI_ATTRIB_CONFIG_CAVEAT: 301848b8605Smrg if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 302848b8605Smrg glxValue = GLX_NON_CONFORMANT_CONFIG; 303848b8605Smrg else if (value & __DRI_ATTRIB_SLOW_BIT) 304848b8605Smrg glxValue = GLX_SLOW_CONFIG; 305848b8605Smrg else 306848b8605Smrg glxValue = GLX_NONE; 307848b8605Smrg if (glxValue != config->visualRating) 308848b8605Smrg return GL_FALSE; 309848b8605Smrg break; 310848b8605Smrg 311848b8605Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 312848b8605Smrg glxValue = 0; 313848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 314848b8605Smrg glxValue |= GLX_TEXTURE_1D_BIT_EXT; 315848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 316848b8605Smrg glxValue |= GLX_TEXTURE_2D_BIT_EXT; 317848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 318848b8605Smrg glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; 319848b8605Smrg if (config->bindToTextureTargets != GLX_DONT_CARE && 320848b8605Smrg glxValue != config->bindToTextureTargets) 321848b8605Smrg return GL_FALSE; 322848b8605Smrg break; 323848b8605Smrg 324848b8605Smrg default: 325848b8605Smrg if (!scalarEqual(config, attrib, value)) 326848b8605Smrg return GL_FALSE; 327848b8605Smrg } 328848b8605Smrg } 329848b8605Smrg 330848b8605Smrg return GL_TRUE; 331848b8605Smrg} 332848b8605Smrg 333848b8605Smrgstatic struct glx_config * 334848b8605SmrgcreateDriMode(const __DRIcoreExtension * core, 335848b8605Smrg struct glx_config *config, const __DRIconfig **driConfigs) 336848b8605Smrg{ 337848b8605Smrg __GLXDRIconfigPrivate *driConfig; 338848b8605Smrg int i; 339848b8605Smrg 340848b8605Smrg for (i = 0; driConfigs[i]; i++) { 341848b8605Smrg if (driConfigEqual(core, config, driConfigs[i])) 342848b8605Smrg break; 343848b8605Smrg } 344848b8605Smrg 345848b8605Smrg if (driConfigs[i] == NULL) 346848b8605Smrg return NULL; 347848b8605Smrg 348848b8605Smrg driConfig = malloc(sizeof *driConfig); 349848b8605Smrg if (driConfig == NULL) 350848b8605Smrg return NULL; 351848b8605Smrg 352848b8605Smrg driConfig->base = *config; 353848b8605Smrg driConfig->driConfig = driConfigs[i]; 354848b8605Smrg 355848b8605Smrg return &driConfig->base; 356848b8605Smrg} 357848b8605Smrg 358848b8605Smrg_X_HIDDEN struct glx_config * 359848b8605SmrgdriConvertConfigs(const __DRIcoreExtension * core, 360848b8605Smrg struct glx_config *configs, const __DRIconfig **driConfigs) 361848b8605Smrg{ 362848b8605Smrg struct glx_config head, *tail, *m; 363848b8605Smrg 364848b8605Smrg tail = &head; 365848b8605Smrg head.next = NULL; 366848b8605Smrg for (m = configs; m; m = m->next) { 367848b8605Smrg tail->next = createDriMode(core, m, driConfigs); 368848b8605Smrg if (tail->next == NULL) { 369848b8605Smrg /* no matching dri config for m */ 370848b8605Smrg continue; 371848b8605Smrg } 372848b8605Smrg 373848b8605Smrg 374848b8605Smrg tail = tail->next; 375848b8605Smrg } 376848b8605Smrg 377848b8605Smrg return head.next; 378848b8605Smrg} 379848b8605Smrg 380848b8605Smrg_X_HIDDEN void 381848b8605SmrgdriDestroyConfigs(const __DRIconfig **configs) 382848b8605Smrg{ 383848b8605Smrg int i; 384848b8605Smrg 385848b8605Smrg for (i = 0; configs[i]; i++) 386848b8605Smrg free((__DRIconfig *) configs[i]); 387848b8605Smrg free(configs); 388848b8605Smrg} 389848b8605Smrg 390848b8605Smrg_X_HIDDEN __GLXDRIdrawable * 391848b8605SmrgdriFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable) 392848b8605Smrg{ 393848b8605Smrg struct glx_display *const priv = __glXInitialize(gc->psc->dpy); 394848b8605Smrg __GLXDRIdrawable *pdraw; 395848b8605Smrg struct glx_screen *psc; 396848b8605Smrg 397848b8605Smrg if (priv == NULL) 398848b8605Smrg return NULL; 399848b8605Smrg 400848b8605Smrg if (glxDrawable == None) 401848b8605Smrg return NULL; 402848b8605Smrg 403848b8605Smrg psc = priv->screens[gc->screen]; 404848b8605Smrg if (priv->drawHash == NULL) 405848b8605Smrg return NULL; 406848b8605Smrg 407848b8605Smrg if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) { 408848b8605Smrg pdraw->refcount ++; 409848b8605Smrg return pdraw; 410848b8605Smrg } 411848b8605Smrg 412848b8605Smrg pdraw = psc->driScreen->createDrawable(psc, glxDrawable, 413848b8605Smrg glxDrawable, gc->config); 414848b8605Smrg 415848b8605Smrg if (pdraw == NULL) { 416848b8605Smrg ErrorMessageF("failed to create drawable\n"); 417848b8605Smrg return NULL; 418848b8605Smrg } 419848b8605Smrg 420848b8605Smrg if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) { 421848b8605Smrg (*pdraw->destroyDrawable) (pdraw); 422848b8605Smrg return NULL; 423848b8605Smrg } 424848b8605Smrg pdraw->refcount = 1; 425848b8605Smrg 426848b8605Smrg return pdraw; 427848b8605Smrg} 428848b8605Smrg 429848b8605Smrg_X_HIDDEN void 430848b8605SmrgdriReleaseDrawables(struct glx_context *gc) 431848b8605Smrg{ 432848b8605Smrg const struct glx_display *priv = gc->psc->display; 433848b8605Smrg __GLXDRIdrawable *pdraw; 434848b8605Smrg 435848b8605Smrg if (priv == NULL) 436848b8605Smrg return; 437848b8605Smrg 438848b8605Smrg if (__glxHashLookup(priv->drawHash, 439848b8605Smrg gc->currentDrawable, (void *) &pdraw) == 0) { 440848b8605Smrg if (pdraw->drawable == pdraw->xDrawable) { 441848b8605Smrg pdraw->refcount --; 442848b8605Smrg if (pdraw->refcount == 0) { 443848b8605Smrg (*pdraw->destroyDrawable)(pdraw); 444848b8605Smrg __glxHashDelete(priv->drawHash, gc->currentDrawable); 445848b8605Smrg } 446848b8605Smrg } 447848b8605Smrg } 448848b8605Smrg 449848b8605Smrg if (__glxHashLookup(priv->drawHash, 450848b8605Smrg gc->currentReadable, (void *) &pdraw) == 0) { 451848b8605Smrg if (pdraw->drawable == pdraw->xDrawable) { 452848b8605Smrg pdraw->refcount --; 453848b8605Smrg if (pdraw->refcount == 0) { 454848b8605Smrg (*pdraw->destroyDrawable)(pdraw); 455848b8605Smrg __glxHashDelete(priv->drawHash, gc->currentReadable); 456848b8605Smrg } 457848b8605Smrg } 458848b8605Smrg } 459848b8605Smrg 460848b8605Smrg gc->currentDrawable = None; 461848b8605Smrg gc->currentReadable = None; 462848b8605Smrg 463848b8605Smrg} 464848b8605Smrg 465848b8605Smrg_X_HIDDEN bool 466848b8605Smrgdri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, 467848b8605Smrg unsigned *major_ver, unsigned *minor_ver, 468848b8605Smrg uint32_t *render_type, uint32_t *flags, unsigned *api, 469848b8605Smrg int *reset, unsigned *error) 470848b8605Smrg{ 471848b8605Smrg unsigned i; 472848b8605Smrg bool got_profile = false; 473848b8605Smrg uint32_t profile; 474848b8605Smrg 475848b8605Smrg *major_ver = 1; 476848b8605Smrg *minor_ver = 0; 477848b8605Smrg *render_type = GLX_RGBA_TYPE; 478848b8605Smrg *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 479848b8605Smrg *flags = 0; 480848b8605Smrg *api = __DRI_API_OPENGL; 481848b8605Smrg 482848b8605Smrg if (num_attribs == 0) { 483848b8605Smrg return true; 484848b8605Smrg } 485848b8605Smrg 486848b8605Smrg /* This is actually an internal error, but what the heck. 487848b8605Smrg */ 488848b8605Smrg if (attribs == NULL) { 489848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 490848b8605Smrg return false; 491848b8605Smrg } 492848b8605Smrg 493848b8605Smrg for (i = 0; i < num_attribs; i++) { 494848b8605Smrg switch (attribs[i * 2]) { 495848b8605Smrg case GLX_CONTEXT_MAJOR_VERSION_ARB: 496848b8605Smrg *major_ver = attribs[i * 2 + 1]; 497848b8605Smrg break; 498848b8605Smrg case GLX_CONTEXT_MINOR_VERSION_ARB: 499848b8605Smrg *minor_ver = attribs[i * 2 + 1]; 500848b8605Smrg break; 501848b8605Smrg case GLX_CONTEXT_FLAGS_ARB: 502848b8605Smrg *flags = attribs[i * 2 + 1]; 503848b8605Smrg break; 504848b8605Smrg case GLX_CONTEXT_PROFILE_MASK_ARB: 505848b8605Smrg profile = attribs[i * 2 + 1]; 506848b8605Smrg got_profile = true; 507848b8605Smrg break; 508848b8605Smrg case GLX_RENDER_TYPE: 509848b8605Smrg *render_type = attribs[i * 2 + 1]; 510848b8605Smrg break; 511848b8605Smrg case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: 512848b8605Smrg switch (attribs[i * 2 + 1]) { 513848b8605Smrg case GLX_NO_RESET_NOTIFICATION_ARB: 514848b8605Smrg *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 515848b8605Smrg break; 516848b8605Smrg case GLX_LOSE_CONTEXT_ON_RESET_ARB: 517848b8605Smrg *reset = __DRI_CTX_RESET_LOSE_CONTEXT; 518848b8605Smrg break; 519848b8605Smrg default: 520848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 521848b8605Smrg return false; 522848b8605Smrg } 523848b8605Smrg break; 524848b8605Smrg default: 525848b8605Smrg /* If an unknown attribute is received, fail. 526848b8605Smrg */ 527848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 528848b8605Smrg return false; 529848b8605Smrg } 530848b8605Smrg } 531848b8605Smrg 532848b8605Smrg if (!got_profile) { 533848b8605Smrg if (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 534848b8605Smrg *api = __DRI_API_OPENGL_CORE; 535848b8605Smrg } else { 536848b8605Smrg switch (profile) { 537848b8605Smrg case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: 538848b8605Smrg /* There are no profiles before OpenGL 3.2. The 539848b8605Smrg * GLX_ARB_create_context_profile spec says: 540848b8605Smrg * 541848b8605Smrg * "If the requested OpenGL version is less than 3.2, 542848b8605Smrg * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality 543848b8605Smrg * of the context is determined solely by the requested version." 544848b8605Smrg */ 545848b8605Smrg *api = (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 546848b8605Smrg ? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL; 547848b8605Smrg break; 548848b8605Smrg case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: 549848b8605Smrg *api = __DRI_API_OPENGL; 550848b8605Smrg break; 551848b8605Smrg case GLX_CONTEXT_ES2_PROFILE_BIT_EXT: 552848b8605Smrg *api = __DRI_API_GLES2; 553848b8605Smrg break; 554848b8605Smrg default: 555848b8605Smrg *error = __DRI_CTX_ERROR_BAD_API; 556848b8605Smrg return false; 557848b8605Smrg } 558848b8605Smrg } 559848b8605Smrg 560848b8605Smrg /* Unknown flag value. 561848b8605Smrg */ 562848b8605Smrg if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE 563848b8605Smrg | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)) { 564848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 565848b8605Smrg return false; 566848b8605Smrg } 567848b8605Smrg 568848b8605Smrg /* There are no forward-compatible contexts before OpenGL 3.0. The 569848b8605Smrg * GLX_ARB_create_context spec says: 570848b8605Smrg * 571848b8605Smrg * "Forward-compatible contexts are defined only for OpenGL versions 572848b8605Smrg * 3.0 and later." 573848b8605Smrg */ 574848b8605Smrg if (*major_ver < 3 && (*flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 575848b8605Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 576848b8605Smrg return false; 577848b8605Smrg } 578848b8605Smrg 579848b8605Smrg if (*major_ver >= 3 && *render_type == GLX_COLOR_INDEX_TYPE) { 580848b8605Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 581848b8605Smrg return false; 582848b8605Smrg } 583848b8605Smrg 584848b8605Smrg /* The GLX_EXT_create_context_es2_profile spec says: 585848b8605Smrg * 586848b8605Smrg * "... If the version requested is 2.0, and the 587848b8605Smrg * GLX_CONTEXT_ES2_PROFILE_BIT_EXT bit is set in the 588848b8605Smrg * GLX_CONTEXT_PROFILE_MASK_ARB attribute (see below), then the context 589848b8605Smrg * returned will implement OpenGL ES 2.0. This is the only way in which 590848b8605Smrg * an implementation may request an OpenGL ES 2.0 context." 591848b8605Smrg */ 592848b8605Smrg if (*api == __DRI_API_GLES2 && (*major_ver != 2 || *minor_ver != 0)) { 593848b8605Smrg *error = __DRI_CTX_ERROR_BAD_API; 594848b8605Smrg return false; 595848b8605Smrg } 596848b8605Smrg 597848b8605Smrg *error = __DRI_CTX_ERROR_SUCCESS; 598848b8605Smrg return true; 599848b8605Smrg} 600848b8605Smrg 601848b8605Smrg#endif /* GLX_DIRECT_RENDERING */ 602