blob: f152882d63a0337dc964125d38d56c858f60f6fe [file] [log] [blame]
George Sapountzis07934572008-06-09 17:47:09 +03001/*
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
Jeremy Huddleston80b280d2010-04-02 01:35:19 -070036#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
George Sapountzis07934572008-06-09 17:47:09 +030037
38#include <unistd.h>
39#include <dlfcn.h>
Brian Paula25e1aa2008-09-18 13:26:30 -060040#include <stdarg.h>
George Sapountzis07934572008-06-09 17:47:09 +030041#include "glxclient.h"
George Sapountzis07934572008-06-09 17:47:09 +030042#include "dri_common.h"
Eric Anholt4a8da402014-01-23 11:03:53 -080043#include "loader.h"
George Sapountzis07934572008-06-09 17:47:09 +030044
45#ifndef RTLD_NOW
46#define RTLD_NOW 0
47#endif
Marek Olšák0d5ec2c2014-06-02 12:51:09 +020048#ifndef RTLD_GLOBAL
49#define RTLD_GLOBAL 0
George Sapountzis07934572008-06-09 17:47:09 +030050#endif
51
Eric Anholt4a8da402014-01-23 11:03:53 -080052_X_HIDDEN void
53dri_message(int level, const char *f, ...)
54{
55 va_list args;
56 int threshold = _LOADER_WARNING;
57 const char *libgl_debug;
58
59 libgl_debug = getenv("LIBGL_DEBUG");
60 if (libgl_debug) {
61 if (strstr(libgl_debug, "quiet"))
62 threshold = _LOADER_FATAL;
63 else if (strstr(libgl_debug, "verbose"))
64 threshold = _LOADER_DEBUG;
65 }
66
67 /* Note that the _LOADER_* levels are lower numbers for more severe. */
68 if (level <= threshold) {
69 fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : "");
70 va_start(args, f);
71 vfprintf(stderr, f, args);
72 va_end(args);
73 }
74}
75
Kyle Brennemand35391c2015-09-28 12:12:05 -060076#ifndef GL_LIB_NAME
77#define GL_LIB_NAME "libGL.so.1"
78#endif
79
George Sapountzis07934572008-06-09 17:47:09 +030080/**
81 * Try to \c dlopen the named driver.
82 *
83 * This function adds the "_dri.so" suffix to the driver name and searches the
84 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
85 * order to find the driver.
86 *
Ian Romanicke4344162011-08-24 15:21:58 -070087 * \param driverName - a name like "i965", "radeon", "nouveau", etc.
Eric Anholtc2b51532018-11-15 14:22:16 -080088 * \param out_driver_handle - Address to return the resulting dlopen() handle.
George Sapountzis07934572008-06-09 17:47:09 +030089 *
90 * \returns
Eric Anholtc2b51532018-11-15 14:22:16 -080091 * The __DRIextension entrypoint table for the driver, or \c NULL if driver
92 * file not found.
George Sapountzis07934572008-06-09 17:47:09 +030093 */
Eric Anholtc2b51532018-11-15 14:22:16 -080094_X_HIDDEN const __DRIextension **
95driOpenDriver(const char *driverName, void **out_driver_handle)
George Sapountzis07934572008-06-09 17:47:09 +030096{
Eric Anholtd971a422018-11-15 13:54:49 -080097 void *glhandle;
George Sapountzis07934572008-06-09 17:47:09 +030098
99 /* Attempt to make sure libGL symbols will be visible to the driver */
Kyle Brennemand35391c2015-09-28 12:12:05 -0600100 glhandle = dlopen(GL_LIB_NAME, RTLD_NOW | RTLD_GLOBAL);
George Sapountzis07934572008-06-09 17:47:09 +0300101
Eric Anholtd971a422018-11-15 13:54:49 -0800102 static const char *search_path_vars[] = {
103 "LIBGL_DRIVERS_PATH",
104 "LIBGL_DRIVERS_DIR", /* deprecated */
105 NULL
106 };
George Sapountzis07934572008-06-09 17:47:09 +0300107
Eric Anholtd971a422018-11-15 13:54:49 -0800108 const __DRIextension **extensions =
109 loader_open_driver(driverName, out_driver_handle, search_path_vars);
George Sapountzis07934572008-06-09 17:47:09 +0300110
111 if (glhandle)
112 dlclose(glhandle);
113
Eric Anholt80806c92013-09-27 15:36:59 -0700114 return extensions;
115}
116
George Sapountzis07934572008-06-09 17:47:09 +0300117#define __ATTRIB(attrib, field) \
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400118 { attrib, offsetof(struct glx_config, field) }
George Sapountzis07934572008-06-09 17:47:09 +0300119
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200120static const struct
121{
122 unsigned int attrib, offset;
123} attribMap[] = {
124 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
125 __ATTRIB(__DRI_ATTRIB_LEVEL, level),
126 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
127 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
128 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
129 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
130 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
131 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
132 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
133 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
134 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
135 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
136 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
137 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
138 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
139 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
140 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
George Sapountzis07934572008-06-09 17:47:09 +0300141#if 0
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200142 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel),
143 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentIndex),
144 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed),
145 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen),
146 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue),
147 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
148 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask),
149 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask),
150 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask),
151 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask),
Kevin Strasserd4a90102019-01-24 16:36:29 -0800152 __ATTRIB(__DRI_ATTRIB_RED_SHIFT, redShift),
153 __ATTRIB(__DRI_ATTRIB_GREEN_SHIFT, greenShift),
154 __ATTRIB(__DRI_ATTRIB_BLUE_SHIFT, blueShift),
155 __ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT, alphaShift),
George Sapountzis07934572008-06-09 17:47:09 +0300156#endif
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200157 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth),
158 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
159 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels),
160 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth),
161 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight),
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200162 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
Thomas Hellstrom48bd9172017-08-09 11:19:18 +0200163 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200164 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
165 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,
166 bindToMipmapTexture),
Dave Airlie6538b582011-03-06 20:06:42 +1000167 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
168 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable)
169};
George Sapountzis07934572008-06-09 17:47:09 +0300170
George Sapountzis07934572008-06-09 17:47:09 +0300171static int
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400172scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value)
George Sapountzis07934572008-06-09 17:47:09 +0300173{
Rhys Kidddc7a1ef2015-08-06 16:34:04 +1000174 unsigned glxValue, i;
George Sapountzis07934572008-06-09 17:47:09 +0300175
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200176 for (i = 0; i < ARRAY_SIZE(attribMap); i++)
177 if (attribMap[i].attrib == attrib) {
178 glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
179 return glxValue == GLX_DONT_CARE || glxValue == value;
180 }
George Sapountzis07934572008-06-09 17:47:09 +0300181
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200182 return GL_TRUE; /* Is a non-existing attribute equal to value? */
George Sapountzis07934572008-06-09 17:47:09 +0300183}
184
185static int
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400186driConfigEqual(const __DRIcoreExtension *core,
187 struct glx_config *config, const __DRIconfig *driConfig)
George Sapountzis07934572008-06-09 17:47:09 +0300188{
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200189 unsigned int attrib, value, glxValue;
190 int i;
George Sapountzis07934572008-06-09 17:47:09 +0300191
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200192 i = 0;
193 while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
194 switch (attrib) {
195 case __DRI_ATTRIB_RENDER_TYPE:
196 glxValue = 0;
197 if (value & __DRI_ATTRIB_RGBA_BIT) {
198 glxValue |= GLX_RGBA_BIT;
199 }
Tomasz Lisc37c3672013-07-17 13:49:21 +0200200 if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200201 glxValue |= GLX_COLOR_INDEX_BIT;
202 }
Tomasz Lisc37c3672013-07-17 13:49:21 +0200203 if (value & __DRI_ATTRIB_FLOAT_BIT) {
204 glxValue |= GLX_RGBA_FLOAT_BIT_ARB;
205 }
206 if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) {
207 glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
208 }
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400209 if (glxValue != config->renderType)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200210 return GL_FALSE;
211 break;
George Sapountzis07934572008-06-09 17:47:09 +0300212
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200213 case __DRI_ATTRIB_CONFIG_CAVEAT:
214 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
215 glxValue = GLX_NON_CONFORMANT_CONFIG;
216 else if (value & __DRI_ATTRIB_SLOW_BIT)
217 glxValue = GLX_SLOW_CONFIG;
218 else
219 glxValue = GLX_NONE;
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400220 if (glxValue != config->visualRating)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200221 return GL_FALSE;
222 break;
George Sapountzis07934572008-06-09 17:47:09 +0300223
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200224 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
225 glxValue = 0;
226 if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
227 glxValue |= GLX_TEXTURE_1D_BIT_EXT;
228 if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
229 glxValue |= GLX_TEXTURE_2D_BIT_EXT;
230 if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
231 glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400232 if (config->bindToTextureTargets != GLX_DONT_CARE &&
Marek Olšáka6f39ec2015-07-23 21:51:48 +0200233 glxValue != config->bindToTextureTargets)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200234 return GL_FALSE;
235 break;
George Sapountzis07934572008-06-09 17:47:09 +0300236
Thomas Hellstrom2437ebd2017-08-09 11:25:10 +0200237 case __DRI_ATTRIB_SWAP_METHOD:
238 if (value == __DRI_ATTRIB_SWAP_EXCHANGE)
239 glxValue = GLX_SWAP_EXCHANGE_OML;
240 else if (value == __DRI_ATTRIB_SWAP_COPY)
241 glxValue = GLX_SWAP_COPY_OML;
242 else
243 glxValue = GLX_SWAP_UNDEFINED_OML;
244
245 if (!scalarEqual(config, attrib, glxValue))
246 return GL_FALSE;
247
248 break;
249
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200250 default:
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400251 if (!scalarEqual(config, attrib, value))
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200252 return GL_FALSE;
253 }
254 }
George Sapountzis07934572008-06-09 17:47:09 +0300255
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200256 return GL_TRUE;
George Sapountzis07934572008-06-09 17:47:09 +0300257}
258
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400259static struct glx_config *
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200260createDriMode(const __DRIcoreExtension * core,
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400261 struct glx_config *config, const __DRIconfig **driConfigs)
George Sapountzis07934572008-06-09 17:47:09 +0300262{
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400263 __GLXDRIconfigPrivate *driConfig;
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200264 int i;
George Sapountzis07934572008-06-09 17:47:09 +0300265
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200266 for (i = 0; driConfigs[i]; i++) {
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400267 if (driConfigEqual(core, config, driConfigs[i]))
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200268 break;
269 }
George Sapountzis07934572008-06-09 17:47:09 +0300270
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200271 if (driConfigs[i] == NULL)
272 return NULL;
George Sapountzis07934572008-06-09 17:47:09 +0300273
Matt Turner7c7b7b02012-09-04 22:52:36 -0700274 driConfig = malloc(sizeof *driConfig);
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400275 if (driConfig == NULL)
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200276 return NULL;
George Sapountzis07934572008-06-09 17:47:09 +0300277
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400278 driConfig->base = *config;
279 driConfig->driConfig = driConfigs[i];
George Sapountzis07934572008-06-09 17:47:09 +0300280
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400281 return &driConfig->base;
George Sapountzis07934572008-06-09 17:47:09 +0300282}
283
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400284_X_HIDDEN struct glx_config *
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200285driConvertConfigs(const __DRIcoreExtension * core,
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400286 struct glx_config *configs, const __DRIconfig **driConfigs)
George Sapountzis07934572008-06-09 17:47:09 +0300287{
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400288 struct glx_config head, *tail, *m;
George Sapountzis07934572008-06-09 17:47:09 +0300289
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200290 tail = &head;
291 head.next = NULL;
Kristian Høgsberg6ddf66e2010-07-28 10:07:52 -0400292 for (m = configs; m; m = m->next) {
293 tail->next = createDriMode(core, m, driConfigs);
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200294 if (tail->next == NULL) {
295 /* no matching dri config for m */
296 continue;
297 }
George Sapountzis07934572008-06-09 17:47:09 +0300298
299
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200300 tail = tail->next;
301 }
George Sapountzis07934572008-06-09 17:47:09 +0300302
RALOVICH, Kristóf08962682009-08-12 12:41:22 +0200303 return head.next;
George Sapountzis07934572008-06-09 17:47:09 +0300304}
305
Kristian Høgsbergbab13962010-07-19 22:12:22 -0400306_X_HIDDEN void
307driDestroyConfigs(const __DRIconfig **configs)
308{
309 int i;
310
311 for (i = 0; configs[i]; i++)
312 free((__DRIconfig *) configs[i]);
313 free(configs);
314}
315
Adam Jacksona48a6b82017-11-14 15:13:05 -0500316static struct glx_config *
317driInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw)
318{
319 unsigned int fbconfig = 0;
320
321 if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) {
322 return glx_config_find_fbconfig(psc->configs, fbconfig);
323 }
324
325 return NULL;
326}
327
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400328_X_HIDDEN __GLXDRIdrawable *
329driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
330{
331 struct glx_display *const priv = __glXInitialize(gc->psc->dpy);
332 __GLXDRIdrawable *pdraw;
333 struct glx_screen *psc;
Adam Jacksona48a6b82017-11-14 15:13:05 -0500334 struct glx_config *config = gc->config;
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400335
336 if (priv == NULL)
337 return NULL;
338
Kristian Høgsbergf6581502014-02-05 11:43:58 -0800339 if (glxDrawable == None)
340 return NULL;
341
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400342 psc = priv->screens[gc->screen];
343 if (priv->drawHash == NULL)
344 return NULL;
345
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700346 if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
347 pdraw->refcount ++;
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400348 return pdraw;
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700349 }
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400350
Adam Jacksona48a6b82017-11-14 15:13:05 -0500351 if (config == NULL)
352 config = driInferDrawableConfig(gc->psc, glxDrawable);
353 if (config == NULL)
354 return NULL;
355
356 pdraw = psc->driScreen->createDrawable(psc, glxDrawable, glxDrawable,
357 config);
Wang YanQing7a6324d2012-03-20 11:49:42 +0800358
359 if (pdraw == NULL) {
360 ErrorMessageF("failed to create drawable\n");
361 return NULL;
362 }
363
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400364 if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) {
365 (*pdraw->destroyDrawable) (pdraw);
366 return NULL;
367 }
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700368 pdraw->refcount = 1;
Kristian Høgsbergc491e582010-07-28 15:33:09 -0400369
370 return pdraw;
371}
372
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400373_X_HIDDEN void
374driReleaseDrawables(struct glx_context *gc)
375{
Henri Verbeet0f20e2e2011-07-18 00:42:27 +0200376 const struct glx_display *priv = gc->psc->display;
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400377 __GLXDRIdrawable *pdraw;
378
379 if (priv == NULL)
380 return;
381
382 if (__glxHashLookup(priv->drawHash,
383 gc->currentDrawable, (void *) &pdraw) == 0) {
Kristian Høgsberg4b70fe82010-09-29 08:32:12 -0400384 if (pdraw->drawable == pdraw->xDrawable) {
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700385 pdraw->refcount --;
386 if (pdraw->refcount == 0) {
Eric Engestrome7e3fd52018-11-22 19:47:28 +0000387 pdraw->destroyDrawable(pdraw);
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700388 __glxHashDelete(priv->drawHash, gc->currentDrawable);
389 }
Kristian Høgsberg4b70fe82010-09-29 08:32:12 -0400390 }
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400391 }
392
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700393 if (__glxHashLookup(priv->drawHash,
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400394 gc->currentReadable, (void *) &pdraw) == 0) {
Kristian Høgsberg4b70fe82010-09-29 08:32:12 -0400395 if (pdraw->drawable == pdraw->xDrawable) {
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700396 pdraw->refcount --;
397 if (pdraw->refcount == 0) {
Eric Engestrome7e3fd52018-11-22 19:47:28 +0000398 pdraw->destroyDrawable(pdraw);
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700399 __glxHashDelete(priv->drawHash, gc->currentReadable);
400 }
Kristian Høgsberg4b70fe82010-09-29 08:32:12 -0400401 }
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400402 }
Stéphane Marchesinbf69ce32011-06-15 15:09:12 -0700403
404 gc->currentDrawable = None;
405 gc->currentReadable = None;
406
Kristian Høgsberg16887d02010-08-27 12:40:11 -0400407}
408
Ian Romanickb45f77d2011-12-01 13:52:53 -0800409_X_HIDDEN bool
410dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
Tomasz Lisa92cd5b2013-07-17 13:49:15 +0200411 unsigned *major_ver, unsigned *minor_ver,
412 uint32_t *render_type, uint32_t *flags, unsigned *api,
Neil Robertsba7679f2014-10-01 20:00:48 +0100413 int *reset, int *release, unsigned *error)
Ian Romanickb45f77d2011-12-01 13:52:53 -0800414{
415 unsigned i;
416 bool got_profile = false;
Grigori Goronzyacfd8822017-08-03 20:07:58 +0200417 int no_error = 0;
Ian Romanickb45f77d2011-12-01 13:52:53 -0800418 uint32_t profile;
Ian Romanickb45f77d2011-12-01 13:52:53 -0800419
Rico Schüller8b302e12013-09-01 21:30:19 +0200420 *major_ver = 1;
421 *minor_ver = 0;
422 *render_type = GLX_RGBA_TYPE;
423 *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
Neil Robertsba7679f2014-10-01 20:00:48 +0100424 *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
Rico Schüller8b302e12013-09-01 21:30:19 +0200425 *flags = 0;
426 *api = __DRI_API_OPENGL;
427
Kenneth Graunke10a6fde2012-01-10 23:32:50 -0800428 if (num_attribs == 0) {
Ian Romanickb45f77d2011-12-01 13:52:53 -0800429 return true;
Kenneth Graunke10a6fde2012-01-10 23:32:50 -0800430 }
Ian Romanickb45f77d2011-12-01 13:52:53 -0800431
432 /* This is actually an internal error, but what the heck.
433 */
434 if (attribs == NULL) {
435 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
436 return false;
437 }
438
Ian Romanickb45f77d2011-12-01 13:52:53 -0800439 for (i = 0; i < num_attribs; i++) {
440 switch (attribs[i * 2]) {
441 case GLX_CONTEXT_MAJOR_VERSION_ARB:
442 *major_ver = attribs[i * 2 + 1];
443 break;
444 case GLX_CONTEXT_MINOR_VERSION_ARB:
445 *minor_ver = attribs[i * 2 + 1];
446 break;
447 case GLX_CONTEXT_FLAGS_ARB:
448 *flags = attribs[i * 2 + 1];
449 break;
Grigori Goronzyacfd8822017-08-03 20:07:58 +0200450 case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
451 no_error = attribs[i * 2 + 1];
452 break;
Ian Romanickb45f77d2011-12-01 13:52:53 -0800453 case GLX_CONTEXT_PROFILE_MASK_ARB:
454 profile = attribs[i * 2 + 1];
455 got_profile = true;
456 break;
457 case GLX_RENDER_TYPE:
Tomasz Lisa92cd5b2013-07-17 13:49:15 +0200458 *render_type = attribs[i * 2 + 1];
Ian Romanickb45f77d2011-12-01 13:52:53 -0800459 break;
Ian Romanicka8724d82012-07-03 11:32:59 -0700460 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
461 switch (attribs[i * 2 + 1]) {
462 case GLX_NO_RESET_NOTIFICATION_ARB:
463 *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
464 break;
465 case GLX_LOSE_CONTEXT_ON_RESET_ARB:
466 *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
467 break;
468 default:
469 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
470 return false;
471 }
472 break;
Neil Robertsba7679f2014-10-01 20:00:48 +0100473 case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
474 switch (attribs[i * 2 + 1]) {
475 case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB:
476 *release = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
477 break;
478 case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB:
479 *release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
480 break;
481 default:
482 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
483 return false;
484 }
485 break;
Ian Romanickb45f77d2011-12-01 13:52:53 -0800486 default:
487 /* If an unknown attribute is received, fail.
488 */
489 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
490 return false;
491 }
492 }
493
Grigori Goronzyacfd8822017-08-03 20:07:58 +0200494 if (no_error) {
495 *flags |= __DRI_CTX_FLAG_NO_ERROR;
496 }
497
Ian Romanickb45f77d2011-12-01 13:52:53 -0800498 if (!got_profile) {
499 if (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2))
500 *api = __DRI_API_OPENGL_CORE;
501 } else {
502 switch (profile) {
503 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
504 /* There are no profiles before OpenGL 3.2. The
505 * GLX_ARB_create_context_profile spec says:
506 *
507 * "If the requested OpenGL version is less than 3.2,
508 * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
509 * of the context is determined solely by the requested version."
510 */
511 *api = (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2))
512 ? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL;
513 break;
514 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
515 *api = __DRI_API_OPENGL;
516 break;
Ilia Mirkin5ac7f042016-01-19 10:07:04 -0500517 case GLX_CONTEXT_ES_PROFILE_BIT_EXT:
518 if (*major_ver >= 3)
519 *api = __DRI_API_GLES3;
520 else if (*major_ver == 2 && *minor_ver == 0)
521 *api = __DRI_API_GLES2;
522 else if (*major_ver == 1 && *minor_ver < 2)
523 *api = __DRI_API_GLES;
524 else {
525 *error = __DRI_CTX_ERROR_BAD_API;
526 return false;
527 }
528 break;
Ian Romanickb45f77d2011-12-01 13:52:53 -0800529 default:
530 *error = __DRI_CTX_ERROR_BAD_API;
531 return false;
532 }
533 }
534
535 /* Unknown flag value.
536 */
Ian Romanicka8724d82012-07-03 11:32:59 -0700537 if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE
Grigori Goronzyacfd8822017-08-03 20:07:58 +0200538 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
539 | __DRI_CTX_FLAG_NO_ERROR)) {
Ian Romanickb45f77d2011-12-01 13:52:53 -0800540 *error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
541 return false;
542 }
543
544 /* There are no forward-compatible contexts before OpenGL 3.0. The
545 * GLX_ARB_create_context spec says:
546 *
547 * "Forward-compatible contexts are defined only for OpenGL versions
548 * 3.0 and later."
549 */
550 if (*major_ver < 3 && (*flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
551 *error = __DRI_CTX_ERROR_BAD_FLAG;
552 return false;
553 }
554
Tomasz Lisa92cd5b2013-07-17 13:49:15 +0200555 if (*major_ver >= 3 && *render_type == GLX_COLOR_INDEX_TYPE) {
Ian Romanickb45f77d2011-12-01 13:52:53 -0800556 *error = __DRI_CTX_ERROR_BAD_FLAG;
557 return false;
558 }
559
560 *error = __DRI_CTX_ERROR_SUCCESS;
561 return true;
562}
563
Grigori Goronzyacfd8822017-08-03 20:07:58 +0200564_X_HIDDEN bool
565dri2_check_no_error(uint32_t flags, struct glx_context *share_context,
566 int major, unsigned *error)
567{
568 Bool noError = flags & __DRI_CTX_FLAG_NO_ERROR;
569
570 /* The KHR_no_error specs say:
571 *
572 * Requires OpenGL ES 2.0 or OpenGL 2.0.
573 */
574 if (noError && major < 2) {
575 *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
576 return false;
577 }
578
579 /* The GLX_ARB_create_context_no_error specs say:
580 *
581 * BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB
582 * used to create <share_context> does not match the value of
583 * GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created.
584 */
585 if (share_context && !!share_context->noError != !!noError) {
586 *error = __DRI_CTX_ERROR_BAD_FLAG;
587 return false;
588 }
589
590 /* The GLX_ARB_create_context_no_error specs say:
591 *
592 * BadMatch is generated if the GLX_CONTEXT_OPENGL_NO_ERROR_ARB is TRUE at
593 * the same time as a debug or robustness context is specified.
594 *
595 */
596 if (noError && ((flags & __DRI_CTX_FLAG_DEBUG) ||
597 (flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) {
598 *error = __DRI_CTX_ERROR_BAD_FLAG;
599 return false;
600 }
601
602 return true;
603}
604
Adam Jacksone6e3d892020-10-16 17:32:25 -0400605/*
606 * Given a display pointer and screen number, determine the name of
607 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
608 * Return True for success, False for failure.
609 */
610static Bool
611driGetDriverName(Display * dpy, int scrNum, char **driverName)
612{
613 struct glx_screen *glx_screen = GetGLXScreenConfigs(dpy, scrNum);
614
615 if (!glx_screen || !glx_screen->vtable->get_driver_name)
616 return False;
617
618 *driverName = glx_screen->vtable->get_driver_name(glx_screen);
619 return True;
620}
621
622/*
623 * Exported function for querying the DRI driver for a given screen.
624 *
625 * The returned char pointer points to a static array that will be
626 * overwritten by subsequent calls.
627 */
628_GLX_PUBLIC const char *
629glXGetScreenDriver(Display * dpy, int scrNum)
630{
631 static char ret[32];
632 char *driverName;
633
634 if (driGetDriverName(dpy, scrNum, &driverName)) {
635 int len;
636 if (!driverName)
637 return NULL;
638 len = strlen(driverName);
639 if (len >= 31)
640 return NULL;
641 memcpy(ret, driverName, len + 1);
642 free(driverName);
643 return ret;
644 }
645 return NULL;
646}
647
648/* glXGetDriverConfig must return a pointer with a static lifetime. To avoid
649 * keeping drivers loaded and other leaks, we keep a cache of results here that
650 * is cleared by an atexit handler.
651 */
652struct driver_config_entry {
653 struct driver_config_entry *next;
654 char *driverName;
655 char *config;
656};
657
658static pthread_mutex_t driver_config_mutex = PTHREAD_MUTEX_INITIALIZER;
659static struct driver_config_entry *driver_config_cache = NULL;
660
661/* Called as an atexit function. Otherwise, this would have to be called with
662 * driver_config_mutex locked.
663 */
664static void
665clear_driver_config_cache()
666{
667 while (driver_config_cache) {
668 struct driver_config_entry *e = driver_config_cache;
669 driver_config_cache = e->next;
670
671 free(e->driverName);
672 free(e->config);
673 free(e);
674 }
675}
676
677static char *
678get_driver_config(const char *driverName)
679{
680 void *handle;
681 char *config = NULL;
682 const __DRIextension **extensions = driOpenDriver(driverName, &handle);
683 if (extensions) {
684 for (int i = 0; extensions[i]; i++) {
685 if (strcmp(extensions[i]->name, __DRI_CONFIG_OPTIONS) != 0)
686 continue;
687
688 __DRIconfigOptionsExtension *ext =
689 (__DRIconfigOptionsExtension *)extensions[i];
690
691 if (ext->base.version >= 2)
692 config = ext->getXml(driverName);
693 else
694 config = strdup(ext->xml);
695
696 break;
697 }
698 }
699
700 if (!config) {
701 /* Fall back to the old method */
702 config = dlsym(handle, "__driConfigOptions");
703 if (config)
704 config = strdup(config);
705 }
706
707 dlclose(handle);
708
709 return config;
710}
711
712/*
713 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
714 *
715 * The returned char pointer points directly into the driver. Therefore
716 * it should be treated as a constant.
717 *
718 * If the driver was not found or does not support configuration NULL is
719 * returned.
720 */
721_GLX_PUBLIC const char *
722glXGetDriverConfig(const char *driverName)
723{
724 struct driver_config_entry *e;
725
726 pthread_mutex_lock(&driver_config_mutex);
727
728 for (e = driver_config_cache; e; e = e->next) {
729 if (strcmp(e->driverName, driverName) == 0)
730 goto out;
731 }
732
733 e = malloc(sizeof(*e));
734 if (!e)
735 goto out;
736
737 e->config = get_driver_config(driverName);
738 e->driverName = strdup(driverName);
739 if (!e->config || !e->driverName) {
740 free(e->config);
741 free(e->driverName);
742 free(e);
743 e = NULL;
744 goto out;
745 }
746
747 e->next = driver_config_cache;
748 driver_config_cache = e;
749
750 if (!e->next)
751 atexit(clear_driver_config_cache);
752
753out:
754 pthread_mutex_unlock(&driver_config_mutex);
755
756 return e ? e->config : NULL;
757}
758
George Sapountzis07934572008-06-09 17:47:09 +0300759#endif /* GLX_DIRECT_RENDERING */