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