Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/glx/dri_common.c
4558 views
1
/*
2
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
3
* Copyright © 2008 Red Hat, Inc.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Soft-
7
* ware"), to deal in the Software without restriction, including without
8
* limitation the rights to use, copy, modify, merge, publish, distribute,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, provided that the above copyright
11
* notice(s) and this permission notice appear in all copies of the Soft-
12
* ware and that both the above copyright notice(s) and this permission
13
* notice appear in supporting documentation.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17
* ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
18
* RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
19
* THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
20
* QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
23
* MANCE OF THIS SOFTWARE.
24
*
25
* Except as contained in this notice, the name of a copyright holder shall
26
* not be used in advertising or otherwise to promote the sale, use or
27
* other dealings in this Software without prior written authorization of
28
* the copyright holder.
29
*
30
* Authors:
31
* Kevin E. Martin <[email protected]>
32
* Brian Paul <[email protected]>
33
* Kristian Høgsberg ([email protected])
34
*/
35
36
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
37
38
#include <unistd.h>
39
#include <dlfcn.h>
40
#include <stdarg.h>
41
#include "glxclient.h"
42
#include "dri_common.h"
43
#include "loader.h"
44
#include <X11/Xlib-xcb.h>
45
#include <xcb/xproto.h>
46
47
#ifndef RTLD_NOW
48
#define RTLD_NOW 0
49
#endif
50
#ifndef RTLD_GLOBAL
51
#define RTLD_GLOBAL 0
52
#endif
53
54
#ifndef GL_LIB_NAME
55
#define GL_LIB_NAME "libGL.so.1"
56
#endif
57
58
/**
59
* Try to \c dlopen the named driver.
60
*
61
* This function adds the "_dri.so" suffix to the driver name and searches the
62
* directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
63
* order to find the driver.
64
*
65
* \param driverName - a name like "i965", "radeon", "nouveau", etc.
66
* \param out_driver_handle - Address to return the resulting dlopen() handle.
67
*
68
* \returns
69
* The __DRIextension entrypoint table for the driver, or \c NULL if driver
70
* file not found.
71
*/
72
_X_HIDDEN const __DRIextension **
73
driOpenDriver(const char *driverName, void **out_driver_handle)
74
{
75
void *glhandle;
76
77
/* Attempt to make sure libGL symbols will be visible to the driver */
78
glhandle = dlopen(GL_LIB_NAME, RTLD_NOW | RTLD_GLOBAL);
79
80
static const char *search_path_vars[] = {
81
"LIBGL_DRIVERS_PATH",
82
"LIBGL_DRIVERS_DIR", /* deprecated */
83
NULL
84
};
85
86
const __DRIextension **extensions =
87
loader_open_driver(driverName, out_driver_handle, search_path_vars);
88
89
if (glhandle)
90
dlclose(glhandle);
91
92
return extensions;
93
}
94
95
#define __ATTRIB(attrib, field) \
96
{ attrib, offsetof(struct glx_config, field) }
97
98
static const struct
99
{
100
unsigned int attrib, offset;
101
} attribMap[] = {
102
__ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits),
103
__ATTRIB(__DRI_ATTRIB_LEVEL, level),
104
__ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits),
105
__ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits),
106
__ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits),
107
__ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits),
108
__ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits),
109
__ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits),
110
__ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits),
111
__ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits),
112
__ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits),
113
__ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits),
114
__ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers),
115
__ATTRIB(__DRI_ATTRIB_SAMPLES, samples),
116
__ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode),
117
__ATTRIB(__DRI_ATTRIB_STEREO, stereoMode),
118
__ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers),
119
__ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod),
120
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb),
121
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba),
122
__ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture),
123
__ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted),
124
__ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable)
125
};
126
127
static int
128
scalarEqual(struct glx_config *mode, unsigned int attrib, unsigned int value)
129
{
130
unsigned glxValue, i;
131
132
for (i = 0; i < ARRAY_SIZE(attribMap); i++)
133
if (attribMap[i].attrib == attrib) {
134
glxValue = *(unsigned int *) ((char *) mode + attribMap[i].offset);
135
return glxValue == GLX_DONT_CARE || glxValue == value;
136
}
137
138
return GL_TRUE; /* Is a non-existing attribute equal to value? */
139
}
140
141
static int
142
driConfigEqual(const __DRIcoreExtension *core,
143
struct glx_config *config, const __DRIconfig *driConfig)
144
{
145
unsigned int attrib, value, glxValue;
146
int i;
147
148
i = 0;
149
while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) {
150
switch (attrib) {
151
case __DRI_ATTRIB_RENDER_TYPE:
152
glxValue = 0;
153
if (value & __DRI_ATTRIB_RGBA_BIT) {
154
glxValue |= GLX_RGBA_BIT;
155
}
156
if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) {
157
glxValue |= GLX_COLOR_INDEX_BIT;
158
}
159
if (value & __DRI_ATTRIB_FLOAT_BIT) {
160
glxValue |= GLX_RGBA_FLOAT_BIT_ARB;
161
}
162
if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) {
163
glxValue |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT;
164
}
165
if (glxValue != config->renderType)
166
return GL_FALSE;
167
break;
168
169
case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
170
glxValue = 0;
171
if (value & __DRI_ATTRIB_TEXTURE_1D_BIT)
172
glxValue |= GLX_TEXTURE_1D_BIT_EXT;
173
if (value & __DRI_ATTRIB_TEXTURE_2D_BIT)
174
glxValue |= GLX_TEXTURE_2D_BIT_EXT;
175
if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT)
176
glxValue |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
177
if (config->bindToTextureTargets != GLX_DONT_CARE &&
178
glxValue != config->bindToTextureTargets)
179
return GL_FALSE;
180
break;
181
182
case __DRI_ATTRIB_SWAP_METHOD:
183
if (value == __DRI_ATTRIB_SWAP_EXCHANGE)
184
glxValue = GLX_SWAP_EXCHANGE_OML;
185
else if (value == __DRI_ATTRIB_SWAP_COPY)
186
glxValue = GLX_SWAP_COPY_OML;
187
else
188
glxValue = GLX_SWAP_UNDEFINED_OML;
189
190
if (!scalarEqual(config, attrib, glxValue))
191
return GL_FALSE;
192
193
break;
194
195
/* Nerf some attributes we can safely ignore if the server claims to
196
* support them but the driver does not.
197
*/
198
case __DRI_ATTRIB_CONFIG_CAVEAT:
199
if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
200
glxValue = GLX_NON_CONFORMANT_CONFIG;
201
else if (value & __DRI_ATTRIB_SLOW_BIT)
202
glxValue = GLX_SLOW_CONFIG;
203
else
204
glxValue = GLX_NONE;
205
if (glxValue != config->visualRating) {
206
if (config->visualRating == GLX_NONE) {
207
static int warned;
208
if (!warned) {
209
DebugMessageF("Not downgrading visual rating\n");
210
warned = 1;
211
}
212
} else {
213
return GL_FALSE;
214
}
215
}
216
break;
217
218
case __DRI_ATTRIB_AUX_BUFFERS:
219
if (!scalarEqual(config, attrib, value)) {
220
static int warned;
221
if (!warned) {
222
DebugMessageF("Disabling server's aux buffer support\n");
223
warned = 1;
224
}
225
config->numAuxBuffers = 0;
226
}
227
break;
228
229
case __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE:
230
if (!scalarEqual(config, attrib, value)) {
231
static int warned;
232
if (!warned) {
233
DebugMessageF("Disabling server's tfp mipmap support\n");
234
warned = 1;
235
}
236
config->bindToMipmapTexture = 0;
237
}
238
break;
239
240
default:
241
if (!scalarEqual(config, attrib, value))
242
return GL_FALSE;
243
}
244
}
245
246
return GL_TRUE;
247
}
248
249
static struct glx_config *
250
createDriMode(const __DRIcoreExtension * core,
251
struct glx_config *config, const __DRIconfig **driConfigs)
252
{
253
__GLXDRIconfigPrivate *driConfig;
254
int i;
255
256
for (i = 0; driConfigs[i]; i++) {
257
if (driConfigEqual(core, config, driConfigs[i]))
258
break;
259
}
260
261
if (driConfigs[i] == NULL)
262
return NULL;
263
264
driConfig = malloc(sizeof *driConfig);
265
if (driConfig == NULL)
266
return NULL;
267
268
driConfig->base = *config;
269
driConfig->driConfig = driConfigs[i];
270
271
return &driConfig->base;
272
}
273
274
_X_HIDDEN struct glx_config *
275
driConvertConfigs(const __DRIcoreExtension * core,
276
struct glx_config *configs, const __DRIconfig **driConfigs)
277
{
278
struct glx_config head, *tail, *m;
279
280
tail = &head;
281
head.next = NULL;
282
for (m = configs; m; m = m->next) {
283
tail->next = createDriMode(core, m, driConfigs);
284
if (tail->next == NULL) {
285
/* no matching dri config for m */
286
continue;
287
}
288
289
290
tail = tail->next;
291
}
292
293
return head.next;
294
}
295
296
_X_HIDDEN void
297
driDestroyConfigs(const __DRIconfig **configs)
298
{
299
int i;
300
301
for (i = 0; configs[i]; i++)
302
free((__DRIconfig *) configs[i]);
303
free(configs);
304
}
305
306
static struct glx_config *
307
driInferDrawableConfig(struct glx_screen *psc, GLXDrawable draw)
308
{
309
unsigned int fbconfig = 0;
310
xcb_get_window_attributes_cookie_t cookie = { 0 };
311
xcb_get_window_attributes_reply_t *attr = NULL;
312
xcb_connection_t *conn = XGetXCBConnection(psc->dpy);
313
314
/* In practice here, either the XID is a bare Window or it was created
315
* by some other client. First let's see if the X server can tell us
316
* the answer. Xorg first added GLX_EXT_no_config_context in 1.20, where
317
* this usually works except for bare Windows that haven't been made
318
* current yet.
319
*/
320
if (__glXGetDrawableAttribute(psc->dpy, draw, GLX_FBCONFIG_ID, &fbconfig)) {
321
return glx_config_find_fbconfig(psc->configs, fbconfig);
322
}
323
324
/* Well this had better be a Window then. Figure out its visual and
325
* then find the corresponding GLX visual.
326
*/
327
cookie = xcb_get_window_attributes(conn, draw);
328
attr = xcb_get_window_attributes_reply(conn, cookie, NULL);
329
330
if (attr) {
331
uint32_t vid = attr->visual;
332
free(attr);
333
return glx_config_find_visual(psc->visuals, vid);
334
}
335
336
return NULL;
337
}
338
339
_X_HIDDEN __GLXDRIdrawable *
340
driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
341
{
342
struct glx_display *const priv = __glXInitialize(gc->psc->dpy);
343
__GLXDRIdrawable *pdraw;
344
struct glx_screen *psc;
345
struct glx_config *config = gc->config;
346
347
if (priv == NULL)
348
return NULL;
349
350
if (glxDrawable == None)
351
return NULL;
352
353
psc = priv->screens[gc->screen];
354
if (priv->drawHash == NULL)
355
return NULL;
356
357
if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
358
pdraw->refcount ++;
359
return pdraw;
360
}
361
362
/* if this is a no-config context, infer the fbconfig from the drawable */
363
if (config == NULL)
364
config = driInferDrawableConfig(gc->psc, glxDrawable);
365
if (config == NULL)
366
return NULL;
367
368
pdraw = psc->driScreen->createDrawable(psc, glxDrawable, glxDrawable,
369
config);
370
371
if (pdraw == NULL) {
372
ErrorMessageF("failed to create drawable\n");
373
return NULL;
374
}
375
376
if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) {
377
(*pdraw->destroyDrawable) (pdraw);
378
return NULL;
379
}
380
pdraw->refcount = 1;
381
382
return pdraw;
383
}
384
385
_X_HIDDEN void
386
driReleaseDrawables(struct glx_context *gc)
387
{
388
const struct glx_display *priv = gc->psc->display;
389
__GLXDRIdrawable *pdraw;
390
391
if (priv == NULL)
392
return;
393
394
if (__glxHashLookup(priv->drawHash,
395
gc->currentDrawable, (void *) &pdraw) == 0) {
396
if (pdraw->drawable == pdraw->xDrawable) {
397
pdraw->refcount --;
398
if (pdraw->refcount == 0) {
399
pdraw->destroyDrawable(pdraw);
400
__glxHashDelete(priv->drawHash, gc->currentDrawable);
401
}
402
}
403
}
404
405
if (__glxHashLookup(priv->drawHash,
406
gc->currentReadable, (void *) &pdraw) == 0) {
407
if (pdraw->drawable == pdraw->xDrawable) {
408
pdraw->refcount --;
409
if (pdraw->refcount == 0) {
410
pdraw->destroyDrawable(pdraw);
411
__glxHashDelete(priv->drawHash, gc->currentReadable);
412
}
413
}
414
}
415
416
gc->currentDrawable = None;
417
gc->currentReadable = None;
418
419
}
420
421
_X_HIDDEN bool
422
dri2_convert_glx_attribs(unsigned num_attribs, const uint32_t *attribs,
423
unsigned *major_ver, unsigned *minor_ver,
424
uint32_t *render_type, uint32_t *flags, unsigned *api,
425
int *reset, int *release, unsigned *error)
426
{
427
unsigned i;
428
bool got_profile = false;
429
int no_error = 0;
430
uint32_t profile;
431
432
*major_ver = 1;
433
*minor_ver = 0;
434
*render_type = GLX_RGBA_TYPE;
435
*reset = __DRI_CTX_RESET_NO_NOTIFICATION;
436
*release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
437
*flags = 0;
438
*api = __DRI_API_OPENGL;
439
440
if (num_attribs == 0) {
441
return true;
442
}
443
444
/* This is actually an internal error, but what the heck.
445
*/
446
if (attribs == NULL) {
447
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
448
return false;
449
}
450
451
for (i = 0; i < num_attribs; i++) {
452
switch (attribs[i * 2]) {
453
case GLX_CONTEXT_MAJOR_VERSION_ARB:
454
*major_ver = attribs[i * 2 + 1];
455
break;
456
case GLX_CONTEXT_MINOR_VERSION_ARB:
457
*minor_ver = attribs[i * 2 + 1];
458
break;
459
case GLX_CONTEXT_FLAGS_ARB:
460
*flags = attribs[i * 2 + 1];
461
break;
462
case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
463
no_error = attribs[i * 2 + 1];
464
break;
465
case GLX_CONTEXT_PROFILE_MASK_ARB:
466
profile = attribs[i * 2 + 1];
467
got_profile = true;
468
break;
469
case GLX_RENDER_TYPE:
470
*render_type = attribs[i * 2 + 1];
471
break;
472
case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
473
switch (attribs[i * 2 + 1]) {
474
case GLX_NO_RESET_NOTIFICATION_ARB:
475
*reset = __DRI_CTX_RESET_NO_NOTIFICATION;
476
break;
477
case GLX_LOSE_CONTEXT_ON_RESET_ARB:
478
*reset = __DRI_CTX_RESET_LOSE_CONTEXT;
479
break;
480
default:
481
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
482
return false;
483
}
484
break;
485
case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
486
switch (attribs[i * 2 + 1]) {
487
case GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB:
488
*release = __DRI_CTX_RELEASE_BEHAVIOR_NONE;
489
break;
490
case GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB:
491
*release = __DRI_CTX_RELEASE_BEHAVIOR_FLUSH;
492
break;
493
default:
494
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
495
return false;
496
}
497
break;
498
case GLX_SCREEN:
499
/* Implies GLX_EXT_no_config_context */
500
*render_type = GLX_DONT_CARE;
501
break;
502
default:
503
/* If an unknown attribute is received, fail.
504
*/
505
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
506
return false;
507
}
508
}
509
510
if (no_error) {
511
*flags |= __DRI_CTX_FLAG_NO_ERROR;
512
}
513
514
if (!got_profile) {
515
if (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2))
516
*api = __DRI_API_OPENGL_CORE;
517
} else {
518
switch (profile) {
519
case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
520
/* There are no profiles before OpenGL 3.2. The
521
* GLX_ARB_create_context_profile spec says:
522
*
523
* "If the requested OpenGL version is less than 3.2,
524
* GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
525
* of the context is determined solely by the requested version."
526
*/
527
*api = (*major_ver > 3 || (*major_ver == 3 && *minor_ver >= 2))
528
? __DRI_API_OPENGL_CORE : __DRI_API_OPENGL;
529
break;
530
case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
531
*api = __DRI_API_OPENGL;
532
break;
533
case GLX_CONTEXT_ES_PROFILE_BIT_EXT:
534
if (*major_ver >= 3)
535
*api = __DRI_API_GLES3;
536
else if (*major_ver == 2 && *minor_ver == 0)
537
*api = __DRI_API_GLES2;
538
else if (*major_ver == 1 && *minor_ver < 2)
539
*api = __DRI_API_GLES;
540
else {
541
*error = __DRI_CTX_ERROR_BAD_API;
542
return false;
543
}
544
break;
545
default:
546
*error = __DRI_CTX_ERROR_BAD_API;
547
return false;
548
}
549
}
550
551
/* Unknown flag value.
552
*/
553
if (*flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE
554
| __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS
555
| __DRI_CTX_FLAG_NO_ERROR)) {
556
*error = __DRI_CTX_ERROR_UNKNOWN_FLAG;
557
return false;
558
}
559
560
/* There are no forward-compatible contexts before OpenGL 3.0. The
561
* GLX_ARB_create_context spec says:
562
*
563
* "Forward-compatible contexts are defined only for OpenGL versions
564
* 3.0 and later."
565
*/
566
if (*major_ver < 3 && (*flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) {
567
*error = __DRI_CTX_ERROR_BAD_FLAG;
568
return false;
569
}
570
571
if (*major_ver >= 3 && *render_type == GLX_COLOR_INDEX_TYPE) {
572
*error = __DRI_CTX_ERROR_BAD_FLAG;
573
return false;
574
}
575
576
*error = __DRI_CTX_ERROR_SUCCESS;
577
return true;
578
}
579
580
_X_HIDDEN bool
581
dri2_check_no_error(uint32_t flags, struct glx_context *share_context,
582
int major, unsigned *error)
583
{
584
Bool noError = flags & __DRI_CTX_FLAG_NO_ERROR;
585
586
/* The KHR_no_error specs say:
587
*
588
* Requires OpenGL ES 2.0 or OpenGL 2.0.
589
*/
590
if (noError && major < 2) {
591
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE;
592
return false;
593
}
594
595
/* The GLX_ARB_create_context_no_error specs say:
596
*
597
* BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB
598
* used to create <share_context> does not match the value of
599
* GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created.
600
*/
601
if (share_context && !!share_context->noError != !!noError) {
602
*error = __DRI_CTX_ERROR_BAD_FLAG;
603
return false;
604
}
605
606
/* The GLX_ARB_create_context_no_error specs say:
607
*
608
* BadMatch is generated if the GLX_CONTEXT_OPENGL_NO_ERROR_ARB is TRUE at
609
* the same time as a debug or robustness context is specified.
610
*
611
*/
612
if (noError && ((flags & __DRI_CTX_FLAG_DEBUG) ||
613
(flags & __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS))) {
614
*error = __DRI_CTX_ERROR_BAD_FLAG;
615
return false;
616
}
617
618
return true;
619
}
620
621
struct glx_context *
622
dri_common_create_context(struct glx_screen *base,
623
struct glx_config *config_base,
624
struct glx_context *shareList,
625
int renderType)
626
{
627
unsigned int error;
628
uint32_t attribs[2] = { GLX_RENDER_TYPE, renderType };
629
630
return base->vtable->create_context_attribs(base, config_base, shareList,
631
1, attribs, &error);
632
}
633
634
635
/*
636
* Given a display pointer and screen number, determine the name of
637
* the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
638
* Return True for success, False for failure.
639
*/
640
static Bool
641
driGetDriverName(Display * dpy, int scrNum, char **driverName)
642
{
643
struct glx_screen *glx_screen = GetGLXScreenConfigs(dpy, scrNum);
644
645
if (!glx_screen || !glx_screen->vtable->get_driver_name)
646
return False;
647
648
*driverName = glx_screen->vtable->get_driver_name(glx_screen);
649
return True;
650
}
651
652
/*
653
* Exported function for querying the DRI driver for a given screen.
654
*
655
* The returned char pointer points to a static array that will be
656
* overwritten by subsequent calls.
657
*/
658
_GLX_PUBLIC const char *
659
glXGetScreenDriver(Display * dpy, int scrNum)
660
{
661
static char ret[32];
662
char *driverName;
663
664
if (driGetDriverName(dpy, scrNum, &driverName)) {
665
int len;
666
if (!driverName)
667
return NULL;
668
len = strlen(driverName);
669
if (len >= 31)
670
return NULL;
671
memcpy(ret, driverName, len + 1);
672
free(driverName);
673
return ret;
674
}
675
return NULL;
676
}
677
678
/* glXGetDriverConfig must return a pointer with a static lifetime. To avoid
679
* keeping drivers loaded and other leaks, we keep a cache of results here that
680
* is cleared by an atexit handler.
681
*/
682
struct driver_config_entry {
683
struct driver_config_entry *next;
684
char *driverName;
685
char *config;
686
};
687
688
static pthread_mutex_t driver_config_mutex = PTHREAD_MUTEX_INITIALIZER;
689
static struct driver_config_entry *driver_config_cache = NULL;
690
691
/* Called as an atexit function. Otherwise, this would have to be called with
692
* driver_config_mutex locked.
693
*/
694
static void
695
clear_driver_config_cache()
696
{
697
while (driver_config_cache) {
698
struct driver_config_entry *e = driver_config_cache;
699
driver_config_cache = e->next;
700
701
free(e->driverName);
702
free(e->config);
703
free(e);
704
}
705
}
706
707
static char *
708
get_driver_config(const char *driverName)
709
{
710
void *handle;
711
char *config = NULL;
712
const __DRIextension **extensions = driOpenDriver(driverName, &handle);
713
if (extensions) {
714
for (int i = 0; extensions[i]; i++) {
715
if (strcmp(extensions[i]->name, __DRI_CONFIG_OPTIONS) != 0)
716
continue;
717
718
__DRIconfigOptionsExtension *ext =
719
(__DRIconfigOptionsExtension *)extensions[i];
720
721
if (ext->base.version >= 2)
722
config = ext->getXml(driverName);
723
else
724
config = strdup(ext->xml);
725
726
break;
727
}
728
}
729
730
if (!config) {
731
/* Fall back to the old method */
732
config = dlsym(handle, "__driConfigOptions");
733
if (config)
734
config = strdup(config);
735
}
736
737
dlclose(handle);
738
739
return config;
740
}
741
742
/*
743
* Exported function for obtaining a driver's option list (UTF-8 encoded XML).
744
*
745
* The returned char pointer points directly into the driver. Therefore
746
* it should be treated as a constant.
747
*
748
* If the driver was not found or does not support configuration NULL is
749
* returned.
750
*/
751
_GLX_PUBLIC const char *
752
glXGetDriverConfig(const char *driverName)
753
{
754
struct driver_config_entry *e;
755
756
pthread_mutex_lock(&driver_config_mutex);
757
758
for (e = driver_config_cache; e; e = e->next) {
759
if (strcmp(e->driverName, driverName) == 0)
760
goto out;
761
}
762
763
e = malloc(sizeof(*e));
764
if (!e)
765
goto out;
766
767
e->config = get_driver_config(driverName);
768
e->driverName = strdup(driverName);
769
if (!e->config || !e->driverName) {
770
free(e->config);
771
free(e->driverName);
772
free(e);
773
e = NULL;
774
goto out;
775
}
776
777
e->next = driver_config_cache;
778
driver_config_cache = e;
779
780
if (!e->next)
781
atexit(clear_driver_config_cache);
782
783
out:
784
pthread_mutex_unlock(&driver_config_mutex);
785
786
return e ? e->config : NULL;
787
}
788
789
#endif /* GLX_DIRECT_RENDERING */
790
791