Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/glx/glxext.c
4558 views
1
/*
2
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice including the dates of first publication and
13
* either this permission notice or a reference to
14
* http://oss.sgi.com/projects/FreeB/
15
* shall be included in all copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
* SOFTWARE.
24
*
25
* Except as contained in this notice, the name of Silicon Graphics, Inc.
26
* shall not be used in advertising or otherwise to promote the sale, use or
27
* other dealings in this Software without prior written authorization from
28
* Silicon Graphics, Inc.
29
*/
30
31
/**
32
* \file glxext.c
33
* GLX protocol interface boot-strap code.
34
*
35
* Direct rendering support added by Precision Insight, Inc.
36
*
37
* \author Kevin E. Martin <[email protected]>
38
*/
39
40
#include <assert.h>
41
#include <stdbool.h>
42
#include <stdarg.h>
43
44
#include "glxclient.h"
45
#include <X11/extensions/Xext.h>
46
#include <X11/extensions/extutil.h>
47
#ifdef GLX_USE_APPLEGL
48
#include "apple/apple_glx.h"
49
#include "apple/apple_visual.h"
50
#endif
51
#include "glxextensions.h"
52
53
#include "util/debug.h"
54
#ifndef GLX_USE_APPLEGL
55
#include "dri_common.h"
56
#endif
57
58
#include <X11/Xlib-xcb.h>
59
#include <xcb/xcb.h>
60
#include <xcb/glx.h>
61
62
#define __GLX_MIN_CONFIG_PROPS 18
63
#define __GLX_EXT_CONFIG_PROPS 32
64
65
/*
66
** Since we send all non-core visual properties as token, value pairs,
67
** we require 2 words across the wire. In order to maintain backwards
68
** compatibility, we need to send the total number of words that the
69
** VisualConfigs are sent back in so old libraries can simply "ignore"
70
** the new properties.
71
*/
72
#define __GLX_TOTAL_CONFIG \
73
(__GLX_MIN_CONFIG_PROPS + 2 * __GLX_EXT_CONFIG_PROPS)
74
75
_X_HIDDEN void
76
glx_message(int level, const char *f, ...)
77
{
78
va_list args;
79
int threshold = _LOADER_WARNING;
80
const char *libgl_debug;
81
82
libgl_debug = getenv("LIBGL_DEBUG");
83
if (libgl_debug) {
84
if (strstr(libgl_debug, "quiet"))
85
threshold = _LOADER_FATAL;
86
else if (strstr(libgl_debug, "verbose"))
87
threshold = _LOADER_DEBUG;
88
}
89
90
/* Note that the _LOADER_* levels are lower numbers for more severe. */
91
if (level <= threshold) {
92
fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : "");
93
va_start(args, f);
94
vfprintf(stderr, f, args);
95
va_end(args);
96
}
97
}
98
99
/*
100
** You can set this cell to 1 to force the gl drawing stuff to be
101
** one command per packet
102
*/
103
_X_HIDDEN int __glXDebug = 0;
104
105
/* Extension required boiler plate */
106
107
static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
108
static struct glx_display *glx_displays;
109
110
static /* const */ char *error_list[] = {
111
"GLXBadContext",
112
"GLXBadContextState",
113
"GLXBadDrawable",
114
"GLXBadPixmap",
115
"GLXBadContextTag",
116
"GLXBadCurrentWindow",
117
"GLXBadRenderRequest",
118
"GLXBadLargeRequest",
119
"GLXUnsupportedPrivateRequest",
120
"GLXBadFBConfig",
121
"GLXBadPbuffer",
122
"GLXBadCurrentDrawable",
123
"GLXBadWindow",
124
"GLXBadProfileARB",
125
};
126
127
#ifdef GLX_USE_APPLEGL
128
static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
129
char *buf, int n);
130
#endif
131
132
static
133
XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
134
__GLX_NUMBER_ERRORS, error_list)
135
136
/*
137
* GLX events are a bit funky. We don't stuff the X event code into
138
* our user exposed (via XNextEvent) structure. Instead we use the GLX
139
* private event code namespace (and hope it doesn't conflict). Clients
140
* have to know that bit 15 in the event type field means they're getting
141
* a GLX event, and then handle the various sub-event types there, rather
142
* than simply checking the event code and handling it directly.
143
*/
144
145
static Bool
146
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
147
{
148
struct glx_display *glx_dpy = __glXInitialize(dpy);
149
150
if (glx_dpy == NULL)
151
return False;
152
153
switch ((wire->u.u.type & 0x7f) - glx_dpy->codes.first_event) {
154
case GLX_PbufferClobber:
155
{
156
GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
157
xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
158
aevent->event_type = awire->type;
159
aevent->serial = awire->sequenceNumber;
160
aevent->event_type = awire->event_type;
161
aevent->draw_type = awire->draw_type;
162
aevent->drawable = awire->drawable;
163
aevent->buffer_mask = awire->buffer_mask;
164
aevent->aux_buffer = awire->aux_buffer;
165
aevent->x = awire->x;
166
aevent->y = awire->y;
167
aevent->width = awire->width;
168
aevent->height = awire->height;
169
aevent->count = awire->count;
170
return True;
171
}
172
case GLX_BufferSwapComplete:
173
{
174
GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
175
xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
176
struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
177
178
if (!glxDraw)
179
return False;
180
181
aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
182
aevent->send_event = (awire->type & 0x80) != 0;
183
aevent->display = dpy;
184
aevent->event_type = awire->event_type;
185
aevent->drawable = glxDraw->xDrawable;
186
aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
187
aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
188
189
/* Handle 32-Bit wire sbc wraparound in both directions to cope with out
190
* of sequence 64-Bit sbc's
191
*/
192
if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
193
glxDraw->eventSbcWrap += 0x100000000;
194
if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
195
glxDraw->eventSbcWrap -= 0x100000000;
196
glxDraw->lastEventSbc = awire->sbc;
197
aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
198
return True;
199
}
200
default:
201
/* client doesn't support server event */
202
break;
203
}
204
205
return False;
206
}
207
208
/* We don't actually support this. It doesn't make sense for clients to
209
* send each other GLX events.
210
*/
211
static Status
212
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
213
{
214
struct glx_display *glx_dpy = __glXInitialize(dpy);
215
216
if (glx_dpy == NULL)
217
return False;
218
219
switch (event->type) {
220
case GLX_DAMAGED:
221
break;
222
case GLX_SAVED:
223
break;
224
case GLX_EXCHANGE_COMPLETE_INTEL:
225
break;
226
case GLX_COPY_COMPLETE_INTEL:
227
break;
228
case GLX_FLIP_COMPLETE_INTEL:
229
break;
230
default:
231
/* client doesn't support server event */
232
break;
233
}
234
235
return Success;
236
}
237
238
/************************************************************************/
239
/*
240
** Free the per screen configs data as well as the array of
241
** __glXScreenConfigs.
242
*/
243
static void
244
FreeScreenConfigs(struct glx_display * priv)
245
{
246
struct glx_screen *psc;
247
GLint i, screens;
248
249
/* Free screen configuration information */
250
screens = ScreenCount(priv->dpy);
251
for (i = 0; i < screens; i++) {
252
psc = priv->screens[i];
253
if (!psc)
254
continue;
255
glx_screen_cleanup(psc);
256
257
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
258
if (psc->driScreen) {
259
psc->driScreen->destroyScreen(psc);
260
} else {
261
free(psc);
262
}
263
#else
264
free(psc);
265
#endif
266
}
267
free((char *) priv->screens);
268
priv->screens = NULL;
269
}
270
271
static void
272
glx_display_free(struct glx_display *priv)
273
{
274
struct glx_context *gc;
275
276
gc = __glXGetCurrentContext();
277
if (priv->dpy == gc->currentDpy) {
278
gc->vtable->destroy(gc);
279
__glXSetCurrentContextNull();
280
}
281
282
FreeScreenConfigs(priv);
283
284
__glxHashDestroy(priv->glXDrawHash);
285
286
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
287
__glxHashDestroy(priv->drawHash);
288
289
/* Free the direct rendering per display data */
290
if (priv->driswDisplay)
291
(*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
292
priv->driswDisplay = NULL;
293
294
#if defined (GLX_USE_DRM)
295
if (priv->dri2Display)
296
(*priv->dri2Display->destroyDisplay) (priv->dri2Display);
297
priv->dri2Display = NULL;
298
299
if (priv->dri3Display)
300
(*priv->dri3Display->destroyDisplay) (priv->dri3Display);
301
priv->dri3Display = NULL;
302
#endif /* GLX_USE_DRM */
303
304
#if defined(GLX_USE_WINDOWSGL)
305
if (priv->windowsdriDisplay)
306
(*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
307
priv->windowsdriDisplay = NULL;
308
#endif /* GLX_USE_WINDOWSGL */
309
310
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
311
312
free((char *) priv);
313
}
314
315
static int
316
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
317
{
318
struct glx_display *priv, **prev;
319
320
_XLockMutex(_Xglobal_lock);
321
prev = &glx_displays;
322
for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
323
if (priv->dpy == dpy) {
324
*prev = priv->next;
325
break;
326
}
327
}
328
_XUnlockMutex(_Xglobal_lock);
329
330
if (priv != NULL)
331
glx_display_free(priv);
332
333
return 1;
334
}
335
336
/*
337
** Query the version of the GLX extension. This procedure works even if
338
** the client extension is not completely set up.
339
*/
340
static Bool
341
QueryVersion(Display * dpy, int opcode, int *major, int *minor)
342
{
343
xcb_connection_t *c = XGetXCBConnection(dpy);
344
xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
345
xcb_glx_query_version
346
(c,
347
GLX_MAJOR_VERSION,
348
GLX_MINOR_VERSION),
349
NULL);
350
351
if (!reply)
352
return GL_FALSE;
353
354
if (reply->major_version != GLX_MAJOR_VERSION) {
355
free(reply);
356
return GL_FALSE;
357
}
358
*major = reply->major_version;
359
*minor = min(reply->minor_version, GLX_MINOR_VERSION);
360
free(reply);
361
return GL_TRUE;
362
}
363
364
/*
365
* We don't want to enable this GLX_OML_swap_method in glxext.h,
366
* because we can't support it. The X server writes it out though,
367
* so we should handle it somehow, to avoid false warnings.
368
*/
369
enum {
370
IGNORE_GLX_SWAP_METHOD_OML = 0x8060
371
};
372
373
374
static GLint
375
convert_from_x_visual_type(int visualType)
376
{
377
static const int glx_visual_types[] = {
378
[StaticGray] = GLX_STATIC_GRAY,
379
[GrayScale] = GLX_GRAY_SCALE,
380
[StaticColor] = GLX_STATIC_COLOR,
381
[PseudoColor] = GLX_PSEUDO_COLOR,
382
[TrueColor] = GLX_TRUE_COLOR,
383
[DirectColor] = GLX_DIRECT_COLOR,
384
};
385
386
if (visualType < ARRAY_SIZE(glx_visual_types))
387
return glx_visual_types[visualType];
388
389
return GLX_NONE;
390
}
391
392
/*
393
* getVisualConfigs uses the !tagged_only path.
394
* getFBConfigs uses the tagged_only path.
395
*/
396
_X_HIDDEN void
397
__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
398
const INT32 * bp, Bool tagged_only,
399
Bool fbconfig_style_tags)
400
{
401
int i;
402
403
if (!tagged_only) {
404
/* Copy in the first set of properties */
405
config->visualID = *bp++;
406
407
config->visualType = convert_from_x_visual_type(*bp++);
408
409
config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
410
411
config->redBits = *bp++;
412
config->greenBits = *bp++;
413
config->blueBits = *bp++;
414
config->alphaBits = *bp++;
415
config->accumRedBits = *bp++;
416
config->accumGreenBits = *bp++;
417
config->accumBlueBits = *bp++;
418
config->accumAlphaBits = *bp++;
419
420
config->doubleBufferMode = *bp++;
421
config->stereoMode = *bp++;
422
423
config->rgbBits = *bp++;
424
config->depthBits = *bp++;
425
config->stencilBits = *bp++;
426
config->numAuxBuffers = *bp++;
427
config->level = *bp++;
428
429
#ifdef GLX_USE_APPLEGL
430
/* AppleSGLX supports pixmap and pbuffers with all config. */
431
config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
432
/* Unfortunately this can create an ABI compatibility problem. */
433
count -= 18;
434
#else
435
count -= __GLX_MIN_CONFIG_PROPS;
436
#endif
437
}
438
439
/*
440
** Additional properties may be in a list at the end
441
** of the reply. They are in pairs of property type
442
** and property value.
443
*/
444
445
#define FETCH_OR_SET(tag) \
446
config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
447
448
for (i = 0; i < count; i += 2) {
449
long int tag = *bp++;
450
451
switch (tag) {
452
case GLX_RGBA:
453
if (fbconfig_style_tags)
454
config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
455
else
456
config->renderType = GLX_RGBA_BIT;
457
break;
458
case GLX_BUFFER_SIZE:
459
config->rgbBits = *bp++;
460
break;
461
case GLX_LEVEL:
462
config->level = *bp++;
463
break;
464
case GLX_DOUBLEBUFFER:
465
FETCH_OR_SET(doubleBufferMode);
466
break;
467
case GLX_STEREO:
468
FETCH_OR_SET(stereoMode);
469
break;
470
case GLX_AUX_BUFFERS:
471
config->numAuxBuffers = *bp++;
472
break;
473
case GLX_RED_SIZE:
474
config->redBits = *bp++;
475
break;
476
case GLX_GREEN_SIZE:
477
config->greenBits = *bp++;
478
break;
479
case GLX_BLUE_SIZE:
480
config->blueBits = *bp++;
481
break;
482
case GLX_ALPHA_SIZE:
483
config->alphaBits = *bp++;
484
break;
485
case GLX_DEPTH_SIZE:
486
config->depthBits = *bp++;
487
break;
488
case GLX_STENCIL_SIZE:
489
config->stencilBits = *bp++;
490
break;
491
case GLX_ACCUM_RED_SIZE:
492
config->accumRedBits = *bp++;
493
break;
494
case GLX_ACCUM_GREEN_SIZE:
495
config->accumGreenBits = *bp++;
496
break;
497
case GLX_ACCUM_BLUE_SIZE:
498
config->accumBlueBits = *bp++;
499
break;
500
case GLX_ACCUM_ALPHA_SIZE:
501
config->accumAlphaBits = *bp++;
502
break;
503
case GLX_VISUAL_CAVEAT_EXT:
504
config->visualRating = *bp++;
505
break;
506
case GLX_X_VISUAL_TYPE:
507
config->visualType = *bp++;
508
break;
509
case GLX_TRANSPARENT_TYPE:
510
config->transparentPixel = *bp++;
511
break;
512
case GLX_TRANSPARENT_INDEX_VALUE:
513
config->transparentIndex = *bp++;
514
break;
515
case GLX_TRANSPARENT_RED_VALUE:
516
config->transparentRed = *bp++;
517
break;
518
case GLX_TRANSPARENT_GREEN_VALUE:
519
config->transparentGreen = *bp++;
520
break;
521
case GLX_TRANSPARENT_BLUE_VALUE:
522
config->transparentBlue = *bp++;
523
break;
524
case GLX_TRANSPARENT_ALPHA_VALUE:
525
config->transparentAlpha = *bp++;
526
break;
527
case GLX_VISUAL_ID:
528
config->visualID = *bp++;
529
break;
530
case GLX_DRAWABLE_TYPE:
531
config->drawableType = *bp++;
532
#ifdef GLX_USE_APPLEGL
533
/* AppleSGLX supports pixmap and pbuffers with all config. */
534
config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
535
#endif
536
break;
537
case GLX_RENDER_TYPE: /* fbconfig render type bits */
538
config->renderType = *bp++;
539
break;
540
case GLX_X_RENDERABLE:
541
config->xRenderable = *bp++;
542
break;
543
case GLX_FBCONFIG_ID:
544
config->fbconfigID = *bp++;
545
break;
546
case GLX_MAX_PBUFFER_WIDTH:
547
config->maxPbufferWidth = *bp++;
548
break;
549
case GLX_MAX_PBUFFER_HEIGHT:
550
config->maxPbufferHeight = *bp++;
551
break;
552
case GLX_MAX_PBUFFER_PIXELS:
553
config->maxPbufferPixels = *bp++;
554
break;
555
#ifndef GLX_USE_APPLEGL
556
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
557
config->optimalPbufferWidth = *bp++;
558
break;
559
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
560
config->optimalPbufferHeight = *bp++;
561
break;
562
case GLX_VISUAL_SELECT_GROUP_SGIX:
563
config->visualSelectGroup = *bp++;
564
break;
565
case GLX_SWAP_METHOD_OML:
566
if (*bp == GLX_SWAP_UNDEFINED_OML ||
567
*bp == GLX_SWAP_COPY_OML ||
568
*bp == GLX_SWAP_EXCHANGE_OML) {
569
config->swapMethod = *bp++;
570
} else {
571
/* X servers with old HW drivers may return any value here, so
572
* assume GLX_SWAP_METHOD_UNDEFINED.
573
*/
574
config->swapMethod = GLX_SWAP_UNDEFINED_OML;
575
bp++;
576
}
577
break;
578
#endif
579
case GLX_SAMPLE_BUFFERS_SGIS:
580
config->sampleBuffers = *bp++;
581
break;
582
case GLX_SAMPLES_SGIS:
583
config->samples = *bp++;
584
break;
585
#ifdef GLX_USE_APPLEGL
586
case IGNORE_GLX_SWAP_METHOD_OML:
587
/* We ignore this tag. See the comment above this function. */
588
++bp;
589
break;
590
#else
591
case GLX_BIND_TO_TEXTURE_RGB_EXT:
592
config->bindToTextureRgb = *bp++;
593
break;
594
case GLX_BIND_TO_TEXTURE_RGBA_EXT:
595
config->bindToTextureRgba = *bp++;
596
break;
597
case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
598
config->bindToMipmapTexture = *bp++;
599
break;
600
case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
601
config->bindToTextureTargets = *bp++;
602
break;
603
case GLX_Y_INVERTED_EXT:
604
config->yInverted = *bp++;
605
break;
606
#endif
607
case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
608
config->sRGBCapable = *bp++;
609
break;
610
611
case GLX_USE_GL:
612
if (fbconfig_style_tags)
613
bp++;
614
break;
615
case None:
616
i = count;
617
break;
618
default: {
619
long int tagvalue = *bp++;
620
DebugMessageF("WARNING: unknown GLX tag from server: "
621
"tag 0x%lx value 0x%lx\n", tag, tagvalue);
622
break;
623
}
624
}
625
}
626
627
/* The GLX_ARB_fbconfig_float spec says:
628
*
629
* "Note that floating point rendering is only supported for
630
* GLXPbuffer drawables."
631
*/
632
if (config->renderType &
633
(GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT))
634
config->drawableType &= GLX_PBUFFER_BIT;
635
}
636
637
static struct glx_config *
638
createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
639
int screen, GLboolean tagged_only)
640
{
641
INT32 buf[__GLX_TOTAL_CONFIG], *props;
642
unsigned prop_size;
643
struct glx_config *modes, *m;
644
int i;
645
646
if (nprops == 0)
647
return NULL;
648
649
/* Check number of properties */
650
if (nprops < __GLX_MIN_CONFIG_PROPS)
651
return NULL;
652
653
/* Allocate memory for our config structure */
654
modes = glx_config_create_list(nvisuals);
655
if (!modes)
656
return NULL;
657
658
prop_size = nprops * __GLX_SIZE_INT32;
659
if (prop_size <= sizeof(buf))
660
props = buf;
661
else
662
props = malloc(prop_size);
663
664
/* Read each config structure and convert it into our format */
665
m = modes;
666
for (i = 0; i < nvisuals; i++) {
667
_XRead(dpy, (char *) props, prop_size);
668
#ifdef GLX_USE_APPLEGL
669
/* Older X servers don't send this so we default it here. */
670
m->drawableType = GLX_WINDOW_BIT;
671
#else
672
/*
673
* The XQuartz 2.3.2.1 X server doesn't set this properly, so
674
* set the proper bits here.
675
* AppleSGLX supports windows, pixmaps, and pbuffers with all config.
676
*/
677
m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
678
#endif
679
__glXInitializeVisualConfigFromTags(m, nprops, props,
680
tagged_only, GL_TRUE);
681
m->screen = screen;
682
m = m->next;
683
}
684
685
if (props != buf)
686
free(props);
687
688
return modes;
689
}
690
691
static GLboolean
692
getVisualConfigs(struct glx_screen *psc,
693
struct glx_display *priv, int screen)
694
{
695
xGLXGetVisualConfigsReq *req;
696
xGLXGetVisualConfigsReply reply;
697
Display *dpy = priv->dpy;
698
699
LockDisplay(dpy);
700
701
psc->visuals = NULL;
702
GetReq(GLXGetVisualConfigs, req);
703
req->reqType = priv->codes.major_opcode;
704
req->glxCode = X_GLXGetVisualConfigs;
705
req->screen = screen;
706
707
if (!_XReply(dpy, (xReply *) & reply, 0, False))
708
goto out;
709
710
psc->visuals = createConfigsFromProperties(dpy,
711
reply.numVisuals,
712
reply.numProps,
713
screen, GL_FALSE);
714
715
out:
716
UnlockDisplay(dpy);
717
return psc->visuals != NULL;
718
}
719
720
static GLboolean
721
getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
722
{
723
xGLXGetFBConfigsReq *fb_req;
724
xGLXGetFBConfigsSGIXReq *sgi_req;
725
xGLXVendorPrivateWithReplyReq *vpreq;
726
xGLXGetFBConfigsReply reply;
727
Display *dpy = priv->dpy;
728
729
psc->serverGLXexts = __glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
730
731
if (psc->serverGLXexts == NULL) {
732
return GL_FALSE;
733
}
734
735
LockDisplay(dpy);
736
737
psc->configs = NULL;
738
if (priv->minorVersion >= 3) {
739
GetReq(GLXGetFBConfigs, fb_req);
740
fb_req->reqType = priv->codes.major_opcode;
741
fb_req->glxCode = X_GLXGetFBConfigs;
742
fb_req->screen = screen;
743
}
744
else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
745
GetReqExtra(GLXVendorPrivateWithReply,
746
sz_xGLXGetFBConfigsSGIXReq -
747
sz_xGLXVendorPrivateWithReplyReq, vpreq);
748
sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
749
sgi_req->reqType = priv->codes.major_opcode;
750
sgi_req->glxCode = X_GLXVendorPrivateWithReply;
751
sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
752
sgi_req->screen = screen;
753
}
754
else
755
goto out;
756
757
if (!_XReply(dpy, (xReply *) & reply, 0, False))
758
goto out;
759
760
psc->configs = createConfigsFromProperties(dpy,
761
reply.numFBConfigs,
762
reply.numAttribs * 2,
763
screen, GL_TRUE);
764
765
out:
766
UnlockDisplay(dpy);
767
return psc->configs != NULL;
768
}
769
770
_X_HIDDEN Bool
771
glx_screen_init(struct glx_screen *psc,
772
int screen, struct glx_display * priv)
773
{
774
/* Initialize per screen dynamic client GLX extensions */
775
psc->ext_list_first_time = GL_TRUE;
776
psc->scr = screen;
777
psc->dpy = priv->dpy;
778
psc->display = priv;
779
780
if (!getVisualConfigs(psc, priv, screen))
781
return GL_FALSE;
782
783
if (!getFBConfigs(psc, priv, screen))
784
return GL_FALSE;
785
786
return GL_TRUE;
787
}
788
789
_X_HIDDEN void
790
glx_screen_cleanup(struct glx_screen *psc)
791
{
792
if (psc->configs) {
793
glx_config_destroy_list(psc->configs);
794
free(psc->effectiveGLXexts);
795
psc->configs = NULL; /* NOTE: just for paranoia */
796
}
797
if (psc->visuals) {
798
glx_config_destroy_list(psc->visuals);
799
psc->visuals = NULL; /* NOTE: just for paranoia */
800
}
801
free((char *) psc->serverGLXexts);
802
free((char *) psc->serverGLXvendor);
803
free((char *) psc->serverGLXversion);
804
}
805
806
/*
807
** Allocate the memory for the per screen configs for each screen.
808
** If that works then fetch the per screen configs data.
809
*/
810
static Bool
811
AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
812
{
813
struct glx_screen *psc;
814
GLint i, screens;
815
816
/*
817
** First allocate memory for the array of per screen configs.
818
*/
819
screens = ScreenCount(dpy);
820
priv->screens = calloc(screens, sizeof *priv->screens);
821
if (!priv->screens)
822
return GL_FALSE;
823
824
for (i = 0; i < screens; i++, psc++) {
825
psc = NULL;
826
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
827
#if defined(GLX_USE_DRM)
828
#if defined(HAVE_DRI3)
829
if (priv->dri3Display)
830
psc = (*priv->dri3Display->createScreen) (i, priv);
831
#endif /* HAVE_DRI3 */
832
if (psc == NULL && priv->dri2Display)
833
psc = (*priv->dri2Display->createScreen) (i, priv);
834
#endif /* GLX_USE_DRM */
835
836
#ifdef GLX_USE_WINDOWSGL
837
if (psc == NULL && priv->windowsdriDisplay)
838
psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
839
#endif
840
841
if (psc == NULL && priv->driswDisplay)
842
psc = (*priv->driswDisplay->createScreen) (i, priv);
843
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
844
845
#if defined(GLX_USE_APPLEGL)
846
if (psc == NULL)
847
psc = applegl_create_screen(i, priv);
848
#else
849
if (psc == NULL)
850
psc = indirect_create_screen(i, priv);
851
#endif
852
priv->screens[i] = psc;
853
}
854
SyncHandle();
855
return GL_TRUE;
856
}
857
858
/*
859
** Initialize the client side extension code.
860
*/
861
_X_HIDDEN struct glx_display *
862
__glXInitialize(Display * dpy)
863
{
864
struct glx_display *dpyPriv, *d;
865
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
866
Bool glx_direct, glx_accel;
867
#endif
868
int i, majorVersion = 0;
869
870
_XLockMutex(_Xglobal_lock);
871
872
for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
873
if (dpyPriv->dpy == dpy) {
874
_XUnlockMutex(_Xglobal_lock);
875
return dpyPriv;
876
}
877
}
878
879
/* Drop the lock while we create the display private. */
880
_XUnlockMutex(_Xglobal_lock);
881
882
dpyPriv = calloc(1, sizeof *dpyPriv);
883
if (!dpyPriv)
884
return NULL;
885
886
dpyPriv->codes = *XInitExtension(dpy, __glXExtensionName);
887
888
dpyPriv->dpy = dpy;
889
890
/* This GLX implementation requires X_GLXQueryExtensionsString
891
* and X_GLXQueryServerString, which are new in GLX 1.1.
892
*/
893
if (!QueryVersion(dpy, dpyPriv->codes.major_opcode,
894
&majorVersion, &dpyPriv->minorVersion)
895
|| (majorVersion != 1)
896
|| (majorVersion == 1 && dpyPriv->minorVersion < 1)) {
897
free(dpyPriv);
898
return NULL;
899
}
900
901
for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
902
XESetWireToEvent(dpy, dpyPriv->codes.first_event + i, __glXWireToEvent);
903
XESetEventToWire(dpy, dpyPriv->codes.first_event + i, __glXEventToWire);
904
}
905
906
XESetCloseDisplay(dpy, dpyPriv->codes.extension, __glXCloseDisplay);
907
XESetErrorString (dpy, dpyPriv->codes.extension, __glXErrorString);
908
909
dpyPriv->glXDrawHash = __glxHashCreate();
910
911
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
912
glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
913
glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
914
915
dpyPriv->drawHash = __glxHashCreate();
916
917
#ifndef GLX_USE_APPLEGL
918
/* Set the logger before the *CreateDisplay functions. */
919
loader_set_logger(glx_message);
920
#endif
921
922
/*
923
** Initialize the direct rendering per display data and functions.
924
** Note: This _must_ be done before calling any other DRI routines
925
** (e.g., those called in AllocAndFetchScreenConfigs).
926
*/
927
#if defined(GLX_USE_DRM)
928
if (glx_direct && glx_accel) {
929
#if defined(HAVE_DRI3)
930
if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
931
dpyPriv->dri3Display = dri3_create_display(dpy);
932
#endif /* HAVE_DRI3 */
933
if (!env_var_as_boolean("LIBGL_DRI2_DISABLE", false))
934
dpyPriv->dri2Display = dri2CreateDisplay(dpy);
935
}
936
#endif /* GLX_USE_DRM */
937
if (glx_direct)
938
dpyPriv->driswDisplay = driswCreateDisplay(dpy);
939
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
940
941
#ifdef GLX_USE_APPLEGL
942
if (!applegl_create_display(dpyPriv)) {
943
free(dpyPriv);
944
return NULL;
945
}
946
#endif
947
948
#ifdef GLX_USE_WINDOWSGL
949
if (glx_direct && glx_accel)
950
dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
951
#endif
952
953
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
954
free(dpyPriv);
955
return NULL;
956
}
957
958
__glX_send_client_info(dpyPriv);
959
960
/* Grab the lock again and add the dispay private, unless somebody
961
* beat us to initializing on this display in the meantime. */
962
_XLockMutex(_Xglobal_lock);
963
964
for (d = glx_displays; d; d = d->next) {
965
if (d->dpy == dpy) {
966
_XUnlockMutex(_Xglobal_lock);
967
glx_display_free(dpyPriv);
968
return d;
969
}
970
}
971
972
dpyPriv->next = glx_displays;
973
glx_displays = dpyPriv;
974
975
_XUnlockMutex(_Xglobal_lock);
976
977
return dpyPriv;
978
}
979
980
/*
981
** Setup for sending a GLX command on dpy. Make sure the extension is
982
** initialized. Try to avoid calling __glXInitialize as its kinda slow.
983
*/
984
_X_HIDDEN CARD8
985
__glXSetupForCommand(Display * dpy)
986
{
987
struct glx_context *gc;
988
struct glx_display *priv;
989
990
/* If this thread has a current context, flush its rendering commands */
991
gc = __glXGetCurrentContext();
992
if (gc->currentDpy) {
993
/* Flush rendering buffer of the current context, if any */
994
(void) __glXFlushRenderBuffer(gc, gc->pc);
995
996
if (gc->currentDpy == dpy) {
997
/* Use opcode from gc because its right */
998
return gc->majorOpcode;
999
}
1000
else {
1001
/*
1002
** Have to get info about argument dpy because it might be to
1003
** a different server
1004
*/
1005
}
1006
}
1007
1008
/* Forced to lookup extension via the slow initialize route */
1009
priv = __glXInitialize(dpy);
1010
if (!priv) {
1011
return 0;
1012
}
1013
return priv->codes.major_opcode;
1014
}
1015
1016
/**
1017
* Flush the drawing command transport buffer.
1018
*
1019
* \param ctx Context whose transport buffer is to be flushed.
1020
* \param pc Pointer to first unused buffer location.
1021
*
1022
* \todo
1023
* Modify this function to use \c ctx->pc instead of the explicit
1024
* \c pc parameter.
1025
*/
1026
_X_HIDDEN GLubyte *
1027
__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1028
{
1029
Display *const dpy = ctx->currentDpy;
1030
xcb_connection_t *c = XGetXCBConnection(dpy);
1031
const GLint size = pc - ctx->buf;
1032
1033
if ((dpy != NULL) && (size > 0)) {
1034
xcb_glx_render(c, ctx->currentContextTag, size,
1035
(const uint8_t *) ctx->buf);
1036
}
1037
1038
/* Reset pointer and return it */
1039
ctx->pc = ctx->buf;
1040
return ctx->pc;
1041
}
1042
1043
1044
/**
1045
* Send a portion of a GLXRenderLarge command to the server. The advantage of
1046
* this function over \c __glXSendLargeCommand is that callers can use the
1047
* data buffer in the GLX context and may be able to avoid allocating an
1048
* extra buffer. The disadvantage is the clients will have to do more
1049
* GLX protocol work (i.e., calculating \c totalRequests, etc.).
1050
*
1051
* \sa __glXSendLargeCommand
1052
*
1053
* \param gc GLX context
1054
* \param requestNumber Which part of the whole command is this? The first
1055
* request is 1.
1056
* \param totalRequests How many requests will there be?
1057
* \param data Command data.
1058
* \param dataLen Size, in bytes, of the command data.
1059
*/
1060
_X_HIDDEN void
1061
__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1062
GLint totalRequests, const GLvoid * data, GLint dataLen)
1063
{
1064
Display *dpy = gc->currentDpy;
1065
xcb_connection_t *c = XGetXCBConnection(dpy);
1066
xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1067
totalRequests, dataLen, data);
1068
}
1069
1070
1071
/**
1072
* Send a command that is too large for the GLXRender protocol request.
1073
*
1074
* Send a large command, one that is too large for some reason to
1075
* send using the GLXRender protocol request. One reason to send
1076
* a large command is to avoid copying the data.
1077
*
1078
* \param ctx GLX context
1079
* \param header Header data.
1080
* \param headerLen Size, in bytes, of the header data. It is assumed that
1081
* the header data will always be small enough to fit in
1082
* a single X protocol packet.
1083
* \param data Command data.
1084
* \param dataLen Size, in bytes, of the command data.
1085
*/
1086
_X_HIDDEN void
1087
__glXSendLargeCommand(struct glx_context * ctx,
1088
const GLvoid * header, GLint headerLen,
1089
const GLvoid * data, GLint dataLen)
1090
{
1091
GLint maxSize;
1092
GLint totalRequests, requestNumber;
1093
1094
/*
1095
** Calculate the maximum amount of data can be stuffed into a single
1096
** packet. sz_xGLXRenderReq is added because bufSize is the maximum
1097
** packet size minus sz_xGLXRenderReq.
1098
*/
1099
maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1100
totalRequests = 1 + (dataLen / maxSize);
1101
if (dataLen % maxSize)
1102
totalRequests++;
1103
1104
/*
1105
** Send all of the command, except the large array, as one request.
1106
*/
1107
assert(headerLen <= maxSize);
1108
__glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1109
1110
/*
1111
** Send enough requests until the whole array is sent.
1112
*/
1113
for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1114
requestNumber++) {
1115
__glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1116
data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1117
dataLen -= maxSize;
1118
assert(dataLen > 0);
1119
}
1120
1121
assert(dataLen <= maxSize);
1122
__glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1123
}
1124
1125