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