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