glx: indent -br -i3 -npcs --no-tabs glxcmds.c
[mesa.git] / src / glx / x11 / glxcmds.c
1 /* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
2 /*
3 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
4 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice including the dates of first publication and
14 * either this permission notice or a reference to
15 * http://oss.sgi.com/projects/FreeB/
16 * shall be included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Except as contained in this notice, the name of Silicon Graphics, Inc.
27 * shall not be used in advertising or otherwise to promote the sale, use or
28 * other dealings in this Software without prior written authorization from
29 * Silicon Graphics, Inc.
30 */
31
32 /**
33 * \file glxcmds.c
34 * Client-side GLX interface.
35 */
36
37 #include "glxclient.h"
38 #include "glapi.h"
39 #include "glxextensions.h"
40 #include "glcontextmodes.h"
41
42 #ifdef GLX_DIRECT_RENDERING
43 #include <sys/time.h>
44 #include <X11/extensions/xf86vmode.h>
45 #include "xf86dri.h"
46 #endif
47
48 static const char __glXGLXClientVendorName[] = "SGI";
49 static const char __glXGLXClientVersion[] = "1.4";
50
51
52 /****************************************************************************/
53
54 #ifdef GLX_DIRECT_RENDERING
55
56 static Bool windowExistsFlag;
57 static int
58 windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr)
59 {
60 if (xerr->error_code == BadWindow) {
61 windowExistsFlag = GL_FALSE;
62 }
63 return 0;
64 }
65
66 /**
67 * Find drawables in the local hash that have been destroyed on the
68 * server.
69 *
70 * \param dpy Display to destroy drawables for
71 * \param screen Screen number to destroy drawables for
72 */
73 static void
74 GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
75 {
76 XID draw;
77 __GLXDRIdrawable *pdraw;
78 XWindowAttributes xwa;
79 int (*oldXErrorHandler) (Display *, XErrorEvent *);
80
81 /* Set no-op error handler so Xlib doesn't bail out if the windows
82 * has alreay been destroyed on the server. */
83 XSync(dpy, GL_FALSE);
84 oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
85
86 if (__glxHashFirst(sc->drawHash, &draw, (void *) &pdraw) == 1) {
87 do {
88 windowExistsFlag = GL_TRUE;
89 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
90 if (!windowExistsFlag) {
91 /* Destroy the local drawable data, if the drawable no
92 longer exists in the Xserver */
93 (*pdraw->destroyDrawable) (pdraw);
94 __glxHashDelete(sc->drawHash, draw);
95 }
96 } while (__glxHashNext(sc->drawHash, &draw, (void *) &pdraw) == 1);
97 }
98
99 XSync(dpy, GL_FALSE);
100 XSetErrorHandler(oldXErrorHandler);
101 }
102
103 extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
104 GLXDrawable drawable,
105 int *const scrn_num);
106
107 /**
108 * Get the __DRIdrawable for the drawable associated with a GLXContext
109 *
110 * \param dpy The display associated with \c drawable.
111 * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
112 * \param scrn_num If non-NULL, the drawables screen is stored there
113 * \returns A pointer to the context's __DRIdrawable on success, or NULL if
114 * the drawable is not associated with a direct-rendering context.
115 */
116 _X_HIDDEN __GLXDRIdrawable *
117 GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable, int *const scrn_num)
118 {
119 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
120 __GLXDRIdrawable *pdraw;
121 const unsigned screen_count = ScreenCount(dpy);
122 unsigned i;
123 __GLXscreenConfigs *psc;
124
125 if (priv == NULL)
126 return NULL;
127
128 for (i = 0; i < screen_count; i++) {
129 psc = &priv->screenConfigs[i];
130 if (psc->drawHash == NULL)
131 continue;
132
133 if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
134 if (scrn_num != NULL)
135 *scrn_num = i;
136 return pdraw;
137 }
138 }
139
140 return NULL;
141 }
142
143 #endif
144
145
146 /**
147 * Get the GLX per-screen data structure associated with a GLX context.
148 *
149 * \param dpy Display for which the GLX per-screen information is to be
150 * retrieved.
151 * \param scrn Screen on \c dpy for which the GLX per-screen information is
152 * to be retrieved.
153 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
154 * specify a valid GLX screen, or NULL otherwise.
155 *
156 * \todo Should this function validate that \c scrn is within the screen
157 * number range for \c dpy?
158 */
159
160 static __GLXscreenConfigs *
161 GetGLXScreenConfigs(Display * dpy, int scrn)
162 {
163 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
164
165 return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;
166 }
167
168
169 static int
170 GetGLXPrivScreenConfig(Display * dpy, int scrn, __GLXdisplayPrivate ** ppriv,
171 __GLXscreenConfigs ** ppsc)
172 {
173 /* Initialize the extension, if needed . This has the added value
174 * of initializing/allocating the display private
175 */
176
177 if (dpy == NULL) {
178 return GLX_NO_EXTENSION;
179 }
180
181 *ppriv = __glXInitialize(dpy);
182 if (*ppriv == NULL) {
183 return GLX_NO_EXTENSION;
184 }
185
186 /* Check screen number to see if its valid */
187 if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
188 return GLX_BAD_SCREEN;
189 }
190
191 /* Check to see if the GL is supported on this screen */
192 *ppsc = &((*ppriv)->screenConfigs[scrn]);
193 if ((*ppsc)->configs == NULL) {
194 /* No support for GL on this screen regardless of visual */
195 return GLX_BAD_VISUAL;
196 }
197
198 return Success;
199 }
200
201
202 /**
203 * Determine if a \c GLXFBConfig supplied by the application is valid.
204 *
205 * \param dpy Application supplied \c Display pointer.
206 * \param config Application supplied \c GLXFBConfig.
207 *
208 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
209 * \c __GLcontextModes structure is returned. Otherwise, \c NULL
210 * is returned.
211 */
212 static __GLcontextModes *
213 ValidateGLXFBConfig(Display * dpy, GLXFBConfig config)
214 {
215 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
216 const unsigned num_screens = ScreenCount(dpy);
217 unsigned i;
218 const __GLcontextModes *modes;
219
220
221 if (priv != NULL) {
222 for (i = 0; i < num_screens; i++) {
223 for (modes = priv->screenConfigs[i].configs; modes != NULL;
224 modes = modes->next) {
225 if (modes == (__GLcontextModes *) config) {
226 return (__GLcontextModes *) config;
227 }
228 }
229 }
230 }
231
232 return NULL;
233 }
234
235
236 /**
237 * \todo It should be possible to move the allocate of \c client_state_private
238 * later in the function for direct-rendering contexts. Direct-rendering
239 * contexts don't need to track client state, so they don't need that memory
240 * at all.
241 *
242 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
243 * function called \c __glXAllocateClientState that allocates the memory and
244 * does all the initialization (including the pixel pack / unpack).
245 */
246 static GLXContext
247 AllocateGLXContext(Display * dpy)
248 {
249 GLXContext gc;
250 int bufSize;
251 CARD8 opcode;
252 __GLXattribute *state;
253
254 if (!dpy)
255 return NULL;
256
257 opcode = __glXSetupForCommand(dpy);
258 if (!opcode) {
259 return NULL;
260 }
261
262 /* Allocate our context record */
263 gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
264 if (!gc) {
265 /* Out of memory */
266 return NULL;
267 }
268 memset(gc, 0, sizeof(struct __GLXcontextRec));
269
270 state = Xmalloc(sizeof(struct __GLXattributeRec));
271 if (state == NULL) {
272 /* Out of memory */
273 Xfree(gc);
274 return NULL;
275 }
276 gc->client_state_private = state;
277 memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
278 state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
279
280 /*
281 ** Create a temporary buffer to hold GLX rendering commands. The size
282 ** of the buffer is selected so that the maximum number of GLX rendering
283 ** commands can fit in a single X packet and still have room in the X
284 ** packet for the GLXRenderReq header.
285 */
286
287 bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
288 gc->buf = (GLubyte *) Xmalloc(bufSize);
289 if (!gc->buf) {
290 Xfree(gc->client_state_private);
291 Xfree(gc);
292 return NULL;
293 }
294 gc->bufSize = bufSize;
295
296 /* Fill in the new context */
297 gc->renderMode = GL_RENDER;
298
299 state->storePack.alignment = 4;
300 state->storeUnpack.alignment = 4;
301
302 gc->attributes.stackPointer = &gc->attributes.stack[0];
303
304 /*
305 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
306 ** Other code uses the fastImageUnpack bit, but it is never set
307 ** to GL_TRUE.
308 */
309 gc->fastImageUnpack = GL_FALSE;
310 gc->fillImage = __glFillImage;
311 gc->pc = gc->buf;
312 gc->bufEnd = gc->buf + bufSize;
313 gc->isDirect = GL_FALSE;
314 if (__glXDebug) {
315 /*
316 ** Set limit register so that there will be one command per packet
317 */
318 gc->limit = gc->buf;
319 }
320 else {
321 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
322 }
323 gc->createDpy = dpy;
324 gc->majorOpcode = opcode;
325
326 /*
327 ** Constrain the maximum drawing command size allowed to be
328 ** transfered using the X_GLXRender protocol request. First
329 ** constrain by a software limit, then constrain by the protocl
330 ** limit.
331 */
332 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
333 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
334 }
335 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
336 bufSize = __GLX_MAX_RENDER_CMD_SIZE;
337 }
338 gc->maxSmallRenderCommandSize = bufSize;
339 return gc;
340 }
341
342
343 /**
344 * Create a new context. Exactly one of \c vis and \c fbconfig should be
345 * non-NULL.
346 *
347 * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or
348 * SGIX_fbconfig protocol be used?
349 * \param renderType For FBConfigs, what is the rendering type?
350 */
351
352 static GLXContext
353 CreateContext(Display * dpy, XVisualInfo * vis,
354 const __GLcontextModes * const fbconfig,
355 GLXContext shareList,
356 Bool allowDirect, GLXContextID contextID,
357 Bool use_glx_1_3, int renderType)
358 {
359 GLXContext gc;
360 #ifdef GLX_DIRECT_RENDERING
361 int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
362 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
363 #endif
364
365 if (dpy == NULL)
366 return NULL;
367
368 gc = AllocateGLXContext(dpy);
369 if (!gc)
370 return NULL;
371
372 if (None == contextID) {
373 if ((vis == NULL) && (fbconfig == NULL))
374 return NULL;
375
376 #ifdef GLX_DIRECT_RENDERING
377 if (allowDirect && psc->driScreen) {
378 const __GLcontextModes *mode;
379
380 if (fbconfig == NULL) {
381 mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
382 if (mode == NULL) {
383 xError error;
384
385 error.errorCode = BadValue;
386 error.resourceID = vis->visualid;
387 error.sequenceNumber = dpy->request;
388 error.type = X_Error;
389 error.majorCode = gc->majorOpcode;
390 error.minorCode = X_GLXCreateContext;
391 _XError(dpy, &error);
392 return None;
393 }
394 }
395 else {
396 mode = fbconfig;
397 }
398
399 gc->driContext = psc->driScreen->createContext(psc, mode, gc,
400 shareList,
401 renderType);
402 if (gc->driContext != NULL) {
403 gc->screen = mode->screen;
404 gc->psc = psc;
405 gc->mode = mode;
406 gc->isDirect = GL_TRUE;
407 }
408 }
409 #endif
410
411 LockDisplay(dpy);
412 if (fbconfig == NULL) {
413 xGLXCreateContextReq *req;
414
415 /* Send the glXCreateContext request */
416 GetReq(GLXCreateContext, req);
417 req->reqType = gc->majorOpcode;
418 req->glxCode = X_GLXCreateContext;
419 req->context = gc->xid = XAllocID(dpy);
420 req->visual = vis->visualid;
421 req->screen = vis->screen;
422 req->shareList = shareList ? shareList->xid : None;
423 #ifdef GLX_DIRECT_RENDERING
424 req->isDirect = gc->driContext != NULL;
425 #else
426 req->isDirect = 0;
427 #endif
428 }
429 else if (use_glx_1_3) {
430 xGLXCreateNewContextReq *req;
431
432 /* Send the glXCreateNewContext request */
433 GetReq(GLXCreateNewContext, req);
434 req->reqType = gc->majorOpcode;
435 req->glxCode = X_GLXCreateNewContext;
436 req->context = gc->xid = XAllocID(dpy);
437 req->fbconfig = fbconfig->fbconfigID;
438 req->screen = fbconfig->screen;
439 req->renderType = renderType;
440 req->shareList = shareList ? shareList->xid : None;
441 #ifdef GLX_DIRECT_RENDERING
442 req->isDirect = gc->driContext != NULL;
443 #else
444 req->isDirect = 0;
445 #endif
446 }
447 else {
448 xGLXVendorPrivateWithReplyReq *vpreq;
449 xGLXCreateContextWithConfigSGIXReq *req;
450
451 /* Send the glXCreateNewContext request */
452 GetReqExtra(GLXVendorPrivateWithReply,
453 sz_xGLXCreateContextWithConfigSGIXReq -
454 sz_xGLXVendorPrivateWithReplyReq, vpreq);
455 req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
456 req->reqType = gc->majorOpcode;
457 req->glxCode = X_GLXVendorPrivateWithReply;
458 req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
459 req->context = gc->xid = XAllocID(dpy);
460 req->fbconfig = fbconfig->fbconfigID;
461 req->screen = fbconfig->screen;
462 req->renderType = renderType;
463 req->shareList = shareList ? shareList->xid : None;
464 #ifdef GLX_DIRECT_RENDERING
465 req->isDirect = gc->driContext != NULL;
466 #else
467 req->isDirect = 0;
468 #endif
469 }
470
471 UnlockDisplay(dpy);
472 SyncHandle();
473 gc->imported = GL_FALSE;
474 }
475 else {
476 gc->xid = contextID;
477 gc->imported = GL_TRUE;
478 }
479
480 return gc;
481 }
482
483 PUBLIC GLXContext
484 glXCreateContext(Display * dpy, XVisualInfo * vis,
485 GLXContext shareList, Bool allowDirect)
486 {
487 return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
488 False, 0);
489 }
490
491 _X_HIDDEN void
492 __glXFreeContext(__GLXcontext * gc)
493 {
494 if (gc->vendor)
495 XFree((char *) gc->vendor);
496 if (gc->renderer)
497 XFree((char *) gc->renderer);
498 if (gc->version)
499 XFree((char *) gc->version);
500 if (gc->extensions)
501 XFree((char *) gc->extensions);
502 __glFreeAttributeState(gc);
503 XFree((char *) gc->buf);
504 Xfree((char *) gc->client_state_private);
505 XFree((char *) gc);
506
507 }
508
509 /*
510 ** Destroy the named context
511 */
512 static void
513 DestroyContext(Display * dpy, GLXContext gc)
514 {
515 xGLXDestroyContextReq *req;
516 GLXContextID xid;
517 CARD8 opcode;
518 GLboolean imported;
519
520 opcode = __glXSetupForCommand(dpy);
521 if (!opcode || !gc) {
522 return;
523 }
524
525 __glXLock();
526 xid = gc->xid;
527 imported = gc->imported;
528 gc->xid = None;
529
530 #ifdef GLX_DIRECT_RENDERING
531 /* Destroy the direct rendering context */
532 if (gc->driContext) {
533 (*gc->driContext->destroyContext) (gc->driContext, gc->psc, dpy);
534 gc->driContext = NULL;
535 GarbageCollectDRIDrawables(dpy, gc->psc);
536 }
537 #endif
538
539 __glXFreeVertexArrayState(gc);
540
541 if (gc->currentDpy) {
542 /* Have to free later cuz it's in use now */
543 __glXUnlock();
544 }
545 else {
546 /* Destroy the handle if not current to anybody */
547 __glXUnlock();
548 __glXFreeContext(gc);
549 }
550
551 if (!imported) {
552 /*
553 ** This dpy also created the server side part of the context.
554 ** Send the glXDestroyContext request.
555 */
556 LockDisplay(dpy);
557 GetReq(GLXDestroyContext, req);
558 req->reqType = opcode;
559 req->glxCode = X_GLXDestroyContext;
560 req->context = xid;
561 UnlockDisplay(dpy);
562 SyncHandle();
563 }
564 }
565
566 PUBLIC void
567 glXDestroyContext(Display * dpy, GLXContext gc)
568 {
569 DestroyContext(dpy, gc);
570 }
571
572 /*
573 ** Return the major and minor version #s for the GLX extension
574 */
575 PUBLIC Bool
576 glXQueryVersion(Display * dpy, int *major, int *minor)
577 {
578 __GLXdisplayPrivate *priv;
579
580 /* Init the extension. This fetches the major and minor version. */
581 priv = __glXInitialize(dpy);
582 if (!priv)
583 return GL_FALSE;
584
585 if (major)
586 *major = priv->majorVersion;
587 if (minor)
588 *minor = priv->minorVersion;
589 return GL_TRUE;
590 }
591
592 /*
593 ** Query the existance of the GLX extension
594 */
595 PUBLIC Bool
596 glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
597 {
598 int major_op, erb, evb;
599 Bool rv;
600
601 rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
602 if (rv) {
603 if (errorBase)
604 *errorBase = erb;
605 if (eventBase)
606 *eventBase = evb;
607 }
608 return rv;
609 }
610
611 /*
612 ** Put a barrier in the token stream that forces the GL to finish its
613 ** work before X can proceed.
614 */
615 PUBLIC void
616 glXWaitGL(void)
617 {
618 xGLXWaitGLReq *req;
619 GLXContext gc = __glXGetCurrentContext();
620 Display *dpy = gc->currentDpy;
621
622 if (!dpy)
623 return;
624
625 /* Flush any pending commands out */
626 __glXFlushRenderBuffer(gc, gc->pc);
627
628 #ifdef GLX_DIRECT_RENDERING
629 if (gc->driContext) {
630 /* This bit of ugliness unwraps the glFinish function */
631 #ifdef glFinish
632 #undef glFinish
633 #endif
634 glFinish();
635 return;
636 }
637 #endif
638
639 /* Send the glXWaitGL request */
640 LockDisplay(dpy);
641 GetReq(GLXWaitGL, req);
642 req->reqType = gc->majorOpcode;
643 req->glxCode = X_GLXWaitGL;
644 req->contextTag = gc->currentContextTag;
645 UnlockDisplay(dpy);
646 SyncHandle();
647 }
648
649 /*
650 ** Put a barrier in the token stream that forces X to finish its
651 ** work before GL can proceed.
652 */
653 PUBLIC void
654 glXWaitX(void)
655 {
656 xGLXWaitXReq *req;
657 GLXContext gc = __glXGetCurrentContext();
658 Display *dpy = gc->currentDpy;
659
660 if (!dpy)
661 return;
662
663 /* Flush any pending commands out */
664 __glXFlushRenderBuffer(gc, gc->pc);
665
666 #ifdef GLX_DIRECT_RENDERING
667 if (gc->driContext) {
668 XSync(dpy, False);
669 return;
670 }
671 #endif
672
673 /*
674 ** Send the glXWaitX request.
675 */
676 LockDisplay(dpy);
677 GetReq(GLXWaitX, req);
678 req->reqType = gc->majorOpcode;
679 req->glxCode = X_GLXWaitX;
680 req->contextTag = gc->currentContextTag;
681 UnlockDisplay(dpy);
682 SyncHandle();
683 }
684
685 PUBLIC void
686 glXUseXFont(Font font, int first, int count, int listBase)
687 {
688 xGLXUseXFontReq *req;
689 GLXContext gc = __glXGetCurrentContext();
690 Display *dpy = gc->currentDpy;
691
692 if (!dpy)
693 return;
694
695 /* Flush any pending commands out */
696 (void) __glXFlushRenderBuffer(gc, gc->pc);
697
698 #ifdef GLX_DIRECT_RENDERING
699 if (gc->driContext) {
700 DRI_glXUseXFont(font, first, count, listBase);
701 return;
702 }
703 #endif
704
705 /* Send the glXUseFont request */
706 LockDisplay(dpy);
707 GetReq(GLXUseXFont, req);
708 req->reqType = gc->majorOpcode;
709 req->glxCode = X_GLXUseXFont;
710 req->contextTag = gc->currentContextTag;
711 req->font = font;
712 req->first = first;
713 req->count = count;
714 req->listBase = listBase;
715 UnlockDisplay(dpy);
716 SyncHandle();
717 }
718
719 /************************************************************************/
720
721 /*
722 ** Copy the source context to the destination context using the
723 ** attribute "mask".
724 */
725 PUBLIC void
726 glXCopyContext(Display * dpy, GLXContext source,
727 GLXContext dest, unsigned long mask)
728 {
729 xGLXCopyContextReq *req;
730 GLXContext gc = __glXGetCurrentContext();
731 GLXContextTag tag;
732 CARD8 opcode;
733
734 opcode = __glXSetupForCommand(dpy);
735 if (!opcode) {
736 return;
737 }
738
739 #ifdef GLX_DIRECT_RENDERING
740 if (gc->driContext) {
741 /* NOT_DONE: This does not work yet */
742 }
743 #endif
744
745 /*
746 ** If the source is the current context, send its tag so that the context
747 ** can be flushed before the copy.
748 */
749 if (source == gc && dpy == gc->currentDpy) {
750 tag = gc->currentContextTag;
751 }
752 else {
753 tag = 0;
754 }
755
756 /* Send the glXCopyContext request */
757 LockDisplay(dpy);
758 GetReq(GLXCopyContext, req);
759 req->reqType = opcode;
760 req->glxCode = X_GLXCopyContext;
761 req->source = source ? source->xid : None;
762 req->dest = dest ? dest->xid : None;
763 req->mask = mask;
764 req->contextTag = tag;
765 UnlockDisplay(dpy);
766 SyncHandle();
767 }
768
769
770 /**
771 * Determine if a context uses direct rendering.
772 *
773 * \param dpy Display where the context was created.
774 * \param contextID ID of the context to be tested.
775 *
776 * \returns \c GL_TRUE if the context is direct rendering or not.
777 */
778 static Bool
779 __glXIsDirect(Display * dpy, GLXContextID contextID)
780 {
781 xGLXIsDirectReq *req;
782 xGLXIsDirectReply reply;
783 CARD8 opcode;
784
785 opcode = __glXSetupForCommand(dpy);
786 if (!opcode) {
787 return GL_FALSE;
788 }
789
790 /* Send the glXIsDirect request */
791 LockDisplay(dpy);
792 GetReq(GLXIsDirect, req);
793 req->reqType = opcode;
794 req->glxCode = X_GLXIsDirect;
795 req->context = contextID;
796 _XReply(dpy, (xReply *) & reply, 0, False);
797 UnlockDisplay(dpy);
798 SyncHandle();
799
800 return reply.isDirect;
801 }
802
803 /**
804 * \todo
805 * Shouldn't this function \b always return \c GL_FALSE when
806 * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with
807 * the GLX protocol here at all?
808 */
809 PUBLIC Bool
810 glXIsDirect(Display * dpy, GLXContext gc)
811 {
812 if (!gc) {
813 return GL_FALSE;
814 #ifdef GLX_DIRECT_RENDERING
815 }
816 else if (gc->driContext) {
817 return GL_TRUE;
818 #endif
819 }
820 return __glXIsDirect(dpy, gc->xid);
821 }
822
823 PUBLIC GLXPixmap
824 glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
825 {
826 xGLXCreateGLXPixmapReq *req;
827 GLXPixmap xid;
828 CARD8 opcode;
829
830 opcode = __glXSetupForCommand(dpy);
831 if (!opcode) {
832 return None;
833 }
834
835 /* Send the glXCreateGLXPixmap request */
836 LockDisplay(dpy);
837 GetReq(GLXCreateGLXPixmap, req);
838 req->reqType = opcode;
839 req->glxCode = X_GLXCreateGLXPixmap;
840 req->screen = vis->screen;
841 req->visual = vis->visualid;
842 req->pixmap = pixmap;
843 req->glxpixmap = xid = XAllocID(dpy);
844 UnlockDisplay(dpy);
845 SyncHandle();
846 return xid;
847 }
848
849 /*
850 ** Destroy the named pixmap
851 */
852 PUBLIC void
853 glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
854 {
855 xGLXDestroyGLXPixmapReq *req;
856 CARD8 opcode;
857
858 opcode = __glXSetupForCommand(dpy);
859 if (!opcode) {
860 return;
861 }
862
863 /* Send the glXDestroyGLXPixmap request */
864 LockDisplay(dpy);
865 GetReq(GLXDestroyGLXPixmap, req);
866 req->reqType = opcode;
867 req->glxCode = X_GLXDestroyGLXPixmap;
868 req->glxpixmap = glxpixmap;
869 UnlockDisplay(dpy);
870 SyncHandle();
871 }
872
873 PUBLIC void
874 glXSwapBuffers(Display * dpy, GLXDrawable drawable)
875 {
876 xGLXSwapBuffersReq *req;
877 GLXContext gc;
878 GLXContextTag tag;
879 CARD8 opcode;
880 #ifdef GLX_DIRECT_RENDERING
881 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
882
883 if (pdraw != NULL) {
884 glFlush();
885 (*pdraw->psc->driScreen->swapBuffers) (pdraw);
886 return;
887 }
888 #endif
889
890 opcode = __glXSetupForCommand(dpy);
891 if (!opcode) {
892 return;
893 }
894
895 /*
896 ** The calling thread may or may not have a current context. If it
897 ** does, send the context tag so the server can do a flush.
898 */
899 gc = __glXGetCurrentContext();
900 if ((gc != NULL) && (dpy == gc->currentDpy) &&
901 ((drawable == gc->currentDrawable)
902 || (drawable == gc->currentReadable))) {
903 tag = gc->currentContextTag;
904 }
905 else {
906 tag = 0;
907 }
908
909 /* Send the glXSwapBuffers request */
910 LockDisplay(dpy);
911 GetReq(GLXSwapBuffers, req);
912 req->reqType = opcode;
913 req->glxCode = X_GLXSwapBuffers;
914 req->drawable = drawable;
915 req->contextTag = tag;
916 UnlockDisplay(dpy);
917 SyncHandle();
918 XFlush(dpy);
919 }
920
921
922 /*
923 ** Return configuration information for the given display, screen and
924 ** visual combination.
925 */
926 PUBLIC int
927 glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
928 int *value_return)
929 {
930 __GLXdisplayPrivate *priv;
931 __GLXscreenConfigs *psc;
932 __GLcontextModes *modes;
933 int status;
934
935 status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
936 if (status == Success) {
937 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
938
939 /* Lookup attribute after first finding a match on the visual */
940 if (modes != NULL) {
941 return _gl_get_context_mode_data(modes, attribute, value_return);
942 }
943
944 status = GLX_BAD_VISUAL;
945 }
946
947 /*
948 ** If we can't find the config for this visual, this visual is not
949 ** supported by the OpenGL implementation on the server.
950 */
951 if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
952 *value_return = GL_FALSE;
953 status = Success;
954 }
955
956 return status;
957 }
958
959 /************************************************************************/
960
961 static void
962 init_fbconfig_for_chooser(__GLcontextModes * config,
963 GLboolean fbconfig_style_tags)
964 {
965 memset(config, 0, sizeof(__GLcontextModes));
966 config->visualID = (XID) GLX_DONT_CARE;
967 config->visualType = GLX_DONT_CARE;
968
969 /* glXChooseFBConfig specifies different defaults for these two than
970 * glXChooseVisual.
971 */
972 if (fbconfig_style_tags) {
973 config->rgbMode = GL_TRUE;
974 config->doubleBufferMode = GLX_DONT_CARE;
975 }
976
977 config->visualRating = GLX_DONT_CARE;
978 config->transparentPixel = GLX_NONE;
979 config->transparentRed = GLX_DONT_CARE;
980 config->transparentGreen = GLX_DONT_CARE;
981 config->transparentBlue = GLX_DONT_CARE;
982 config->transparentAlpha = GLX_DONT_CARE;
983 config->transparentIndex = GLX_DONT_CARE;
984
985 config->drawableType = GLX_WINDOW_BIT;
986 config->renderType =
987 (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
988 config->xRenderable = GLX_DONT_CARE;
989 config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
990
991 config->swapMethod = GLX_DONT_CARE;
992 }
993
994 #define MATCH_DONT_CARE( param ) \
995 do { \
996 if ( (a-> param != GLX_DONT_CARE) \
997 && (a-> param != b-> param) ) { \
998 return False; \
999 } \
1000 } while ( 0 )
1001
1002 #define MATCH_MINIMUM( param ) \
1003 do { \
1004 if ( (a-> param != GLX_DONT_CARE) \
1005 && (a-> param > b-> param) ) { \
1006 return False; \
1007 } \
1008 } while ( 0 )
1009
1010 #define MATCH_EXACT( param ) \
1011 do { \
1012 if ( a-> param != b-> param) { \
1013 return False; \
1014 } \
1015 } while ( 0 )
1016
1017 /**
1018 * Determine if two GLXFBConfigs are compatible.
1019 *
1020 * \param a Application specified config to test.
1021 * \param b Server specified config to test against \c a.
1022 */
1023 static Bool
1024 fbconfigs_compatible(const __GLcontextModes * const a,
1025 const __GLcontextModes * const b)
1026 {
1027 MATCH_DONT_CARE(doubleBufferMode);
1028 MATCH_DONT_CARE(visualType);
1029 MATCH_DONT_CARE(visualRating);
1030 MATCH_DONT_CARE(xRenderable);
1031 MATCH_DONT_CARE(fbconfigID);
1032 MATCH_DONT_CARE(swapMethod);
1033
1034 MATCH_MINIMUM(rgbBits);
1035 MATCH_MINIMUM(numAuxBuffers);
1036 MATCH_MINIMUM(redBits);
1037 MATCH_MINIMUM(greenBits);
1038 MATCH_MINIMUM(blueBits);
1039 MATCH_MINIMUM(alphaBits);
1040 MATCH_MINIMUM(depthBits);
1041 MATCH_MINIMUM(stencilBits);
1042 MATCH_MINIMUM(accumRedBits);
1043 MATCH_MINIMUM(accumGreenBits);
1044 MATCH_MINIMUM(accumBlueBits);
1045 MATCH_MINIMUM(accumAlphaBits);
1046 MATCH_MINIMUM(sampleBuffers);
1047 MATCH_MINIMUM(maxPbufferWidth);
1048 MATCH_MINIMUM(maxPbufferHeight);
1049 MATCH_MINIMUM(maxPbufferPixels);
1050 MATCH_MINIMUM(samples);
1051
1052 MATCH_DONT_CARE(stereoMode);
1053 MATCH_EXACT(level);
1054
1055 if (((a->drawableType & b->drawableType) == 0)
1056 || ((a->renderType & b->renderType) == 0)) {
1057 return False;
1058 }
1059
1060
1061 /* There is a bug in a few of the XFree86 DDX drivers. They contain
1062 * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1063 * Technically speaking, it is a bug in the DDX driver, but there is
1064 * enough of an installed base to work around the problem here. In any
1065 * case, 0 is not a valid value of the transparent type, so we'll treat 0
1066 * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1067 * 0 from the server to be a match to maintain backward compatibility with
1068 * the (broken) drivers.
1069 */
1070
1071 if (a->transparentPixel != GLX_DONT_CARE && a->transparentPixel != 0) {
1072 if (a->transparentPixel == GLX_NONE) {
1073 if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
1074 return False;
1075 }
1076 else {
1077 MATCH_EXACT(transparentPixel);
1078 }
1079
1080 switch (a->transparentPixel) {
1081 case GLX_TRANSPARENT_RGB:
1082 MATCH_DONT_CARE(transparentRed);
1083 MATCH_DONT_CARE(transparentGreen);
1084 MATCH_DONT_CARE(transparentBlue);
1085 MATCH_DONT_CARE(transparentAlpha);
1086 break;
1087
1088 case GLX_TRANSPARENT_INDEX:
1089 MATCH_DONT_CARE(transparentIndex);
1090 break;
1091
1092 default:
1093 break;
1094 }
1095 }
1096
1097 return True;
1098 }
1099
1100
1101 /* There's some trickly language in the GLX spec about how this is supposed
1102 * to work. Basically, if a given component size is either not specified
1103 * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1104 * Well, that's really hard to do with the code as-is. This behavior is
1105 * closer to correct, but still not technically right.
1106 */
1107 #define PREFER_LARGER_OR_ZERO(comp) \
1108 do { \
1109 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1110 if ( ((*a)-> comp) == 0 ) { \
1111 return -1; \
1112 } \
1113 else if ( ((*b)-> comp) == 0 ) { \
1114 return 1; \
1115 } \
1116 else { \
1117 return ((*b)-> comp) - ((*a)-> comp) ; \
1118 } \
1119 } \
1120 } while( 0 )
1121
1122 #define PREFER_LARGER(comp) \
1123 do { \
1124 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1125 return ((*b)-> comp) - ((*a)-> comp) ; \
1126 } \
1127 } while( 0 )
1128
1129 #define PREFER_SMALLER(comp) \
1130 do { \
1131 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1132 return ((*a)-> comp) - ((*b)-> comp) ; \
1133 } \
1134 } while( 0 )
1135
1136 /**
1137 * Compare two GLXFBConfigs. This function is intended to be used as the
1138 * compare function passed in to qsort.
1139 *
1140 * \returns If \c a is a "better" config, according to the specification of
1141 * SGIX_fbconfig, a number less than zero is returned. If \c b is
1142 * better, then a number greater than zero is return. If both are
1143 * equal, zero is returned.
1144 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1145 */
1146 static int
1147 fbconfig_compare(const __GLcontextModes * const *const a,
1148 const __GLcontextModes * const *const b)
1149 {
1150 /* The order of these comparisons must NOT change. It is defined by
1151 * the GLX 1.3 spec and ARB_multisample.
1152 */
1153
1154 PREFER_SMALLER(visualSelectGroup);
1155
1156 /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1157 * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
1158 * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1159 */
1160 PREFER_SMALLER(visualRating);
1161
1162 /* This isn't quite right. It is supposed to compare the sum of the
1163 * components the user specifically set minimums for.
1164 */
1165 PREFER_LARGER_OR_ZERO(redBits);
1166 PREFER_LARGER_OR_ZERO(greenBits);
1167 PREFER_LARGER_OR_ZERO(blueBits);
1168 PREFER_LARGER_OR_ZERO(alphaBits);
1169
1170 PREFER_SMALLER(rgbBits);
1171
1172 if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
1173 /* Prefer single-buffer.
1174 */
1175 return (!(*a)->doubleBufferMode) ? -1 : 1;
1176 }
1177
1178 PREFER_SMALLER(numAuxBuffers);
1179
1180 PREFER_LARGER_OR_ZERO(depthBits);
1181 PREFER_SMALLER(stencilBits);
1182
1183 /* This isn't quite right. It is supposed to compare the sum of the
1184 * components the user specifically set minimums for.
1185 */
1186 PREFER_LARGER_OR_ZERO(accumRedBits);
1187 PREFER_LARGER_OR_ZERO(accumGreenBits);
1188 PREFER_LARGER_OR_ZERO(accumBlueBits);
1189 PREFER_LARGER_OR_ZERO(accumAlphaBits);
1190
1191 PREFER_SMALLER(visualType);
1192
1193 /* None of the multisample specs say where this comparison should happen,
1194 * so I put it near the end.
1195 */
1196 PREFER_SMALLER(sampleBuffers);
1197 PREFER_SMALLER(samples);
1198
1199 /* None of the pbuffer or fbconfig specs say that this comparison needs
1200 * to happen at all, but it seems like it should.
1201 */
1202 PREFER_LARGER(maxPbufferWidth);
1203 PREFER_LARGER(maxPbufferHeight);
1204 PREFER_LARGER(maxPbufferPixels);
1205
1206 return 0;
1207 }
1208
1209
1210 /**
1211 * Selects and sorts a subset of the supplied configs based on the attributes.
1212 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1213 * and \c glXChooseFBConfigSGIX.
1214 *
1215 * \param configs Array of pointers to possible configs. The elements of
1216 * this array that do not meet the criteria will be set to
1217 * NULL. The remaining elements will be sorted according to
1218 * the various visual / FBConfig selection rules.
1219 * \param num_configs Number of elements in the \c configs array.
1220 * \param attribList Attributes used select from \c configs. This array is
1221 * terminated by a \c None tag. The array can either take
1222 * the form expected by \c glXChooseVisual (where boolean
1223 * tags do not have a value) or by \c glXChooseFBConfig
1224 * (where every tag has a value).
1225 * \param fbconfig_style_tags Selects whether \c attribList is in
1226 * \c glXChooseVisual style or
1227 * \c glXChooseFBConfig style.
1228 * \returns The number of valid elements left in \c configs.
1229 *
1230 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1231 */
1232 static int
1233 choose_visual(__GLcontextModes ** configs, int num_configs,
1234 const int *attribList, GLboolean fbconfig_style_tags)
1235 {
1236 __GLcontextModes test_config;
1237 int base;
1238 int i;
1239
1240 /* This is a fairly direct implementation of the selection method
1241 * described by GLX_SGIX_fbconfig. Start by culling out all the
1242 * configs that are not compatible with the selected parameter
1243 * list.
1244 */
1245
1246 init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
1247 __glXInitializeVisualConfigFromTags(&test_config, 512,
1248 (const INT32 *) attribList,
1249 GL_TRUE, fbconfig_style_tags);
1250
1251 base = 0;
1252 for (i = 0; i < num_configs; i++) {
1253 if (fbconfigs_compatible(&test_config, configs[i])) {
1254 configs[base] = configs[i];
1255 base++;
1256 }
1257 }
1258
1259 if (base == 0) {
1260 return 0;
1261 }
1262
1263 if (base < num_configs) {
1264 (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
1265 }
1266
1267 /* After the incompatible configs are removed, the resulting
1268 * list is sorted according to the rules set out in the various
1269 * specifications.
1270 */
1271
1272 qsort(configs, base, sizeof(__GLcontextModes *),
1273 (int (*)(const void *, const void *)) fbconfig_compare);
1274 return base;
1275 }
1276
1277
1278
1279
1280 /*
1281 ** Return the visual that best matches the template. Return None if no
1282 ** visual matches the template.
1283 */
1284 PUBLIC XVisualInfo *
1285 glXChooseVisual(Display * dpy, int screen, int *attribList)
1286 {
1287 XVisualInfo *visualList = NULL;
1288 __GLXdisplayPrivate *priv;
1289 __GLXscreenConfigs *psc;
1290 __GLcontextModes test_config;
1291 __GLcontextModes *modes;
1292 const __GLcontextModes *best_config = NULL;
1293
1294 /*
1295 ** Get a list of all visuals, return if list is empty
1296 */
1297 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1298 return None;
1299 }
1300
1301
1302 /*
1303 ** Build a template from the defaults and the attribute list
1304 ** Free visual list and return if an unexpected token is encountered
1305 */
1306 init_fbconfig_for_chooser(&test_config, GL_FALSE);
1307 __glXInitializeVisualConfigFromTags(&test_config, 512,
1308 (const INT32 *) attribList,
1309 GL_TRUE, GL_FALSE);
1310
1311 /*
1312 ** Eliminate visuals that don't meet minimum requirements
1313 ** Compute a score for those that do
1314 ** Remember which visual, if any, got the highest score
1315 */
1316 for (modes = psc->visuals; modes != NULL; modes = modes->next) {
1317 if (fbconfigs_compatible(&test_config, modes)
1318 && ((best_config == NULL)
1319 ||
1320 (fbconfig_compare
1321 ((const __GLcontextModes * const *const) &modes,
1322 &best_config) < 0))) {
1323 best_config = modes;
1324 }
1325 }
1326
1327 /*
1328 ** If no visual is acceptable, return None
1329 ** Otherwise, create an XVisualInfo list with just the selected X visual
1330 ** and return this.
1331 */
1332 if (best_config != NULL) {
1333 XVisualInfo visualTemplate;
1334 int i;
1335
1336 visualTemplate.screen = screen;
1337 visualTemplate.visualid = best_config->visualID;
1338 visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
1339 &visualTemplate, &i);
1340 }
1341
1342 return visualList;
1343 }
1344
1345
1346 PUBLIC const char *
1347 glXQueryExtensionsString(Display * dpy, int screen)
1348 {
1349 __GLXscreenConfigs *psc;
1350 __GLXdisplayPrivate *priv;
1351
1352 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1353 return NULL;
1354 }
1355
1356 if (!psc->effectiveGLXexts) {
1357 if (!psc->serverGLXexts) {
1358 psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode,
1359 X_GLXQueryServerString,
1360 screen,
1361 GLX_EXTENSIONS);
1362 }
1363
1364 __glXCalculateUsableExtensions(psc,
1365 #ifdef GLX_DIRECT_RENDERING
1366 (psc->driScreen != NULL),
1367 #else
1368 GL_FALSE,
1369 #endif
1370 priv->minorVersion);
1371 }
1372
1373 return psc->effectiveGLXexts;
1374 }
1375
1376 PUBLIC const char *
1377 glXGetClientString(Display * dpy, int name)
1378 {
1379 switch (name) {
1380 case GLX_VENDOR:
1381 return (__glXGLXClientVendorName);
1382 case GLX_VERSION:
1383 return (__glXGLXClientVersion);
1384 case GLX_EXTENSIONS:
1385 return (__glXGetClientExtensions());
1386 default:
1387 return NULL;
1388 }
1389 }
1390
1391 PUBLIC const char *
1392 glXQueryServerString(Display * dpy, int screen, int name)
1393 {
1394 __GLXscreenConfigs *psc;
1395 __GLXdisplayPrivate *priv;
1396 const char **str;
1397
1398
1399 if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1400 return NULL;
1401 }
1402
1403 switch (name) {
1404 case GLX_VENDOR:
1405 str = &priv->serverGLXvendor;
1406 break;
1407 case GLX_VERSION:
1408 str = &priv->serverGLXversion;
1409 break;
1410 case GLX_EXTENSIONS:
1411 str = &psc->serverGLXexts;
1412 break;
1413 default:
1414 return NULL;
1415 }
1416
1417 if (*str == NULL) {
1418 *str = __glXGetStringFromServer(dpy, priv->majorOpcode,
1419 X_GLXQueryServerString, screen, name);
1420 }
1421
1422 return *str;
1423 }
1424
1425 void
1426 __glXClientInfo(Display * dpy, int opcode)
1427 {
1428 xGLXClientInfoReq *req;
1429 int size;
1430 char *ext_str = __glXGetClientGLExtensionString();
1431
1432 /* Send the glXClientInfo request */
1433 LockDisplay(dpy);
1434 GetReq(GLXClientInfo, req);
1435 req->reqType = opcode;
1436 req->glxCode = X_GLXClientInfo;
1437 req->major = GLX_MAJOR_VERSION;
1438 req->minor = GLX_MINOR_VERSION;
1439
1440 size = strlen(ext_str) + 1;
1441 req->length += (size + 3) >> 2;
1442 req->numbytes = size;
1443 Data(dpy, ext_str, size);
1444
1445 UnlockDisplay(dpy);
1446 SyncHandle();
1447
1448 Xfree(ext_str);
1449 }
1450
1451
1452 /*
1453 ** EXT_import_context
1454 */
1455
1456 PUBLIC Display *
1457 glXGetCurrentDisplay(void)
1458 {
1459 GLXContext gc = __glXGetCurrentContext();
1460 if (NULL == gc)
1461 return NULL;
1462 return gc->currentDpy;
1463 }
1464
1465 PUBLIC
1466 GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1467 glXGetCurrentDisplay)
1468
1469 /**
1470 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
1471 * to the X-server.
1472 *
1473 * \param dpy Display where \c ctx was created.
1474 * \param ctx Context to query.
1475 * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid,
1476 * or zero if the request failed due to internal problems (i.e.,
1477 * unable to allocate temporary memory, etc.)
1478 *
1479 * \note
1480 * This function dynamically determines whether to use the EXT_import_context
1481 * version of the protocol or the GLX 1.3 version of the protocol.
1482 */
1483 static int __glXQueryContextInfo(Display * dpy, GLXContext ctx)
1484 {
1485 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1486 xGLXQueryContextReply reply;
1487 CARD8 opcode;
1488 GLuint numValues;
1489 int retval;
1490
1491 if (ctx == NULL) {
1492 return GLX_BAD_CONTEXT;
1493 }
1494 opcode = __glXSetupForCommand(dpy);
1495 if (!opcode) {
1496 return 0;
1497 }
1498
1499 /* Send the glXQueryContextInfoEXT request */
1500 LockDisplay(dpy);
1501
1502 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
1503 xGLXQueryContextReq *req;
1504
1505 GetReq(GLXQueryContext, req);
1506
1507 req->reqType = opcode;
1508 req->glxCode = X_GLXQueryContext;
1509 req->context = (unsigned int) (ctx->xid);
1510 }
1511 else {
1512 xGLXVendorPrivateReq *vpreq;
1513 xGLXQueryContextInfoEXTReq *req;
1514
1515 GetReqExtra(GLXVendorPrivate,
1516 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1517 vpreq);
1518 req = (xGLXQueryContextInfoEXTReq *) vpreq;
1519 req->reqType = opcode;
1520 req->glxCode = X_GLXVendorPrivateWithReply;
1521 req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1522 req->context = (unsigned int) (ctx->xid);
1523 }
1524
1525 _XReply(dpy, (xReply *) & reply, 0, False);
1526
1527 numValues = reply.n;
1528 if (numValues == 0)
1529 retval = Success;
1530 else if (numValues > __GLX_MAX_CONTEXT_PROPS)
1531 retval = 0;
1532 else {
1533 int *propList, *pProp;
1534 int nPropListBytes;
1535 int i;
1536
1537 nPropListBytes = numValues << 3;
1538 propList = (int *) Xmalloc(nPropListBytes);
1539 if (NULL == propList) {
1540 retval = 0;
1541 }
1542 else {
1543 _XRead(dpy, (char *) propList, nPropListBytes);
1544 pProp = propList;
1545 for (i = 0; i < numValues; i++) {
1546 switch (*pProp++) {
1547 case GLX_SHARE_CONTEXT_EXT:
1548 ctx->share_xid = *pProp++;
1549 break;
1550 case GLX_VISUAL_ID_EXT:
1551 ctx->mode =
1552 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
1553 break;
1554 case GLX_SCREEN:
1555 ctx->screen = *pProp++;
1556 break;
1557 case GLX_FBCONFIG_ID:
1558 ctx->mode =
1559 _gl_context_modes_find_fbconfig(ctx->psc->configs,
1560 *pProp++);
1561 break;
1562 case GLX_RENDER_TYPE:
1563 ctx->renderType = *pProp++;
1564 break;
1565 default:
1566 pProp++;
1567 continue;
1568 }
1569 }
1570 Xfree((char *) propList);
1571 retval = Success;
1572 }
1573 }
1574 UnlockDisplay(dpy);
1575 SyncHandle();
1576 return retval;
1577 }
1578
1579 PUBLIC int
1580 glXQueryContext(Display * dpy, GLXContext ctx, int attribute, int *value)
1581 {
1582 int retVal;
1583
1584 /* get the information from the server if we don't have it already */
1585 #ifdef GLX_DIRECT_RENDERING
1586 if (!ctx->driContext && (ctx->mode == NULL)) {
1587 #else
1588 if (ctx->mode == NULL) {
1589 #endif
1590 retVal = __glXQueryContextInfo(dpy, ctx);
1591 if (Success != retVal)
1592 return retVal;
1593 }
1594 switch (attribute) {
1595 case GLX_SHARE_CONTEXT_EXT:
1596 *value = (int) (ctx->share_xid);
1597 break;
1598 case GLX_VISUAL_ID_EXT:
1599 *value = ctx->mode ? ctx->mode->visualID : None;
1600 break;
1601 case GLX_SCREEN:
1602 *value = (int) (ctx->screen);
1603 break;
1604 case GLX_FBCONFIG_ID:
1605 *value = ctx->mode ? ctx->mode->fbconfigID : None;
1606 break;
1607 case GLX_RENDER_TYPE:
1608 *value = (int) (ctx->renderType);
1609 break;
1610 default:
1611 return GLX_BAD_ATTRIBUTE;
1612 }
1613 return Success;
1614 }
1615
1616 PUBLIC
1617 GLX_ALIAS(int, glXQueryContextInfoEXT,
1618 (Display * dpy, GLXContext ctx, int attribute, int *value),
1619 (dpy, ctx, attribute, value), glXQueryContext)
1620
1621 PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
1622 {
1623 return ctx->xid;
1624 }
1625
1626 PUBLIC GLXContext
1627 glXImportContextEXT(Display * dpy, GLXContextID contextID)
1628 {
1629 GLXContext ctx;
1630
1631 if (contextID == None) {
1632 return NULL;
1633 }
1634 if (__glXIsDirect(dpy, contextID)) {
1635 return NULL;
1636 }
1637
1638 ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
1639 if (NULL != ctx) {
1640 if (Success != __glXQueryContextInfo(dpy, ctx)) {
1641 return NULL;
1642 }
1643 }
1644 return ctx;
1645 }
1646
1647 PUBLIC void
1648 glXFreeContextEXT(Display * dpy, GLXContext ctx)
1649 {
1650 DestroyContext(dpy, ctx);
1651 }
1652
1653
1654
1655 /*
1656 * GLX 1.3 functions - these are just stubs for now!
1657 */
1658
1659 PUBLIC GLXFBConfig *
1660 glXChooseFBConfig(Display * dpy, int screen,
1661 const int *attribList, int *nitems)
1662 {
1663 __GLcontextModes **config_list;
1664 int list_size;
1665
1666
1667 config_list = (__GLcontextModes **)
1668 glXGetFBConfigs(dpy, screen, &list_size);
1669
1670 if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1671 list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
1672 if (list_size == 0) {
1673 XFree(config_list);
1674 config_list = NULL;
1675 }
1676 }
1677
1678 *nitems = list_size;
1679 return (GLXFBConfig *) config_list;
1680 }
1681
1682
1683 PUBLIC GLXContext
1684 glXCreateNewContext(Display * dpy, GLXFBConfig config,
1685 int renderType, GLXContext shareList, Bool allowDirect)
1686 {
1687 return CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
1688 allowDirect, None, True, renderType);
1689 }
1690
1691
1692 PUBLIC GLXDrawable
1693 glXGetCurrentReadDrawable(void)
1694 {
1695 GLXContext gc = __glXGetCurrentContext();
1696 return gc->currentReadable;
1697 }
1698
1699
1700 PUBLIC GLXFBConfig *
1701 glXGetFBConfigs(Display * dpy, int screen, int *nelements)
1702 {
1703 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1704 __GLcontextModes **config = NULL;
1705 int i;
1706
1707 *nelements = 0;
1708 if ((priv->screenConfigs != NULL)
1709 && (screen >= 0) && (screen <= ScreenCount(dpy))
1710 && (priv->screenConfigs[screen].configs != NULL)
1711 && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE)) {
1712 unsigned num_configs = 0;
1713 __GLcontextModes *modes;
1714
1715
1716 for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1717 modes = modes->next) {
1718 if (modes->fbconfigID != GLX_DONT_CARE) {
1719 num_configs++;
1720 }
1721 }
1722
1723 config = (__GLcontextModes **) Xmalloc(sizeof(__GLcontextModes *)
1724 * num_configs);
1725 if (config != NULL) {
1726 *nelements = num_configs;
1727 i = 0;
1728 for (modes = priv->screenConfigs[screen].configs; modes != NULL;
1729 modes = modes->next) {
1730 if (modes->fbconfigID != GLX_DONT_CARE) {
1731 config[i] = modes;
1732 i++;
1733 }
1734 }
1735 }
1736 }
1737 return (GLXFBConfig *) config;
1738 }
1739
1740
1741 PUBLIC int
1742 glXGetFBConfigAttrib(Display * dpy, GLXFBConfig config,
1743 int attribute, int *value)
1744 {
1745 __GLcontextModes *const modes = ValidateGLXFBConfig(dpy, config);
1746
1747 return (modes != NULL)
1748 ? _gl_get_context_mode_data(modes, attribute, value)
1749 : GLXBadFBConfig;
1750 }
1751
1752
1753 PUBLIC XVisualInfo *
1754 glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig config)
1755 {
1756 XVisualInfo visualTemplate;
1757 __GLcontextModes *fbconfig = (__GLcontextModes *) config;
1758 int count;
1759
1760 /*
1761 ** Get a list of all visuals, return if list is empty
1762 */
1763 visualTemplate.visualid = fbconfig->visualID;
1764 return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
1765 }
1766
1767
1768 /*
1769 ** GLX_SGI_swap_control
1770 */
1771 static int
1772 __glXSwapIntervalSGI(int interval)
1773 {
1774 xGLXVendorPrivateReq *req;
1775 GLXContext gc = __glXGetCurrentContext();
1776 Display *dpy;
1777 CARD32 *interval_ptr;
1778 CARD8 opcode;
1779
1780 if (gc == NULL) {
1781 return GLX_BAD_CONTEXT;
1782 }
1783
1784 if (interval <= 0) {
1785 return GLX_BAD_VALUE;
1786 }
1787
1788 #ifdef __DRI_SWAP_CONTROL
1789 if (gc->driContext) {
1790 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1791 gc->screen);
1792 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
1793 gc->currentDrawable,
1794 NULL);
1795 if (psc->swapControl != NULL && pdraw != NULL) {
1796 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1797 return 0;
1798 }
1799 else {
1800 return GLX_BAD_CONTEXT;
1801 }
1802 }
1803 #endif
1804 dpy = gc->currentDpy;
1805 opcode = __glXSetupForCommand(dpy);
1806 if (!opcode) {
1807 return 0;
1808 }
1809
1810 /* Send the glXSwapIntervalSGI request */
1811 LockDisplay(dpy);
1812 GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
1813 req->reqType = opcode;
1814 req->glxCode = X_GLXVendorPrivate;
1815 req->vendorCode = X_GLXvop_SwapIntervalSGI;
1816 req->contextTag = gc->currentContextTag;
1817
1818 interval_ptr = (CARD32 *) (req + 1);
1819 *interval_ptr = interval;
1820
1821 UnlockDisplay(dpy);
1822 SyncHandle();
1823 XFlush(dpy);
1824
1825 return 0;
1826 }
1827
1828
1829 /*
1830 ** GLX_MESA_swap_control
1831 */
1832 static int
1833 __glXSwapIntervalMESA(unsigned int interval)
1834 {
1835 #ifdef __DRI_SWAP_CONTROL
1836 GLXContext gc = __glXGetCurrentContext();
1837
1838 if (interval < 0) {
1839 return GLX_BAD_VALUE;
1840 }
1841
1842 if (gc != NULL && gc->driContext) {
1843 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1844 gc->screen);
1845
1846 if ((psc != NULL) && (psc->driScreen != NULL)) {
1847 __GLXDRIdrawable *pdraw =
1848 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1849 if (psc->swapControl != NULL && pdraw != NULL) {
1850 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1851 return 0;
1852 }
1853 }
1854 }
1855 #else
1856 (void) interval;
1857 #endif
1858
1859 return GLX_BAD_CONTEXT;
1860 }
1861
1862
1863 static int
1864 __glXGetSwapIntervalMESA(void)
1865 {
1866 #ifdef __DRI_SWAP_CONTROL
1867 GLXContext gc = __glXGetCurrentContext();
1868
1869 if (gc != NULL && gc->driContext) {
1870 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
1871 gc->screen);
1872
1873 if ((psc != NULL) && (psc->driScreen != NULL)) {
1874 __GLXDRIdrawable *pdraw =
1875 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1876 if (psc->swapControl != NULL && pdraw != NULL) {
1877 return psc->swapControl->getSwapInterval(pdraw->driDrawable);
1878 }
1879 }
1880 }
1881 #endif
1882
1883 return 0;
1884 }
1885
1886
1887 /*
1888 ** GLX_MESA_swap_frame_usage
1889 */
1890
1891 static GLint
1892 __glXBeginFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
1893 {
1894 int status = GLX_BAD_CONTEXT;
1895 #ifdef __DRI_FRAME_TRACKING
1896 int screen;
1897 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1898 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
1899
1900 if (pdraw != NULL && psc->frameTracking != NULL)
1901 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
1902 #else
1903 (void) dpy;
1904 (void) drawable;
1905 #endif
1906 return status;
1907 }
1908
1909
1910 static GLint
1911 __glXEndFrameTrackingMESA(Display * dpy, GLXDrawable drawable)
1912 {
1913 int status = GLX_BAD_CONTEXT;
1914 #ifdef __DRI_FRAME_TRACKING
1915 int screen;
1916 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1917 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
1918
1919 if (pdraw != NULL && psc->frameTracking != NULL)
1920 status = psc->frameTracking->frameTracking(pdraw->driDrawable,
1921 GL_FALSE);
1922 #else
1923 (void) dpy;
1924 (void) drawable;
1925 #endif
1926 return status;
1927 }
1928
1929
1930 static GLint
1931 __glXGetFrameUsageMESA(Display * dpy, GLXDrawable drawable, GLfloat * usage)
1932 {
1933 int status = GLX_BAD_CONTEXT;
1934 #ifdef __DRI_FRAME_TRACKING
1935 int screen;
1936 __GLXDRIdrawable *const pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1937 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
1938
1939 if (pdraw != NULL && psc->frameTracking != NULL) {
1940 int64_t sbc, missedFrames;
1941 float lastMissedUsage;
1942
1943 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
1944 &sbc,
1945 &missedFrames,
1946 &lastMissedUsage,
1947 usage);
1948 }
1949 #else
1950 (void) dpy;
1951 (void) drawable;
1952 (void) usage;
1953 #endif
1954 return status;
1955 }
1956
1957
1958 static GLint
1959 __glXQueryFrameTrackingMESA(Display * dpy, GLXDrawable drawable,
1960 int64_t * sbc, int64_t * missedFrames,
1961 GLfloat * lastMissedUsage)
1962 {
1963 int status = GLX_BAD_CONTEXT;
1964 #ifdef __DRI_FRAME_TRACKING
1965 int screen;
1966 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
1967 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
1968
1969 if (pdraw != NULL && psc->frameTracking != NULL) {
1970 float usage;
1971
1972 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
1973 sbc, missedFrames,
1974 lastMissedUsage,
1975 &usage);
1976 }
1977 #else
1978 (void) dpy;
1979 (void) drawable;
1980 (void) sbc;
1981 (void) missedFrames;
1982 (void) lastMissedUsage;
1983 #endif
1984 return status;
1985 }
1986
1987
1988 /*
1989 ** GLX_SGI_video_sync
1990 */
1991 static int
1992 __glXGetVideoSyncSGI(unsigned int *count)
1993 {
1994 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1995 * FIXME: there should be a GLX encoding for this call. I can find no
1996 * FIXME: documentation for the GLX encoding.
1997 */
1998 #ifdef __DRI_MEDIA_STREAM_COUNTER
1999 GLXContext gc = __glXGetCurrentContext();
2000
2001
2002 if (gc != NULL && gc->driContext) {
2003 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2004 gc->screen);
2005 if (psc->msc && psc->driScreen) {
2006 __GLXDRIdrawable *pdraw =
2007 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2008 int64_t temp;
2009 int ret;
2010
2011 ret = (*psc->msc->getDrawableMSC) (psc->__driScreen,
2012 pdraw->driDrawable, &temp);
2013 *count = (unsigned) temp;
2014
2015 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2016 }
2017 }
2018 #else
2019 (void) count;
2020 #endif
2021 return GLX_BAD_CONTEXT;
2022 }
2023
2024 static int
2025 __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
2026 {
2027 #ifdef __DRI_MEDIA_STREAM_COUNTER
2028 GLXContext gc = __glXGetCurrentContext();
2029
2030 if (divisor <= 0 || remainder < 0)
2031 return GLX_BAD_VALUE;
2032
2033 if (gc != NULL && gc->driContext) {
2034 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(gc->currentDpy,
2035 gc->screen);
2036 if (psc->msc != NULL && psc->driScreen) {
2037 __GLXDRIdrawable *pdraw =
2038 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2039 int ret;
2040 int64_t msc;
2041 int64_t sbc;
2042
2043 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, 0,
2044 divisor, remainder, &msc, &sbc);
2045 *count = (unsigned) msc;
2046 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
2047 }
2048 }
2049 #else
2050 (void) count;
2051 #endif
2052 return GLX_BAD_CONTEXT;
2053 }
2054
2055
2056 /*
2057 ** GLX_SGIX_fbconfig
2058 ** Many of these functions are aliased to GLX 1.3 entry points in the
2059 ** GLX_functions table.
2060 */
2061
2062 PUBLIC
2063 GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
2064 (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
2065 (dpy, config, attribute, value), glXGetFBConfigAttrib)
2066
2067 PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
2068 (Display * dpy, int screen, int *attrib_list,
2069 int *nelements), (dpy, screen, attrib_list, nelements),
2070 glXChooseFBConfig)
2071
2072 PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
2073 (Display * dpy, GLXFBConfigSGIX config),
2074 (dpy, config), glXGetVisualFromFBConfig)
2075
2076 PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
2077 GLXFBConfigSGIX config,
2078 Pixmap pixmap)
2079 {
2080 xGLXVendorPrivateWithReplyReq *vpreq;
2081 xGLXCreateGLXPixmapWithConfigSGIXReq *req;
2082 GLXPixmap xid = None;
2083 CARD8 opcode;
2084 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2085 __GLXscreenConfigs *psc;
2086
2087
2088 if ((dpy == NULL) || (config == NULL)) {
2089 return None;
2090 }
2091
2092 psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2093 if ((psc != NULL)
2094 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2095 opcode = __glXSetupForCommand(dpy);
2096 if (!opcode) {
2097 return None;
2098 }
2099
2100 /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2101 LockDisplay(dpy);
2102 GetReqExtra(GLXVendorPrivateWithReply,
2103 sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
2104 sz_xGLXVendorPrivateWithReplyReq, vpreq);
2105 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
2106 req->reqType = opcode;
2107 req->glxCode = X_GLXVendorPrivateWithReply;
2108 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2109 req->screen = fbconfig->screen;
2110 req->fbconfig = fbconfig->fbconfigID;
2111 req->pixmap = pixmap;
2112 req->glxpixmap = xid = XAllocID(dpy);
2113 UnlockDisplay(dpy);
2114 SyncHandle();
2115 }
2116
2117 return xid;
2118 }
2119
2120 PUBLIC GLXContext
2121 glXCreateContextWithConfigSGIX(Display * dpy,
2122 GLXFBConfigSGIX config, int renderType,
2123 GLXContext shareList, Bool allowDirect)
2124 {
2125 GLXContext gc = NULL;
2126 const __GLcontextModes *const fbconfig = (__GLcontextModes *) config;
2127 __GLXscreenConfigs *psc;
2128
2129
2130 if ((dpy == NULL) || (config == NULL)) {
2131 return None;
2132 }
2133
2134 psc = GetGLXScreenConfigs(dpy, fbconfig->screen);
2135 if ((psc != NULL)
2136 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2137 gc = CreateContext(dpy, NULL, (__GLcontextModes *) config, shareList,
2138 allowDirect, None, False, renderType);
2139 }
2140
2141 return gc;
2142 }
2143
2144
2145 PUBLIC GLXFBConfigSGIX
2146 glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
2147 {
2148 __GLXdisplayPrivate *priv;
2149 __GLXscreenConfigs *psc;
2150
2151 if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
2152 && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2153 && (psc->configs->fbconfigID != GLX_DONT_CARE)) {
2154 return (GLXFBConfigSGIX) _gl_context_modes_find_visual(psc->configs,
2155 vis->visualid);
2156 }
2157
2158 return NULL;
2159 }
2160
2161
2162 /*
2163 ** GLX_SGIX_swap_group
2164 */
2165 static void
2166 __glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
2167 GLXDrawable member)
2168 {
2169 (void) dpy;
2170 (void) drawable;
2171 (void) member;
2172 }
2173
2174
2175 /*
2176 ** GLX_SGIX_swap_barrier
2177 */
2178 static void
2179 __glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
2180 {
2181 (void) dpy;
2182 (void) drawable;
2183 (void) barrier;
2184 }
2185
2186 static Bool
2187 __glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
2188 {
2189 (void) dpy;
2190 (void) screen;
2191 (void) max;
2192 return False;
2193 }
2194
2195
2196 /*
2197 ** GLX_OML_sync_control
2198 */
2199 static Bool
2200 __glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2201 int64_t * ust, int64_t * msc, int64_t * sbc)
2202 {
2203 #if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
2204 __GLXdisplayPrivate *const priv = __glXInitialize(dpy);
2205
2206 if (priv != NULL) {
2207 int i;
2208 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
2209 __GLXscreenConfigs *const psc = &priv->screenConfigs[i];
2210
2211 assert((pdraw == NULL) || (i != -1));
2212 return ((pdraw && psc->sbc && psc->msc)
2213 && ((*psc->msc->getMSC) (psc->driScreen, msc) == 0)
2214 && ((*psc->sbc->getSBC) (pdraw->driDrawable, sbc) == 0)
2215 && (__glXGetUST(ust) == 0));
2216 }
2217 #else
2218 (void) dpy;
2219 (void) drawable;
2220 (void) ust;
2221 (void) msc;
2222 (void) sbc;
2223 #endif
2224 return False;
2225 }
2226
2227 #ifdef GLX_DIRECT_RENDERING
2228 _X_HIDDEN GLboolean
2229 __driGetMscRateOML(__DRIdrawable * draw,
2230 int32_t * numerator, int32_t * denominator, void *private)
2231 {
2232 #ifdef XF86VIDMODE
2233 __GLXscreenConfigs *psc;
2234 XF86VidModeModeLine mode_line;
2235 int dot_clock;
2236 int i;
2237 __GLXDRIdrawable *glxDraw = private;
2238
2239 psc = glxDraw->psc;
2240 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2241 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2242 unsigned n = dot_clock * 1000;
2243 unsigned d = mode_line.vtotal * mode_line.htotal;
2244
2245 # define V_INTERLACE 0x010
2246 # define V_DBLSCAN 0x020
2247
2248 if (mode_line.flags & V_INTERLACE)
2249 n *= 2;
2250 else if (mode_line.flags & V_DBLSCAN)
2251 d *= 2;
2252
2253 /* The OML_sync_control spec requires that if the refresh rate is a
2254 * whole number, that the returned numerator be equal to the refresh
2255 * rate and the denominator be 1.
2256 */
2257
2258 if (n % d == 0) {
2259 n /= d;
2260 d = 1;
2261 }
2262 else {
2263 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2264
2265 /* This is a poor man's way to reduce a fraction. It's far from
2266 * perfect, but it will work well enough for this situation.
2267 */
2268
2269 for (i = 0; f[i] != 0; i++) {
2270 while (n % f[i] == 0 && d % f[i] == 0) {
2271 d /= f[i];
2272 n /= f[i];
2273 }
2274 }
2275 }
2276
2277 *numerator = n;
2278 *denominator = d;
2279
2280 return True;
2281 }
2282 else
2283 return False;
2284 #else
2285 return False;
2286 #endif
2287 }
2288 #endif
2289
2290 /**
2291 * Determine the refresh rate of the specified drawable and display.
2292 *
2293 * \param dpy Display whose refresh rate is to be determined.
2294 * \param drawable Drawable whose refresh rate is to be determined.
2295 * \param numerator Numerator of the refresh rate.
2296 * \param demoninator Denominator of the refresh rate.
2297 * \return If the refresh rate for the specified display and drawable could
2298 * be calculated, True is returned. Otherwise False is returned.
2299 *
2300 * \note This function is implemented entirely client-side. A lot of other
2301 * functionality is required to export GLX_OML_sync_control, so on
2302 * XFree86 this function can be called for direct-rendering contexts
2303 * when GLX_OML_sync_control appears in the client extension string.
2304 */
2305
2306 _X_HIDDEN GLboolean
2307 __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2308 int32_t * numerator, int32_t * denominator)
2309 {
2310 #if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
2311 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
2312
2313 if (draw == NULL)
2314 return False;
2315
2316 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
2317 #else
2318 (void) dpy;
2319 (void) drawable;
2320 (void) numerator;
2321 (void) denominator;
2322 #endif
2323 return False;
2324 }
2325
2326
2327 static int64_t
2328 __glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
2329 int64_t target_msc, int64_t divisor, int64_t remainder)
2330 {
2331 #ifdef __DRI_SWAP_BUFFER_COUNTER
2332 int screen;
2333 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2334 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2335
2336 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2337 * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2338 * of -1 if the function failed because of errors detected in the input
2339 * parameters"
2340 */
2341 if (divisor < 0 || remainder < 0 || target_msc < 0)
2342 return -1;
2343 if (divisor > 0 && remainder >= divisor)
2344 return -1;
2345
2346 if (pdraw != NULL && psc->counters != NULL)
2347 return (*psc->sbc->swapBuffersMSC) (pdraw->driDrawable, target_msc,
2348 divisor, remainder);
2349
2350 #else
2351 (void) dpy;
2352 (void) drawable;
2353 (void) target_msc;
2354 (void) divisor;
2355 (void) remainder;
2356 #endif
2357 return 0;
2358 }
2359
2360
2361 static Bool
2362 __glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2363 int64_t target_msc, int64_t divisor,
2364 int64_t remainder, int64_t * ust,
2365 int64_t * msc, int64_t * sbc)
2366 {
2367 #ifdef __DRI_MEDIA_STREAM_COUNTER
2368 int screen;
2369 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2370 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2371 int ret;
2372
2373 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2374 * error", but the return type in the spec is Bool.
2375 */
2376 if (divisor < 0 || remainder < 0 || target_msc < 0)
2377 return False;
2378 if (divisor > 0 && remainder >= divisor)
2379 return False;
2380
2381 if (pdraw != NULL && psc->msc != NULL) {
2382 ret = (*psc->msc->waitForMSC) (pdraw->driDrawable, target_msc,
2383 divisor, remainder, msc, sbc);
2384
2385 /* __glXGetUST returns zero on success and non-zero on failure.
2386 * This function returns True on success and False on failure.
2387 */
2388 return ((ret == 0) && (__glXGetUST(ust) == 0));
2389 }
2390 #else
2391 (void) dpy;
2392 (void) drawable;
2393 (void) target_msc;
2394 (void) divisor;
2395 (void) remainder;
2396 (void) ust;
2397 (void) msc;
2398 (void) sbc;
2399 #endif
2400 return False;
2401 }
2402
2403
2404 static Bool
2405 __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2406 int64_t target_sbc, int64_t * ust,
2407 int64_t * msc, int64_t * sbc)
2408 {
2409 #ifdef __DRI_SWAP_BUFFER_COUNTER
2410 int screen;
2411 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2412 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2413 int ret;
2414
2415 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2416 * error", but the return type in the spec is Bool.
2417 */
2418 if (target_sbc < 0)
2419 return False;
2420
2421 if (pdraw != NULL && psc->sbc != NULL) {
2422 ret =
2423 (*psc->sbc->waitForSBC) (pdraw->driDrawable, target_sbc, msc, sbc);
2424
2425 /* __glXGetUST returns zero on success and non-zero on failure.
2426 * This function returns True on success and False on failure.
2427 */
2428 return ((ret == 0) && (__glXGetUST(ust) == 0));
2429 }
2430 #else
2431 (void) dpy;
2432 (void) drawable;
2433 (void) target_sbc;
2434 (void) ust;
2435 (void) msc;
2436 (void) sbc;
2437 #endif
2438 return False;
2439 }
2440
2441
2442 /**
2443 * GLX_MESA_allocate_memory
2444 */
2445 /*@{*/
2446
2447 PUBLIC void *
2448 glXAllocateMemoryMESA(Display * dpy, int scrn,
2449 size_t size, float readFreq,
2450 float writeFreq, float priority)
2451 {
2452 #ifdef __DRI_ALLOCATE
2453 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2454
2455 if (psc && psc->allocate)
2456 return (*psc->allocate->allocateMemory) (psc->__driScreen, size,
2457 readFreq, writeFreq, priority);
2458
2459 #else
2460 (void) dpy;
2461 (void) scrn;
2462 (void) size;
2463 (void) readFreq;
2464 (void) writeFreq;
2465 (void) priority;
2466 #endif /* GLX_DIRECT_RENDERING */
2467
2468 return NULL;
2469 }
2470
2471
2472 PUBLIC void
2473 glXFreeMemoryMESA(Display * dpy, int scrn, void *pointer)
2474 {
2475 #ifdef __DRI_ALLOCATE
2476 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2477
2478 if (psc && psc->allocate)
2479 (*psc->allocate->freeMemory) (psc->__driScreen, pointer);
2480
2481 #else
2482 (void) dpy;
2483 (void) scrn;
2484 (void) pointer;
2485 #endif /* GLX_DIRECT_RENDERING */
2486 }
2487
2488
2489 PUBLIC GLuint
2490 glXGetMemoryOffsetMESA(Display * dpy, int scrn, const void *pointer)
2491 {
2492 #ifdef __DRI_ALLOCATE
2493 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, scrn);
2494
2495 if (psc && psc->allocate)
2496 return (*psc->allocate->memoryOffset) (psc->__driScreen, pointer);
2497
2498 #else
2499 (void) dpy;
2500 (void) scrn;
2501 (void) pointer;
2502 #endif /* GLX_DIRECT_RENDERING */
2503
2504 return ~0L;
2505 }
2506
2507 /*@}*/
2508
2509
2510 /**
2511 * Mesa extension stubs. These will help reduce portability problems.
2512 */
2513 /*@{*/
2514
2515 /**
2516 * Release all buffers associated with the specified GLX drawable.
2517 *
2518 * \todo
2519 * This function was intended for stand-alone Mesa. The issue there is that
2520 * the library doesn't get any notification when a window is closed. In
2521 * DRI there is a similar but slightly different issue. When GLX 1.3 is
2522 * supported, there are 3 different functions to destroy a drawable. It
2523 * should be possible to create GLX protocol (or have it determine which
2524 * protocol to use based on the type of the drawable) to have one function
2525 * do the work of 3. For the direct-rendering case, this function could
2526 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2527 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2528 * would need to be used. This really should be done as part of the new DRI
2529 * interface work.
2530 *
2531 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2532 * __driGarbageCollectDrawables
2533 * glXDestroyGLXPixmap
2534 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2535 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2536 */
2537 static Bool
2538 __glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
2539 {
2540 (void) dpy;
2541 (void) d;
2542 return False;
2543 }
2544
2545
2546 PUBLIC GLXPixmap
2547 glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
2548 Pixmap pixmap, Colormap cmap)
2549 {
2550 (void) dpy;
2551 (void) visual;
2552 (void) pixmap;
2553 (void) cmap;
2554 return 0;
2555 }
2556
2557 /*@}*/
2558
2559
2560 /**
2561 * GLX_MESA_copy_sub_buffer
2562 */
2563 #define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
2564 static void
2565 __glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
2566 int x, int y, int width, int height)
2567 {
2568 xGLXVendorPrivateReq *req;
2569 GLXContext gc;
2570 GLXContextTag tag;
2571 CARD32 *drawable_ptr;
2572 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2573 CARD8 opcode;
2574
2575 #ifdef __DRI_COPY_SUB_BUFFER
2576 int screen;
2577 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2578 if (pdraw != NULL) {
2579 __GLXscreenConfigs *const psc = GetGLXScreenConfigs(dpy, screen);
2580 if (psc->copySubBuffer != NULL) {
2581 (*psc->copySubBuffer->copySubBuffer) (pdraw->driDrawable,
2582 x, y, width, height);
2583 }
2584
2585 return;
2586 }
2587 #endif
2588
2589 opcode = __glXSetupForCommand(dpy);
2590 if (!opcode)
2591 return;
2592
2593 /*
2594 ** The calling thread may or may not have a current context. If it
2595 ** does, send the context tag so the server can do a flush.
2596 */
2597 gc = __glXGetCurrentContext();
2598 if ((gc != NULL) && (dpy == gc->currentDpy) &&
2599 ((drawable == gc->currentDrawable) ||
2600 (drawable == gc->currentReadable))) {
2601 tag = gc->currentContextTag;
2602 }
2603 else {
2604 tag = 0;
2605 }
2606
2607 LockDisplay(dpy);
2608 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
2609 req->reqType = opcode;
2610 req->glxCode = X_GLXVendorPrivate;
2611 req->vendorCode = X_GLXvop_CopySubBufferMESA;
2612 req->contextTag = tag;
2613
2614 drawable_ptr = (CARD32 *) (req + 1);
2615 x_ptr = (INT32 *) (drawable_ptr + 1);
2616 y_ptr = (INT32 *) (drawable_ptr + 2);
2617 w_ptr = (INT32 *) (drawable_ptr + 3);
2618 h_ptr = (INT32 *) (drawable_ptr + 4);
2619
2620 *drawable_ptr = drawable;
2621 *x_ptr = x;
2622 *y_ptr = y;
2623 *w_ptr = width;
2624 *h_ptr = height;
2625
2626 UnlockDisplay(dpy);
2627 SyncHandle();
2628 }
2629
2630
2631 /**
2632 * GLX_EXT_texture_from_pixmap
2633 */
2634 /*@{*/
2635 static void
2636 __glXBindTexImageEXT(Display * dpy,
2637 GLXDrawable drawable, int buffer, const int *attrib_list)
2638 {
2639 xGLXVendorPrivateReq *req;
2640 GLXContext gc = __glXGetCurrentContext();
2641 CARD32 *drawable_ptr;
2642 INT32 *buffer_ptr;
2643 CARD32 *num_attrib_ptr;
2644 CARD32 *attrib_ptr;
2645 CARD8 opcode;
2646 unsigned int i;
2647
2648 if (gc == NULL)
2649 return;
2650
2651 i = 0;
2652 if (attrib_list) {
2653 while (attrib_list[i * 2] != None)
2654 i++;
2655 }
2656
2657 #ifdef GLX_DIRECT_RENDERING
2658 if (gc->driContext) {
2659 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
2660
2661 if (pdraw != NULL)
2662 (*pdraw->psc->texBuffer->setTexBuffer) (gc->__driContext,
2663 pdraw->textureTarget,
2664 pdraw->driDrawable);
2665
2666 return;
2667 }
2668 #endif
2669
2670 opcode = __glXSetupForCommand(dpy);
2671 if (!opcode)
2672 return;
2673
2674 LockDisplay(dpy);
2675 GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
2676 req->reqType = opcode;
2677 req->glxCode = X_GLXVendorPrivate;
2678 req->vendorCode = X_GLXvop_BindTexImageEXT;
2679 req->contextTag = gc->currentContextTag;
2680
2681 drawable_ptr = (CARD32 *) (req + 1);
2682 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2683 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2684 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
2685
2686 *drawable_ptr = drawable;
2687 *buffer_ptr = buffer;
2688 *num_attrib_ptr = (CARD32) i;
2689
2690 i = 0;
2691 if (attrib_list) {
2692 while (attrib_list[i * 2] != None) {
2693 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2694 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2695 i++;
2696 }
2697 }
2698
2699 UnlockDisplay(dpy);
2700 SyncHandle();
2701 }
2702
2703 static void
2704 __glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
2705 {
2706 xGLXVendorPrivateReq *req;
2707 GLXContext gc = __glXGetCurrentContext();
2708 CARD32 *drawable_ptr;
2709 INT32 *buffer_ptr;
2710 CARD8 opcode;
2711
2712 if (gc == NULL)
2713 return;
2714
2715 #ifdef GLX_DIRECT_RENDERING
2716 if (gc->driContext)
2717 return;
2718 #endif
2719
2720 opcode = __glXSetupForCommand(dpy);
2721 if (!opcode)
2722 return;
2723
2724 LockDisplay(dpy);
2725 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
2726 req->reqType = opcode;
2727 req->glxCode = X_GLXVendorPrivate;
2728 req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
2729 req->contextTag = gc->currentContextTag;
2730
2731 drawable_ptr = (CARD32 *) (req + 1);
2732 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2733
2734 *drawable_ptr = drawable;
2735 *buffer_ptr = buffer;
2736
2737 UnlockDisplay(dpy);
2738 SyncHandle();
2739 }
2740
2741 /*@}*/
2742
2743 /**
2744 * \c strdup is actually not a standard ANSI C or POSIX routine.
2745 * Irix will not define it if ANSI mode is in effect.
2746 *
2747 * \sa strdup
2748 */
2749 _X_HIDDEN char *
2750 __glXstrdup(const char *str)
2751 {
2752 char *copy;
2753 copy = (char *) Xmalloc(strlen(str) + 1);
2754 if (!copy)
2755 return NULL;
2756 strcpy(copy, str);
2757 return copy;
2758 }
2759
2760 /*
2761 ** glXGetProcAddress support
2762 */
2763
2764 struct name_address_pair
2765 {
2766 const char *Name;
2767 GLvoid *Address;
2768 };
2769
2770 #define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2771 #define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2772
2773 static const struct name_address_pair GLX_functions[] = {
2774 /*** GLX_VERSION_1_0 ***/
2775 GLX_FUNCTION( glXChooseVisual ),
2776 GLX_FUNCTION( glXCopyContext ),
2777 GLX_FUNCTION( glXCreateContext ),
2778 GLX_FUNCTION( glXCreateGLXPixmap ),
2779 GLX_FUNCTION( glXDestroyContext ),
2780 GLX_FUNCTION( glXDestroyGLXPixmap ),
2781 GLX_FUNCTION( glXGetConfig ),
2782 GLX_FUNCTION( glXGetCurrentContext ),
2783 GLX_FUNCTION( glXGetCurrentDrawable ),
2784 GLX_FUNCTION( glXIsDirect ),
2785 GLX_FUNCTION( glXMakeCurrent ),
2786 GLX_FUNCTION( glXQueryExtension ),
2787 GLX_FUNCTION( glXQueryVersion ),
2788 GLX_FUNCTION( glXSwapBuffers ),
2789 GLX_FUNCTION( glXUseXFont ),
2790 GLX_FUNCTION( glXWaitGL ),
2791 GLX_FUNCTION( glXWaitX ),
2792
2793 /*** GLX_VERSION_1_1 ***/
2794 GLX_FUNCTION( glXGetClientString ),
2795 GLX_FUNCTION( glXQueryExtensionsString ),
2796 GLX_FUNCTION( glXQueryServerString ),
2797
2798 /*** GLX_VERSION_1_2 ***/
2799 GLX_FUNCTION( glXGetCurrentDisplay ),
2800
2801 /*** GLX_VERSION_1_3 ***/
2802 GLX_FUNCTION( glXChooseFBConfig ),
2803 GLX_FUNCTION( glXCreateNewContext ),
2804 GLX_FUNCTION( glXCreatePbuffer ),
2805 GLX_FUNCTION( glXCreatePixmap ),
2806 GLX_FUNCTION( glXCreateWindow ),
2807 GLX_FUNCTION( glXDestroyPbuffer ),
2808 GLX_FUNCTION( glXDestroyPixmap ),
2809 GLX_FUNCTION( glXDestroyWindow ),
2810 GLX_FUNCTION( glXGetCurrentReadDrawable ),
2811 GLX_FUNCTION( glXGetFBConfigAttrib ),
2812 GLX_FUNCTION( glXGetFBConfigs ),
2813 GLX_FUNCTION( glXGetSelectedEvent ),
2814 GLX_FUNCTION( glXGetVisualFromFBConfig ),
2815 GLX_FUNCTION( glXMakeContextCurrent ),
2816 GLX_FUNCTION( glXQueryContext ),
2817 GLX_FUNCTION( glXQueryDrawable ),
2818 GLX_FUNCTION( glXSelectEvent ),
2819
2820 /*** GLX_SGI_swap_control ***/
2821 GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ),
2822
2823 /*** GLX_SGI_video_sync ***/
2824 GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ),
2825 GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ),
2826
2827 /*** GLX_SGI_make_current_read ***/
2828 GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ),
2829 GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ),
2830
2831 /*** GLX_EXT_import_context ***/
2832 GLX_FUNCTION( glXFreeContextEXT ),
2833 GLX_FUNCTION( glXGetContextIDEXT ),
2834 GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ),
2835 GLX_FUNCTION( glXImportContextEXT ),
2836 GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ),
2837
2838 /*** GLX_SGIX_fbconfig ***/
2839 GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ),
2840 GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ),
2841 GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ),
2842 GLX_FUNCTION( glXCreateContextWithConfigSGIX ),
2843 GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ),
2844 GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ),
2845
2846 /*** GLX_SGIX_pbuffer ***/
2847 GLX_FUNCTION( glXCreateGLXPbufferSGIX ),
2848 GLX_FUNCTION( glXDestroyGLXPbufferSGIX ),
2849 GLX_FUNCTION( glXQueryGLXPbufferSGIX ),
2850 GLX_FUNCTION( glXSelectEventSGIX ),
2851 GLX_FUNCTION( glXGetSelectedEventSGIX ),
2852
2853 /*** GLX_SGIX_swap_group ***/
2854 GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ),
2855
2856 /*** GLX_SGIX_swap_barrier ***/
2857 GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ),
2858 GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ),
2859
2860 /*** GLX_MESA_allocate_memory ***/
2861 GLX_FUNCTION( glXAllocateMemoryMESA ),
2862 GLX_FUNCTION( glXFreeMemoryMESA ),
2863 GLX_FUNCTION( glXGetMemoryOffsetMESA ),
2864
2865 /*** GLX_MESA_copy_sub_buffer ***/
2866 GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ),
2867
2868 /*** GLX_MESA_pixmap_colormap ***/
2869 GLX_FUNCTION( glXCreateGLXPixmapMESA ),
2870
2871 /*** GLX_MESA_release_buffers ***/
2872 GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ),
2873
2874 /*** GLX_MESA_swap_control ***/
2875 GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ),
2876 GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ),
2877
2878 /*** GLX_MESA_swap_frame_usage ***/
2879 GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ),
2880 GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ),
2881 GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ),
2882 GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ),
2883
2884 /*** GLX_ARB_get_proc_address ***/
2885 GLX_FUNCTION( glXGetProcAddressARB ),
2886
2887 /*** GLX 1.4 ***/
2888 GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ),
2889
2890 /*** GLX_OML_sync_control ***/
2891 GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ),
2892 GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ),
2893 GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ),
2894 GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ),
2895 GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ),
2896
2897 /*** GLX_EXT_texture_from_pixmap ***/
2898 GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ),
2899 GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ),
2900
2901 #ifdef GLX_DIRECT_RENDERING
2902 /*** DRI configuration ***/
2903 GLX_FUNCTION( glXGetScreenDriver ),
2904 GLX_FUNCTION( glXGetDriverConfig ),
2905 #endif
2906
2907 { NULL, NULL } /* end of list */
2908 };
2909
2910 static const GLvoid *
2911 get_glx_proc_address(const char *funcName)
2912 {
2913 GLuint i;
2914
2915 /* try static functions */
2916 for (i = 0; GLX_functions[i].Name; i++) {
2917 if (strcmp(GLX_functions[i].Name, funcName) == 0)
2918 return GLX_functions[i].Address;
2919 }
2920
2921 return NULL;
2922 }
2923
2924
2925 /**
2926 * Get the address of a named GL function. This is the pre-GLX 1.4 name for
2927 * \c glXGetProcAddress.
2928 *
2929 * \param procName Name of a GL or GLX function.
2930 * \returns A pointer to the named function
2931 *
2932 * \sa glXGetProcAddress
2933 */
2934 PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
2935 {
2936 typedef void (*gl_function) (void);
2937 gl_function f;
2938
2939
2940 /* Search the table of GLX and internal functions first. If that
2941 * fails and the supplied name could be a valid core GL name, try
2942 * searching the core GL function table. This check is done to prevent
2943 * DRI based drivers from searching the core GL function table for
2944 * internal API functions.
2945 */
2946
2947 f = (gl_function) get_glx_proc_address((const char *) procName);
2948 if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2949 && (procName[2] != 'X')) {
2950 f = (gl_function) _glapi_get_proc_address((const char *) procName);
2951 }
2952
2953 return f;
2954 }
2955
2956 /**
2957 * Get the address of a named GL function. This is the GLX 1.4 name for
2958 * \c glXGetProcAddressARB.
2959 *
2960 * \param procName Name of a GL or GLX function.
2961 * \returns A pointer to the named function
2962 *
2963 * \sa glXGetProcAddressARB
2964 */
2965 PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
2966 #if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
2967 __attribute__ ((alias("glXGetProcAddressARB")));
2968 #else
2969 {
2970 return glXGetProcAddressARB(procName);
2971 }
2972 #endif /* __GNUC__ */
2973
2974
2975 #ifdef GLX_DIRECT_RENDERING
2976 /**
2977 * Get the unadjusted system time (UST). Currently, the UST is measured in
2978 * microseconds since Epoc. The actual resolution of the UST may vary from
2979 * system to system, and the units may vary from release to release.
2980 * Drivers should not call this function directly. They should instead use
2981 * \c glXGetProcAddress to obtain a pointer to the function.
2982 *
2983 * \param ust Location to store the 64-bit UST
2984 * \returns Zero on success or a negative errno value on failure.
2985 *
2986 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2987 *
2988 * \since Internal API version 20030317.
2989 */
2990 _X_HIDDEN int
2991 __glXGetUST(int64_t * ust)
2992 {
2993 struct timeval tv;
2994
2995 if (ust == NULL) {
2996 return -EFAULT;
2997 }
2998
2999 if (gettimeofday(&tv, NULL) == 0) {
3000 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
3001 return 0;
3002 }
3003 else {
3004 return -errno;
3005 }
3006 }
3007 #endif /* GLX_DIRECT_RENDERING */