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