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