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