glx: properly release DRI configs
[mesa.git] / src / glx / x11 / 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 #include "glapi.h"
45 #include "glxextensions.h"
46 #include "glcontextmodes.h"
47
48 #ifdef USE_XCB
49 #include <X11/Xlib-xcb.h>
50 #include <xcb/xcb.h>
51 #include <xcb/glx.h>
52 #endif
53
54
55 #ifdef DEBUG
56 void __glXDumpDrawBuffer(__GLXcontext * 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 char *__glXExtensionName = GLX_EXTENSION_NAME;
68 XExtensionInfo *__glXExtensionInfo = NULL;
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 };
85
86 static int
87 __glXCloseDisplay(Display * dpy, XExtCodes * codes)
88 {
89 GLXContext gc;
90
91 gc = __glXGetCurrentContext();
92 if (dpy == gc->currentDpy) {
93 __glXSetCurrentContextNull();
94 __glXFreeContext(gc);
95 }
96
97 return XextRemoveDisplay(__glXExtensionInfo, dpy);
98 }
99
100
101 static
102 XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
103 __GLX_NUMBER_ERRORS, error_list)
104
105 static /* const */ XExtensionHooks __glXExtensionHooks = {
106 NULL, /* create_gc */
107 NULL, /* copy_gc */
108 NULL, /* flush_gc */
109 NULL, /* free_gc */
110 NULL, /* create_font */
111 NULL, /* free_font */
112 __glXCloseDisplay, /* close_display */
113 NULL, /* wire_to_event */
114 NULL, /* event_to_wire */
115 NULL, /* error */
116 __glXErrorString, /* error_string */
117 };
118
119 static
120 XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
121 __glXExtensionName, &__glXExtensionHooks,
122 __GLX_NUMBER_EVENTS, NULL)
123
124 /************************************************************************/
125 /*
126 ** Free the per screen configs data as well as the array of
127 ** __glXScreenConfigs.
128 */
129 static void
130 FreeScreenConfigs(__GLXdisplayPrivate * priv)
131 {
132 __GLXscreenConfigs *psc;
133 GLint i, screens;
134
135 /* Free screen configuration information */
136 psc = priv->screenConfigs;
137 screens = ScreenCount(priv->dpy);
138 for (i = 0; i < screens; i++, psc++) {
139 if (psc->configs) {
140 _gl_context_modes_destroy(psc->configs);
141 if (psc->effectiveGLXexts)
142 Xfree(psc->effectiveGLXexts);
143 psc->configs = NULL; /* NOTE: just for paranoia */
144 }
145 if (psc->visuals) {
146 _gl_context_modes_destroy(psc->visuals);
147 psc->visuals = NULL; /* NOTE: just for paranoia */
148 }
149 Xfree((char *) psc->serverGLXexts);
150
151 #ifdef GLX_DIRECT_RENDERING
152 if (psc->driver_configs) {
153 for(unsigned int i = 0; psc->driver_configs[i]; i++)
154 free((__DRIconfig*)psc->driver_configs[i]);
155 free(psc->driver_configs);
156 psc->driver_configs = NULL;
157 }
158 if (psc->driScreen) {
159 psc->driScreen->destroyScreen(psc);
160 __glxHashDestroy(psc->drawHash);
161 XFree(psc->driScreen);
162 psc->driScreen = NULL;
163 }
164 #endif
165 }
166 XFree((char *) priv->screenConfigs);
167 priv->screenConfigs = NULL;
168 }
169
170 /*
171 ** Release the private memory referred to in a display private
172 ** structure. The caller will free the extension structure.
173 */
174 static int
175 __glXFreeDisplayPrivate(XExtData * extension)
176 {
177 __GLXdisplayPrivate *priv;
178
179 priv = (__GLXdisplayPrivate *) extension->private_data;
180 FreeScreenConfigs(priv);
181 if (priv->serverGLXvendor) {
182 Xfree((char *) priv->serverGLXvendor);
183 priv->serverGLXvendor = 0x0; /* to protect against double free's */
184 }
185 if (priv->serverGLXversion) {
186 Xfree((char *) priv->serverGLXversion);
187 priv->serverGLXversion = 0x0; /* to protect against double free's */
188 }
189
190 #ifdef GLX_DIRECT_RENDERING
191 /* Free the direct rendering per display data */
192 if (priv->driswDisplay)
193 (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
194 priv->driswDisplay = NULL;
195
196 if (priv->driDisplay)
197 (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
198 priv->driDisplay = NULL;
199
200 if (priv->dri2Display)
201 (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
202 priv->dri2Display = NULL;
203 #endif
204
205 Xfree((char *) priv);
206 return 0;
207 }
208
209 /************************************************************************/
210
211 /*
212 ** Query the version of the GLX extension. This procedure works even if
213 ** the client extension is not completely set up.
214 */
215 static Bool
216 QueryVersion(Display * dpy, int opcode, int *major, int *minor)
217 {
218 #ifdef USE_XCB
219 xcb_connection_t *c = XGetXCBConnection(dpy);
220 xcb_glx_query_version_reply_t* reply =
221 xcb_glx_query_version_reply(c,
222 xcb_glx_query_version(c,
223 GLX_MAJOR_VERSION,
224 GLX_MINOR_VERSION),
225 NULL);
226
227 if(reply->major_version != GLX_MAJOR_VERSION)
228 {
229 free(reply);
230 return GL_FALSE;
231 }
232 *major = reply->major_version;
233 *minor = min(reply->minor_version, GLX_MINOR_VERSION);
234 free(reply);
235 return GL_TRUE;
236 #else
237 xGLXQueryVersionReq *req;
238 xGLXQueryVersionReply reply;
239
240 /* Send the glXQueryVersion request */
241 LockDisplay(dpy);
242 GetReq(GLXQueryVersion, req);
243 req->reqType = opcode;
244 req->glxCode = X_GLXQueryVersion;
245 req->majorVersion = GLX_MAJOR_VERSION;
246 req->minorVersion = GLX_MINOR_VERSION;
247 _XReply(dpy, (xReply *) & reply, 0, False);
248 UnlockDisplay(dpy);
249 SyncHandle();
250
251 if (reply.majorVersion != GLX_MAJOR_VERSION) {
252 /*
253 ** The server does not support the same major release as this
254 ** client.
255 */
256 return GL_FALSE;
257 }
258 *major = reply.majorVersion;
259 *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
260 return GL_TRUE;
261 #endif /* USE_XCB */
262 }
263
264
265 _X_HIDDEN void
266 __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
267 const INT32 * bp, Bool tagged_only,
268 Bool fbconfig_style_tags)
269 {
270 int i;
271
272 if (!tagged_only) {
273 /* Copy in the first set of properties */
274 config->visualID = *bp++;
275
276 config->visualType = _gl_convert_from_x_visual_type(*bp++);
277
278 config->rgbMode = *bp++;
279
280 config->redBits = *bp++;
281 config->greenBits = *bp++;
282 config->blueBits = *bp++;
283 config->alphaBits = *bp++;
284 config->accumRedBits = *bp++;
285 config->accumGreenBits = *bp++;
286 config->accumBlueBits = *bp++;
287 config->accumAlphaBits = *bp++;
288
289 config->doubleBufferMode = *bp++;
290 config->stereoMode = *bp++;
291
292 config->rgbBits = *bp++;
293 config->depthBits = *bp++;
294 config->stencilBits = *bp++;
295 config->numAuxBuffers = *bp++;
296 config->level = *bp++;
297
298 count -= __GLX_MIN_CONFIG_PROPS;
299 }
300
301 /*
302 ** Additional properties may be in a list at the end
303 ** of the reply. They are in pairs of property type
304 ** and property value.
305 */
306
307 #define FETCH_OR_SET(tag) \
308 config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
309
310 for (i = 0; i < count; i += 2) {
311 switch (*bp++) {
312 case GLX_RGBA:
313 FETCH_OR_SET(rgbMode);
314 break;
315 case GLX_BUFFER_SIZE:
316 config->rgbBits = *bp++;
317 break;
318 case GLX_LEVEL:
319 config->level = *bp++;
320 break;
321 case GLX_DOUBLEBUFFER:
322 FETCH_OR_SET(doubleBufferMode);
323 break;
324 case GLX_STEREO:
325 FETCH_OR_SET(stereoMode);
326 break;
327 case GLX_AUX_BUFFERS:
328 config->numAuxBuffers = *bp++;
329 break;
330 case GLX_RED_SIZE:
331 config->redBits = *bp++;
332 break;
333 case GLX_GREEN_SIZE:
334 config->greenBits = *bp++;
335 break;
336 case GLX_BLUE_SIZE:
337 config->blueBits = *bp++;
338 break;
339 case GLX_ALPHA_SIZE:
340 config->alphaBits = *bp++;
341 break;
342 case GLX_DEPTH_SIZE:
343 config->depthBits = *bp++;
344 break;
345 case GLX_STENCIL_SIZE:
346 config->stencilBits = *bp++;
347 break;
348 case GLX_ACCUM_RED_SIZE:
349 config->accumRedBits = *bp++;
350 break;
351 case GLX_ACCUM_GREEN_SIZE:
352 config->accumGreenBits = *bp++;
353 break;
354 case GLX_ACCUM_BLUE_SIZE:
355 config->accumBlueBits = *bp++;
356 break;
357 case GLX_ACCUM_ALPHA_SIZE:
358 config->accumAlphaBits = *bp++;
359 break;
360 case GLX_VISUAL_CAVEAT_EXT:
361 config->visualRating = *bp++;
362 break;
363 case GLX_X_VISUAL_TYPE:
364 config->visualType = *bp++;
365 break;
366 case GLX_TRANSPARENT_TYPE:
367 config->transparentPixel = *bp++;
368 break;
369 case GLX_TRANSPARENT_INDEX_VALUE:
370 config->transparentIndex = *bp++;
371 break;
372 case GLX_TRANSPARENT_RED_VALUE:
373 config->transparentRed = *bp++;
374 break;
375 case GLX_TRANSPARENT_GREEN_VALUE:
376 config->transparentGreen = *bp++;
377 break;
378 case GLX_TRANSPARENT_BLUE_VALUE:
379 config->transparentBlue = *bp++;
380 break;
381 case GLX_TRANSPARENT_ALPHA_VALUE:
382 config->transparentAlpha = *bp++;
383 break;
384 case GLX_VISUAL_ID:
385 config->visualID = *bp++;
386 break;
387 case GLX_DRAWABLE_TYPE:
388 config->drawableType = *bp++;
389 break;
390 case GLX_RENDER_TYPE:
391 config->renderType = *bp++;
392 break;
393 case GLX_X_RENDERABLE:
394 config->xRenderable = *bp++;
395 break;
396 case GLX_FBCONFIG_ID:
397 config->fbconfigID = *bp++;
398 break;
399 case GLX_MAX_PBUFFER_WIDTH:
400 config->maxPbufferWidth = *bp++;
401 break;
402 case GLX_MAX_PBUFFER_HEIGHT:
403 config->maxPbufferHeight = *bp++;
404 break;
405 case GLX_MAX_PBUFFER_PIXELS:
406 config->maxPbufferPixels = *bp++;
407 break;
408 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
409 config->optimalPbufferWidth = *bp++;
410 break;
411 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
412 config->optimalPbufferHeight = *bp++;
413 break;
414 case GLX_VISUAL_SELECT_GROUP_SGIX:
415 config->visualSelectGroup = *bp++;
416 break;
417 case GLX_SWAP_METHOD_OML:
418 config->swapMethod = *bp++;
419 break;
420 case GLX_SAMPLE_BUFFERS_SGIS:
421 config->sampleBuffers = *bp++;
422 break;
423 case GLX_SAMPLES_SGIS:
424 config->samples = *bp++;
425 break;
426 case GLX_BIND_TO_TEXTURE_RGB_EXT:
427 config->bindToTextureRgb = *bp++;
428 break;
429 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
430 config->bindToTextureRgba = *bp++;
431 break;
432 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
433 config->bindToMipmapTexture = *bp++;
434 break;
435 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
436 config->bindToTextureTargets = *bp++;
437 break;
438 case GLX_Y_INVERTED_EXT:
439 config->yInverted = *bp++;
440 break;
441 case None:
442 i = count;
443 break;
444 default:
445 break;
446 }
447 }
448
449 config->renderType =
450 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
451
452 config->haveAccumBuffer = ((config->accumRedBits +
453 config->accumGreenBits +
454 config->accumBlueBits +
455 config->accumAlphaBits) > 0);
456 config->haveDepthBuffer = (config->depthBits > 0);
457 config->haveStencilBuffer = (config->stencilBits > 0);
458 }
459
460 static __GLcontextModes *
461 createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
462 int screen, GLboolean tagged_only)
463 {
464 INT32 buf[__GLX_TOTAL_CONFIG], *props;
465 unsigned prop_size;
466 __GLcontextModes *modes, *m;
467 int i;
468
469 if (nprops == 0)
470 return NULL;
471
472 /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
473
474 /* Check number of properties */
475 if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
476 return NULL;
477
478 /* Allocate memory for our config structure */
479 modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
480 if (!modes)
481 return NULL;
482
483 prop_size = nprops * __GLX_SIZE_INT32;
484 if (prop_size <= sizeof(buf))
485 props = buf;
486 else
487 props = Xmalloc(prop_size);
488
489 /* Read each config structure and convert it into our format */
490 m = modes;
491 for (i = 0; i < nvisuals; i++) {
492 _XRead(dpy, (char *) props, prop_size);
493 /* Older X servers don't send this so we default it here. */
494 m->drawableType = GLX_WINDOW_BIT;
495 __glXInitializeVisualConfigFromTags(m, nprops, props,
496 tagged_only, GL_TRUE);
497 m->screen = screen;
498 m = m->next;
499 }
500
501 if (props != buf)
502 Xfree(props);
503
504 return modes;
505 }
506
507 static GLboolean
508 getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
509 {
510 xGLXGetVisualConfigsReq *req;
511 __GLXscreenConfigs *psc;
512 xGLXGetVisualConfigsReply reply;
513
514 LockDisplay(dpy);
515
516 psc = priv->screenConfigs + screen;
517 psc->visuals = NULL;
518 GetReq(GLXGetVisualConfigs, req);
519 req->reqType = priv->majorOpcode;
520 req->glxCode = X_GLXGetVisualConfigs;
521 req->screen = screen;
522
523 if (!_XReply(dpy, (xReply *) & reply, 0, False))
524 goto out;
525
526 psc->visuals = createConfigsFromProperties(dpy,
527 reply.numVisuals,
528 reply.numProps,
529 screen, GL_FALSE);
530
531 out:
532 UnlockDisplay(dpy);
533 return psc->visuals != NULL;
534 }
535
536 static GLboolean
537 getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
538 {
539 xGLXGetFBConfigsReq *fb_req;
540 xGLXGetFBConfigsSGIXReq *sgi_req;
541 xGLXVendorPrivateWithReplyReq *vpreq;
542 xGLXGetFBConfigsReply reply;
543 __GLXscreenConfigs *psc;
544
545 psc = priv->screenConfigs + screen;
546 psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
547
548 LockDisplay(dpy);
549
550 psc->configs = NULL;
551 if (atof(priv->serverGLXversion) >= 1.3) {
552 GetReq(GLXGetFBConfigs, fb_req);
553 fb_req->reqType = priv->majorOpcode;
554 fb_req->glxCode = X_GLXGetFBConfigs;
555 fb_req->screen = screen;
556 }
557 else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
558 GetReqExtra(GLXVendorPrivateWithReply,
559 sz_xGLXGetFBConfigsSGIXReq +
560 sz_xGLXVendorPrivateWithReplyReq, vpreq);
561 sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
562 sgi_req->reqType = priv->majorOpcode;
563 sgi_req->glxCode = X_GLXVendorPrivateWithReply;
564 sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
565 sgi_req->screen = screen;
566 }
567 else
568 goto out;
569
570 if (!_XReply(dpy, (xReply *) & reply, 0, False))
571 goto out;
572
573 psc->configs = createConfigsFromProperties(dpy,
574 reply.numFBConfigs,
575 reply.numAttribs * 2,
576 screen, GL_TRUE);
577
578 out:
579 UnlockDisplay(dpy);
580 return psc->configs != NULL;
581 }
582
583 /*
584 ** Allocate the memory for the per screen configs for each screen.
585 ** If that works then fetch the per screen configs data.
586 */
587 static Bool
588 AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
589 {
590 __GLXscreenConfigs *psc;
591 GLint i, screens;
592
593 /*
594 ** First allocate memory for the array of per screen configs.
595 */
596 screens = ScreenCount(dpy);
597 psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
598 if (!psc) {
599 return GL_FALSE;
600 }
601 memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
602 priv->screenConfigs = psc;
603
604 priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
605 if (priv->serverGLXversion == NULL) {
606 FreeScreenConfigs(priv);
607 return GL_FALSE;
608 }
609
610 for (i = 0; i < screens; i++, psc++) {
611 getVisualConfigs(dpy, priv, i);
612 getFBConfigs(dpy, priv, i);
613
614 #ifdef GLX_DIRECT_RENDERING
615 psc->scr = i;
616 psc->dpy = dpy;
617 psc->drawHash = __glxHashCreate();
618 if (psc->drawHash == NULL)
619 continue;
620
621 if (priv->dri2Display)
622 psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
623
624 if (psc->driScreen == NULL && priv->driDisplay)
625 psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
626
627 if (psc->driScreen == NULL && priv->driswDisplay)
628 psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
629
630 if (psc->driScreen == NULL) {
631 __glxHashDestroy(psc->drawHash);
632 psc->drawHash = NULL;
633 }
634 #endif
635 }
636 SyncHandle();
637 return GL_TRUE;
638 }
639
640 /*
641 ** Initialize the client side extension code.
642 */
643 _X_HIDDEN __GLXdisplayPrivate *
644 __glXInitialize(Display * dpy)
645 {
646 XExtDisplayInfo *info = __glXFindDisplay(dpy);
647 XExtData **privList, *private, *found;
648 __GLXdisplayPrivate *dpyPriv;
649 XEDataObject dataObj;
650 int major, minor;
651 #ifdef GLX_DIRECT_RENDERING
652 Bool glx_direct, glx_accel;
653 #endif
654
655 #if defined(USE_XTHREADS)
656 {
657 static int firstCall = 1;
658 if (firstCall) {
659 /* initialize the GLX mutexes */
660 xmutex_init(&__glXmutex);
661 firstCall = 0;
662 }
663 }
664 #endif
665
666 /* The one and only long long lock */
667 __glXLock();
668
669 if (!XextHasExtension(info)) {
670 /* No GLX extension supported by this server. Oh well. */
671 __glXUnlock();
672 XMissingExtension(dpy, __glXExtensionName);
673 return 0;
674 }
675
676 /* See if a display private already exists. If so, return it */
677 dataObj.display = dpy;
678 privList = XEHeadOfExtensionList(dataObj);
679 found = XFindOnExtensionList(privList, info->codes->extension);
680 if (found) {
681 __glXUnlock();
682 return (__GLXdisplayPrivate *) found->private_data;
683 }
684
685 /* See if the versions are compatible */
686 if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
687 /* The client and server do not agree on versions. Punt. */
688 __glXUnlock();
689 return 0;
690 }
691
692 /*
693 ** Allocate memory for all the pieces needed for this buffer.
694 */
695 private = (XExtData *) Xmalloc(sizeof(XExtData));
696 if (!private) {
697 __glXUnlock();
698 return 0;
699 }
700 dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
701 if (!dpyPriv) {
702 __glXUnlock();
703 Xfree((char *) private);
704 return 0;
705 }
706
707 /*
708 ** Init the display private and then read in the screen config
709 ** structures from the server.
710 */
711 dpyPriv->majorOpcode = info->codes->major_opcode;
712 dpyPriv->majorVersion = major;
713 dpyPriv->minorVersion = minor;
714 dpyPriv->dpy = dpy;
715
716 dpyPriv->serverGLXvendor = 0x0;
717 dpyPriv->serverGLXversion = 0x0;
718
719 #ifdef GLX_DIRECT_RENDERING
720 glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
721 glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
722
723 /*
724 ** Initialize the direct rendering per display data and functions.
725 ** Note: This _must_ be done before calling any other DRI routines
726 ** (e.g., those called in AllocAndFetchScreenConfigs).
727 */
728 if (glx_direct && glx_accel) {
729 dpyPriv->dri2Display = dri2CreateDisplay(dpy);
730 dpyPriv->driDisplay = driCreateDisplay(dpy);
731 }
732 if (glx_direct)
733 dpyPriv->driswDisplay = driswCreateDisplay(dpy);
734 #endif
735
736 if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
737 __glXUnlock();
738 Xfree((char *) dpyPriv);
739 Xfree((char *) private);
740 return 0;
741 }
742
743 /*
744 ** Fill in the private structure. This is the actual structure that
745 ** hangs off of the Display structure. Our private structure is
746 ** referred to by this structure. Got that?
747 */
748 private->number = info->codes->extension;
749 private->next = 0;
750 private->free_private = __glXFreeDisplayPrivate;
751 private->private_data = (char *) dpyPriv;
752 XAddToExtensionList(privList, private);
753
754 if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
755 __glXClientInfo(dpy, dpyPriv->majorOpcode);
756 }
757 __glXUnlock();
758
759 return dpyPriv;
760 }
761
762 /*
763 ** Setup for sending a GLX command on dpy. Make sure the extension is
764 ** initialized. Try to avoid calling __glXInitialize as its kinda slow.
765 */
766 _X_HIDDEN CARD8
767 __glXSetupForCommand(Display * dpy)
768 {
769 GLXContext gc;
770 __GLXdisplayPrivate *priv;
771
772 /* If this thread has a current context, flush its rendering commands */
773 gc = __glXGetCurrentContext();
774 if (gc->currentDpy) {
775 /* Flush rendering buffer of the current context, if any */
776 (void) __glXFlushRenderBuffer(gc, gc->pc);
777
778 if (gc->currentDpy == dpy) {
779 /* Use opcode from gc because its right */
780 return gc->majorOpcode;
781 }
782 else {
783 /*
784 ** Have to get info about argument dpy because it might be to
785 ** a different server
786 */
787 }
788 }
789
790 /* Forced to lookup extension via the slow initialize route */
791 priv = __glXInitialize(dpy);
792 if (!priv) {
793 return 0;
794 }
795 return priv->majorOpcode;
796 }
797
798 /**
799 * Flush the drawing command transport buffer.
800 *
801 * \param ctx Context whose transport buffer is to be flushed.
802 * \param pc Pointer to first unused buffer location.
803 *
804 * \todo
805 * Modify this function to use \c ctx->pc instead of the explicit
806 * \c pc parameter.
807 */
808 _X_HIDDEN GLubyte *
809 __glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
810 {
811 Display *const dpy = ctx->currentDpy;
812 #ifdef USE_XCB
813 xcb_connection_t *c = XGetXCBConnection(dpy);
814 #else
815 xGLXRenderReq *req;
816 #endif /* USE_XCB */
817 const GLint size = pc - ctx->buf;
818
819 if ((dpy != NULL) && (size > 0)) {
820 #ifdef USE_XCB
821 xcb_glx_render(c, ctx->currentContextTag, size,
822 (const uint8_t *) ctx->buf);
823 #else
824 /* Send the entire buffer as an X request */
825 LockDisplay(dpy);
826 GetReq(GLXRender, req);
827 req->reqType = ctx->majorOpcode;
828 req->glxCode = X_GLXRender;
829 req->contextTag = ctx->currentContextTag;
830 req->length += (size + 3) >> 2;
831 _XSend(dpy, (char *) ctx->buf, size);
832 UnlockDisplay(dpy);
833 SyncHandle();
834 #endif
835 }
836
837 /* Reset pointer and return it */
838 ctx->pc = ctx->buf;
839 return ctx->pc;
840 }
841
842
843 /**
844 * Send a portion of a GLXRenderLarge command to the server. The advantage of
845 * this function over \c __glXSendLargeCommand is that callers can use the
846 * data buffer in the GLX context and may be able to avoid allocating an
847 * extra buffer. The disadvantage is the clients will have to do more
848 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
849 *
850 * \sa __glXSendLargeCommand
851 *
852 * \param gc GLX context
853 * \param requestNumber Which part of the whole command is this? The first
854 * request is 1.
855 * \param totalRequests How many requests will there be?
856 * \param data Command data.
857 * \param dataLen Size, in bytes, of the command data.
858 */
859 _X_HIDDEN void
860 __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
861 GLint totalRequests, const GLvoid * data, GLint dataLen)
862 {
863 Display *dpy = gc->currentDpy;
864 #ifdef USE_XCB
865 xcb_connection_t *c = XGetXCBConnection(dpy);
866 xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
867 totalRequests, dataLen, data);
868 #else
869 xGLXRenderLargeReq *req;
870
871 if (requestNumber == 1) {
872 LockDisplay(dpy);
873 }
874
875 GetReq(GLXRenderLarge, req);
876 req->reqType = gc->majorOpcode;
877 req->glxCode = X_GLXRenderLarge;
878 req->contextTag = gc->currentContextTag;
879 req->length += (dataLen + 3) >> 2;
880 req->requestNumber = requestNumber;
881 req->requestTotal = totalRequests;
882 req->dataBytes = dataLen;
883 Data(dpy, data, dataLen);
884
885 if (requestNumber == totalRequests) {
886 UnlockDisplay(dpy);
887 SyncHandle();
888 }
889 #endif /* USE_XCB */
890 }
891
892
893 /**
894 * Send a command that is too large for the GLXRender protocol request.
895 *
896 * Send a large command, one that is too large for some reason to
897 * send using the GLXRender protocol request. One reason to send
898 * a large command is to avoid copying the data.
899 *
900 * \param ctx GLX context
901 * \param header Header data.
902 * \param headerLen Size, in bytes, of the header data. It is assumed that
903 * the header data will always be small enough to fit in
904 * a single X protocol packet.
905 * \param data Command data.
906 * \param dataLen Size, in bytes, of the command data.
907 */
908 _X_HIDDEN void
909 __glXSendLargeCommand(__GLXcontext * ctx,
910 const GLvoid * header, GLint headerLen,
911 const GLvoid * data, GLint dataLen)
912 {
913 GLint maxSize;
914 GLint totalRequests, requestNumber;
915
916 /*
917 ** Calculate the maximum amount of data can be stuffed into a single
918 ** packet. sz_xGLXRenderReq is added because bufSize is the maximum
919 ** packet size minus sz_xGLXRenderReq.
920 */
921 maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
922 totalRequests = 1 + (dataLen / maxSize);
923 if (dataLen % maxSize)
924 totalRequests++;
925
926 /*
927 ** Send all of the command, except the large array, as one request.
928 */
929 assert(headerLen <= maxSize);
930 __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
931
932 /*
933 ** Send enough requests until the whole array is sent.
934 */
935 for (requestNumber = 2; requestNumber <= (totalRequests - 1);
936 requestNumber++) {
937 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
938 data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
939 dataLen -= maxSize;
940 assert(dataLen > 0);
941 }
942
943 assert(dataLen <= maxSize);
944 __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
945 }
946
947 /************************************************************************/
948
949 #ifdef DEBUG
950 _X_HIDDEN void
951 __glXDumpDrawBuffer(__GLXcontext * ctx)
952 {
953 GLubyte *p = ctx->buf;
954 GLubyte *end = ctx->pc;
955 GLushort opcode, length;
956
957 while (p < end) {
958 /* Fetch opcode */
959 opcode = *((GLushort *) p);
960 length = *((GLushort *) (p + 2));
961 printf("%2x: %5d: ", opcode, length);
962 length -= 4;
963 p += 4;
964 while (length > 0) {
965 printf("%08x ", *((unsigned *) p));
966 p += 4;
967 length -= 4;
968 }
969 printf("\n");
970 }
971 }
972 #endif