2 * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3 * Copyright © 2008 Red Hat, Inc.
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.
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.
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.
31 * Kevin E. Martin <kevin@precisioninsight.com>
32 * Brian Paul <brian@precisioninsight.com>
33 * Kristian Høgsberg (krh@redhat.com)
36 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
41 #include "glxclient.h"
42 #include "dri_common.h"
53 dri_message(int level
, const char *f
, ...)
56 int threshold
= _LOADER_WARNING
;
57 const char *libgl_debug
;
59 libgl_debug
= getenv("LIBGL_DEBUG");
61 if (strstr(libgl_debug
, "quiet"))
62 threshold
= _LOADER_FATAL
;
63 else if (strstr(libgl_debug
, "verbose"))
64 threshold
= _LOADER_DEBUG
;
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" : "");
71 vfprintf(stderr
, f
, args
);
77 #define GL_LIB_NAME "libGL.so.1"
81 * Try to \c dlopen the named driver.
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.
87 * \param driverName - a name like "i965", "radeon", "nouveau", etc.
88 * \param out_driver_handle - Address to return the resulting dlopen() handle.
91 * The __DRIextension entrypoint table for the driver, or \c NULL if driver
94 _X_HIDDEN
const __DRIextension
**
95 driOpenDriver(const char *driverName
, void **out_driver_handle
)
99 /* Attempt to make sure libGL symbols will be visible to the driver */
100 glhandle
= dlopen(GL_LIB_NAME
, RTLD_NOW
| RTLD_GLOBAL
);
102 static const char *search_path_vars
[] = {
103 "LIBGL_DRIVERS_PATH",
104 "LIBGL_DRIVERS_DIR", /* deprecated */
108 const __DRIextension
**extensions
=
109 loader_open_driver(driverName
, out_driver_handle
, search_path_vars
);
118 __driGetMSCRate(__DRIdrawable
*draw
,
119 int32_t * numerator
, int32_t * denominator
,
122 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
124 return __glxGetMscRate(glxDraw
->psc
, numerator
, denominator
);
127 _X_HIDDEN
const __DRIsystemTimeExtension systemTimeExtension
= {
128 .base
= {__DRI_SYSTEM_TIME
, 1 },
130 .getUST
= __glXGetUST
,
131 .getMSCRate
= __driGetMSCRate
134 #define __ATTRIB(attrib, field) \
135 { attrib, offsetof(struct glx_config, field) }
139 unsigned int attrib
, offset
;
141 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE
, rgbBits
),
142 __ATTRIB(__DRI_ATTRIB_LEVEL
, level
),
143 __ATTRIB(__DRI_ATTRIB_RED_SIZE
, redBits
),
144 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE
, greenBits
),
145 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE
, blueBits
),
146 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE
, alphaBits
),
147 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE
, depthBits
),
148 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE
, stencilBits
),
149 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE
, accumRedBits
),
150 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE
, accumGreenBits
),
151 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE
, accumBlueBits
),
152 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
153 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS
, sampleBuffers
),
154 __ATTRIB(__DRI_ATTRIB_SAMPLES
, samples
),
155 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER
, doubleBufferMode
),
156 __ATTRIB(__DRI_ATTRIB_STEREO
, stereoMode
),
157 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS
, numAuxBuffers
),
159 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE
, transparentPixel
),
160 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE
, transparentIndex
),
161 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE
, transparentRed
),
162 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE
, transparentGreen
),
163 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE
, transparentBlue
),
164 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE
, transparentAlpha
),
165 __ATTRIB(__DRI_ATTRIB_RED_MASK
, redMask
),
166 __ATTRIB(__DRI_ATTRIB_GREEN_MASK
, greenMask
),
167 __ATTRIB(__DRI_ATTRIB_BLUE_MASK
, blueMask
),
168 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK
, alphaMask
),
169 __ATTRIB(__DRI_ATTRIB_RED_SHIFT
, redShift
),
170 __ATTRIB(__DRI_ATTRIB_GREEN_SHIFT
, greenShift
),
171 __ATTRIB(__DRI_ATTRIB_BLUE_SHIFT
, blueShift
),
172 __ATTRIB(__DRI_ATTRIB_ALPHA_SHIFT
, alphaShift
),
174 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH
, maxPbufferWidth
),
175 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT
, maxPbufferHeight
),
176 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS
, maxPbufferPixels
),
177 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH
, optimalPbufferWidth
),
178 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT
, optimalPbufferHeight
),
179 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD
, swapMethod
),
180 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB
, bindToTextureRgb
),
181 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA
, bindToTextureRgba
),
182 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE
,
183 bindToMipmapTexture
),
184 __ATTRIB(__DRI_ATTRIB_YINVERTED
, yInverted
),
185 __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE
, sRGBCapable
)
189 scalarEqual(struct glx_config
*mode
, unsigned int attrib
, unsigned int value
)
191 unsigned glxValue
, i
;
193 for (i
= 0; i
< ARRAY_SIZE(attribMap
); i
++)
194 if (attribMap
[i
].attrib
== attrib
) {
195 glxValue
= *(unsigned int *) ((char *) mode
+ attribMap
[i
].offset
);
196 return glxValue
== GLX_DONT_CARE
|| glxValue
== value
;
199 return GL_TRUE
; /* Is a non-existing attribute equal to value? */
203 driConfigEqual(const __DRIcoreExtension
*core
,
204 struct glx_config
*config
, const __DRIconfig
*driConfig
)
206 unsigned int attrib
, value
, glxValue
;
210 while (core
->indexConfigAttrib(driConfig
, i
++, &attrib
, &value
)) {
212 case __DRI_ATTRIB_RENDER_TYPE
:
214 if (value
& __DRI_ATTRIB_RGBA_BIT
) {
215 glxValue
|= GLX_RGBA_BIT
;
217 if (value
& __DRI_ATTRIB_COLOR_INDEX_BIT
) {
218 glxValue
|= GLX_COLOR_INDEX_BIT
;
220 if (value
& __DRI_ATTRIB_FLOAT_BIT
) {
221 glxValue
|= GLX_RGBA_FLOAT_BIT_ARB
;
223 if (value
& __DRI_ATTRIB_UNSIGNED_FLOAT_BIT
) {
224 glxValue
|= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT
;
226 if (glxValue
!= config
->renderType
)
230 case __DRI_ATTRIB_CONFIG_CAVEAT
:
231 if (value
& __DRI_ATTRIB_NON_CONFORMANT_CONFIG
)
232 glxValue
= GLX_NON_CONFORMANT_CONFIG
;
233 else if (value
& __DRI_ATTRIB_SLOW_BIT
)
234 glxValue
= GLX_SLOW_CONFIG
;
237 if (glxValue
!= config
->visualRating
)
241 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS
:
243 if (value
& __DRI_ATTRIB_TEXTURE_1D_BIT
)
244 glxValue
|= GLX_TEXTURE_1D_BIT_EXT
;
245 if (value
& __DRI_ATTRIB_TEXTURE_2D_BIT
)
246 glxValue
|= GLX_TEXTURE_2D_BIT_EXT
;
247 if (value
& __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT
)
248 glxValue
|= GLX_TEXTURE_RECTANGLE_BIT_EXT
;
249 if (config
->bindToTextureTargets
!= GLX_DONT_CARE
&&
250 glxValue
!= config
->bindToTextureTargets
)
254 case __DRI_ATTRIB_SWAP_METHOD
:
255 if (value
== __DRI_ATTRIB_SWAP_EXCHANGE
)
256 glxValue
= GLX_SWAP_EXCHANGE_OML
;
257 else if (value
== __DRI_ATTRIB_SWAP_COPY
)
258 glxValue
= GLX_SWAP_COPY_OML
;
260 glxValue
= GLX_SWAP_UNDEFINED_OML
;
262 if (!scalarEqual(config
, attrib
, glxValue
))
268 if (!scalarEqual(config
, attrib
, value
))
276 static struct glx_config
*
277 createDriMode(const __DRIcoreExtension
* core
,
278 struct glx_config
*config
, const __DRIconfig
**driConfigs
)
280 __GLXDRIconfigPrivate
*driConfig
;
283 for (i
= 0; driConfigs
[i
]; i
++) {
284 if (driConfigEqual(core
, config
, driConfigs
[i
]))
288 if (driConfigs
[i
] == NULL
)
291 driConfig
= malloc(sizeof *driConfig
);
292 if (driConfig
== NULL
)
295 driConfig
->base
= *config
;
296 driConfig
->driConfig
= driConfigs
[i
];
298 return &driConfig
->base
;
301 _X_HIDDEN
struct glx_config
*
302 driConvertConfigs(const __DRIcoreExtension
* core
,
303 struct glx_config
*configs
, const __DRIconfig
**driConfigs
)
305 struct glx_config head
, *tail
, *m
;
309 for (m
= configs
; m
; m
= m
->next
) {
310 tail
->next
= createDriMode(core
, m
, driConfigs
);
311 if (tail
->next
== NULL
) {
312 /* no matching dri config for m */
324 driDestroyConfigs(const __DRIconfig
**configs
)
328 for (i
= 0; configs
[i
]; i
++)
329 free((__DRIconfig
*) configs
[i
]);
333 static struct glx_config
*
334 driInferDrawableConfig(struct glx_screen
*psc
, GLXDrawable draw
)
336 unsigned int fbconfig
= 0;
338 if (__glXGetDrawableAttribute(psc
->dpy
, draw
, GLX_FBCONFIG_ID
, &fbconfig
)) {
339 return glx_config_find_fbconfig(psc
->configs
, fbconfig
);
345 _X_HIDDEN __GLXDRIdrawable
*
346 driFetchDrawable(struct glx_context
*gc
, GLXDrawable glxDrawable
)
348 struct glx_display
*const priv
= __glXInitialize(gc
->psc
->dpy
);
349 __GLXDRIdrawable
*pdraw
;
350 struct glx_screen
*psc
;
351 struct glx_config
*config
= gc
->config
;
356 if (glxDrawable
== None
)
359 psc
= priv
->screens
[gc
->screen
];
360 if (priv
->drawHash
== NULL
)
363 if (__glxHashLookup(priv
->drawHash
, glxDrawable
, (void *) &pdraw
) == 0) {
369 config
= driInferDrawableConfig(gc
->psc
, glxDrawable
);
373 pdraw
= psc
->driScreen
->createDrawable(psc
, glxDrawable
, glxDrawable
,
377 ErrorMessageF("failed to create drawable\n");
381 if (__glxHashInsert(priv
->drawHash
, glxDrawable
, pdraw
)) {
382 (*pdraw
->destroyDrawable
) (pdraw
);
391 driReleaseDrawables(struct glx_context
*gc
)
393 const struct glx_display
*priv
= gc
->psc
->display
;
394 __GLXDRIdrawable
*pdraw
;
399 if (__glxHashLookup(priv
->drawHash
,
400 gc
->currentDrawable
, (void *) &pdraw
) == 0) {
401 if (pdraw
->drawable
== pdraw
->xDrawable
) {
403 if (pdraw
->refcount
== 0) {
404 pdraw
->destroyDrawable(pdraw
);
405 __glxHashDelete(priv
->drawHash
, gc
->currentDrawable
);
410 if (__glxHashLookup(priv
->drawHash
,
411 gc
->currentReadable
, (void *) &pdraw
) == 0) {
412 if (pdraw
->drawable
== pdraw
->xDrawable
) {
414 if (pdraw
->refcount
== 0) {
415 pdraw
->destroyDrawable(pdraw
);
416 __glxHashDelete(priv
->drawHash
, gc
->currentReadable
);
421 gc
->currentDrawable
= None
;
422 gc
->currentReadable
= None
;
427 dri2_convert_glx_attribs(unsigned num_attribs
, const uint32_t *attribs
,
428 unsigned *major_ver
, unsigned *minor_ver
,
429 uint32_t *render_type
, uint32_t *flags
, unsigned *api
,
430 int *reset
, int *release
, unsigned *error
)
433 bool got_profile
= false;
439 *render_type
= GLX_RGBA_TYPE
;
440 *reset
= __DRI_CTX_RESET_NO_NOTIFICATION
;
441 *release
= __DRI_CTX_RELEASE_BEHAVIOR_FLUSH
;
443 *api
= __DRI_API_OPENGL
;
445 if (num_attribs
== 0) {
449 /* This is actually an internal error, but what the heck.
451 if (attribs
== NULL
) {
452 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
456 for (i
= 0; i
< num_attribs
; i
++) {
457 switch (attribs
[i
* 2]) {
458 case GLX_CONTEXT_MAJOR_VERSION_ARB
:
459 *major_ver
= attribs
[i
* 2 + 1];
461 case GLX_CONTEXT_MINOR_VERSION_ARB
:
462 *minor_ver
= attribs
[i
* 2 + 1];
464 case GLX_CONTEXT_FLAGS_ARB
:
465 *flags
= attribs
[i
* 2 + 1];
467 case GLX_CONTEXT_OPENGL_NO_ERROR_ARB
:
468 no_error
= attribs
[i
* 2 + 1];
470 case GLX_CONTEXT_PROFILE_MASK_ARB
:
471 profile
= attribs
[i
* 2 + 1];
474 case GLX_RENDER_TYPE
:
475 *render_type
= attribs
[i
* 2 + 1];
477 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
:
478 switch (attribs
[i
* 2 + 1]) {
479 case GLX_NO_RESET_NOTIFICATION_ARB
:
480 *reset
= __DRI_CTX_RESET_NO_NOTIFICATION
;
482 case GLX_LOSE_CONTEXT_ON_RESET_ARB
:
483 *reset
= __DRI_CTX_RESET_LOSE_CONTEXT
;
486 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
490 case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
:
491 switch (attribs
[i
* 2 + 1]) {
492 case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB
:
493 *release
= __DRI_CTX_RELEASE_BEHAVIOR_NONE
;
495 case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB
:
496 *release
= __DRI_CTX_RELEASE_BEHAVIOR_FLUSH
;
499 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
504 /* If an unknown attribute is received, fail.
506 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
512 *flags
|= __DRI_CTX_FLAG_NO_ERROR
;
516 if (*major_ver
> 3 || (*major_ver
== 3 && *minor_ver
>= 2))
517 *api
= __DRI_API_OPENGL_CORE
;
520 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB
:
521 /* There are no profiles before OpenGL 3.2. The
522 * GLX_ARB_create_context_profile spec says:
524 * "If the requested OpenGL version is less than 3.2,
525 * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
526 * of the context is determined solely by the requested version."
528 *api
= (*major_ver
> 3 || (*major_ver
== 3 && *minor_ver
>= 2))
529 ? __DRI_API_OPENGL_CORE
: __DRI_API_OPENGL
;
531 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
:
532 *api
= __DRI_API_OPENGL
;
534 case GLX_CONTEXT_ES_PROFILE_BIT_EXT
:
536 *api
= __DRI_API_GLES3
;
537 else if (*major_ver
== 2 && *minor_ver
== 0)
538 *api
= __DRI_API_GLES2
;
539 else if (*major_ver
== 1 && *minor_ver
< 2)
540 *api
= __DRI_API_GLES
;
542 *error
= __DRI_CTX_ERROR_BAD_API
;
547 *error
= __DRI_CTX_ERROR_BAD_API
;
552 /* Unknown flag value.
554 if (*flags
& ~(__DRI_CTX_FLAG_DEBUG
| __DRI_CTX_FLAG_FORWARD_COMPATIBLE
555 | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
556 | __DRI_CTX_FLAG_NO_ERROR
)) {
557 *error
= __DRI_CTX_ERROR_UNKNOWN_FLAG
;
561 /* There are no forward-compatible contexts before OpenGL 3.0. The
562 * GLX_ARB_create_context spec says:
564 * "Forward-compatible contexts are defined only for OpenGL versions
567 if (*major_ver
< 3 && (*flags
& __DRI_CTX_FLAG_FORWARD_COMPATIBLE
) != 0) {
568 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
572 if (*major_ver
>= 3 && *render_type
== GLX_COLOR_INDEX_TYPE
) {
573 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
577 *error
= __DRI_CTX_ERROR_SUCCESS
;
582 dri2_check_no_error(uint32_t flags
, struct glx_context
*share_context
,
583 int major
, unsigned *error
)
585 Bool noError
= flags
& __DRI_CTX_FLAG_NO_ERROR
;
587 /* The KHR_no_error specs say:
589 * Requires OpenGL ES 2.0 or OpenGL 2.0.
591 if (noError
&& major
< 2) {
592 *error
= __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE
;
596 /* The GLX_ARB_create_context_no_error specs say:
598 * BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB
599 * used to create <share_context> does not match the value of
600 * GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created.
602 if (share_context
&& !!share_context
->noError
!= !!noError
) {
603 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
607 /* The GLX_ARB_create_context_no_error specs say:
609 * BadMatch is generated if the GLX_CONTEXT_OPENGL_NO_ERROR_ARB is TRUE at
610 * the same time as a debug or robustness context is specified.
613 if (noError
&& ((flags
& __DRI_CTX_FLAG_DEBUG
) ||
614 (flags
& __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
))) {
615 *error
= __DRI_CTX_ERROR_BAD_FLAG
;
622 #endif /* GLX_DIRECT_RENDERING */