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 76b8e80941Smrg#ifndef GL_LIB_NAME 77b8e80941Smrg#define GL_LIB_NAME "libGL.so.1" 78848b8605Smrg#endif 79848b8605Smrg 80848b8605Smrg/** 81848b8605Smrg * Try to \c dlopen the named driver. 82848b8605Smrg * 83848b8605Smrg * This function adds the "_dri.so" suffix to the driver name and searches the 84848b8605Smrg * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in 85848b8605Smrg * order to find the driver. 86848b8605Smrg * 87848b8605Smrg * \param driverName - a name like "i965", "radeon", "nouveau", etc. 88b8e80941Smrg * \param out_driver_handle - Address to return the resulting dlopen() handle. 89848b8605Smrg * 90848b8605Smrg * \returns 91b8e80941Smrg * The __DRIextension entrypoint table for the driver, or \c NULL if driver 92b8e80941Smrg * file not found. 93848b8605Smrg */ 94b8e80941Smrg_X_HIDDEN const __DRIextension ** 95b8e80941SmrgdriOpenDriver(const char *driverName, void **out_driver_handle) 96848b8605Smrg{ 97b8e80941Smrg void *glhandle; 98848b8605Smrg 99848b8605Smrg /* Attempt to make sure libGL symbols will be visible to the driver */ 100b8e80941Smrg glhandle = dlopen(GL_LIB_NAME, RTLD_NOW | RTLD_GLOBAL); 101848b8605Smrg 102b8e80941Smrg static const char *search_path_vars[] = { 103b8e80941Smrg "LIBGL_DRIVERS_PATH", 104b8e80941Smrg "LIBGL_DRIVERS_DIR", /* deprecated */ 105b8e80941Smrg NULL 106b8e80941Smrg }; 107848b8605Smrg 108b8e80941Smrg const __DRIextension **extensions = 109b8e80941Smrg loader_open_driver(driverName, out_driver_handle, search_path_vars); 110848b8605Smrg 111848b8605Smrg if (glhandle) 112848b8605Smrg dlclose(glhandle); 113848b8605Smrg 114848b8605Smrg return extensions; 115848b8605Smrg} 116848b8605Smrg 117848b8605Smrgstatic GLboolean 118848b8605Smrg__driGetMSCRate(__DRIdrawable *draw, 119848b8605Smrg int32_t * numerator, int32_t * denominator, 120848b8605Smrg void *loaderPrivate) 121848b8605Smrg{ 122848b8605Smrg __GLXDRIdrawable *glxDraw = loaderPrivate; 123848b8605Smrg 124848b8605Smrg return __glxGetMscRate(glxDraw->psc, numerator, denominator); 125848b8605Smrg} 126848b8605Smrg 127848b8605Smrg_X_HIDDEN const __DRIsystemTimeExtension systemTimeExtension = { 128848b8605Smrg .base = {__DRI_SYSTEM_TIME, 1 }, 129848b8605Smrg 130848b8605Smrg .getUST = __glXGetUST, 131848b8605Smrg .getMSCRate = __driGetMSCRate 132848b8605Smrg}; 133848b8605Smrg 134848b8605Smrg#define __ATTRIB(attrib, field) \ 135848b8605Smrg { attrib, offsetof(struct glx_config, field) } 136848b8605Smrg 137848b8605Smrgstatic const struct 138848b8605Smrg{ 139848b8605Smrg unsigned int attrib, offset; 140848b8605Smrg} attribMap[] = { 141848b8605Smrg __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 142848b8605Smrg __ATTRIB(__DRI_ATTRIB_LEVEL, level), 143848b8605Smrg __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 144848b8605Smrg __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 145848b8605Smrg __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 146848b8605Smrg __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 147848b8605Smrg __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 148848b8605Smrg __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 149848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 150848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 151848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 152848b8605Smrg __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 153848b8605Smrg __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 154848b8605Smrg __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 155848b8605Smrg __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 156848b8605Smrg __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 157848b8605Smrg __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 158848b8605Smrg#if 0 159848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 160848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex), 161848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 162848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 163848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 164848b8605Smrg __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 165848b8605Smrg __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 166848b8605Smrg __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 167848b8605Smrg __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 168848b8605Smrg __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 169848b8605Smrg#endif 170848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 171848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 172848b8605Smrg __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 173848b8605Smrg __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 174848b8605Smrg __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 175848b8605Smrg __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 176b8e80941Smrg __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 177848b8605Smrg __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 178848b8605Smrg __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, 179848b8605Smrg bindToMipmapTexture), 180848b8605Smrg __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), 181848b8605Smrg __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable) 182848b8605Smrg}; 183848b8605Smrg 184848b8605Smrgstatic int 185848b8605SmrgscalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value) 186848b8605Smrg{ 187b8e80941Smrg unsigned glxValue, i; 188848b8605Smrg 189848b8605Smrg for (i = 0; i < ARRAY_SIZE(attribMap); i++) 190848b8605Smrg if (attribMap[i].attrib == attrib) { 191848b8605Smrg glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset); 192848b8605Smrg return glxValue == GLX_DONT_CARE || glxValue == value; 193848b8605Smrg } 194848b8605Smrg 195848b8605Smrg return GL_TRUE; /* Is a non-existing attribute equal to value? */ 196848b8605Smrg} 197848b8605Smrg 198848b8605Smrgstatic int 199848b8605SmrgdriConfigEqual(const __DRIcoreExtension *core, 200848b8605Smrg struct glx_config *config, const __DRIconfig *driConfig) 201848b8605Smrg{ 202848b8605Smrg unsigned int attrib, value, glxValue; 203848b8605Smrg int i; 204848b8605Smrg 205848b8605Smrg i = 0; 206848b8605Smrg while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { 207848b8605Smrg switch (attrib) { 208848b8605Smrg case __DRI_ATTRIB_RENDER_TYPE: 209848b8605Smrg glxValue = 0; 210848b8605Smrg if (value & __DRI_ATTRIB_RGBA_BIT) { 211848b8605Smrg glxValue |= GLX_RGBA_BIT; 212848b8605Smrg } 213848b8605Smrg if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) { 214848b8605Smrg glxValue |= GLX_COLOR_INDEX_BIT; 215848b8605Smrg } 216848b8605Smrg if (value & __DRI_ATTRIB_FLOAT_BIT) { 217848b8605Smrg glxValue |= GLX_RGBA_FLOAT_BIT_ARB; 218848b8605Smrg } 219848b8605Smrg if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) { 220848b8605Smrg glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; 221848b8605Smrg } 222848b8605Smrg if (glxValue != config->renderType) 223848b8605Smrg return GL_FALSE; 224848b8605Smrg break; 225848b8605Smrg 226848b8605Smrg case __DRI_ATTRIB_CONFIG_CAVEAT: 227848b8605Smrg if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 228848b8605Smrg glxValue = GLX_NON_CONFORMANT_CONFIG; 229848b8605Smrg else if (value & __DRI_ATTRIB_SLOW_BIT) 230848b8605Smrg glxValue = GLX_SLOW_CONFIG; 231848b8605Smrg else 232848b8605Smrg glxValue = GLX_NONE; 233848b8605Smrg if (glxValue != config->visualRating) 234848b8605Smrg return GL_FALSE; 235848b8605Smrg break; 236848b8605Smrg 237848b8605Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: 238848b8605Smrg glxValue = 0; 239848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) 240848b8605Smrg glxValue |= GLX_TEXTURE_1D_BIT_EXT; 241848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) 242848b8605Smrg glxValue |= GLX_TEXTURE_2D_BIT_EXT; 243848b8605Smrg if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) 244848b8605Smrg glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT; 245848b8605Smrg if (config->bindToTextureTargets != GLX_DONT_CARE && 246848b8605Smrg glxValue != config->bindToTextureTargets) 247848b8605Smrg return GL_FALSE; 248848b8605Smrg break; 249848b8605Smrg 250b8e80941Smrg case __DRI_ATTRIB_SWAP_METHOD: 251b8e80941Smrg if (value == __DRI_ATTRIB_SWAP_EXCHANGE) 252b8e80941Smrg glxValue = GLX_SWAP_EXCHANGE_OML; 253b8e80941Smrg else if (value == __DRI_ATTRIB_SWAP_COPY) 254b8e80941Smrg glxValue = GLX_SWAP_COPY_OML; 255b8e80941Smrg else 256b8e80941Smrg glxValue = GLX_SWAP_UNDEFINED_OML; 257b8e80941Smrg 258b8e80941Smrg if (!scalarEqual(config, attrib, glxValue)) 259b8e80941Smrg return GL_FALSE; 260b8e80941Smrg 261b8e80941Smrg break; 262b8e80941Smrg 263848b8605Smrg default: 264848b8605Smrg if (!scalarEqual(config, attrib, value)) 265848b8605Smrg return GL_FALSE; 266848b8605Smrg } 267848b8605Smrg } 268848b8605Smrg 269848b8605Smrg return GL_TRUE; 270848b8605Smrg} 271848b8605Smrg 272848b8605Smrgstatic struct glx_config * 273848b8605SmrgcreateDriMode(const __DRIcoreExtension * core, 274848b8605Smrg struct glx_config *config, const __DRIconfig **driConfigs) 275848b8605Smrg{ 276848b8605Smrg __GLXDRIconfigPrivate *driConfig; 277848b8605Smrg int i; 278848b8605Smrg 279848b8605Smrg for (i = 0; driConfigs[i]; i++) { 280848b8605Smrg if (driConfigEqual(core, config, driConfigs[i])) 281848b8605Smrg break; 282848b8605Smrg } 283848b8605Smrg 284848b8605Smrg if (driConfigs[i] == NULL) 285848b8605Smrg return NULL; 286848b8605Smrg 287848b8605Smrg driConfig = malloc(sizeof *driConfig); 288848b8605Smrg if (driConfig == NULL) 289848b8605Smrg return NULL; 290848b8605Smrg 291848b8605Smrg driConfig->base = *config; 292848b8605Smrg driConfig->driConfig = driConfigs[i]; 293848b8605Smrg 294848b8605Smrg return &driConfig->base; 295848b8605Smrg} 296848b8605Smrg 297848b8605Smrg_X_HIDDEN struct glx_config * 298848b8605SmrgdriConvertConfigs(const __DRIcoreExtension * core, 299848b8605Smrg struct glx_config *configs, const __DRIconfig **driConfigs) 300848b8605Smrg{ 301848b8605Smrg struct glx_config head, *tail, *m; 302848b8605Smrg 303848b8605Smrg tail = &head; 304848b8605Smrg head.next = NULL; 305848b8605Smrg for (m = configs; m; m = m->next) { 306848b8605Smrg tail->next = createDriMode(core, m, driConfigs); 307848b8605Smrg if (tail->next == NULL) { 308848b8605Smrg /* no matching dri config for m */ 309848b8605Smrg continue; 310848b8605Smrg } 311848b8605Smrg 312848b8605Smrg 313848b8605Smrg tail = tail->next; 314848b8605Smrg } 315848b8605Smrg 316848b8605Smrg return head.next; 317848b8605Smrg} 318848b8605Smrg 319848b8605Smrg_X_HIDDEN void 320848b8605SmrgdriDestroyConfigs(const __DRIconfig **configs) 321848b8605Smrg{ 322848b8605Smrg int i; 323848b8605Smrg 324848b8605Smrg for (i = 0; configs[i]; i++) 325848b8605Smrg free((__DRIconfig *) configs[i]); 326848b8605Smrg free(configs); 327848b8605Smrg} 328848b8605Smrg 329b8e80941Smrgstatic struct glx_config * 330b8e80941SmrgdriInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw) 331b8e80941Smrg{ 332b8e80941Smrg unsigned int fbconfig = 0; 333b8e80941Smrg 334b8e80941Smrg if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) { 335b8e80941Smrg return glx_config_find_fbconfig(psc->configs, fbconfig); 336b8e80941Smrg } 337b8e80941Smrg 338b8e80941Smrg return NULL; 339b8e80941Smrg} 340b8e80941Smrg 341848b8605Smrg_X_HIDDEN __GLXDRIdrawable * 342848b8605SmrgdriFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable) 343848b8605Smrg{ 344848b8605Smrg struct glx_display *const priv = __glXInitialize(gc->psc->dpy); 345848b8605Smrg __GLXDRIdrawable *pdraw; 346848b8605Smrg struct glx_screen *psc; 347b8e80941Smrg struct glx_config *config = gc->config; 348848b8605Smrg 349848b8605Smrg if (priv == NULL) 350848b8605Smrg return NULL; 351848b8605Smrg 352848b8605Smrg if (glxDrawable == None) 353848b8605Smrg return NULL; 354848b8605Smrg 355848b8605Smrg psc = priv->screens[gc->screen]; 356848b8605Smrg if (priv->drawHash == NULL) 357848b8605Smrg return NULL; 358848b8605Smrg 359848b8605Smrg if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) { 360848b8605Smrg pdraw->refcount ++; 361848b8605Smrg return pdraw; 362848b8605Smrg } 363848b8605Smrg 364b8e80941Smrg if (config == NULL) 365b8e80941Smrg config = driInferDrawableConfig(gc->psc, glxDrawable); 366b8e80941Smrg if (config == NULL) 367b8e80941Smrg return NULL; 368b8e80941Smrg 369b8e80941Smrg pdraw = psc->driScreen->createDrawable(psc, glxDrawable, glxDrawable, 370b8e80941Smrg config); 371848b8605Smrg 372848b8605Smrg if (pdraw == NULL) { 373848b8605Smrg ErrorMessageF("failed to create drawable\n"); 374848b8605Smrg return NULL; 375848b8605Smrg } 376848b8605Smrg 377848b8605Smrg if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) { 378848b8605Smrg (*pdraw->destroyDrawable) (pdraw); 379848b8605Smrg return NULL; 380848b8605Smrg } 381848b8605Smrg pdraw->refcount = 1; 382848b8605Smrg 383848b8605Smrg return pdraw; 384848b8605Smrg} 385848b8605Smrg 386848b8605Smrg_X_HIDDEN void 387848b8605SmrgdriReleaseDrawables(struct glx_context *gc) 388848b8605Smrg{ 389848b8605Smrg const struct glx_display *priv = gc->psc->display; 390848b8605Smrg __GLXDRIdrawable *pdraw; 391848b8605Smrg 392848b8605Smrg if (priv == NULL) 393848b8605Smrg return; 394848b8605Smrg 395848b8605Smrg if (__glxHashLookup(priv->drawHash, 396848b8605Smrg gc->currentDrawable, (void *) &pdraw) == 0) { 397848b8605Smrg if (pdraw->drawable == pdraw->xDrawable) { 398848b8605Smrg pdraw->refcount --; 399848b8605Smrg if (pdraw->refcount == 0) { 400848b8605Smrg (*pdraw->destroyDrawable)(pdraw); 401848b8605Smrg __glxHashDelete(priv->drawHash, gc->currentDrawable); 402848b8605Smrg } 403848b8605Smrg } 404848b8605Smrg } 405848b8605Smrg 406848b8605Smrg if (__glxHashLookup(priv->drawHash, 407848b8605Smrg gc->currentReadable, (void *) &pdraw) == 0) { 408848b8605Smrg if (pdraw->drawable == pdraw->xDrawable) { 409848b8605Smrg pdraw->refcount --; 410848b8605Smrg if (pdraw->refcount == 0) { 411848b8605Smrg (*pdraw->destroyDrawable)(pdraw); 412848b8605Smrg __glxHashDelete(priv->drawHash, gc->currentReadable); 413848b8605Smrg } 414848b8605Smrg } 415848b8605Smrg } 416848b8605Smrg 417848b8605Smrg gc->currentDrawable = None; 418848b8605Smrg gc->currentReadable = None; 419848b8605Smrg 420848b8605Smrg} 421848b8605Smrg 422848b8605Smrg_X_HIDDEN bool 423848b8605Smrgdri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs, 424848b8605Smrg unsigned *major_ver, unsigned *minor_ver, 425848b8605Smrg uint32_t *render_type, uint32_t *flags, unsigned *api, 426b8e80941Smrg int *reset, int *release, unsigned *error) 427848b8605Smrg{ 428848b8605Smrg unsigned i; 429848b8605Smrg bool got_profile = false; 430b8e80941Smrg int no_error = 0; 431848b8605Smrg uint32_t profile; 432848b8605Smrg 433848b8605Smrg *major_ver = 1; 434848b8605Smrg *minor_ver = 0; 435848b8605Smrg *render_type = GLX_RGBA_TYPE; 436848b8605Smrg *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 437b8e80941Smrg *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH; 438848b8605Smrg *flags = 0; 439848b8605Smrg *api = __DRI_API_OPENGL; 440848b8605Smrg 441848b8605Smrg if (num_attribs == 0) { 442848b8605Smrg return true; 443848b8605Smrg } 444848b8605Smrg 445848b8605Smrg /* This is actually an internal error, but what the heck. 446848b8605Smrg */ 447848b8605Smrg if (attribs == NULL) { 448848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 449848b8605Smrg return false; 450848b8605Smrg } 451848b8605Smrg 452848b8605Smrg for (i = 0; i < num_attribs; i++) { 453848b8605Smrg switch (attribs[i * 2]) { 454848b8605Smrg case GLX_CONTEXT_MAJOR_VERSION_ARB: 455848b8605Smrg *major_ver = attribs[i * 2 + 1]; 456848b8605Smrg break; 457848b8605Smrg case GLX_CONTEXT_MINOR_VERSION_ARB: 458848b8605Smrg *minor_ver = attribs[i * 2 + 1]; 459848b8605Smrg break; 460848b8605Smrg case GLX_CONTEXT_FLAGS_ARB: 461848b8605Smrg *flags = attribs[i * 2 + 1]; 462848b8605Smrg break; 463b8e80941Smrg case GLX_CONTEXT_OPENGL_NO_ERROR_ARB: 464b8e80941Smrg no_error = attribs[i * 2 + 1]; 465b8e80941Smrg break; 466848b8605Smrg case GLX_CONTEXT_PROFILE_MASK_ARB: 467848b8605Smrg profile = attribs[i * 2 + 1]; 468848b8605Smrg got_profile = true; 469848b8605Smrg break; 470848b8605Smrg case GLX_RENDER_TYPE: 471848b8605Smrg *render_type = attribs[i * 2 + 1]; 472848b8605Smrg break; 473848b8605Smrg case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: 474848b8605Smrg switch (attribs[i * 2 + 1]) { 475848b8605Smrg case GLX_NO_RESET_NOTIFICATION_ARB: 476848b8605Smrg *reset = __DRI_CTX_RESET_NO_NOTIFICATION; 477848b8605Smrg break; 478848b8605Smrg case GLX_LOSE_CONTEXT_ON_RESET_ARB: 479848b8605Smrg *reset = __DRI_CTX_RESET_LOSE_CONTEXT; 480848b8605Smrg break; 481848b8605Smrg default: 482848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 483848b8605Smrg return false; 484848b8605Smrg } 485848b8605Smrg break; 486b8e80941Smrg case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB: 487b8e80941Smrg switch (attribs[i * 2 + 1]) { 488b8e80941Smrg case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB: 489b8e80941Smrg *release = __DRI_CTX_RELEASE_BEHAVIOR_NONE; 490b8e80941Smrg break; 491b8e80941Smrg case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB: 492b8e80941Smrg *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH; 493b8e80941Smrg break; 494b8e80941Smrg default: 495b8e80941Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 496b8e80941Smrg return false; 497b8e80941Smrg } 498b8e80941Smrg break; 499848b8605Smrg default: 500848b8605Smrg /* If an unknown attribute is received, fail. 501848b8605Smrg */ 502848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 503848b8605Smrg return false; 504848b8605Smrg } 505848b8605Smrg } 506848b8605Smrg 507b8e80941Smrg if (no_error) { 508b8e80941Smrg *flags |= __DRI_CTX_FLAG_NO_ERROR; 509b8e80941Smrg } 510b8e80941Smrg 511848b8605Smrg if (!got_profile) { 512848b8605Smrg if (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 513848b8605Smrg *api = __DRI_API_OPENGL_CORE; 514848b8605Smrg } else { 515848b8605Smrg switch (profile) { 516848b8605Smrg case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: 517848b8605Smrg /* There are no profiles before OpenGL 3.2. The 518848b8605Smrg * GLX_ARB_create_context_profile spec says: 519848b8605Smrg * 520848b8605Smrg * "If the requested OpenGL version is less than 3.2, 521848b8605Smrg * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality 522848b8605Smrg * of the context is determined solely by the requested version." 523848b8605Smrg */ 524848b8605Smrg *api = (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2)) 525848b8605Smrg ? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL; 526848b8605Smrg break; 527848b8605Smrg case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: 528848b8605Smrg *api = __DRI_API_OPENGL; 529848b8605Smrg break; 530b8e80941Smrg case GLX_CONTEXT_ES_PROFILE_BIT_EXT: 531b8e80941Smrg if (*major_ver >= 3) 532b8e80941Smrg *api = __DRI_API_GLES3; 533b8e80941Smrg else if (*major_ver == 2 && *minor_ver == 0) 534b8e80941Smrg *api = __DRI_API_GLES2; 535b8e80941Smrg else if (*major_ver == 1 && *minor_ver < 2) 536b8e80941Smrg *api = __DRI_API_GLES; 537b8e80941Smrg else { 538b8e80941Smrg *error = __DRI_CTX_ERROR_BAD_API; 539b8e80941Smrg return false; 540b8e80941Smrg } 541b8e80941Smrg break; 542848b8605Smrg default: 543848b8605Smrg *error = __DRI_CTX_ERROR_BAD_API; 544848b8605Smrg return false; 545848b8605Smrg } 546848b8605Smrg } 547848b8605Smrg 548848b8605Smrg /* Unknown flag value. 549848b8605Smrg */ 550848b8605Smrg if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE 551b8e80941Smrg | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS 552b8e80941Smrg | __DRI_CTX_FLAG_NO_ERROR)) { 553848b8605Smrg *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; 554848b8605Smrg return false; 555848b8605Smrg } 556848b8605Smrg 557848b8605Smrg /* There are no forward-compatible contexts before OpenGL 3.0. The 558848b8605Smrg * GLX_ARB_create_context spec says: 559848b8605Smrg * 560848b8605Smrg * "Forward-compatible contexts are defined only for OpenGL versions 561848b8605Smrg * 3.0 and later." 562848b8605Smrg */ 563848b8605Smrg if (*major_ver < 3 && (*flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { 564848b8605Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 565848b8605Smrg return false; 566848b8605Smrg } 567848b8605Smrg 568848b8605Smrg if (*major_ver >= 3 && *render_type == GLX_COLOR_INDEX_TYPE) { 569848b8605Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 570848b8605Smrg return false; 571848b8605Smrg } 572848b8605Smrg 573b8e80941Smrg *error = __DRI_CTX_ERROR_SUCCESS; 574b8e80941Smrg return true; 575b8e80941Smrg} 576b8e80941Smrg 577b8e80941Smrg_X_HIDDEN bool 578b8e80941Smrgdri2_check_no_error(uint32_t flags, struct glx_context *share_context, 579b8e80941Smrg int major, unsigned *error) 580b8e80941Smrg{ 581b8e80941Smrg Bool noError = flags & __DRI_CTX_FLAG_NO_ERROR; 582b8e80941Smrg 583b8e80941Smrg /* The KHR_no_error specs say: 584b8e80941Smrg * 585b8e80941Smrg * Requires OpenGL ES 2.0 or OpenGL 2.0. 586b8e80941Smrg */ 587b8e80941Smrg if (noError && major < 2) { 588b8e80941Smrg *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; 589b8e80941Smrg return false; 590b8e80941Smrg } 591b8e80941Smrg 592b8e80941Smrg /* The GLX_ARB_create_context_no_error specs say: 593b8e80941Smrg * 594b8e80941Smrg * BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB 595b8e80941Smrg * used to create <share_context> does not match the value of 596b8e80941Smrg * GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created. 597b8e80941Smrg */ 598b8e80941Smrg if (share_context && !!share_context->noError != !!noError) { 599b8e80941Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 600b8e80941Smrg return false; 601b8e80941Smrg } 602b8e80941Smrg 603b8e80941Smrg /* The GLX_ARB_create_context_no_error specs say: 604b8e80941Smrg * 605b8e80941Smrg * BadMatch is generated if the GLX_CONTEXT_OPENGL_NO_ERROR_ARB is TRUE at 606b8e80941Smrg * the same time as a debug or robustness context is specified. 607848b8605Smrg * 608848b8605Smrg */ 609b8e80941Smrg if (noError && ((flags & __DRI_CTX_FLAG_DEBUG) || 610b8e80941Smrg (flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) { 611b8e80941Smrg *error = __DRI_CTX_ERROR_BAD_FLAG; 612848b8605Smrg return false; 613848b8605Smrg } 614848b8605Smrg 615848b8605Smrg return true; 616848b8605Smrg} 617848b8605Smrg 618848b8605Smrg#endif /* GLX_DIRECT_RENDERING */ 619