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