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