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