2
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
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:
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.
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
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.
33
* GLX protocol interface boot-strap code.
35
* Direct rendering support added by Precision Insight, Inc.
37
* \author Kevin E. Martin <kevin@precisioninsight.com>
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"
51
#include "glxextensions.h"
53
#include "util/debug.h"
54
#ifndef GLX_USE_APPLEGL
55
#include "dri_common.h"
58
#include <X11/Xlib-xcb.h>
62
#define __GLX_MIN_CONFIG_PROPS 18
63
#define __GLX_EXT_CONFIG_PROPS 32
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.
72
#define __GLX_TOTAL_CONFIG \
73
(__GLX_MIN_CONFIG_PROPS + 2 * __GLX_EXT_CONFIG_PROPS)
76
glx_message(int level, const char *f, ...)
79
int threshold = _LOADER_WARNING;
80
const char *libgl_debug;
82
libgl_debug = getenv("LIBGL_DEBUG");
84
if (strstr(libgl_debug, "quiet"))
85
threshold = _LOADER_FATAL;
86
else if (strstr(libgl_debug, "verbose"))
87
threshold = _LOADER_DEBUG;
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" : "");
94
vfprintf(stderr, f, args);
100
** You can set this cell to 1 to force the gl drawing stuff to be
101
** one command per packet
103
_X_HIDDEN int __glXDebug = 0;
105
/* Extension required boiler plate */
107
static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
108
static struct glx_display *glx_displays;
110
static /* const */ char *error_list[] = {
112
"GLXBadContextState",
116
"GLXBadCurrentWindow",
117
"GLXBadRenderRequest",
118
"GLXBadLargeRequest",
119
"GLXUnsupportedPrivateRequest",
122
"GLXBadCurrentDrawable",
127
#ifdef GLX_USE_APPLEGL
128
static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
133
XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
134
__GLX_NUMBER_ERRORS, error_list)
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.
146
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
148
struct glx_display *glx_dpy = __glXInitialize(dpy);
153
switch ((wire->u.u.type & 0x7f) - glx_dpy->codes.first_event) {
154
case GLX_PbufferClobber:
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;
172
case GLX_BufferSwapComplete:
174
GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
175
xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
176
struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
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;
189
/* Handle 32-Bit wire sbc wraparound in both directions to cope with out
190
* of sequence 64-Bit sbc's
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;
201
/* client doesn't support server event */
208
/* We don't actually support this. It doesn't make sense for clients to
209
* send each other GLX events.
212
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
214
struct glx_display *glx_dpy = __glXInitialize(dpy);
219
switch (event->type) {
224
case GLX_EXCHANGE_COMPLETE_INTEL:
226
case GLX_COPY_COMPLETE_INTEL:
228
case GLX_FLIP_COMPLETE_INTEL:
231
/* client doesn't support server event */
238
/************************************************************************/
240
** Free the per screen configs data as well as the array of
241
** __glXScreenConfigs.
244
FreeScreenConfigs(struct glx_display * priv)
246
struct glx_screen *psc;
249
/* Free screen configuration information */
250
screens = ScreenCount(priv->dpy);
251
for (i = 0; i < screens; i++) {
252
psc = priv->screens[i];
255
glx_screen_cleanup(psc);
257
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
258
if (psc->driScreen) {
259
psc->driScreen->destroyScreen(psc);
267
free((char *) priv->screens);
268
priv->screens = NULL;
271
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
273
free_zombie_glx_drawable(struct set_entry *entry)
275
__GLXDRIdrawable *pdraw = (__GLXDRIdrawable *)entry->key;
277
pdraw->destroyDrawable(pdraw);
282
glx_display_free(struct glx_display *priv)
284
struct glx_context *gc;
286
gc = __glXGetCurrentContext();
287
if (priv->dpy == gc->currentDpy) {
288
gc->vtable->destroy(gc);
289
__glXSetCurrentContextNull();
292
/* Needs to be done before free screen. */
293
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
294
_mesa_set_destroy(priv->zombieGLXDrawable, free_zombie_glx_drawable);
297
FreeScreenConfigs(priv);
299
__glxHashDestroy(priv->glXDrawHash);
301
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
302
__glxHashDestroy(priv->drawHash);
304
/* Free the direct rendering per display data */
305
if (priv->driswDisplay)
306
(*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
307
priv->driswDisplay = NULL;
309
#if defined (GLX_USE_DRM)
310
if (priv->dri2Display)
311
(*priv->dri2Display->destroyDisplay) (priv->dri2Display);
312
priv->dri2Display = NULL;
314
if (priv->dri3Display)
315
(*priv->dri3Display->destroyDisplay) (priv->dri3Display);
316
priv->dri3Display = NULL;
317
#endif /* GLX_USE_DRM */
319
#if defined(GLX_USE_WINDOWSGL)
320
if (priv->windowsdriDisplay)
321
(*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
322
priv->windowsdriDisplay = NULL;
323
#endif /* GLX_USE_WINDOWSGL */
325
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
331
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
333
struct glx_display *priv, **prev;
335
_XLockMutex(_Xglobal_lock);
336
prev = &glx_displays;
337
for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
338
if (priv->dpy == dpy) {
343
_XUnlockMutex(_Xglobal_lock);
346
glx_display_free(priv);
352
** Query the version of the GLX extension. This procedure works even if
353
** the client extension is not completely set up.
356
QueryVersion(Display * dpy, int opcode, int *major, int *minor)
358
xcb_connection_t *c = XGetXCBConnection(dpy);
359
xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
360
xcb_glx_query_version
369
if (reply->major_version != GLX_MAJOR_VERSION) {
373
*major = reply->major_version;
374
*minor = min(reply->minor_version, GLX_MINOR_VERSION);
380
* We don't want to enable this GLX_OML_swap_method in glxext.h,
381
* because we can't support it. The X server writes it out though,
382
* so we should handle it somehow, to avoid false warnings.
385
IGNORE_GLX_SWAP_METHOD_OML = 0x8060
390
convert_from_x_visual_type(int visualType)
392
static const int glx_visual_types[] = {
393
[StaticGray] = GLX_STATIC_GRAY,
394
[GrayScale] = GLX_GRAY_SCALE,
395
[StaticColor] = GLX_STATIC_COLOR,
396
[PseudoColor] = GLX_PSEUDO_COLOR,
397
[TrueColor] = GLX_TRUE_COLOR,
398
[DirectColor] = GLX_DIRECT_COLOR,
401
if (visualType < ARRAY_SIZE(glx_visual_types))
402
return glx_visual_types[visualType];
408
* getVisualConfigs uses the !tagged_only path.
409
* getFBConfigs uses the tagged_only path.
412
__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
413
const INT32 * bp, Bool tagged_only,
414
Bool fbconfig_style_tags)
419
/* Copy in the first set of properties */
420
config->visualID = *bp++;
422
config->visualType = convert_from_x_visual_type(*bp++);
424
config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
426
config->redBits = *bp++;
427
config->greenBits = *bp++;
428
config->blueBits = *bp++;
429
config->alphaBits = *bp++;
430
config->accumRedBits = *bp++;
431
config->accumGreenBits = *bp++;
432
config->accumBlueBits = *bp++;
433
config->accumAlphaBits = *bp++;
435
config->doubleBufferMode = *bp++;
436
config->stereoMode = *bp++;
438
config->rgbBits = *bp++;
439
config->depthBits = *bp++;
440
config->stencilBits = *bp++;
441
config->numAuxBuffers = *bp++;
442
config->level = *bp++;
444
#ifdef GLX_USE_APPLEGL
445
/* AppleSGLX supports pixmap and pbuffers with all config. */
446
config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
447
/* Unfortunately this can create an ABI compatibility problem. */
450
count -= __GLX_MIN_CONFIG_PROPS;
455
** Additional properties may be in a list at the end
456
** of the reply. They are in pairs of property type
457
** and property value.
460
#define FETCH_OR_SET(tag) \
461
config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
463
for (i = 0; i < count; i += 2) {
464
long int tag = *bp++;
468
if (fbconfig_style_tags)
469
config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
471
config->renderType = GLX_RGBA_BIT;
473
case GLX_BUFFER_SIZE:
474
config->rgbBits = *bp++;
477
config->level = *bp++;
479
case GLX_DOUBLEBUFFER:
480
FETCH_OR_SET(doubleBufferMode);
483
FETCH_OR_SET(stereoMode);
485
case GLX_AUX_BUFFERS:
486
config->numAuxBuffers = *bp++;
489
config->redBits = *bp++;
492
config->greenBits = *bp++;
495
config->blueBits = *bp++;
498
config->alphaBits = *bp++;
501
config->depthBits = *bp++;
503
case GLX_STENCIL_SIZE:
504
config->stencilBits = *bp++;
506
case GLX_ACCUM_RED_SIZE:
507
config->accumRedBits = *bp++;
509
case GLX_ACCUM_GREEN_SIZE:
510
config->accumGreenBits = *bp++;
512
case GLX_ACCUM_BLUE_SIZE:
513
config->accumBlueBits = *bp++;
515
case GLX_ACCUM_ALPHA_SIZE:
516
config->accumAlphaBits = *bp++;
518
case GLX_VISUAL_CAVEAT_EXT:
519
config->visualRating = *bp++;
521
case GLX_X_VISUAL_TYPE:
522
config->visualType = *bp++;
524
case GLX_TRANSPARENT_TYPE:
525
config->transparentPixel = *bp++;
527
case GLX_TRANSPARENT_INDEX_VALUE:
528
config->transparentIndex = *bp++;
530
case GLX_TRANSPARENT_RED_VALUE:
531
config->transparentRed = *bp++;
533
case GLX_TRANSPARENT_GREEN_VALUE:
534
config->transparentGreen = *bp++;
536
case GLX_TRANSPARENT_BLUE_VALUE:
537
config->transparentBlue = *bp++;
539
case GLX_TRANSPARENT_ALPHA_VALUE:
540
config->transparentAlpha = *bp++;
543
config->visualID = *bp++;
545
case GLX_DRAWABLE_TYPE:
546
config->drawableType = *bp++;
547
#ifdef GLX_USE_APPLEGL
548
/* AppleSGLX supports pixmap and pbuffers with all config. */
549
config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
552
case GLX_RENDER_TYPE: /* fbconfig render type bits */
553
config->renderType = *bp++;
555
case GLX_X_RENDERABLE:
556
config->xRenderable = *bp++;
558
case GLX_FBCONFIG_ID:
559
config->fbconfigID = *bp++;
561
case GLX_MAX_PBUFFER_WIDTH:
562
config->maxPbufferWidth = *bp++;
564
case GLX_MAX_PBUFFER_HEIGHT:
565
config->maxPbufferHeight = *bp++;
567
case GLX_MAX_PBUFFER_PIXELS:
568
config->maxPbufferPixels = *bp++;
570
#ifndef GLX_USE_APPLEGL
571
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
572
config->optimalPbufferWidth = *bp++;
574
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
575
config->optimalPbufferHeight = *bp++;
577
case GLX_VISUAL_SELECT_GROUP_SGIX:
578
config->visualSelectGroup = *bp++;
580
case GLX_SWAP_METHOD_OML:
581
if (*bp == GLX_SWAP_UNDEFINED_OML ||
582
*bp == GLX_SWAP_COPY_OML ||
583
*bp == GLX_SWAP_EXCHANGE_OML) {
584
config->swapMethod = *bp++;
586
/* X servers with old HW drivers may return any value here, so
587
* assume GLX_SWAP_METHOD_UNDEFINED.
589
config->swapMethod = GLX_SWAP_UNDEFINED_OML;
594
case GLX_SAMPLE_BUFFERS_SGIS:
595
config->sampleBuffers = *bp++;
597
case GLX_SAMPLES_SGIS:
598
config->samples = *bp++;
600
#ifdef GLX_USE_APPLEGL
601
case IGNORE_GLX_SWAP_METHOD_OML:
602
/* We ignore this tag. See the comment above this function. */
606
case GLX_BIND_TO_TEXTURE_RGB_EXT:
607
config->bindToTextureRgb = *bp++;
609
case GLX_BIND_TO_TEXTURE_RGBA_EXT:
610
config->bindToTextureRgba = *bp++;
612
case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
613
config->bindToMipmapTexture = *bp++;
615
case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
616
config->bindToTextureTargets = *bp++;
618
case GLX_Y_INVERTED_EXT:
619
config->yInverted = *bp++;
622
case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
623
config->sRGBCapable = *bp++;
627
if (fbconfig_style_tags)
630
case GLX_FLOAT_COMPONENTS_NV:
631
config->floatComponentsNV = *bp++;
637
long int tagvalue = *bp++;
638
DebugMessageF("WARNING: unknown fbconfig attribute from server: "
639
"tag 0x%lx value 0x%lx\n", tag, tagvalue);
646
static struct glx_config *
647
createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
648
int screen, GLboolean tagged_only)
650
INT32 buf[__GLX_TOTAL_CONFIG], *props;
652
struct glx_config *modes, *m;
658
/* Check number of properties */
659
if (nprops < __GLX_MIN_CONFIG_PROPS)
662
/* Allocate memory for our config structure */
663
modes = glx_config_create_list(nvisuals);
667
prop_size = nprops * __GLX_SIZE_INT32;
668
if (prop_size <= sizeof(buf))
671
props = malloc(prop_size);
673
/* Read each config structure and convert it into our format */
675
for (i = 0; i < nvisuals; i++) {
676
_XRead(dpy, (char *) props, prop_size);
677
#ifdef GLX_USE_APPLEGL
678
/* Older X servers don't send this so we default it here. */
679
m->drawableType = GLX_WINDOW_BIT;
682
* The XQuartz 2.3.2.1 X server doesn't set this properly, so
683
* set the proper bits here.
684
* AppleSGLX supports windows, pixmaps, and pbuffers with all config.
686
m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
688
__glXInitializeVisualConfigFromTags(m, nprops, props,
689
tagged_only, GL_TRUE);
701
getVisualConfigs(struct glx_screen *psc,
702
struct glx_display *priv, int screen)
704
xGLXGetVisualConfigsReq *req;
705
xGLXGetVisualConfigsReply reply;
706
Display *dpy = priv->dpy;
711
GetReq(GLXGetVisualConfigs, req);
712
req->reqType = priv->codes.major_opcode;
713
req->glxCode = X_GLXGetVisualConfigs;
714
req->screen = screen;
716
if (!_XReply(dpy, (xReply *) & reply, 0, False))
719
psc->visuals = createConfigsFromProperties(dpy,
726
return psc->visuals != NULL;
730
getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
732
xGLXGetFBConfigsReq *fb_req;
733
xGLXGetFBConfigsSGIXReq *sgi_req;
734
xGLXVendorPrivateWithReplyReq *vpreq;
735
xGLXGetFBConfigsReply reply;
736
Display *dpy = priv->dpy;
738
psc->serverGLXexts = __glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
740
if (psc->serverGLXexts == NULL) {
747
if (priv->minorVersion >= 3) {
748
GetReq(GLXGetFBConfigs, fb_req);
749
fb_req->reqType = priv->codes.major_opcode;
750
fb_req->glxCode = X_GLXGetFBConfigs;
751
fb_req->screen = screen;
753
else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
754
GetReqExtra(GLXVendorPrivateWithReply,
755
sz_xGLXGetFBConfigsSGIXReq -
756
sz_xGLXVendorPrivateWithReplyReq, vpreq);
757
sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
758
sgi_req->reqType = priv->codes.major_opcode;
759
sgi_req->glxCode = X_GLXVendorPrivateWithReply;
760
sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
761
sgi_req->screen = screen;
766
if (!_XReply(dpy, (xReply *) & reply, 0, False))
769
psc->configs = createConfigsFromProperties(dpy,
771
reply.numAttribs * 2,
776
return psc->configs != NULL;
780
glx_screen_init(struct glx_screen *psc,
781
int screen, struct glx_display * priv)
783
/* Initialize per screen dynamic client GLX extensions */
784
psc->ext_list_first_time = GL_TRUE;
786
psc->dpy = priv->dpy;
789
if (!getVisualConfigs(psc, priv, screen))
792
if (!getFBConfigs(psc, priv, screen))
799
glx_screen_cleanup(struct glx_screen *psc)
802
glx_config_destroy_list(psc->configs);
803
free(psc->effectiveGLXexts);
804
psc->configs = NULL; /* NOTE: just for paranoia */
807
glx_config_destroy_list(psc->visuals);
808
psc->visuals = NULL; /* NOTE: just for paranoia */
810
free((char *) psc->serverGLXexts);
811
free((char *) psc->serverGLXvendor);
812
free((char *) psc->serverGLXversion);
816
** Allocate the memory for the per screen configs for each screen.
817
** If that works then fetch the per screen configs data.
820
AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
822
struct glx_screen *psc;
826
** First allocate memory for the array of per screen configs.
828
screens = ScreenCount(dpy);
829
priv->screens = calloc(screens, sizeof *priv->screens);
833
for (i = 0; i < screens; i++, psc++) {
835
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
836
#if defined(GLX_USE_DRM)
837
#if defined(HAVE_DRI3)
838
if (priv->dri3Display)
839
psc = (*priv->dri3Display->createScreen) (i, priv);
840
#endif /* HAVE_DRI3 */
841
if (psc == NULL && priv->dri2Display)
842
psc = (*priv->dri2Display->createScreen) (i, priv);
843
#endif /* GLX_USE_DRM */
845
#ifdef GLX_USE_WINDOWSGL
846
if (psc == NULL && priv->windowsdriDisplay)
847
psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
850
if (psc == NULL && priv->driswDisplay)
851
psc = (*priv->driswDisplay->createScreen) (i, priv);
852
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
854
#if defined(GLX_USE_APPLEGL)
856
psc = applegl_create_screen(i, priv);
859
psc = indirect_create_screen(i, priv);
861
priv->screens[i] = psc;
868
** Initialize the client side extension code.
870
_X_HIDDEN struct glx_display *
871
__glXInitialize(Display * dpy)
874
struct glx_display *dpyPriv, *d;
875
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
876
Bool glx_direct, glx_accel;
878
int i, majorVersion = 0;
880
_XLockMutex(_Xglobal_lock);
882
for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
883
if (dpyPriv->dpy == dpy) {
884
_XUnlockMutex(_Xglobal_lock);
889
/* Drop the lock while we create the display private. */
890
_XUnlockMutex(_Xglobal_lock);
892
dpyPriv = calloc(1, sizeof *dpyPriv);
896
codes = XInitExtension(dpy, __glXExtensionName);
902
dpyPriv->codes = *codes;
905
/* This GLX implementation requires X_GLXQueryExtensionsString
906
* and X_GLXQueryServerString, which are new in GLX 1.1.
908
if (!QueryVersion(dpy, dpyPriv->codes.major_opcode,
909
&majorVersion, &dpyPriv->minorVersion)
910
|| (majorVersion != 1)
911
|| (majorVersion == 1 && dpyPriv->minorVersion < 1)) {
916
for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
917
XESetWireToEvent(dpy, dpyPriv->codes.first_event + i, __glXWireToEvent);
918
XESetEventToWire(dpy, dpyPriv->codes.first_event + i, __glXEventToWire);
921
XESetCloseDisplay(dpy, dpyPriv->codes.extension, __glXCloseDisplay);
922
XESetErrorString (dpy, dpyPriv->codes.extension, __glXErrorString);
924
dpyPriv->glXDrawHash = __glxHashCreate();
926
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
927
glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
928
glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
930
const char *env = getenv("MESA_LOADER_DRIVER_OVERRIDE");
931
zink = env && !strcmp(env, "zink");
933
dpyPriv->drawHash = __glxHashCreate();
935
dpyPriv->zombieGLXDrawable = _mesa_pointer_set_create(NULL);
937
#ifndef GLX_USE_APPLEGL
938
/* Set the logger before the *CreateDisplay functions. */
939
loader_set_logger(glx_message);
943
** Initialize the direct rendering per display data and functions.
944
** Note: This _must_ be done before calling any other DRI routines
945
** (e.g., those called in AllocAndFetchScreenConfigs).
947
#if defined(GLX_USE_DRM)
948
if (glx_direct && glx_accel && !zink) {
949
#if defined(HAVE_DRI3)
950
if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
951
dpyPriv->dri3Display = dri3_create_display(dpy);
952
#endif /* HAVE_DRI3 */
953
if (!env_var_as_boolean("LIBGL_DRI2_DISABLE", false))
954
dpyPriv->dri2Display = dri2CreateDisplay(dpy);
956
#endif /* GLX_USE_DRM */
958
dpyPriv->driswDisplay = driswCreateDisplay(dpy, zink);
959
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
961
#ifdef GLX_USE_APPLEGL
962
if (!applegl_create_display(dpyPriv)) {
968
#ifdef GLX_USE_WINDOWSGL
969
if (glx_direct && glx_accel)
970
dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
973
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
978
__glX_send_client_info(dpyPriv);
980
/* Grab the lock again and add the dispay private, unless somebody
981
* beat us to initializing on this display in the meantime. */
982
_XLockMutex(_Xglobal_lock);
984
for (d = glx_displays; d; d = d->next) {
986
_XUnlockMutex(_Xglobal_lock);
987
glx_display_free(dpyPriv);
992
dpyPriv->next = glx_displays;
993
glx_displays = dpyPriv;
995
_XUnlockMutex(_Xglobal_lock);
1001
** Setup for sending a GLX command on dpy. Make sure the extension is
1002
** initialized. Try to avoid calling __glXInitialize as its kinda slow.
1005
__glXSetupForCommand(Display * dpy)
1007
struct glx_context *gc;
1008
struct glx_display *priv;
1010
/* If this thread has a current context, flush its rendering commands */
1011
gc = __glXGetCurrentContext();
1012
if (gc->currentDpy) {
1013
/* Flush rendering buffer of the current context, if any */
1014
(void) __glXFlushRenderBuffer(gc, gc->pc);
1016
if (gc->currentDpy == dpy) {
1017
/* Use opcode from gc because its right */
1018
return gc->majorOpcode;
1022
** Have to get info about argument dpy because it might be to
1023
** a different server
1028
/* Forced to lookup extension via the slow initialize route */
1029
priv = __glXInitialize(dpy);
1033
return priv->codes.major_opcode;
1037
* Flush the drawing command transport buffer.
1039
* \param ctx Context whose transport buffer is to be flushed.
1040
* \param pc Pointer to first unused buffer location.
1043
* Modify this function to use \c ctx->pc instead of the explicit
1047
__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1049
Display *const dpy = ctx->currentDpy;
1050
xcb_connection_t *c = XGetXCBConnection(dpy);
1051
const GLint size = pc - ctx->buf;
1053
if ((dpy != NULL) && (size > 0)) {
1054
xcb_glx_render(c, ctx->currentContextTag, size,
1055
(const uint8_t *) ctx->buf);
1058
/* Reset pointer and return it */
1065
* Send a portion of a GLXRenderLarge command to the server. The advantage of
1066
* this function over \c __glXSendLargeCommand is that callers can use the
1067
* data buffer in the GLX context and may be able to avoid allocating an
1068
* extra buffer. The disadvantage is the clients will have to do more
1069
* GLX protocol work (i.e., calculating \c totalRequests, etc.).
1071
* \sa __glXSendLargeCommand
1073
* \param gc GLX context
1074
* \param requestNumber Which part of the whole command is this? The first
1076
* \param totalRequests How many requests will there be?
1077
* \param data Command data.
1078
* \param dataLen Size, in bytes, of the command data.
1081
__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1082
GLint totalRequests, const GLvoid * data, GLint dataLen)
1084
Display *dpy = gc->currentDpy;
1085
xcb_connection_t *c = XGetXCBConnection(dpy);
1086
xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1087
totalRequests, dataLen, data);
1092
* Send a command that is too large for the GLXRender protocol request.
1094
* Send a large command, one that is too large for some reason to
1095
* send using the GLXRender protocol request. One reason to send
1096
* a large command is to avoid copying the data.
1098
* \param ctx GLX context
1099
* \param header Header data.
1100
* \param headerLen Size, in bytes, of the header data. It is assumed that
1101
* the header data will always be small enough to fit in
1102
* a single X protocol packet.
1103
* \param data Command data.
1104
* \param dataLen Size, in bytes, of the command data.
1107
__glXSendLargeCommand(struct glx_context * ctx,
1108
const GLvoid * header, GLint headerLen,
1109
const GLvoid * data, GLint dataLen)
1112
GLint totalRequests, requestNumber;
1115
** Calculate the maximum amount of data can be stuffed into a single
1116
** packet. sz_xGLXRenderReq is added because bufSize is the maximum
1117
** packet size minus sz_xGLXRenderReq.
1119
maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1120
totalRequests = 1 + (dataLen / maxSize);
1121
if (dataLen % maxSize)
1125
** Send all of the command, except the large array, as one request.
1127
assert(headerLen <= maxSize);
1128
__glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1131
** Send enough requests until the whole array is sent.
1133
for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1135
__glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1136
data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1138
assert(dataLen > 0);
1141
assert(dataLen <= maxSize);
1142
__glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);