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