1848b8605Smrg/*
2848b8605Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3848b8605Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
10848b8605Smrg * Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice including the dates of first publication and
13848b8605Smrg * either this permission notice or a reference to
14848b8605Smrg * http://oss.sgi.com/projects/FreeB/
15848b8605Smrg * shall be included in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20848b8605Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22848b8605Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23848b8605Smrg * SOFTWARE.
24848b8605Smrg *
25848b8605Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
26848b8605Smrg * shall not be used in advertising or otherwise to promote the sale, use or
27848b8605Smrg * other dealings in this Software without prior written authorization from
28848b8605Smrg * Silicon Graphics, Inc.
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg/**
32848b8605Smrg * \file glxcmds.c
33848b8605Smrg * Client-side GLX interface.
34848b8605Smrg */
35848b8605Smrg
36848b8605Smrg#include "glxclient.h"
37848b8605Smrg#include "glapi.h"
38848b8605Smrg#include "glxextensions.h"
39848b8605Smrg#include "indirect.h"
40848b8605Smrg#include "glx_error.h"
41848b8605Smrg
42848b8605Smrg#ifdef GLX_DIRECT_RENDERING
43848b8605Smrg#ifdef GLX_USE_APPLEGL
44848b8605Smrg#include "apple/apple_glx_context.h"
45848b8605Smrg#include "apple/apple_glx.h"
46b8e80941Smrg#include "util/debug.h"
47848b8605Smrg#else
48848b8605Smrg#include <sys/time.h>
49b8e80941Smrg#ifndef GLX_USE_WINDOWSGL
50848b8605Smrg#include <X11/extensions/xf86vmode.h>
51b8e80941Smrg#endif /* GLX_USE_WINDOWSGL */
52848b8605Smrg#endif
53848b8605Smrg#endif
54848b8605Smrg
55848b8605Smrg#include <X11/Xlib-xcb.h>
56848b8605Smrg#include <xcb/xcb.h>
57848b8605Smrg#include <xcb/glx.h>
58b8e80941Smrg#include "GL/mesa_glinterop.h"
59848b8605Smrg
60848b8605Smrgstatic const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
61848b8605Smrgstatic const char __glXGLXClientVersion[] = "1.4";
62848b8605Smrg
63848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
64848b8605Smrg
65848b8605Smrg/**
66848b8605Smrg * Get the __DRIdrawable for the drawable associated with a GLXContext
67848b8605Smrg *
68848b8605Smrg * \param dpy       The display associated with \c drawable.
69848b8605Smrg * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved.
70848b8605Smrg * \param scrn_num  If non-NULL, the drawables screen is stored there
71848b8605Smrg * \returns  A pointer to the context's __DRIdrawable on success, or NULL if
72848b8605Smrg *           the drawable is not associated with a direct-rendering context.
73848b8605Smrg */
74848b8605Smrg_X_HIDDEN __GLXDRIdrawable *
75848b8605SmrgGetGLXDRIDrawable(Display * dpy, GLXDrawable drawable)
76848b8605Smrg{
77848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
78848b8605Smrg   __GLXDRIdrawable *pdraw;
79848b8605Smrg
80848b8605Smrg   if (priv == NULL)
81848b8605Smrg      return NULL;
82848b8605Smrg
83848b8605Smrg   if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0)
84848b8605Smrg      return pdraw;
85848b8605Smrg
86848b8605Smrg   return NULL;
87848b8605Smrg}
88848b8605Smrg
89848b8605Smrg#endif
90848b8605Smrg
91848b8605Smrg_X_HIDDEN struct glx_drawable *
92848b8605SmrgGetGLXDrawable(Display *dpy, GLXDrawable drawable)
93848b8605Smrg{
94848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
95848b8605Smrg   struct glx_drawable *glxDraw;
96848b8605Smrg
97848b8605Smrg   if (priv == NULL)
98848b8605Smrg      return NULL;
99848b8605Smrg
100848b8605Smrg   if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0)
101848b8605Smrg      return glxDraw;
102848b8605Smrg
103848b8605Smrg   return NULL;
104848b8605Smrg}
105848b8605Smrg
106848b8605Smrg_X_HIDDEN int
107848b8605SmrgInitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable,
108848b8605Smrg		GLXDrawable drawable)
109848b8605Smrg{
110848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
111848b8605Smrg
112848b8605Smrg   if (!priv)
113848b8605Smrg      return -1;
114848b8605Smrg
115848b8605Smrg   glxDraw->xDrawable = xDrawable;
116848b8605Smrg   glxDraw->drawable = drawable;
117848b8605Smrg   glxDraw->lastEventSbc = 0;
118848b8605Smrg   glxDraw->eventSbcWrap = 0;
119848b8605Smrg
120848b8605Smrg   return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw);
121848b8605Smrg}
122848b8605Smrg
123848b8605Smrg_X_HIDDEN void
124848b8605SmrgDestroyGLXDrawable(Display *dpy, GLXDrawable drawable)
125848b8605Smrg{
126848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
127848b8605Smrg   struct glx_drawable *glxDraw;
128848b8605Smrg
129848b8605Smrg   if (!priv)
130848b8605Smrg      return;
131848b8605Smrg
132848b8605Smrg   glxDraw = GetGLXDrawable(dpy, drawable);
133848b8605Smrg   __glxHashDelete(priv->glXDrawHash, drawable);
134848b8605Smrg   free(glxDraw);
135848b8605Smrg}
136848b8605Smrg
137848b8605Smrg/**
138848b8605Smrg * Get the GLX per-screen data structure associated with a GLX context.
139848b8605Smrg *
140848b8605Smrg * \param dpy   Display for which the GLX per-screen information is to be
141848b8605Smrg *              retrieved.
142848b8605Smrg * \param scrn  Screen on \c dpy for which the GLX per-screen information is
143848b8605Smrg *              to be retrieved.
144848b8605Smrg * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
145848b8605Smrg *          specify a valid GLX screen, or NULL otherwise.
146848b8605Smrg *
147848b8605Smrg * \todo Should this function validate that \c scrn is within the screen
148848b8605Smrg *       number range for \c dpy?
149848b8605Smrg */
150848b8605Smrg
151848b8605Smrg_X_HIDDEN struct glx_screen *
152848b8605SmrgGetGLXScreenConfigs(Display * dpy, int scrn)
153848b8605Smrg{
154848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
155848b8605Smrg
156848b8605Smrg   return (priv
157848b8605Smrg           && priv->screens !=
158848b8605Smrg           NULL) ? priv->screens[scrn] : NULL;
159848b8605Smrg}
160848b8605Smrg
161848b8605Smrg
162848b8605Smrgstatic int
163848b8605SmrgGetGLXPrivScreenConfig(Display * dpy, int scrn, struct glx_display ** ppriv,
164848b8605Smrg                       struct glx_screen ** ppsc)
165848b8605Smrg{
166848b8605Smrg   /* Initialize the extension, if needed .  This has the added value
167848b8605Smrg    * of initializing/allocating the display private
168848b8605Smrg    */
169848b8605Smrg
170848b8605Smrg   if (dpy == NULL) {
171848b8605Smrg      return GLX_NO_EXTENSION;
172848b8605Smrg   }
173848b8605Smrg
174848b8605Smrg   *ppriv = __glXInitialize(dpy);
175848b8605Smrg   if (*ppriv == NULL) {
176848b8605Smrg      return GLX_NO_EXTENSION;
177848b8605Smrg   }
178848b8605Smrg
179848b8605Smrg   /* Check screen number to see if its valid */
180848b8605Smrg   if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
181848b8605Smrg      return GLX_BAD_SCREEN;
182848b8605Smrg   }
183848b8605Smrg
184848b8605Smrg   /* Check to see if the GL is supported on this screen */
185848b8605Smrg   *ppsc = (*ppriv)->screens[scrn];
186848b8605Smrg   if ((*ppsc)->configs == NULL && (*ppsc)->visuals == NULL) {
187848b8605Smrg      /* No support for GL on this screen regardless of visual */
188848b8605Smrg      return GLX_BAD_VISUAL;
189848b8605Smrg   }
190848b8605Smrg
191848b8605Smrg   return Success;
192848b8605Smrg}
193848b8605Smrg
194848b8605Smrg
195848b8605Smrg/**
196848b8605Smrg * Determine if a \c GLXFBConfig supplied by the application is valid.
197848b8605Smrg *
198848b8605Smrg * \param dpy     Application supplied \c Display pointer.
199848b8605Smrg * \param config  Application supplied \c GLXFBConfig.
200848b8605Smrg *
201848b8605Smrg * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
202848b8605Smrg *          \c struct glx_config structure is returned.  Otherwise, \c NULL
203848b8605Smrg *          is returned.
204848b8605Smrg */
205848b8605Smrgstatic struct glx_config *
206848b8605SmrgValidateGLXFBConfig(Display * dpy, GLXFBConfig fbconfig)
207848b8605Smrg{
208848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
209848b8605Smrg   int num_screens = ScreenCount(dpy);
210848b8605Smrg   unsigned i;
211848b8605Smrg   struct glx_config *config;
212848b8605Smrg
213848b8605Smrg   if (priv != NULL) {
214848b8605Smrg      for (i = 0; i < num_screens; i++) {
215848b8605Smrg	 for (config = priv->screens[i]->configs; config != NULL;
216848b8605Smrg	      config = config->next) {
217848b8605Smrg	    if (config == (struct glx_config *) fbconfig) {
218848b8605Smrg	       return config;
219848b8605Smrg	    }
220848b8605Smrg	 }
221848b8605Smrg      }
222848b8605Smrg   }
223848b8605Smrg
224848b8605Smrg   return NULL;
225848b8605Smrg}
226848b8605Smrg
227848b8605Smrg/**
228848b8605Smrg * Verifies context's GLX_RENDER_TYPE value with config.
229848b8605Smrg *
230848b8605Smrg * \param config GLX FBConfig which will support the returned renderType.
231848b8605Smrg * \param renderType The context render type to be verified.
232848b8605Smrg * \return True if the value of context renderType was approved, or 0 if no
233848b8605Smrg * valid value was found.
234848b8605Smrg */
235848b8605SmrgBool
236848b8605Smrgvalidate_renderType_against_config(const struct glx_config *config,
237848b8605Smrg                                   int renderType)
238848b8605Smrg{
239b8e80941Smrg   /* GLX_EXT_no_config_context supports any render type */
240b8e80941Smrg   if (!config)
241b8e80941Smrg      return True;
242b8e80941Smrg
243b8e80941Smrg   switch (renderType) {
244b8e80941Smrg      case GLX_RGBA_TYPE:
245b8e80941Smrg         return (config->renderType & GLX_RGBA_BIT) != 0;
246b8e80941Smrg      case GLX_COLOR_INDEX_TYPE:
247b8e80941Smrg         return (config->renderType & GLX_COLOR_INDEX_BIT) != 0;
248b8e80941Smrg      case GLX_RGBA_FLOAT_TYPE_ARB:
249b8e80941Smrg         return (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) != 0;
250b8e80941Smrg      case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
251b8e80941Smrg         return (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) != 0;
252b8e80941Smrg      default:
253b8e80941Smrg         break;
254b8e80941Smrg   }
255b8e80941Smrg   return 0;
256848b8605Smrg}
257848b8605Smrg
258848b8605Smrg_X_HIDDEN Bool
259848b8605Smrgglx_context_init(struct glx_context *gc,
260848b8605Smrg		 struct glx_screen *psc, struct glx_config *config)
261848b8605Smrg{
262848b8605Smrg   gc->majorOpcode = __glXSetupForCommand(psc->display->dpy);
263848b8605Smrg   if (!gc->majorOpcode)
264848b8605Smrg      return False;
265848b8605Smrg
266848b8605Smrg   gc->screen = psc->scr;
267848b8605Smrg   gc->psc = psc;
268848b8605Smrg   gc->config = config;
269848b8605Smrg   gc->isDirect = GL_TRUE;
270848b8605Smrg   gc->currentContextTag = -1;
271848b8605Smrg
272848b8605Smrg   return True;
273848b8605Smrg}
274848b8605Smrg
275b8e80941Smrg/**
276b8e80941Smrg * Determine if a context uses direct rendering.
277b8e80941Smrg *
278b8e80941Smrg * \param dpy        Display where the context was created.
279b8e80941Smrg * \param contextID  ID of the context to be tested.
280b8e80941Smrg * \param error      Out parameter, set to True on error if not NULL
281b8e80941Smrg *
282b8e80941Smrg * \returns \c True if the context is direct rendering or not.
283b8e80941Smrg */
284b8e80941Smrgstatic Bool
285b8e80941Smrg__glXIsDirect(Display * dpy, GLXContextID contextID, Bool *error)
286b8e80941Smrg{
287b8e80941Smrg   CARD8 opcode;
288b8e80941Smrg   xcb_connection_t *c;
289b8e80941Smrg   xcb_generic_error_t *err;
290b8e80941Smrg   xcb_glx_is_direct_reply_t *reply;
291b8e80941Smrg   Bool is_direct;
292b8e80941Smrg
293b8e80941Smrg   opcode = __glXSetupForCommand(dpy);
294b8e80941Smrg   if (!opcode) {
295b8e80941Smrg      return False;
296b8e80941Smrg   }
297b8e80941Smrg
298b8e80941Smrg   c = XGetXCBConnection(dpy);
299b8e80941Smrg   reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err);
300b8e80941Smrg   is_direct = (reply != NULL && reply->is_direct) ? True : False;
301b8e80941Smrg
302b8e80941Smrg   if (err != NULL) {
303b8e80941Smrg      if (error)
304b8e80941Smrg         *error = True;
305b8e80941Smrg      __glXSendErrorForXcb(dpy, err);
306b8e80941Smrg      free(err);
307b8e80941Smrg   }
308b8e80941Smrg
309b8e80941Smrg   free(reply);
310b8e80941Smrg
311b8e80941Smrg   return is_direct;
312b8e80941Smrg}
313848b8605Smrg
314848b8605Smrg/**
315848b8605Smrg * Create a new context.
316848b8605Smrg *
317848b8605Smrg * \param renderType   For FBConfigs, what is the rendering type?
318848b8605Smrg */
319848b8605Smrg
320848b8605Smrgstatic GLXContext
321848b8605SmrgCreateContext(Display *dpy, int generic_id, struct glx_config *config,
322848b8605Smrg              GLXContext shareList_user, Bool allowDirect,
323848b8605Smrg	      unsigned code, int renderType, int screen)
324848b8605Smrg{
325848b8605Smrg   struct glx_context *gc;
326848b8605Smrg   struct glx_screen *psc;
327848b8605Smrg   struct glx_context *shareList = (struct glx_context *) shareList_user;
328848b8605Smrg   if (dpy == NULL)
329848b8605Smrg      return NULL;
330848b8605Smrg
331848b8605Smrg   psc = GetGLXScreenConfigs(dpy, screen);
332848b8605Smrg   if (psc == NULL)
333848b8605Smrg      return NULL;
334848b8605Smrg
335848b8605Smrg   if (generic_id == None)
336848b8605Smrg      return NULL;
337848b8605Smrg
338848b8605Smrg   gc = NULL;
339848b8605Smrg#ifdef GLX_USE_APPLEGL
340848b8605Smrg   gc = applegl_create_context(psc, config, shareList, renderType);
341848b8605Smrg#else
342848b8605Smrg   if (allowDirect && psc->vtable->create_context)
343848b8605Smrg      gc = psc->vtable->create_context(psc, config, shareList, renderType);
344848b8605Smrg   if (!gc)
345848b8605Smrg      gc = indirect_create_context(psc, config, shareList, renderType);
346848b8605Smrg#endif
347848b8605Smrg   if (!gc)
348848b8605Smrg      return NULL;
349848b8605Smrg
350848b8605Smrg   LockDisplay(dpy);
351848b8605Smrg   switch (code) {
352848b8605Smrg   case X_GLXCreateContext: {
353848b8605Smrg      xGLXCreateContextReq *req;
354848b8605Smrg
355848b8605Smrg      /* Send the glXCreateContext request */
356848b8605Smrg      GetReq(GLXCreateContext, req);
357848b8605Smrg      req->reqType = gc->majorOpcode;
358848b8605Smrg      req->glxCode = X_GLXCreateContext;
359848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
360848b8605Smrg      req->visual = generic_id;
361848b8605Smrg      req->screen = screen;
362848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
363848b8605Smrg      req->isDirect = gc->isDirect;
364848b8605Smrg      break;
365848b8605Smrg   }
366848b8605Smrg
367848b8605Smrg   case X_GLXCreateNewContext: {
368848b8605Smrg      xGLXCreateNewContextReq *req;
369848b8605Smrg
370848b8605Smrg      /* Send the glXCreateNewContext request */
371848b8605Smrg      GetReq(GLXCreateNewContext, req);
372848b8605Smrg      req->reqType = gc->majorOpcode;
373848b8605Smrg      req->glxCode = X_GLXCreateNewContext;
374848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
375848b8605Smrg      req->fbconfig = generic_id;
376848b8605Smrg      req->screen = screen;
377848b8605Smrg      req->renderType = renderType;
378848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
379848b8605Smrg      req->isDirect = gc->isDirect;
380848b8605Smrg      break;
381848b8605Smrg   }
382848b8605Smrg
383848b8605Smrg   case X_GLXvop_CreateContextWithConfigSGIX: {
384848b8605Smrg      xGLXVendorPrivateWithReplyReq *vpreq;
385848b8605Smrg      xGLXCreateContextWithConfigSGIXReq *req;
386848b8605Smrg
387848b8605Smrg      /* Send the glXCreateNewContext request */
388848b8605Smrg      GetReqExtra(GLXVendorPrivateWithReply,
389848b8605Smrg		  sz_xGLXCreateContextWithConfigSGIXReq -
390848b8605Smrg		  sz_xGLXVendorPrivateWithReplyReq, vpreq);
391848b8605Smrg      req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
392848b8605Smrg      req->reqType = gc->majorOpcode;
393848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
394848b8605Smrg      req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
395848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
396848b8605Smrg      req->fbconfig = generic_id;
397848b8605Smrg      req->screen = screen;
398848b8605Smrg      req->renderType = renderType;
399848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
400848b8605Smrg      req->isDirect = gc->isDirect;
401848b8605Smrg      break;
402848b8605Smrg   }
403848b8605Smrg
404848b8605Smrg   default:
405848b8605Smrg      /* What to do here?  This case is the sign of an internal error.  It
406848b8605Smrg       * should never be reachable.
407848b8605Smrg       */
408848b8605Smrg      break;
409848b8605Smrg   }
410848b8605Smrg
411848b8605Smrg   UnlockDisplay(dpy);
412848b8605Smrg   SyncHandle();
413848b8605Smrg
414848b8605Smrg   gc->share_xid = shareList ? shareList->xid : None;
415848b8605Smrg   gc->imported = GL_FALSE;
416848b8605Smrg
417b8e80941Smrg   /* Unlike most X resource creation requests, we're about to return a handle
418b8e80941Smrg    * with client-side state, not just an XID. To simplify error handling
419b8e80941Smrg    * elsewhere in libGL, force a round-trip here to ensure the CreateContext
420b8e80941Smrg    * request above succeeded.
421b8e80941Smrg    */
422b8e80941Smrg   {
423b8e80941Smrg      Bool error = False;
424b8e80941Smrg      int isDirect = __glXIsDirect(dpy, gc->xid, &error);
425b8e80941Smrg
426b8e80941Smrg      if (error != False || isDirect != gc->isDirect) {
427b8e80941Smrg         gc->vtable->destroy(gc);
428b8e80941Smrg         gc = NULL;
429b8e80941Smrg      }
430b8e80941Smrg   }
431b8e80941Smrg
432848b8605Smrg   return (GLXContext) gc;
433848b8605Smrg}
434848b8605Smrg
435b8e80941Smrg_GLX_PUBLIC GLXContext
436848b8605SmrgglXCreateContext(Display * dpy, XVisualInfo * vis,
437848b8605Smrg                 GLXContext shareList, Bool allowDirect)
438848b8605Smrg{
439848b8605Smrg   struct glx_config *config = NULL;
440848b8605Smrg   int renderType = GLX_RGBA_TYPE;
441848b8605Smrg
442848b8605Smrg#if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL)
443848b8605Smrg   struct glx_screen *const psc = GetGLXScreenConfigs(dpy, vis->screen);
444848b8605Smrg
445848b8605Smrg   if (psc)
446848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
447848b8605Smrg
448848b8605Smrg   if (config == NULL) {
449b8e80941Smrg      __glXSendError(dpy, BadValue, vis->visualid, X_GLXCreateContext, True);
450848b8605Smrg      return None;
451848b8605Smrg   }
452848b8605Smrg
453848b8605Smrg   /* Choose the context render type based on DRI config values.  It is
454848b8605Smrg    * unusual to set this type from config, but we have no other choice, as
455848b8605Smrg    * this old API does not provide renderType parameter.
456848b8605Smrg    */
457848b8605Smrg   if (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) {
458848b8605Smrg       renderType = GLX_RGBA_FLOAT_TYPE_ARB;
459848b8605Smrg   } else if (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) {
460848b8605Smrg       renderType = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
461848b8605Smrg   } else if (config->renderType & GLX_RGBA_BIT) {
462848b8605Smrg       renderType = GLX_RGBA_TYPE;
463848b8605Smrg   } else if (config->renderType & GLX_COLOR_INDEX_BIT) {
464848b8605Smrg       renderType = GLX_COLOR_INDEX_TYPE;
465848b8605Smrg   } else if (config->rgbMode) {
466848b8605Smrg       /* If we're here, then renderType is not set correctly.  Let's use a
467848b8605Smrg        * safeguard - any TrueColor or DirectColor mode is RGB mode.  Such
468848b8605Smrg        * default value is needed by old DRI drivers, which didn't set
469848b8605Smrg        * renderType correctly as the value was just ignored.
470848b8605Smrg        */
471848b8605Smrg       renderType = GLX_RGBA_TYPE;
472848b8605Smrg   } else {
473848b8605Smrg       /* Safeguard - only one option left, all non-RGB modes are indexed
474848b8605Smrg        * modes.  Again, this allows drivers with invalid renderType to work
475848b8605Smrg        * properly.
476848b8605Smrg        */
477848b8605Smrg       renderType = GLX_COLOR_INDEX_TYPE;
478848b8605Smrg   }
479848b8605Smrg#endif
480848b8605Smrg
481848b8605Smrg   return CreateContext(dpy, vis->visualid, config, shareList, allowDirect,
482848b8605Smrg                        X_GLXCreateContext, renderType, vis->screen);
483848b8605Smrg}
484848b8605Smrg
485848b8605Smrgstatic void
486848b8605Smrgglx_send_destroy_context(Display *dpy, XID xid)
487848b8605Smrg{
488848b8605Smrg   CARD8 opcode = __glXSetupForCommand(dpy);
489848b8605Smrg   xGLXDestroyContextReq *req;
490848b8605Smrg
491848b8605Smrg   LockDisplay(dpy);
492848b8605Smrg   GetReq(GLXDestroyContext, req);
493848b8605Smrg   req->reqType = opcode;
494848b8605Smrg   req->glxCode = X_GLXDestroyContext;
495848b8605Smrg   req->context = xid;
496848b8605Smrg   UnlockDisplay(dpy);
497848b8605Smrg   SyncHandle();
498848b8605Smrg}
499848b8605Smrg
500848b8605Smrg/*
501848b8605Smrg** Destroy the named context
502848b8605Smrg*/
503848b8605Smrg
504b8e80941Smrg_GLX_PUBLIC void
505848b8605SmrgglXDestroyContext(Display * dpy, GLXContext ctx)
506848b8605Smrg{
507848b8605Smrg   struct glx_context *gc = (struct glx_context *) ctx;
508848b8605Smrg
509848b8605Smrg   if (gc == NULL || gc->xid == None)
510848b8605Smrg      return;
511848b8605Smrg
512848b8605Smrg   __glXLock();
513848b8605Smrg   if (!gc->imported)
514848b8605Smrg      glx_send_destroy_context(dpy, gc->xid);
515848b8605Smrg
516848b8605Smrg   if (gc->currentDpy) {
517848b8605Smrg      /* This context is bound to some thread.  According to the man page,
518848b8605Smrg       * we should not actually delete the context until it's unbound.
519848b8605Smrg       * Note that we set gc->xid = None above.  In MakeContextCurrent()
520848b8605Smrg       * we check for that and delete the context there.
521848b8605Smrg       */
522848b8605Smrg      gc->xid = None;
523848b8605Smrg   } else {
524848b8605Smrg      gc->vtable->destroy(gc);
525848b8605Smrg   }
526848b8605Smrg   __glXUnlock();
527848b8605Smrg}
528848b8605Smrg
529848b8605Smrg/*
530848b8605Smrg** Return the major and minor version #s for the GLX extension
531848b8605Smrg*/
532b8e80941Smrg_GLX_PUBLIC Bool
533848b8605SmrgglXQueryVersion(Display * dpy, int *major, int *minor)
534848b8605Smrg{
535848b8605Smrg   struct glx_display *priv;
536848b8605Smrg
537848b8605Smrg   /* Init the extension.  This fetches the major and minor version. */
538848b8605Smrg   priv = __glXInitialize(dpy);
539848b8605Smrg   if (!priv)
540848b8605Smrg      return False;
541848b8605Smrg
542848b8605Smrg   if (major)
543848b8605Smrg      *major = priv->majorVersion;
544848b8605Smrg   if (minor)
545848b8605Smrg      *minor = priv->minorVersion;
546848b8605Smrg   return True;
547848b8605Smrg}
548848b8605Smrg
549848b8605Smrg/*
550b8e80941Smrg** Query the existence of the GLX extension
551848b8605Smrg*/
552b8e80941Smrg_GLX_PUBLIC Bool
553848b8605SmrgglXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
554848b8605Smrg{
555848b8605Smrg   int major_op, erb, evb;
556848b8605Smrg   Bool rv;
557848b8605Smrg
558848b8605Smrg   rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
559848b8605Smrg   if (rv) {
560848b8605Smrg      if (errorBase)
561848b8605Smrg         *errorBase = erb;
562848b8605Smrg      if (eventBase)
563848b8605Smrg         *eventBase = evb;
564848b8605Smrg   }
565848b8605Smrg   return rv;
566848b8605Smrg}
567848b8605Smrg
568848b8605Smrg/*
569848b8605Smrg** Put a barrier in the token stream that forces the GL to finish its
570848b8605Smrg** work before X can proceed.
571848b8605Smrg*/
572b8e80941Smrg_GLX_PUBLIC void
573848b8605SmrgglXWaitGL(void)
574848b8605Smrg{
575848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
576848b8605Smrg
577b8e80941Smrg   if (gc->vtable->wait_gl)
578848b8605Smrg      gc->vtable->wait_gl(gc);
579848b8605Smrg}
580848b8605Smrg
581848b8605Smrg/*
582848b8605Smrg** Put a barrier in the token stream that forces X to finish its
583848b8605Smrg** work before GL can proceed.
584848b8605Smrg*/
585b8e80941Smrg_GLX_PUBLIC void
586848b8605SmrgglXWaitX(void)
587848b8605Smrg{
588848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
589848b8605Smrg
590b8e80941Smrg   if (gc->vtable->wait_x)
591848b8605Smrg      gc->vtable->wait_x(gc);
592848b8605Smrg}
593848b8605Smrg
594b8e80941Smrg_GLX_PUBLIC void
595848b8605SmrgglXUseXFont(Font font, int first, int count, int listBase)
596848b8605Smrg{
597848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
598848b8605Smrg
599b8e80941Smrg   if (gc->vtable->use_x_font)
600848b8605Smrg      gc->vtable->use_x_font(gc, font, first, count, listBase);
601848b8605Smrg}
602848b8605Smrg
603848b8605Smrg/************************************************************************/
604848b8605Smrg
605848b8605Smrg/*
606848b8605Smrg** Copy the source context to the destination context using the
607848b8605Smrg** attribute "mask".
608848b8605Smrg*/
609b8e80941Smrg_GLX_PUBLIC void
610848b8605SmrgglXCopyContext(Display * dpy, GLXContext source_user,
611848b8605Smrg	       GLXContext dest_user, unsigned long mask)
612848b8605Smrg{
613848b8605Smrg   struct glx_context *source = (struct glx_context *) source_user;
614848b8605Smrg   struct glx_context *dest = (struct glx_context *) dest_user;
615848b8605Smrg#ifdef GLX_USE_APPLEGL
616848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
617848b8605Smrg   int errorcode;
618848b8605Smrg   bool x11error;
619848b8605Smrg
620848b8605Smrg   if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext,
621848b8605Smrg                             mask, &errorcode, &x11error)) {
622848b8605Smrg      __glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error);
623848b8605Smrg   }
624848b8605Smrg
625848b8605Smrg#else
626848b8605Smrg   xGLXCopyContextReq *req;
627848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
628848b8605Smrg   GLXContextTag tag;
629848b8605Smrg   CARD8 opcode;
630848b8605Smrg
631848b8605Smrg   opcode = __glXSetupForCommand(dpy);
632848b8605Smrg   if (!opcode) {
633848b8605Smrg      return;
634848b8605Smrg   }
635848b8605Smrg
636848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
637848b8605Smrg   if (gc->isDirect) {
638848b8605Smrg      /* NOT_DONE: This does not work yet */
639848b8605Smrg   }
640848b8605Smrg#endif
641848b8605Smrg
642848b8605Smrg   /*
643848b8605Smrg    ** If the source is the current context, send its tag so that the context
644848b8605Smrg    ** can be flushed before the copy.
645848b8605Smrg    */
646848b8605Smrg   if (source == gc && dpy == gc->currentDpy) {
647848b8605Smrg      tag = gc->currentContextTag;
648848b8605Smrg   }
649848b8605Smrg   else {
650848b8605Smrg      tag = 0;
651848b8605Smrg   }
652848b8605Smrg
653848b8605Smrg   /* Send the glXCopyContext request */
654848b8605Smrg   LockDisplay(dpy);
655848b8605Smrg   GetReq(GLXCopyContext, req);
656848b8605Smrg   req->reqType = opcode;
657848b8605Smrg   req->glxCode = X_GLXCopyContext;
658848b8605Smrg   req->source = source ? source->xid : None;
659848b8605Smrg   req->dest = dest ? dest->xid : None;
660848b8605Smrg   req->mask = mask;
661848b8605Smrg   req->contextTag = tag;
662848b8605Smrg   UnlockDisplay(dpy);
663848b8605Smrg   SyncHandle();
664848b8605Smrg#endif /* GLX_USE_APPLEGL */
665848b8605Smrg}
666848b8605Smrg
667848b8605Smrg
668848b8605Smrg/**
669848b8605Smrg * \todo
670848b8605Smrg * Shouldn't this function \b always return \c False when
671848b8605Smrg * \c GLX_DIRECT_RENDERING is not defined?  Do we really need to bother with
672848b8605Smrg * the GLX protocol here at all?
673848b8605Smrg */
674b8e80941Smrg_GLX_PUBLIC Bool
675848b8605SmrgglXIsDirect(Display * dpy, GLXContext gc_user)
676848b8605Smrg{
677848b8605Smrg   struct glx_context *gc = (struct glx_context *) gc_user;
678848b8605Smrg
679848b8605Smrg   if (!gc) {
680848b8605Smrg      return False;
681848b8605Smrg   }
682848b8605Smrg   else if (gc->isDirect) {
683848b8605Smrg      return True;
684848b8605Smrg   }
685848b8605Smrg#ifdef GLX_USE_APPLEGL  /* TODO: indirect on darwin */
686848b8605Smrg   return False;
687848b8605Smrg#else
688b8e80941Smrg   return __glXIsDirect(dpy, gc->xid, NULL);
689848b8605Smrg#endif
690848b8605Smrg}
691848b8605Smrg
692b8e80941Smrg_GLX_PUBLIC GLXPixmap
693848b8605SmrgglXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
694848b8605Smrg{
695848b8605Smrg#ifdef GLX_USE_APPLEGL
696848b8605Smrg   int screen = vis->screen;
697848b8605Smrg   struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
698848b8605Smrg   const struct glx_config *config;
699848b8605Smrg
700848b8605Smrg   config = glx_config_find_visual(psc->visuals, vis->visualid);
701848b8605Smrg
702848b8605Smrg   if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config))
703848b8605Smrg      return None;
704848b8605Smrg
705848b8605Smrg   return pixmap;
706848b8605Smrg#else
707848b8605Smrg   xGLXCreateGLXPixmapReq *req;
708848b8605Smrg   struct glx_drawable *glxDraw;
709848b8605Smrg   GLXPixmap xid;
710848b8605Smrg   CARD8 opcode;
711848b8605Smrg
712848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
713848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
714848b8605Smrg
715848b8605Smrg   if (priv == NULL)
716848b8605Smrg      return None;
717848b8605Smrg#endif
718848b8605Smrg
719848b8605Smrg   opcode = __glXSetupForCommand(dpy);
720848b8605Smrg   if (!opcode) {
721848b8605Smrg      return None;
722848b8605Smrg   }
723848b8605Smrg
724848b8605Smrg   glxDraw = malloc(sizeof(*glxDraw));
725848b8605Smrg   if (!glxDraw)
726848b8605Smrg      return None;
727848b8605Smrg
728848b8605Smrg   /* Send the glXCreateGLXPixmap request */
729848b8605Smrg   LockDisplay(dpy);
730848b8605Smrg   GetReq(GLXCreateGLXPixmap, req);
731848b8605Smrg   req->reqType = opcode;
732848b8605Smrg   req->glxCode = X_GLXCreateGLXPixmap;
733848b8605Smrg   req->screen = vis->screen;
734848b8605Smrg   req->visual = vis->visualid;
735848b8605Smrg   req->pixmap = pixmap;
736848b8605Smrg   req->glxpixmap = xid = XAllocID(dpy);
737848b8605Smrg   UnlockDisplay(dpy);
738848b8605Smrg   SyncHandle();
739848b8605Smrg
740848b8605Smrg   if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
741848b8605Smrg      free(glxDraw);
742848b8605Smrg      return None;
743848b8605Smrg   }
744848b8605Smrg
745848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
746848b8605Smrg   do {
747848b8605Smrg      /* FIXME: Maybe delay __DRIdrawable creation until the drawable
748848b8605Smrg       * is actually bound to a context... */
749848b8605Smrg
750848b8605Smrg      __GLXDRIdrawable *pdraw;
751848b8605Smrg      struct glx_screen *psc;
752848b8605Smrg      struct glx_config *config;
753848b8605Smrg
754848b8605Smrg      psc = priv->screens[vis->screen];
755848b8605Smrg      if (psc->driScreen == NULL)
756848b8605Smrg         return xid;
757848b8605Smrg
758848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
759848b8605Smrg      pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, config);
760848b8605Smrg      if (pdraw == NULL) {
761848b8605Smrg         fprintf(stderr, "failed to create pixmap\n");
762848b8605Smrg         xid = None;
763848b8605Smrg         break;
764848b8605Smrg      }
765848b8605Smrg
766848b8605Smrg      if (__glxHashInsert(priv->drawHash, xid, pdraw)) {
767848b8605Smrg         (*pdraw->destroyDrawable) (pdraw);
768848b8605Smrg         xid = None;
769848b8605Smrg         break;
770848b8605Smrg      }
771848b8605Smrg   } while (0);
772848b8605Smrg
773848b8605Smrg   if (xid == None) {
774848b8605Smrg      xGLXDestroyGLXPixmapReq *dreq;
775848b8605Smrg      LockDisplay(dpy);
776848b8605Smrg      GetReq(GLXDestroyGLXPixmap, dreq);
777848b8605Smrg      dreq->reqType = opcode;
778848b8605Smrg      dreq->glxCode = X_GLXDestroyGLXPixmap;
779848b8605Smrg      dreq->glxpixmap = xid;
780848b8605Smrg      UnlockDisplay(dpy);
781848b8605Smrg      SyncHandle();
782848b8605Smrg   }
783848b8605Smrg#endif
784848b8605Smrg
785848b8605Smrg   return xid;
786848b8605Smrg#endif
787848b8605Smrg}
788848b8605Smrg
789848b8605Smrg/*
790848b8605Smrg** Destroy the named pixmap
791848b8605Smrg*/
792b8e80941Smrg_GLX_PUBLIC void
793848b8605SmrgglXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
794848b8605Smrg{
795848b8605Smrg#ifdef GLX_USE_APPLEGL
796848b8605Smrg   if(apple_glx_pixmap_destroy(dpy, glxpixmap))
797848b8605Smrg      __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false);
798848b8605Smrg#else
799848b8605Smrg   xGLXDestroyGLXPixmapReq *req;
800848b8605Smrg   CARD8 opcode;
801848b8605Smrg
802848b8605Smrg   opcode = __glXSetupForCommand(dpy);
803848b8605Smrg   if (!opcode) {
804848b8605Smrg      return;
805848b8605Smrg   }
806848b8605Smrg
807848b8605Smrg   /* Send the glXDestroyGLXPixmap request */
808848b8605Smrg   LockDisplay(dpy);
809848b8605Smrg   GetReq(GLXDestroyGLXPixmap, req);
810848b8605Smrg   req->reqType = opcode;
811848b8605Smrg   req->glxCode = X_GLXDestroyGLXPixmap;
812848b8605Smrg   req->glxpixmap = glxpixmap;
813848b8605Smrg   UnlockDisplay(dpy);
814848b8605Smrg   SyncHandle();
815848b8605Smrg
816848b8605Smrg   DestroyGLXDrawable(dpy, glxpixmap);
817848b8605Smrg
818848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
819848b8605Smrg   {
820848b8605Smrg      struct glx_display *const priv = __glXInitialize(dpy);
821848b8605Smrg      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap);
822848b8605Smrg
823848b8605Smrg      if (priv != NULL && pdraw != NULL) {
824848b8605Smrg         (*pdraw->destroyDrawable) (pdraw);
825848b8605Smrg         __glxHashDelete(priv->drawHash, glxpixmap);
826848b8605Smrg      }
827848b8605Smrg   }
828848b8605Smrg#endif
829848b8605Smrg#endif /* GLX_USE_APPLEGL */
830848b8605Smrg}
831848b8605Smrg
832b8e80941Smrg_GLX_PUBLIC void
833848b8605SmrgglXSwapBuffers(Display * dpy, GLXDrawable drawable)
834848b8605Smrg{
835848b8605Smrg#ifdef GLX_USE_APPLEGL
836848b8605Smrg   struct glx_context * gc = __glXGetCurrentContext();
837b8e80941Smrg   if(gc != &dummyContext && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
838848b8605Smrg      apple_glx_swap_buffers(gc->driContext);
839848b8605Smrg   } else {
840848b8605Smrg      __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);
841848b8605Smrg   }
842848b8605Smrg#else
843848b8605Smrg   struct glx_context *gc;
844848b8605Smrg   GLXContextTag tag;
845848b8605Smrg   CARD8 opcode;
846848b8605Smrg   xcb_connection_t *c;
847848b8605Smrg
848848b8605Smrg   gc = __glXGetCurrentContext();
849848b8605Smrg
850848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
851848b8605Smrg   {
852848b8605Smrg      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
853848b8605Smrg
854848b8605Smrg      if (pdraw != NULL) {
855b8e80941Smrg         Bool flush = gc != &dummyContext && drawable == gc->currentDrawable;
856848b8605Smrg
857848b8605Smrg         (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0, flush);
858848b8605Smrg         return;
859848b8605Smrg      }
860848b8605Smrg   }
861848b8605Smrg#endif
862848b8605Smrg
863848b8605Smrg   opcode = __glXSetupForCommand(dpy);
864848b8605Smrg   if (!opcode) {
865848b8605Smrg      return;
866848b8605Smrg   }
867848b8605Smrg
868848b8605Smrg   /*
869848b8605Smrg    ** The calling thread may or may not have a current context.  If it
870848b8605Smrg    ** does, send the context tag so the server can do a flush.
871848b8605Smrg    */
872b8e80941Smrg   if ((gc != &dummyContext) && (dpy == gc->currentDpy) &&
873848b8605Smrg       ((drawable == gc->currentDrawable)
874848b8605Smrg        || (drawable == gc->currentReadable))) {
875848b8605Smrg      tag = gc->currentContextTag;
876848b8605Smrg   }
877848b8605Smrg   else {
878848b8605Smrg      tag = 0;
879848b8605Smrg   }
880848b8605Smrg
881848b8605Smrg   c = XGetXCBConnection(dpy);
882848b8605Smrg   xcb_glx_swap_buffers(c, tag, drawable);
883848b8605Smrg   xcb_flush(c);
884848b8605Smrg#endif /* GLX_USE_APPLEGL */
885848b8605Smrg}
886848b8605Smrg
887848b8605Smrg
888848b8605Smrg/*
889848b8605Smrg** Return configuration information for the given display, screen and
890848b8605Smrg** visual combination.
891848b8605Smrg*/
892b8e80941Smrg_GLX_PUBLIC int
893848b8605SmrgglXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
894848b8605Smrg             int *value_return)
895848b8605Smrg{
896848b8605Smrg   struct glx_display *priv;
897848b8605Smrg   struct glx_screen *psc;
898848b8605Smrg   struct glx_config *config;
899848b8605Smrg   int status;
900848b8605Smrg
901848b8605Smrg   status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
902848b8605Smrg   if (status == Success) {
903848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
904848b8605Smrg
905848b8605Smrg      /* Lookup attribute after first finding a match on the visual */
906848b8605Smrg      if (config != NULL) {
907848b8605Smrg	 return glx_config_get(config, attribute, value_return);
908848b8605Smrg      }
909848b8605Smrg
910848b8605Smrg      status = GLX_BAD_VISUAL;
911848b8605Smrg   }
912848b8605Smrg
913848b8605Smrg   /*
914848b8605Smrg    ** If we can't find the config for this visual, this visual is not
915848b8605Smrg    ** supported by the OpenGL implementation on the server.
916848b8605Smrg    */
917848b8605Smrg   if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
918848b8605Smrg      *value_return = False;
919848b8605Smrg      status = Success;
920848b8605Smrg   }
921848b8605Smrg
922848b8605Smrg   return status;
923848b8605Smrg}
924848b8605Smrg
925848b8605Smrg/************************************************************************/
926848b8605Smrg
927848b8605Smrgstatic void
928848b8605Smrginit_fbconfig_for_chooser(struct glx_config * config,
929848b8605Smrg                          GLboolean fbconfig_style_tags)
930848b8605Smrg{
931848b8605Smrg   memset(config, 0, sizeof(struct glx_config));
932848b8605Smrg   config->visualID = (XID) GLX_DONT_CARE;
933848b8605Smrg   config->visualType = GLX_DONT_CARE;
934848b8605Smrg
935848b8605Smrg   /* glXChooseFBConfig specifies different defaults for these properties than
936848b8605Smrg    * glXChooseVisual.
937848b8605Smrg    */
938848b8605Smrg   if (fbconfig_style_tags) {
939848b8605Smrg      config->rgbMode = GL_TRUE;
940848b8605Smrg      config->doubleBufferMode = GLX_DONT_CARE;
941848b8605Smrg      config->renderType = GLX_RGBA_BIT;
942848b8605Smrg   }
943848b8605Smrg
944848b8605Smrg   config->drawableType = GLX_WINDOW_BIT;
945848b8605Smrg   config->visualRating = GLX_DONT_CARE;
946848b8605Smrg   config->transparentPixel = GLX_NONE;
947848b8605Smrg   config->transparentRed = GLX_DONT_CARE;
948848b8605Smrg   config->transparentGreen = GLX_DONT_CARE;
949848b8605Smrg   config->transparentBlue = GLX_DONT_CARE;
950848b8605Smrg   config->transparentAlpha = GLX_DONT_CARE;
951848b8605Smrg   config->transparentIndex = GLX_DONT_CARE;
952848b8605Smrg
953848b8605Smrg   config->xRenderable = GLX_DONT_CARE;
954848b8605Smrg   config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
955848b8605Smrg
956848b8605Smrg   config->swapMethod = GLX_DONT_CARE;
957b8e80941Smrg   config->sRGBCapable = GLX_DONT_CARE;
958848b8605Smrg}
959848b8605Smrg
960848b8605Smrg#define MATCH_DONT_CARE( param )        \
961848b8605Smrg  do {                                  \
962848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)   \
963848b8605Smrg         && (a-> param != b-> param) ) {        \
964848b8605Smrg      return False;                             \
965848b8605Smrg    }                                           \
966848b8605Smrg  } while ( 0 )
967848b8605Smrg
968848b8605Smrg#define MATCH_MINIMUM( param )                  \
969848b8605Smrg  do {                                          \
970848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)	\
971848b8605Smrg         && (a-> param > b-> param) ) {         \
972848b8605Smrg      return False;                             \
973848b8605Smrg    }                                           \
974848b8605Smrg  } while ( 0 )
975848b8605Smrg
976848b8605Smrg#define MATCH_EXACT( param )                    \
977848b8605Smrg  do {                                          \
978848b8605Smrg    if ( a-> param != b-> param) {              \
979848b8605Smrg      return False;                             \
980848b8605Smrg    }                                           \
981848b8605Smrg  } while ( 0 )
982848b8605Smrg
983848b8605Smrg/* Test that all bits from a are contained in b */
984848b8605Smrg#define MATCH_MASK(param)			\
985848b8605Smrg  do {						\
986848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)	\
987848b8605Smrg         && ((a->param & ~b->param) != 0) ) {   \
988848b8605Smrg      return False;				\
989848b8605Smrg    }                                           \
990848b8605Smrg  } while (0);
991848b8605Smrg
992848b8605Smrg/**
993848b8605Smrg * Determine if two GLXFBConfigs are compatible.
994848b8605Smrg *
995848b8605Smrg * \param a  Application specified config to test.
996848b8605Smrg * \param b  Server specified config to test against \c a.
997848b8605Smrg */
998848b8605Smrgstatic Bool
999848b8605Smrgfbconfigs_compatible(const struct glx_config * const a,
1000848b8605Smrg                     const struct glx_config * const b)
1001848b8605Smrg{
1002848b8605Smrg   MATCH_DONT_CARE(doubleBufferMode);
1003848b8605Smrg   MATCH_DONT_CARE(visualType);
1004848b8605Smrg   MATCH_DONT_CARE(visualRating);
1005848b8605Smrg   MATCH_DONT_CARE(xRenderable);
1006848b8605Smrg   MATCH_DONT_CARE(fbconfigID);
1007848b8605Smrg   MATCH_DONT_CARE(swapMethod);
1008848b8605Smrg
1009848b8605Smrg   MATCH_MINIMUM(rgbBits);
1010848b8605Smrg   MATCH_MINIMUM(numAuxBuffers);
1011848b8605Smrg   MATCH_MINIMUM(redBits);
1012848b8605Smrg   MATCH_MINIMUM(greenBits);
1013848b8605Smrg   MATCH_MINIMUM(blueBits);
1014848b8605Smrg   MATCH_MINIMUM(alphaBits);
1015848b8605Smrg   MATCH_MINIMUM(depthBits);
1016848b8605Smrg   MATCH_MINIMUM(stencilBits);
1017848b8605Smrg   MATCH_MINIMUM(accumRedBits);
1018848b8605Smrg   MATCH_MINIMUM(accumGreenBits);
1019848b8605Smrg   MATCH_MINIMUM(accumBlueBits);
1020848b8605Smrg   MATCH_MINIMUM(accumAlphaBits);
1021848b8605Smrg   MATCH_MINIMUM(sampleBuffers);
1022848b8605Smrg   MATCH_MINIMUM(maxPbufferWidth);
1023848b8605Smrg   MATCH_MINIMUM(maxPbufferHeight);
1024848b8605Smrg   MATCH_MINIMUM(maxPbufferPixels);
1025848b8605Smrg   MATCH_MINIMUM(samples);
1026848b8605Smrg
1027848b8605Smrg   MATCH_DONT_CARE(stereoMode);
1028848b8605Smrg   MATCH_EXACT(level);
1029848b8605Smrg
1030848b8605Smrg   MATCH_MASK(drawableType);
1031848b8605Smrg   MATCH_MASK(renderType);
1032b8e80941Smrg   MATCH_DONT_CARE(sRGBCapable);
1033848b8605Smrg
1034848b8605Smrg   /* There is a bug in a few of the XFree86 DDX drivers.  They contain
1035848b8605Smrg    * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1036848b8605Smrg    * Technically speaking, it is a bug in the DDX driver, but there is
1037848b8605Smrg    * enough of an installed base to work around the problem here.  In any
1038848b8605Smrg    * case, 0 is not a valid value of the transparent type, so we'll treat 0
1039848b8605Smrg    * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1040848b8605Smrg    * 0 from the server to be a match to maintain backward compatibility with
1041848b8605Smrg    * the (broken) drivers.
1042848b8605Smrg    */
1043848b8605Smrg
1044848b8605Smrg   if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) {
1045848b8605Smrg      if (a->transparentPixel == GLX_NONE) {
1046848b8605Smrg         if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
1047848b8605Smrg            return False;
1048848b8605Smrg      }
1049848b8605Smrg      else {
1050848b8605Smrg         MATCH_EXACT(transparentPixel);
1051848b8605Smrg      }
1052848b8605Smrg
1053848b8605Smrg      switch (a->transparentPixel) {
1054848b8605Smrg      case GLX_TRANSPARENT_RGB:
1055848b8605Smrg         MATCH_DONT_CARE(transparentRed);
1056848b8605Smrg         MATCH_DONT_CARE(transparentGreen);
1057848b8605Smrg         MATCH_DONT_CARE(transparentBlue);
1058848b8605Smrg         MATCH_DONT_CARE(transparentAlpha);
1059848b8605Smrg         break;
1060848b8605Smrg
1061848b8605Smrg      case GLX_TRANSPARENT_INDEX:
1062848b8605Smrg         MATCH_DONT_CARE(transparentIndex);
1063848b8605Smrg         break;
1064848b8605Smrg
1065848b8605Smrg      default:
1066848b8605Smrg         break;
1067848b8605Smrg      }
1068848b8605Smrg   }
1069848b8605Smrg
1070848b8605Smrg   return True;
1071848b8605Smrg}
1072848b8605Smrg
1073848b8605Smrg
1074848b8605Smrg/* There's some trickly language in the GLX spec about how this is supposed
1075848b8605Smrg * to work.  Basically, if a given component size is either not specified
1076848b8605Smrg * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1077848b8605Smrg * Well, that's really hard to do with the code as-is.  This behavior is
1078848b8605Smrg * closer to correct, but still not technically right.
1079848b8605Smrg */
1080848b8605Smrg#define PREFER_LARGER_OR_ZERO(comp)             \
1081848b8605Smrg  do {                                          \
1082848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1083848b8605Smrg      if ( ((*a)-> comp) == 0 ) {               \
1084848b8605Smrg        return -1;                              \
1085848b8605Smrg      }                                         \
1086848b8605Smrg      else if ( ((*b)-> comp) == 0 ) {          \
1087848b8605Smrg        return 1;                               \
1088848b8605Smrg      }                                         \
1089848b8605Smrg      else {                                    \
1090848b8605Smrg        return ((*b)-> comp) - ((*a)-> comp) ;  \
1091848b8605Smrg      }                                         \
1092848b8605Smrg    }                                           \
1093848b8605Smrg  } while( 0 )
1094848b8605Smrg
1095848b8605Smrg#define PREFER_LARGER(comp)                     \
1096848b8605Smrg  do {                                          \
1097848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1098848b8605Smrg      return ((*b)-> comp) - ((*a)-> comp) ;    \
1099848b8605Smrg    }                                           \
1100848b8605Smrg  } while( 0 )
1101848b8605Smrg
1102848b8605Smrg#define PREFER_SMALLER(comp)                    \
1103848b8605Smrg  do {                                          \
1104848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1105848b8605Smrg      return ((*a)-> comp) - ((*b)-> comp) ;    \
1106848b8605Smrg    }                                           \
1107848b8605Smrg  } while( 0 )
1108848b8605Smrg
1109848b8605Smrg/**
1110848b8605Smrg * Compare two GLXFBConfigs.  This function is intended to be used as the
1111848b8605Smrg * compare function passed in to qsort.
1112848b8605Smrg *
1113848b8605Smrg * \returns If \c a is a "better" config, according to the specification of
1114848b8605Smrg *          SGIX_fbconfig, a number less than zero is returned.  If \c b is
1115848b8605Smrg *          better, then a number greater than zero is return.  If both are
1116848b8605Smrg *          equal, zero is returned.
1117848b8605Smrg * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1118848b8605Smrg */
1119848b8605Smrgstatic int
1120848b8605Smrgfbconfig_compare(struct glx_config **a, struct glx_config **b)
1121848b8605Smrg{
1122848b8605Smrg   /* The order of these comparisons must NOT change.  It is defined by
1123848b8605Smrg    * the GLX 1.4 specification.
1124848b8605Smrg    */
1125848b8605Smrg
1126848b8605Smrg   PREFER_SMALLER(visualSelectGroup);
1127848b8605Smrg
1128848b8605Smrg   /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1129848b8605Smrg    * GLX_NON_CONFORMANT_CONFIG.  It just so happens that this is the
1130848b8605Smrg    * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1131848b8605Smrg    */
1132848b8605Smrg   PREFER_SMALLER(visualRating);
1133848b8605Smrg
1134848b8605Smrg   /* This isn't quite right.  It is supposed to compare the sum of the
1135848b8605Smrg    * components the user specifically set minimums for.
1136848b8605Smrg    */
1137848b8605Smrg   PREFER_LARGER_OR_ZERO(redBits);
1138848b8605Smrg   PREFER_LARGER_OR_ZERO(greenBits);
1139848b8605Smrg   PREFER_LARGER_OR_ZERO(blueBits);
1140848b8605Smrg   PREFER_LARGER_OR_ZERO(alphaBits);
1141848b8605Smrg
1142848b8605Smrg   PREFER_SMALLER(rgbBits);
1143848b8605Smrg
1144848b8605Smrg   if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
1145848b8605Smrg      /* Prefer single-buffer.
1146848b8605Smrg       */
1147848b8605Smrg      return (!(*a)->doubleBufferMode) ? -1 : 1;
1148848b8605Smrg   }
1149848b8605Smrg
1150848b8605Smrg   PREFER_SMALLER(numAuxBuffers);
1151848b8605Smrg
1152848b8605Smrg   PREFER_SMALLER(sampleBuffers);
1153848b8605Smrg   PREFER_SMALLER(samples);
1154848b8605Smrg
1155848b8605Smrg   PREFER_LARGER_OR_ZERO(depthBits);
1156848b8605Smrg   PREFER_SMALLER(stencilBits);
1157848b8605Smrg
1158848b8605Smrg   /* This isn't quite right.  It is supposed to compare the sum of the
1159848b8605Smrg    * components the user specifically set minimums for.
1160848b8605Smrg    */
1161848b8605Smrg   PREFER_LARGER_OR_ZERO(accumRedBits);
1162848b8605Smrg   PREFER_LARGER_OR_ZERO(accumGreenBits);
1163848b8605Smrg   PREFER_LARGER_OR_ZERO(accumBlueBits);
1164848b8605Smrg   PREFER_LARGER_OR_ZERO(accumAlphaBits);
1165848b8605Smrg
1166848b8605Smrg   PREFER_SMALLER(visualType);
1167848b8605Smrg
1168848b8605Smrg   /* None of the pbuffer or fbconfig specs say that this comparison needs
1169848b8605Smrg    * to happen at all, but it seems like it should.
1170848b8605Smrg    */
1171848b8605Smrg   PREFER_LARGER(maxPbufferWidth);
1172848b8605Smrg   PREFER_LARGER(maxPbufferHeight);
1173848b8605Smrg   PREFER_LARGER(maxPbufferPixels);
1174848b8605Smrg
1175848b8605Smrg   return 0;
1176848b8605Smrg}
1177848b8605Smrg
1178848b8605Smrg
1179848b8605Smrg/**
1180848b8605Smrg * Selects and sorts a subset of the supplied configs based on the attributes.
1181b8e80941Smrg * This function forms to basis of \c glXChooseFBConfig and
1182b8e80941Smrg * \c glXChooseFBConfigSGIX.
1183848b8605Smrg *
1184848b8605Smrg * \param configs   Array of pointers to possible configs.  The elements of
1185848b8605Smrg *                  this array that do not meet the criteria will be set to
1186848b8605Smrg *                  NULL.  The remaining elements will be sorted according to
1187848b8605Smrg *                  the various visual / FBConfig selection rules.
1188848b8605Smrg * \param num_configs  Number of elements in the \c configs array.
1189848b8605Smrg * \param attribList   Attributes used select from \c configs.  This array is
1190b8e80941Smrg *                     terminated by a \c None tag.  The array is of the form
1191b8e80941Smrg *                     expected by \c glXChooseFBConfig (where every tag has a
1192b8e80941Smrg *                     value).
1193848b8605Smrg * \returns The number of valid elements left in \c configs.
1194848b8605Smrg *
1195b8e80941Smrg * \sa glXChooseFBConfig, glXChooseFBConfigSGIX
1196848b8605Smrg */
1197848b8605Smrgstatic int
1198b8e80941Smrgchoose_fbconfig(struct glx_config ** configs, int num_configs,
1199b8e80941Smrg              const int *attribList)
1200848b8605Smrg{
1201848b8605Smrg   struct glx_config test_config;
1202848b8605Smrg   int base;
1203848b8605Smrg   int i;
1204848b8605Smrg
1205848b8605Smrg   /* This is a fairly direct implementation of the selection method
1206848b8605Smrg    * described by GLX_SGIX_fbconfig.  Start by culling out all the
1207848b8605Smrg    * configs that are not compatible with the selected parameter
1208848b8605Smrg    * list.
1209848b8605Smrg    */
1210848b8605Smrg
1211b8e80941Smrg   init_fbconfig_for_chooser(&test_config, GL_TRUE);
1212848b8605Smrg   __glXInitializeVisualConfigFromTags(&test_config, 512,
1213848b8605Smrg                                       (const INT32 *) attribList,
1214b8e80941Smrg                                       GL_TRUE, GL_TRUE);
1215848b8605Smrg
1216848b8605Smrg   base = 0;
1217848b8605Smrg   for (i = 0; i < num_configs; i++) {
1218848b8605Smrg      if (fbconfigs_compatible(&test_config, configs[i])) {
1219848b8605Smrg         configs[base] = configs[i];
1220848b8605Smrg         base++;
1221848b8605Smrg      }
1222848b8605Smrg   }
1223848b8605Smrg
1224848b8605Smrg   if (base == 0) {
1225848b8605Smrg      return 0;
1226848b8605Smrg   }
1227848b8605Smrg
1228848b8605Smrg   if (base < num_configs) {
1229848b8605Smrg      (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
1230848b8605Smrg   }
1231848b8605Smrg
1232848b8605Smrg   /* After the incompatible configs are removed, the resulting
1233848b8605Smrg    * list is sorted according to the rules set out in the various
1234848b8605Smrg    * specifications.
1235848b8605Smrg    */
1236848b8605Smrg
1237848b8605Smrg   qsort(configs, base, sizeof(struct glx_config *),
1238848b8605Smrg         (int (*)(const void *, const void *)) fbconfig_compare);
1239848b8605Smrg   return base;
1240848b8605Smrg}
1241848b8605Smrg
1242848b8605Smrg
1243848b8605Smrg
1244848b8605Smrg
1245848b8605Smrg/*
1246848b8605Smrg** Return the visual that best matches the template.  Return None if no
1247848b8605Smrg** visual matches the template.
1248848b8605Smrg*/
1249b8e80941Smrg_GLX_PUBLIC XVisualInfo *
1250848b8605SmrgglXChooseVisual(Display * dpy, int screen, int *attribList)
1251848b8605Smrg{
1252848b8605Smrg   XVisualInfo *visualList = NULL;
1253848b8605Smrg   struct glx_display *priv;
1254848b8605Smrg   struct glx_screen *psc;
1255848b8605Smrg   struct glx_config test_config;
1256848b8605Smrg   struct glx_config *config;
1257848b8605Smrg   struct glx_config *best_config = NULL;
1258848b8605Smrg
1259848b8605Smrg   /*
1260848b8605Smrg    ** Get a list of all visuals, return if list is empty
1261848b8605Smrg    */
1262848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1263848b8605Smrg      return None;
1264848b8605Smrg   }
1265848b8605Smrg
1266848b8605Smrg
1267848b8605Smrg   /*
1268848b8605Smrg    ** Build a template from the defaults and the attribute list
1269848b8605Smrg    ** Free visual list and return if an unexpected token is encountered
1270848b8605Smrg    */
1271848b8605Smrg   init_fbconfig_for_chooser(&test_config, GL_FALSE);
1272848b8605Smrg   __glXInitializeVisualConfigFromTags(&test_config, 512,
1273848b8605Smrg                                       (const INT32 *) attribList,
1274848b8605Smrg                                       GL_TRUE, GL_FALSE);
1275848b8605Smrg
1276848b8605Smrg   /*
1277848b8605Smrg    ** Eliminate visuals that don't meet minimum requirements
1278848b8605Smrg    ** Compute a score for those that do
1279848b8605Smrg    ** Remember which visual, if any, got the highest score
1280848b8605Smrg    ** If no visual is acceptable, return None
1281848b8605Smrg    ** Otherwise, create an XVisualInfo list with just the selected X visual
1282848b8605Smrg    ** and return this.
1283848b8605Smrg    */
1284848b8605Smrg   for (config = psc->visuals; config != NULL; config = config->next) {
1285848b8605Smrg      if (fbconfigs_compatible(&test_config, config)
1286848b8605Smrg          && ((best_config == NULL) ||
1287848b8605Smrg              (fbconfig_compare (&config, &best_config) < 0))) {
1288848b8605Smrg         XVisualInfo visualTemplate;
1289848b8605Smrg         XVisualInfo *newList;
1290848b8605Smrg         int i;
1291848b8605Smrg
1292848b8605Smrg         visualTemplate.screen = screen;
1293848b8605Smrg         visualTemplate.visualid = config->visualID;
1294848b8605Smrg         newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
1295848b8605Smrg                                  &visualTemplate, &i);
1296848b8605Smrg
1297848b8605Smrg         if (newList) {
1298848b8605Smrg            free(visualList);
1299848b8605Smrg            visualList = newList;
1300848b8605Smrg            best_config = config;
1301848b8605Smrg         }
1302848b8605Smrg      }
1303848b8605Smrg   }
1304848b8605Smrg
1305848b8605Smrg#ifdef GLX_USE_APPLEGL
1306b8e80941Smrg   if(visualList && env_var_as_boolean("LIBGL_DUMP_VISUALID", false)) {
1307848b8605Smrg      printf("visualid 0x%lx\n", visualList[0].visualid);
1308848b8605Smrg   }
1309848b8605Smrg#endif
1310848b8605Smrg
1311848b8605Smrg   return visualList;
1312848b8605Smrg}
1313848b8605Smrg
1314848b8605Smrg
1315b8e80941Smrg_GLX_PUBLIC const char *
1316848b8605SmrgglXQueryExtensionsString(Display * dpy, int screen)
1317848b8605Smrg{
1318848b8605Smrg   struct glx_screen *psc;
1319848b8605Smrg   struct glx_display *priv;
1320848b8605Smrg
1321848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1322848b8605Smrg      return NULL;
1323848b8605Smrg   }
1324848b8605Smrg
1325848b8605Smrg   if (!psc->effectiveGLXexts) {
1326848b8605Smrg      if (!psc->serverGLXexts) {
1327848b8605Smrg         psc->serverGLXexts =
1328848b8605Smrg            __glXQueryServerString(dpy, priv->majorOpcode, screen,
1329848b8605Smrg                                   GLX_EXTENSIONS);
1330848b8605Smrg      }
1331848b8605Smrg
1332848b8605Smrg      __glXCalculateUsableExtensions(psc,
1333848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1334848b8605Smrg                                     (psc->driScreen != NULL),
1335848b8605Smrg#else
1336848b8605Smrg                                     GL_FALSE,
1337848b8605Smrg#endif
1338848b8605Smrg                                     priv->minorVersion);
1339848b8605Smrg   }
1340848b8605Smrg
1341848b8605Smrg   return psc->effectiveGLXexts;
1342848b8605Smrg}
1343848b8605Smrg
1344b8e80941Smrg_GLX_PUBLIC const char *
1345848b8605SmrgglXGetClientString(Display * dpy, int name)
1346848b8605Smrg{
1347848b8605Smrg   (void) dpy;
1348848b8605Smrg
1349848b8605Smrg   switch (name) {
1350848b8605Smrg   case GLX_VENDOR:
1351848b8605Smrg      return (__glXGLXClientVendorName);
1352848b8605Smrg   case GLX_VERSION:
1353848b8605Smrg      return (__glXGLXClientVersion);
1354848b8605Smrg   case GLX_EXTENSIONS:
1355848b8605Smrg      return (__glXGetClientExtensions());
1356848b8605Smrg   default:
1357848b8605Smrg      return NULL;
1358848b8605Smrg   }
1359848b8605Smrg}
1360848b8605Smrg
1361b8e80941Smrg_GLX_PUBLIC const char *
1362848b8605SmrgglXQueryServerString(Display * dpy, int screen, int name)
1363848b8605Smrg{
1364848b8605Smrg   struct glx_screen *psc;
1365848b8605Smrg   struct glx_display *priv;
1366848b8605Smrg   const char **str;
1367848b8605Smrg
1368848b8605Smrg
1369848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1370848b8605Smrg      return NULL;
1371848b8605Smrg   }
1372848b8605Smrg
1373848b8605Smrg   switch (name) {
1374848b8605Smrg   case GLX_VENDOR:
1375848b8605Smrg      str = &priv->serverGLXvendor;
1376848b8605Smrg      break;
1377848b8605Smrg   case GLX_VERSION:
1378848b8605Smrg      str = &priv->serverGLXversion;
1379848b8605Smrg      break;
1380848b8605Smrg   case GLX_EXTENSIONS:
1381848b8605Smrg      str = &psc->serverGLXexts;
1382848b8605Smrg      break;
1383848b8605Smrg   default:
1384848b8605Smrg      return NULL;
1385848b8605Smrg   }
1386848b8605Smrg
1387848b8605Smrg   if (*str == NULL) {
1388848b8605Smrg      *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
1389848b8605Smrg   }
1390848b8605Smrg
1391848b8605Smrg   return *str;
1392848b8605Smrg}
1393848b8605Smrg
1394848b8605Smrg
1395848b8605Smrg/*
1396848b8605Smrg** EXT_import_context
1397848b8605Smrg*/
1398848b8605Smrg
1399b8e80941Smrg_GLX_PUBLIC Display *
1400848b8605SmrgglXGetCurrentDisplay(void)
1401848b8605Smrg{
1402848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1403b8e80941Smrg   if (gc == &dummyContext)
1404848b8605Smrg      return NULL;
1405848b8605Smrg   return gc->currentDpy;
1406848b8605Smrg}
1407848b8605Smrg
1408b8e80941Smrg_GLX_PUBLIC
1409848b8605SmrgGLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1410848b8605Smrg          glXGetCurrentDisplay)
1411848b8605Smrg
1412848b8605Smrg#ifndef GLX_USE_APPLEGL
1413b8e80941Smrg_GLX_PUBLIC GLXContext
1414848b8605SmrgglXImportContextEXT(Display *dpy, GLXContextID contextID)
1415848b8605Smrg{
1416848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
1417848b8605Smrg   struct glx_screen *psc = NULL;
1418848b8605Smrg   xGLXQueryContextReply reply;
1419848b8605Smrg   CARD8 opcode;
1420848b8605Smrg   struct glx_context *ctx;
1421b8e80941Smrg   int i, renderType = GLX_RGBA_TYPE; /* By default, assume RGBA context */
1422b8e80941Smrg   XID share = None;
1423b8e80941Smrg   struct glx_config *mode = NULL;
1424848b8605Smrg   uint32_t fbconfigID = 0;
1425848b8605Smrg   uint32_t visualID = 0;
1426848b8605Smrg   uint32_t screen = 0;
1427848b8605Smrg   Bool got_screen = False;
1428848b8605Smrg
1429848b8605Smrg   if (priv == NULL)
1430848b8605Smrg      return NULL;
1431848b8605Smrg
1432848b8605Smrg   /* The GLX_EXT_import_context spec says:
1433848b8605Smrg    *
1434848b8605Smrg    *     "If <contextID> does not refer to a valid context, then a BadContext
1435848b8605Smrg    *     error is generated; if <contextID> refers to direct rendering
1436848b8605Smrg    *     context then no error is generated but glXImportContextEXT returns
1437848b8605Smrg    *     NULL."
1438848b8605Smrg    *
1439848b8605Smrg    * If contextID is None, generate BadContext on the client-side.  Other
1440848b8605Smrg    * sorts of invalid contexts will be detected by the server in the
1441848b8605Smrg    * __glXIsDirect call.
1442848b8605Smrg    */
1443848b8605Smrg   if (contextID == None) {
1444848b8605Smrg      __glXSendError(dpy, GLXBadContext, contextID, X_GLXIsDirect, false);
1445848b8605Smrg      return NULL;
1446848b8605Smrg   }
1447848b8605Smrg
1448b8e80941Smrg   if (__glXIsDirect(dpy, contextID, NULL))
1449848b8605Smrg      return NULL;
1450848b8605Smrg
1451848b8605Smrg   opcode = __glXSetupForCommand(dpy);
1452848b8605Smrg   if (!opcode)
1453848b8605Smrg      return 0;
1454848b8605Smrg
1455848b8605Smrg   /* Send the glXQueryContextInfoEXT request */
1456848b8605Smrg   LockDisplay(dpy);
1457848b8605Smrg
1458848b8605Smrg   if (priv->majorVersion > 1 || priv->minorVersion >= 3) {
1459848b8605Smrg      xGLXQueryContextReq *req;
1460848b8605Smrg
1461848b8605Smrg      GetReq(GLXQueryContext, req);
1462848b8605Smrg
1463848b8605Smrg      req->reqType = opcode;
1464848b8605Smrg      req->glxCode = X_GLXQueryContext;
1465848b8605Smrg      req->context = contextID;
1466848b8605Smrg   }
1467848b8605Smrg   else {
1468848b8605Smrg      xGLXVendorPrivateReq *vpreq;
1469848b8605Smrg      xGLXQueryContextInfoEXTReq *req;
1470848b8605Smrg
1471848b8605Smrg      GetReqExtra(GLXVendorPrivate,
1472848b8605Smrg		  sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1473848b8605Smrg		  vpreq);
1474848b8605Smrg      req = (xGLXQueryContextInfoEXTReq *) vpreq;
1475848b8605Smrg      req->reqType = opcode;
1476848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
1477848b8605Smrg      req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1478848b8605Smrg      req->context = contextID;
1479848b8605Smrg   }
1480848b8605Smrg
1481b8e80941Smrg   if (_XReply(dpy, (xReply *) & reply, 0, False) &&
1482b8e80941Smrg       reply.n < (INT32_MAX / 2)) {
1483b8e80941Smrg
1484b8e80941Smrg      for (i = 0; i < reply.n; i++) {
1485b8e80941Smrg         int prop[2];
1486b8e80941Smrg
1487b8e80941Smrg         _XRead(dpy, (char *)prop, sizeof(prop));
1488b8e80941Smrg         switch (prop[0]) {
1489b8e80941Smrg         case GLX_SCREEN:
1490b8e80941Smrg            screen = prop[1];
1491b8e80941Smrg            got_screen = True;
1492b8e80941Smrg            break;
1493b8e80941Smrg         case GLX_SHARE_CONTEXT_EXT:
1494b8e80941Smrg            share = prop[1];
1495b8e80941Smrg            break;
1496b8e80941Smrg         case GLX_VISUAL_ID_EXT:
1497b8e80941Smrg            visualID = prop[1];
1498b8e80941Smrg            break;
1499b8e80941Smrg         case GLX_FBCONFIG_ID:
1500b8e80941Smrg            fbconfigID = prop[1];
1501b8e80941Smrg            break;
1502b8e80941Smrg         case GLX_RENDER_TYPE:
1503b8e80941Smrg            renderType = prop[1];
1504b8e80941Smrg            break;
1505b8e80941Smrg         }
1506b8e80941Smrg      }
1507b8e80941Smrg   }
1508848b8605Smrg   UnlockDisplay(dpy);
1509848b8605Smrg   SyncHandle();
1510848b8605Smrg
1511848b8605Smrg   if (!got_screen)
1512848b8605Smrg      return NULL;
1513848b8605Smrg
1514848b8605Smrg   psc = GetGLXScreenConfigs(dpy, screen);
1515848b8605Smrg   if (psc == NULL)
1516848b8605Smrg      return NULL;
1517848b8605Smrg
1518848b8605Smrg   if (fbconfigID != 0) {
1519848b8605Smrg      mode = glx_config_find_fbconfig(psc->configs, fbconfigID);
1520848b8605Smrg   } else if (visualID != 0) {
1521848b8605Smrg      mode = glx_config_find_visual(psc->visuals, visualID);
1522848b8605Smrg   }
1523848b8605Smrg
1524848b8605Smrg   if (mode == NULL)
1525848b8605Smrg      return NULL;
1526848b8605Smrg
1527848b8605Smrg   ctx = indirect_create_context(psc, mode, NULL, renderType);
1528848b8605Smrg   if (ctx == NULL)
1529848b8605Smrg      return NULL;
1530848b8605Smrg
1531848b8605Smrg   ctx->xid = contextID;
1532848b8605Smrg   ctx->imported = GL_TRUE;
1533848b8605Smrg   ctx->share_xid = share;
1534848b8605Smrg
1535848b8605Smrg   return (GLXContext) ctx;
1536848b8605Smrg}
1537848b8605Smrg
1538848b8605Smrg#endif
1539848b8605Smrg
1540b8e80941Smrg_GLX_PUBLIC int
1541848b8605SmrgglXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value)
1542848b8605Smrg{
1543848b8605Smrg   struct glx_context *ctx = (struct glx_context *) ctx_user;
1544848b8605Smrg
1545848b8605Smrg   switch (attribute) {
1546848b8605Smrg      case GLX_SHARE_CONTEXT_EXT:
1547848b8605Smrg      *value = ctx->share_xid;
1548848b8605Smrg      break;
1549848b8605Smrg   case GLX_VISUAL_ID_EXT:
1550848b8605Smrg      *value = ctx->config ? ctx->config->visualID : None;
1551848b8605Smrg      break;
1552848b8605Smrg   case GLX_SCREEN:
1553848b8605Smrg      *value = ctx->screen;
1554848b8605Smrg      break;
1555848b8605Smrg   case GLX_FBCONFIG_ID:
1556848b8605Smrg      *value = ctx->config ? ctx->config->fbconfigID : None;
1557848b8605Smrg      break;
1558848b8605Smrg   case GLX_RENDER_TYPE:
1559848b8605Smrg      *value = ctx->renderType;
1560848b8605Smrg      break;
1561848b8605Smrg   default:
1562848b8605Smrg      return GLX_BAD_ATTRIBUTE;
1563848b8605Smrg   }
1564848b8605Smrg   return Success;
1565848b8605Smrg}
1566848b8605Smrg
1567b8e80941Smrg_GLX_PUBLIC
1568848b8605SmrgGLX_ALIAS(int, glXQueryContextInfoEXT,
1569848b8605Smrg          (Display * dpy, GLXContext ctx, int attribute, int *value),
1570848b8605Smrg          (dpy, ctx, attribute, value), glXQueryContext)
1571848b8605Smrg
1572b8e80941Smrg_GLX_PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
1573848b8605Smrg{
1574848b8605Smrg   struct glx_context *ctx = (struct glx_context *) ctx_user;
1575848b8605Smrg
1576848b8605Smrg   return (ctx == NULL) ? None : ctx->xid;
1577848b8605Smrg}
1578848b8605Smrg
1579b8e80941Smrg_GLX_PUBLIC void
1580848b8605SmrgglXFreeContextEXT(Display *dpy, GLXContext ctx)
1581848b8605Smrg{
1582848b8605Smrg   struct glx_context *gc = (struct glx_context *) ctx;
1583848b8605Smrg
1584848b8605Smrg   if (gc == NULL || gc->xid == None)
1585848b8605Smrg      return;
1586848b8605Smrg
1587848b8605Smrg   /* The GLX_EXT_import_context spec says:
1588848b8605Smrg    *
1589848b8605Smrg    *     "glXFreeContext does not free the server-side context information or
1590848b8605Smrg    *     the XID associated with the server-side context."
1591848b8605Smrg    *
1592848b8605Smrg    * Don't send any protocol.  Just destroy the client-side tracking of the
1593848b8605Smrg    * context.  Also, only release the context structure if it's not current.
1594848b8605Smrg    */
1595848b8605Smrg   __glXLock();
1596848b8605Smrg   if (gc->currentDpy) {
1597848b8605Smrg      gc->xid = None;
1598848b8605Smrg   } else {
1599848b8605Smrg      gc->vtable->destroy(gc);
1600848b8605Smrg   }
1601848b8605Smrg   __glXUnlock();
1602848b8605Smrg}
1603848b8605Smrg
1604b8e80941Smrg_GLX_PUBLIC GLXFBConfig *
1605848b8605SmrgglXChooseFBConfig(Display * dpy, int screen,
1606848b8605Smrg                  const int *attribList, int *nitems)
1607848b8605Smrg{
1608848b8605Smrg   struct glx_config **config_list;
1609848b8605Smrg   int list_size;
1610848b8605Smrg
1611848b8605Smrg
1612848b8605Smrg   config_list = (struct glx_config **)
1613848b8605Smrg      glXGetFBConfigs(dpy, screen, &list_size);
1614848b8605Smrg
1615848b8605Smrg   if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1616b8e80941Smrg      list_size = choose_fbconfig(config_list, list_size, attribList);
1617848b8605Smrg      if (list_size == 0) {
1618848b8605Smrg         free(config_list);
1619848b8605Smrg         config_list = NULL;
1620848b8605Smrg      }
1621848b8605Smrg   }
1622848b8605Smrg
1623848b8605Smrg   *nitems = list_size;
1624848b8605Smrg   return (GLXFBConfig *) config_list;
1625848b8605Smrg}
1626848b8605Smrg
1627848b8605Smrg
1628b8e80941Smrg_GLX_PUBLIC GLXContext
1629848b8605SmrgglXCreateNewContext(Display * dpy, GLXFBConfig fbconfig,
1630848b8605Smrg                    int renderType, GLXContext shareList, Bool allowDirect)
1631848b8605Smrg{
1632848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1633b8e80941Smrg   struct glx_config **config_list;
1634b8e80941Smrg   int list_size;
1635b8e80941Smrg   unsigned i;
1636b8e80941Smrg
1637b8e80941Smrg   if (!config) {
1638b8e80941Smrg       __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false);
1639b8e80941Smrg       return NULL;
1640b8e80941Smrg   }
1641b8e80941Smrg
1642b8e80941Smrg   config_list = (struct glx_config **)
1643b8e80941Smrg      glXGetFBConfigs(dpy, config->screen, &list_size);
1644b8e80941Smrg
1645b8e80941Smrg   for (i = 0; i < list_size; i++) {
1646b8e80941Smrg       if (config_list[i] == config)
1647b8e80941Smrg           break;
1648b8e80941Smrg   }
1649b8e80941Smrg   free(config_list);
1650b8e80941Smrg
1651b8e80941Smrg   if (i == list_size) {
1652b8e80941Smrg       __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false);
1653b8e80941Smrg       return NULL;
1654b8e80941Smrg   }
1655848b8605Smrg
1656848b8605Smrg   return CreateContext(dpy, config->fbconfigID, config, shareList,
1657848b8605Smrg			allowDirect, X_GLXCreateNewContext, renderType,
1658848b8605Smrg			config->screen);
1659848b8605Smrg}
1660848b8605Smrg
1661848b8605Smrg
1662b8e80941Smrg_GLX_PUBLIC GLXDrawable
1663848b8605SmrgglXGetCurrentReadDrawable(void)
1664848b8605Smrg{
1665848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1666848b8605Smrg
1667848b8605Smrg   return gc->currentReadable;
1668848b8605Smrg}
1669848b8605Smrg
1670848b8605Smrg
1671b8e80941Smrg_GLX_PUBLIC GLXFBConfig *
1672848b8605SmrgglXGetFBConfigs(Display * dpy, int screen, int *nelements)
1673848b8605Smrg{
1674848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
1675848b8605Smrg   struct glx_config **config_list = NULL;
1676848b8605Smrg   struct glx_config *config;
1677848b8605Smrg   unsigned num_configs = 0;
1678848b8605Smrg   int i;
1679848b8605Smrg
1680848b8605Smrg   *nelements = 0;
1681848b8605Smrg   if (priv && (priv->screens != NULL)
1682b8e80941Smrg       && (screen >= 0) && (screen < ScreenCount(dpy))
1683848b8605Smrg       && (priv->screens[screen]->configs != NULL)
1684848b8605Smrg       && (priv->screens[screen]->configs->fbconfigID
1685848b8605Smrg	   != (int) GLX_DONT_CARE)) {
1686848b8605Smrg
1687848b8605Smrg      for (config = priv->screens[screen]->configs; config != NULL;
1688848b8605Smrg           config = config->next) {
1689848b8605Smrg         if (config->fbconfigID != (int) GLX_DONT_CARE) {
1690848b8605Smrg            num_configs++;
1691848b8605Smrg         }
1692848b8605Smrg      }
1693848b8605Smrg
1694848b8605Smrg      config_list = malloc(num_configs * sizeof *config_list);
1695848b8605Smrg      if (config_list != NULL) {
1696848b8605Smrg         *nelements = num_configs;
1697848b8605Smrg         i = 0;
1698848b8605Smrg         for (config = priv->screens[screen]->configs; config != NULL;
1699848b8605Smrg              config = config->next) {
1700848b8605Smrg            if (config->fbconfigID != (int) GLX_DONT_CARE) {
1701848b8605Smrg               config_list[i] = config;
1702848b8605Smrg               i++;
1703848b8605Smrg            }
1704848b8605Smrg         }
1705848b8605Smrg      }
1706848b8605Smrg   }
1707848b8605Smrg
1708848b8605Smrg   return (GLXFBConfig *) config_list;
1709848b8605Smrg}
1710848b8605Smrg
1711848b8605Smrg
1712b8e80941Smrg_GLX_PUBLIC int
1713848b8605SmrgglXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig,
1714848b8605Smrg                     int attribute, int *value)
1715848b8605Smrg{
1716848b8605Smrg   struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig);
1717848b8605Smrg
1718848b8605Smrg   if (config == NULL)
1719848b8605Smrg      return GLXBadFBConfig;
1720848b8605Smrg
1721848b8605Smrg   return glx_config_get(config, attribute, value);
1722848b8605Smrg}
1723848b8605Smrg
1724848b8605Smrg
1725b8e80941Smrg_GLX_PUBLIC XVisualInfo *
1726848b8605SmrgglXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig)
1727848b8605Smrg{
1728848b8605Smrg   XVisualInfo visualTemplate;
1729848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1730848b8605Smrg   int count;
1731848b8605Smrg
1732848b8605Smrg   /*
1733848b8605Smrg    ** Get a list of all visuals, return if list is empty
1734848b8605Smrg    */
1735848b8605Smrg   visualTemplate.visualid = config->visualID;
1736848b8605Smrg   return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
1737848b8605Smrg}
1738848b8605Smrg
1739848b8605Smrg#ifndef GLX_USE_APPLEGL
1740848b8605Smrg/*
1741848b8605Smrg** GLX_SGI_swap_control
1742848b8605Smrg*/
1743848b8605Smrgstatic int
1744848b8605Smrg__glXSwapIntervalSGI(int interval)
1745848b8605Smrg{
1746848b8605Smrg   xGLXVendorPrivateReq *req;
1747848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1748848b8605Smrg   struct glx_screen *psc;
1749848b8605Smrg   Display *dpy;
1750848b8605Smrg   CARD32 *interval_ptr;
1751848b8605Smrg   CARD8 opcode;
1752848b8605Smrg
1753b8e80941Smrg   if (gc == &dummyContext) {
1754848b8605Smrg      return GLX_BAD_CONTEXT;
1755848b8605Smrg   }
1756848b8605Smrg
1757848b8605Smrg   if (interval <= 0) {
1758848b8605Smrg      return GLX_BAD_VALUE;
1759848b8605Smrg   }
1760848b8605Smrg
1761848b8605Smrg   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1762848b8605Smrg
1763848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1764848b8605Smrg   if (gc->isDirect && psc && psc->driScreen &&
1765848b8605Smrg          psc->driScreen->setSwapInterval) {
1766848b8605Smrg      __GLXDRIdrawable *pdraw =
1767848b8605Smrg	 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1768b8e80941Smrg      /* Simply ignore the command if the GLX drawable has been destroyed but
1769b8e80941Smrg       * the context is still bound.
1770b8e80941Smrg       */
1771b8e80941Smrg      if (pdraw)
1772b8e80941Smrg         psc->driScreen->setSwapInterval(pdraw, interval);
1773848b8605Smrg      return 0;
1774848b8605Smrg   }
1775848b8605Smrg#endif
1776848b8605Smrg
1777848b8605Smrg   dpy = gc->currentDpy;
1778848b8605Smrg   opcode = __glXSetupForCommand(dpy);
1779848b8605Smrg   if (!opcode) {
1780848b8605Smrg      return 0;
1781848b8605Smrg   }
1782848b8605Smrg
1783848b8605Smrg   /* Send the glXSwapIntervalSGI request */
1784848b8605Smrg   LockDisplay(dpy);
1785848b8605Smrg   GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
1786848b8605Smrg   req->reqType = opcode;
1787848b8605Smrg   req->glxCode = X_GLXVendorPrivate;
1788848b8605Smrg   req->vendorCode = X_GLXvop_SwapIntervalSGI;
1789848b8605Smrg   req->contextTag = gc->currentContextTag;
1790848b8605Smrg
1791848b8605Smrg   interval_ptr = (CARD32 *) (req + 1);
1792848b8605Smrg   *interval_ptr = interval;
1793848b8605Smrg
1794848b8605Smrg   UnlockDisplay(dpy);
1795848b8605Smrg   SyncHandle();
1796848b8605Smrg   XFlush(dpy);
1797848b8605Smrg
1798848b8605Smrg   return 0;
1799848b8605Smrg}
1800848b8605Smrg
1801848b8605Smrg
1802848b8605Smrg/*
1803848b8605Smrg** GLX_MESA_swap_control
1804848b8605Smrg*/
1805848b8605Smrgstatic int
1806848b8605Smrg__glXSwapIntervalMESA(unsigned int interval)
1807848b8605Smrg{
1808848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1809848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1810848b8605Smrg
1811b8e80941Smrg   if (gc != &dummyContext && gc->isDirect) {
1812848b8605Smrg      struct glx_screen *psc;
1813848b8605Smrg
1814848b8605Smrg      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1815848b8605Smrg      if (psc && psc->driScreen && psc->driScreen->setSwapInterval) {
1816848b8605Smrg         __GLXDRIdrawable *pdraw =
1817848b8605Smrg	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1818b8e80941Smrg
1819b8e80941Smrg         /* Simply ignore the command if the GLX drawable has been destroyed but
1820b8e80941Smrg          * the context is still bound.
1821b8e80941Smrg          */
1822b8e80941Smrg         if (!pdraw)
1823b8e80941Smrg            return 0;
1824b8e80941Smrg
1825b8e80941Smrg         return psc->driScreen->setSwapInterval(pdraw, interval);
1826848b8605Smrg      }
1827848b8605Smrg   }
1828848b8605Smrg#endif
1829848b8605Smrg
1830848b8605Smrg   return GLX_BAD_CONTEXT;
1831848b8605Smrg}
1832848b8605Smrg
1833848b8605Smrg
1834848b8605Smrgstatic int
1835848b8605Smrg__glXGetSwapIntervalMESA(void)
1836848b8605Smrg{
1837848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1838848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1839848b8605Smrg
1840b8e80941Smrg   if (gc != &dummyContext && gc->isDirect) {
1841848b8605Smrg      struct glx_screen *psc;
1842848b8605Smrg
1843848b8605Smrg      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1844848b8605Smrg      if (psc && psc->driScreen && psc->driScreen->getSwapInterval) {
1845848b8605Smrg         __GLXDRIdrawable *pdraw =
1846848b8605Smrg	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1847b8e80941Smrg         if (pdraw)
1848b8e80941Smrg            return psc->driScreen->getSwapInterval(pdraw);
1849848b8605Smrg      }
1850848b8605Smrg   }
1851848b8605Smrg#endif
1852848b8605Smrg
1853848b8605Smrg   return 0;
1854848b8605Smrg}
1855848b8605Smrg
1856848b8605Smrg
1857848b8605Smrg/*
1858848b8605Smrg** GLX_SGI_video_sync
1859848b8605Smrg*/
1860848b8605Smrgstatic int
1861848b8605Smrg__glXGetVideoSyncSGI(unsigned int *count)
1862848b8605Smrg{
1863848b8605Smrg   int64_t ust, msc, sbc;
1864848b8605Smrg   int ret;
1865848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1866848b8605Smrg   struct glx_screen *psc;
1867848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1868848b8605Smrg   __GLXDRIdrawable *pdraw;
1869848b8605Smrg#endif
1870848b8605Smrg
1871b8e80941Smrg   if (gc == &dummyContext)
1872848b8605Smrg      return GLX_BAD_CONTEXT;
1873848b8605Smrg
1874848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1875848b8605Smrg   if (!gc->isDirect)
1876848b8605Smrg      return GLX_BAD_CONTEXT;
1877848b8605Smrg#endif
1878848b8605Smrg
1879848b8605Smrg   psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen);
1880848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1881848b8605Smrg   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1882848b8605Smrg#endif
1883848b8605Smrg
1884848b8605Smrg   /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1885848b8605Smrg    * FIXME: there should be a GLX encoding for this call.  I can find no
1886848b8605Smrg    * FIXME: documentation for the GLX encoding.
1887848b8605Smrg    */
1888848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1889848b8605Smrg   if (psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
1890848b8605Smrg      ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
1891848b8605Smrg      *count = (unsigned) msc;
1892848b8605Smrg      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
1893848b8605Smrg   }
1894848b8605Smrg#endif
1895848b8605Smrg
1896848b8605Smrg   return GLX_BAD_CONTEXT;
1897848b8605Smrg}
1898848b8605Smrg
1899848b8605Smrgstatic int
1900848b8605Smrg__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
1901848b8605Smrg{
1902848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1903848b8605Smrg   struct glx_screen *psc;
1904848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1905848b8605Smrg   __GLXDRIdrawable *pdraw;
1906848b8605Smrg#endif
1907848b8605Smrg   int64_t ust, msc, sbc;
1908848b8605Smrg   int ret;
1909848b8605Smrg
1910848b8605Smrg   if (divisor <= 0 || remainder < 0)
1911848b8605Smrg      return GLX_BAD_VALUE;
1912848b8605Smrg
1913b8e80941Smrg   if (gc == &dummyContext)
1914848b8605Smrg      return GLX_BAD_CONTEXT;
1915848b8605Smrg
1916848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1917848b8605Smrg   if (!gc->isDirect)
1918848b8605Smrg      return GLX_BAD_CONTEXT;
1919848b8605Smrg#endif
1920848b8605Smrg
1921848b8605Smrg   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1922848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1923848b8605Smrg   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1924848b8605Smrg#endif
1925848b8605Smrg
1926848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1927848b8605Smrg   if (psc && psc->driScreen && psc->driScreen->waitForMSC) {
1928848b8605Smrg      ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
1929848b8605Smrg				       &sbc);
1930848b8605Smrg      *count = (unsigned) msc;
1931848b8605Smrg      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
1932848b8605Smrg   }
1933848b8605Smrg#endif
1934848b8605Smrg
1935848b8605Smrg   return GLX_BAD_CONTEXT;
1936848b8605Smrg}
1937848b8605Smrg
1938848b8605Smrg#endif /* GLX_USE_APPLEGL */
1939848b8605Smrg
1940848b8605Smrg/*
1941848b8605Smrg** GLX_SGIX_fbconfig
1942848b8605Smrg** Many of these functions are aliased to GLX 1.3 entry points in the
1943848b8605Smrg** GLX_functions table.
1944848b8605Smrg*/
1945848b8605Smrg
1946b8e80941Smrg_GLX_PUBLIC
1947848b8605SmrgGLX_ALIAS(int, glXGetFBConfigAttribSGIX,
1948848b8605Smrg          (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
1949848b8605Smrg          (dpy, config, attribute, value), glXGetFBConfigAttrib)
1950848b8605Smrg
1951b8e80941Smrg_GLX_PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
1952848b8605Smrg                 (Display * dpy, int screen, int *attrib_list,
1953848b8605Smrg                  int *nelements), (dpy, screen, attrib_list, nelements),
1954848b8605Smrg                 glXChooseFBConfig)
1955848b8605Smrg
1956b8e80941Smrg_GLX_PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
1957848b8605Smrg                 (Display * dpy, GLXFBConfigSGIX config),
1958848b8605Smrg                 (dpy, config), glXGetVisualFromFBConfig)
1959848b8605Smrg
1960b8e80941Smrg_GLX_PUBLIC GLXPixmap
1961848b8605SmrgglXCreateGLXPixmapWithConfigSGIX(Display * dpy,
1962848b8605Smrg                                 GLXFBConfigSGIX fbconfig,
1963848b8605Smrg                                 Pixmap pixmap)
1964848b8605Smrg{
1965848b8605Smrg#ifndef GLX_USE_APPLEGL
1966848b8605Smrg   xGLXVendorPrivateWithReplyReq *vpreq;
1967848b8605Smrg   xGLXCreateGLXPixmapWithConfigSGIXReq *req;
1968848b8605Smrg   GLXPixmap xid = None;
1969848b8605Smrg   CARD8 opcode;
1970848b8605Smrg   struct glx_screen *psc;
1971848b8605Smrg#endif
1972848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1973848b8605Smrg
1974848b8605Smrg
1975848b8605Smrg   if ((dpy == NULL) || (config == NULL)) {
1976848b8605Smrg      return None;
1977848b8605Smrg   }
1978848b8605Smrg#ifdef GLX_USE_APPLEGL
1979848b8605Smrg   if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config))
1980848b8605Smrg      return None;
1981848b8605Smrg   return pixmap;
1982848b8605Smrg#else
1983848b8605Smrg
1984848b8605Smrg   psc = GetGLXScreenConfigs(dpy, config->screen);
1985848b8605Smrg   if ((psc != NULL)
1986848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
1987848b8605Smrg      opcode = __glXSetupForCommand(dpy);
1988848b8605Smrg      if (!opcode) {
1989848b8605Smrg         return None;
1990848b8605Smrg      }
1991848b8605Smrg
1992848b8605Smrg      /* Send the glXCreateGLXPixmapWithConfigSGIX request */
1993848b8605Smrg      LockDisplay(dpy);
1994848b8605Smrg      GetReqExtra(GLXVendorPrivateWithReply,
1995848b8605Smrg                  sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
1996848b8605Smrg                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
1997848b8605Smrg      req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
1998848b8605Smrg      req->reqType = opcode;
1999848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
2000848b8605Smrg      req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2001848b8605Smrg      req->screen = config->screen;
2002848b8605Smrg      req->fbconfig = config->fbconfigID;
2003848b8605Smrg      req->pixmap = pixmap;
2004848b8605Smrg      req->glxpixmap = xid = XAllocID(dpy);
2005848b8605Smrg      UnlockDisplay(dpy);
2006848b8605Smrg      SyncHandle();
2007848b8605Smrg   }
2008848b8605Smrg
2009848b8605Smrg   return xid;
2010848b8605Smrg#endif
2011848b8605Smrg}
2012848b8605Smrg
2013b8e80941Smrg_GLX_PUBLIC GLXContext
2014848b8605SmrgglXCreateContextWithConfigSGIX(Display * dpy,
2015848b8605Smrg                               GLXFBConfigSGIX fbconfig, int renderType,
2016848b8605Smrg                               GLXContext shareList, Bool allowDirect)
2017848b8605Smrg{
2018848b8605Smrg   GLXContext gc = NULL;
2019848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
2020848b8605Smrg   struct glx_screen *psc;
2021848b8605Smrg
2022848b8605Smrg
2023848b8605Smrg   if ((dpy == NULL) || (config == NULL)) {
2024848b8605Smrg      return None;
2025848b8605Smrg   }
2026848b8605Smrg
2027848b8605Smrg   psc = GetGLXScreenConfigs(dpy, config->screen);
2028848b8605Smrg   if ((psc != NULL)
2029848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
2030848b8605Smrg      gc = CreateContext(dpy, config->fbconfigID, config, shareList,
2031848b8605Smrg                         allowDirect,
2032848b8605Smrg			 X_GLXvop_CreateContextWithConfigSGIX, renderType,
2033848b8605Smrg			 config->screen);
2034848b8605Smrg   }
2035848b8605Smrg
2036848b8605Smrg   return gc;
2037848b8605Smrg}
2038848b8605Smrg
2039848b8605Smrg
2040b8e80941Smrg_GLX_PUBLIC GLXFBConfigSGIX
2041848b8605SmrgglXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
2042848b8605Smrg{
2043848b8605Smrg   struct glx_display *priv;
2044848b8605Smrg   struct glx_screen *psc = NULL;
2045848b8605Smrg
2046848b8605Smrg   if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success)
2047848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2048848b8605Smrg       && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
2049848b8605Smrg      return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs,
2050848b8605Smrg						      vis->visualid);
2051848b8605Smrg   }
2052848b8605Smrg
2053848b8605Smrg   return NULL;
2054848b8605Smrg}
2055848b8605Smrg
2056848b8605Smrg#ifndef GLX_USE_APPLEGL
2057848b8605Smrg/*
2058848b8605Smrg** GLX_OML_sync_control
2059848b8605Smrg*/
2060848b8605Smrgstatic Bool
2061848b8605Smrg__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2062848b8605Smrg                      int64_t * ust, int64_t * msc, int64_t * sbc)
2063848b8605Smrg{
2064848b8605Smrg   struct glx_display * const priv = __glXInitialize(dpy);
2065848b8605Smrg   int ret;
2066848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2067848b8605Smrg   __GLXDRIdrawable *pdraw;
2068848b8605Smrg#endif
2069848b8605Smrg   struct glx_screen *psc;
2070848b8605Smrg
2071848b8605Smrg   if (!priv)
2072848b8605Smrg      return False;
2073848b8605Smrg
2074848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2075848b8605Smrg   pdraw = GetGLXDRIDrawable(dpy, drawable);
2076848b8605Smrg   psc = pdraw ? pdraw->psc : NULL;
2077848b8605Smrg   if (pdraw && psc->driScreen->getDrawableMSC) {
2078848b8605Smrg      ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
2079848b8605Smrg      return ret;
2080848b8605Smrg   }
2081848b8605Smrg#endif
2082848b8605Smrg
2083848b8605Smrg   return False;
2084848b8605Smrg}
2085848b8605Smrg
2086848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2087848b8605Smrg_X_HIDDEN GLboolean
2088848b8605Smrg__glxGetMscRate(struct glx_screen *psc,
2089848b8605Smrg		int32_t * numerator, int32_t * denominator)
2090848b8605Smrg{
2091b8e80941Smrg#if !defined(GLX_USE_WINDOWSGL)
2092848b8605Smrg   XF86VidModeModeLine mode_line;
2093848b8605Smrg   int dot_clock;
2094848b8605Smrg   int i;
2095848b8605Smrg
2096848b8605Smrg   if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2097848b8605Smrg       XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2098848b8605Smrg      unsigned n = dot_clock * 1000;
2099848b8605Smrg      unsigned d = mode_line.vtotal * mode_line.htotal;
2100848b8605Smrg
2101848b8605Smrg# define V_INTERLACE 0x010
2102848b8605Smrg# define V_DBLSCAN   0x020
2103848b8605Smrg
2104848b8605Smrg      if (mode_line.flags & V_INTERLACE)
2105848b8605Smrg         n *= 2;
2106848b8605Smrg      else if (mode_line.flags & V_DBLSCAN)
2107848b8605Smrg         d *= 2;
2108848b8605Smrg
2109848b8605Smrg      /* The OML_sync_control spec requires that if the refresh rate is a
2110848b8605Smrg       * whole number, that the returned numerator be equal to the refresh
2111848b8605Smrg       * rate and the denominator be 1.
2112848b8605Smrg       */
2113848b8605Smrg
2114848b8605Smrg      if (n % d == 0) {
2115848b8605Smrg         n /= d;
2116848b8605Smrg         d = 1;
2117848b8605Smrg      }
2118848b8605Smrg      else {
2119848b8605Smrg         static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2120848b8605Smrg
2121848b8605Smrg         /* This is a poor man's way to reduce a fraction.  It's far from
2122848b8605Smrg          * perfect, but it will work well enough for this situation.
2123848b8605Smrg          */
2124848b8605Smrg
2125848b8605Smrg         for (i = 0; f[i] != 0; i++) {
2126848b8605Smrg            while (n % f[i] == 0 && d % f[i] == 0) {
2127848b8605Smrg               d /= f[i];
2128848b8605Smrg               n /= f[i];
2129848b8605Smrg            }
2130848b8605Smrg         }
2131848b8605Smrg      }
2132848b8605Smrg
2133848b8605Smrg      *numerator = n;
2134848b8605Smrg      *denominator = d;
2135848b8605Smrg
2136848b8605Smrg      return True;
2137848b8605Smrg   }
2138848b8605Smrg#endif
2139848b8605Smrg
2140848b8605Smrg   return False;
2141848b8605Smrg}
2142848b8605Smrg#endif
2143848b8605Smrg
2144848b8605Smrg/**
2145848b8605Smrg * Determine the refresh rate of the specified drawable and display.
2146848b8605Smrg *
2147848b8605Smrg * \param dpy          Display whose refresh rate is to be determined.
2148848b8605Smrg * \param drawable     Drawable whose refresh rate is to be determined.
2149848b8605Smrg * \param numerator    Numerator of the refresh rate.
2150848b8605Smrg * \param demoninator  Denominator of the refresh rate.
2151848b8605Smrg * \return  If the refresh rate for the specified display and drawable could
2152848b8605Smrg *          be calculated, True is returned.  Otherwise False is returned.
2153848b8605Smrg *
2154848b8605Smrg * \note This function is implemented entirely client-side.  A lot of other
2155848b8605Smrg *       functionality is required to export GLX_OML_sync_control, so on
2156848b8605Smrg *       XFree86 this function can be called for direct-rendering contexts
2157848b8605Smrg *       when GLX_OML_sync_control appears in the client extension string.
2158848b8605Smrg */
2159848b8605Smrg
2160848b8605Smrg_X_HIDDEN GLboolean
2161848b8605Smrg__glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2162848b8605Smrg                   int32_t * numerator, int32_t * denominator)
2163848b8605Smrg{
2164b8e80941Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) && !defined(GLX_USE_WINDOWSGL)
2165848b8605Smrg   __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable);
2166848b8605Smrg
2167848b8605Smrg   if (draw == NULL)
2168848b8605Smrg      return False;
2169848b8605Smrg
2170848b8605Smrg   return __glxGetMscRate(draw->psc, numerator, denominator);
2171848b8605Smrg#else
2172848b8605Smrg   (void) dpy;
2173848b8605Smrg   (void) drawable;
2174848b8605Smrg   (void) numerator;
2175848b8605Smrg   (void) denominator;
2176848b8605Smrg#endif
2177848b8605Smrg   return False;
2178848b8605Smrg}
2179848b8605Smrg
2180848b8605Smrg
2181848b8605Smrgstatic int64_t
2182848b8605Smrg__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable,
2183848b8605Smrg                       int64_t target_msc, int64_t divisor, int64_t remainder)
2184848b8605Smrg{
2185848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
2186848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2187848b8605Smrg   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
2188848b8605Smrg   struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
2189848b8605Smrg#endif
2190848b8605Smrg
2191b8e80941Smrg   if (gc == &dummyContext) /* no GLX for this */
2192848b8605Smrg      return -1;
2193848b8605Smrg
2194848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2195848b8605Smrg   if (!pdraw || !gc->isDirect)
2196848b8605Smrg      return -1;
2197848b8605Smrg#endif
2198848b8605Smrg
2199848b8605Smrg   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2200848b8605Smrg    * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2201848b8605Smrg    * of -1 if the function failed because of errors detected in the input
2202848b8605Smrg    * parameters"
2203848b8605Smrg    */
2204848b8605Smrg   if (divisor < 0 || remainder < 0 || target_msc < 0)
2205848b8605Smrg      return -1;
2206848b8605Smrg   if (divisor > 0 && remainder >= divisor)
2207848b8605Smrg      return -1;
2208848b8605Smrg
2209848b8605Smrg   if (target_msc == 0 && divisor == 0 && remainder == 0)
2210848b8605Smrg      remainder = 1;
2211848b8605Smrg
2212848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2213848b8605Smrg   if (psc->driScreen && psc->driScreen->swapBuffers)
2214848b8605Smrg      return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
2215848b8605Smrg					    remainder, False);
2216848b8605Smrg#endif
2217848b8605Smrg
2218848b8605Smrg   return -1;
2219848b8605Smrg}
2220848b8605Smrg
2221848b8605Smrg
2222848b8605Smrgstatic Bool
2223848b8605Smrg__glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2224848b8605Smrg                   int64_t target_msc, int64_t divisor,
2225848b8605Smrg                   int64_t remainder, int64_t * ust,
2226848b8605Smrg                   int64_t * msc, int64_t * sbc)
2227848b8605Smrg{
2228848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2229848b8605Smrg   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
2230848b8605Smrg   struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
2231848b8605Smrg   int ret;
2232848b8605Smrg#endif
2233848b8605Smrg
2234848b8605Smrg
2235848b8605Smrg   /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2236848b8605Smrg    * error", but the return type in the spec is Bool.
2237848b8605Smrg    */
2238848b8605Smrg   if (divisor < 0 || remainder < 0 || target_msc < 0)
2239848b8605Smrg      return False;
2240848b8605Smrg   if (divisor > 0 && remainder >= divisor)
2241848b8605Smrg      return False;
2242848b8605Smrg
2243848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2244848b8605Smrg   if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) {
2245848b8605Smrg      ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder,
2246848b8605Smrg				       ust, msc, sbc);
2247848b8605Smrg      return ret;
2248848b8605Smrg   }
2249848b8605Smrg#endif
2250848b8605Smrg
2251848b8605Smrg   return False;
2252848b8605Smrg}
2253848b8605Smrg
2254848b8605Smrg
2255848b8605Smrgstatic Bool
2256848b8605Smrg__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2257848b8605Smrg                   int64_t target_sbc, int64_t * ust,
2258848b8605Smrg                   int64_t * msc, int64_t * sbc)
2259848b8605Smrg{
2260848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2261848b8605Smrg   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
2262848b8605Smrg   struct glx_screen *psc = pdraw ? pdraw->psc : NULL;
2263848b8605Smrg   int ret;
2264848b8605Smrg#endif
2265848b8605Smrg
2266848b8605Smrg   /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2267848b8605Smrg    * error", but the return type in the spec is Bool.
2268848b8605Smrg    */
2269848b8605Smrg   if (target_sbc < 0)
2270848b8605Smrg      return False;
2271848b8605Smrg
2272848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2273848b8605Smrg   if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) {
2274848b8605Smrg      ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc);
2275848b8605Smrg      return ret;
2276848b8605Smrg   }
2277848b8605Smrg#endif
2278848b8605Smrg
2279848b8605Smrg   return False;
2280848b8605Smrg}
2281848b8605Smrg
2282848b8605Smrg/*@}*/
2283848b8605Smrg
2284848b8605Smrg
2285848b8605Smrg/**
2286848b8605Smrg * Mesa extension stubs.  These will help reduce portability problems.
2287848b8605Smrg */
2288848b8605Smrg/*@{*/
2289848b8605Smrg
2290848b8605Smrg/**
2291848b8605Smrg * Release all buffers associated with the specified GLX drawable.
2292848b8605Smrg *
2293848b8605Smrg * \todo
2294848b8605Smrg * This function was intended for stand-alone Mesa.  The issue there is that
2295848b8605Smrg * the library doesn't get any notification when a window is closed.  In
2296848b8605Smrg * DRI there is a similar but slightly different issue.  When GLX 1.3 is
2297848b8605Smrg * supported, there are 3 different functions to destroy a drawable.  It
2298848b8605Smrg * should be possible to create GLX protocol (or have it determine which
2299848b8605Smrg * protocol to use based on the type of the drawable) to have one function
2300848b8605Smrg * do the work of 3.  For the direct-rendering case, this function could
2301848b8605Smrg * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2302848b8605Smrg * This would reduce the frequency with which \c __driGarbageCollectDrawables
2303848b8605Smrg * would need to be used.  This really should be done as part of the new DRI
2304848b8605Smrg * interface work.
2305848b8605Smrg *
2306848b8605Smrg * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2307848b8605Smrg *     __driGarbageCollectDrawables
2308848b8605Smrg *     glXDestroyGLXPixmap
2309848b8605Smrg *     glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2310848b8605Smrg *     glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2311848b8605Smrg */
2312848b8605Smrgstatic Bool
2313848b8605Smrg__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
2314848b8605Smrg{
2315848b8605Smrg   (void) dpy;
2316848b8605Smrg   (void) d;
2317848b8605Smrg   return False;
2318848b8605Smrg}
2319848b8605Smrg
2320848b8605Smrg
2321b8e80941Smrg_GLX_PUBLIC GLXPixmap
2322848b8605SmrgglXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
2323848b8605Smrg                       Pixmap pixmap, Colormap cmap)
2324848b8605Smrg{
2325848b8605Smrg   (void) dpy;
2326848b8605Smrg   (void) visual;
2327848b8605Smrg   (void) pixmap;
2328848b8605Smrg   (void) cmap;
2329848b8605Smrg   return 0;
2330848b8605Smrg}
2331848b8605Smrg
2332848b8605Smrg/*@}*/
2333848b8605Smrg
2334848b8605Smrg
2335848b8605Smrg/**
2336848b8605Smrg * GLX_MESA_copy_sub_buffer
2337848b8605Smrg */
2338848b8605Smrg#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
2339848b8605Smrgstatic void
2340848b8605Smrg__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable,
2341848b8605Smrg                       int x, int y, int width, int height)
2342848b8605Smrg{
2343848b8605Smrg   xGLXVendorPrivateReq *req;
2344848b8605Smrg   struct glx_context *gc;
2345848b8605Smrg   GLXContextTag tag;
2346848b8605Smrg   CARD32 *drawable_ptr;
2347848b8605Smrg   INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2348848b8605Smrg   CARD8 opcode;
2349848b8605Smrg
2350848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2351848b8605Smrg   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
2352848b8605Smrg   if (pdraw != NULL) {
2353848b8605Smrg      struct glx_screen *psc = pdraw->psc;
2354848b8605Smrg      if (psc->driScreen->copySubBuffer != NULL) {
2355848b8605Smrg         (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height, True);
2356848b8605Smrg      }
2357848b8605Smrg
2358848b8605Smrg      return;
2359848b8605Smrg   }
2360848b8605Smrg#endif
2361848b8605Smrg
2362848b8605Smrg   opcode = __glXSetupForCommand(dpy);
2363848b8605Smrg   if (!opcode)
2364848b8605Smrg      return;
2365848b8605Smrg
2366848b8605Smrg   /*
2367848b8605Smrg    ** The calling thread may or may not have a current context.  If it
2368848b8605Smrg    ** does, send the context tag so the server can do a flush.
2369848b8605Smrg    */
2370848b8605Smrg   gc = __glXGetCurrentContext();
2371b8e80941Smrg   if ((gc != &dummyContext) && (dpy == gc->currentDpy) &&
2372848b8605Smrg       ((drawable == gc->currentDrawable) ||
2373848b8605Smrg        (drawable == gc->currentReadable))) {
2374848b8605Smrg      tag = gc->currentContextTag;
2375848b8605Smrg   }
2376848b8605Smrg   else {
2377848b8605Smrg      tag = 0;
2378848b8605Smrg   }
2379848b8605Smrg
2380848b8605Smrg   LockDisplay(dpy);
2381848b8605Smrg   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req);
2382848b8605Smrg   req->reqType = opcode;
2383848b8605Smrg   req->glxCode = X_GLXVendorPrivate;
2384848b8605Smrg   req->vendorCode = X_GLXvop_CopySubBufferMESA;
2385848b8605Smrg   req->contextTag = tag;
2386848b8605Smrg
2387848b8605Smrg   drawable_ptr = (CARD32 *) (req + 1);
2388848b8605Smrg   x_ptr = (INT32 *) (drawable_ptr + 1);
2389848b8605Smrg   y_ptr = (INT32 *) (drawable_ptr + 2);
2390848b8605Smrg   w_ptr = (INT32 *) (drawable_ptr + 3);
2391848b8605Smrg   h_ptr = (INT32 *) (drawable_ptr + 4);
2392848b8605Smrg
2393848b8605Smrg   *drawable_ptr = drawable;
2394848b8605Smrg   *x_ptr = x;
2395848b8605Smrg   *y_ptr = y;
2396848b8605Smrg   *w_ptr = width;
2397848b8605Smrg   *h_ptr = height;
2398848b8605Smrg
2399848b8605Smrg   UnlockDisplay(dpy);
2400848b8605Smrg   SyncHandle();
2401848b8605Smrg}
2402848b8605Smrg
2403848b8605Smrg/*@{*/
2404848b8605Smrgstatic void
2405848b8605Smrg__glXBindTexImageEXT(Display * dpy,
2406848b8605Smrg                     GLXDrawable drawable, int buffer, const int *attrib_list)
2407848b8605Smrg{
2408848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
2409848b8605Smrg
2410b8e80941Smrg   if (gc->vtable->bind_tex_image == NULL)
2411848b8605Smrg      return;
2412848b8605Smrg
2413848b8605Smrg   gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list);
2414848b8605Smrg}
2415848b8605Smrg
2416848b8605Smrgstatic void
2417848b8605Smrg__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer)
2418848b8605Smrg{
2419848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
2420848b8605Smrg
2421b8e80941Smrg   if (gc->vtable->release_tex_image == NULL)
2422848b8605Smrg      return;
2423848b8605Smrg
2424848b8605Smrg   gc->vtable->release_tex_image(dpy, drawable, buffer);
2425848b8605Smrg}
2426848b8605Smrg
2427848b8605Smrg/*@}*/
2428848b8605Smrg
2429848b8605Smrg#endif /* GLX_USE_APPLEGL */
2430848b8605Smrg
2431848b8605Smrg/*
2432848b8605Smrg** glXGetProcAddress support
2433848b8605Smrg*/
2434848b8605Smrg
2435848b8605Smrgstruct name_address_pair
2436848b8605Smrg{
2437848b8605Smrg   const char *Name;
2438848b8605Smrg   GLvoid *Address;
2439848b8605Smrg};
2440848b8605Smrg
2441848b8605Smrg#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2442848b8605Smrg#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2443848b8605Smrg
2444848b8605Smrgstatic const struct name_address_pair GLX_functions[] = {
2445848b8605Smrg   /*** GLX_VERSION_1_0 ***/
2446848b8605Smrg   GLX_FUNCTION(glXChooseVisual),
2447848b8605Smrg   GLX_FUNCTION(glXCopyContext),
2448848b8605Smrg   GLX_FUNCTION(glXCreateContext),
2449848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmap),
2450848b8605Smrg   GLX_FUNCTION(glXDestroyContext),
2451848b8605Smrg   GLX_FUNCTION(glXDestroyGLXPixmap),
2452848b8605Smrg   GLX_FUNCTION(glXGetConfig),
2453848b8605Smrg   GLX_FUNCTION(glXGetCurrentContext),
2454848b8605Smrg   GLX_FUNCTION(glXGetCurrentDrawable),
2455848b8605Smrg   GLX_FUNCTION(glXIsDirect),
2456848b8605Smrg   GLX_FUNCTION(glXMakeCurrent),
2457848b8605Smrg   GLX_FUNCTION(glXQueryExtension),
2458848b8605Smrg   GLX_FUNCTION(glXQueryVersion),
2459848b8605Smrg   GLX_FUNCTION(glXSwapBuffers),
2460848b8605Smrg   GLX_FUNCTION(glXUseXFont),
2461848b8605Smrg   GLX_FUNCTION(glXWaitGL),
2462848b8605Smrg   GLX_FUNCTION(glXWaitX),
2463848b8605Smrg
2464848b8605Smrg   /*** GLX_VERSION_1_1 ***/
2465848b8605Smrg   GLX_FUNCTION(glXGetClientString),
2466848b8605Smrg   GLX_FUNCTION(glXQueryExtensionsString),
2467848b8605Smrg   GLX_FUNCTION(glXQueryServerString),
2468848b8605Smrg
2469848b8605Smrg   /*** GLX_VERSION_1_2 ***/
2470848b8605Smrg   GLX_FUNCTION(glXGetCurrentDisplay),
2471848b8605Smrg
2472848b8605Smrg   /*** GLX_VERSION_1_3 ***/
2473848b8605Smrg   GLX_FUNCTION(glXChooseFBConfig),
2474848b8605Smrg   GLX_FUNCTION(glXCreateNewContext),
2475848b8605Smrg   GLX_FUNCTION(glXCreatePbuffer),
2476848b8605Smrg   GLX_FUNCTION(glXCreatePixmap),
2477848b8605Smrg   GLX_FUNCTION(glXCreateWindow),
2478848b8605Smrg   GLX_FUNCTION(glXDestroyPbuffer),
2479848b8605Smrg   GLX_FUNCTION(glXDestroyPixmap),
2480848b8605Smrg   GLX_FUNCTION(glXDestroyWindow),
2481848b8605Smrg   GLX_FUNCTION(glXGetCurrentReadDrawable),
2482848b8605Smrg   GLX_FUNCTION(glXGetFBConfigAttrib),
2483848b8605Smrg   GLX_FUNCTION(glXGetFBConfigs),
2484848b8605Smrg   GLX_FUNCTION(glXGetSelectedEvent),
2485848b8605Smrg   GLX_FUNCTION(glXGetVisualFromFBConfig),
2486848b8605Smrg   GLX_FUNCTION(glXMakeContextCurrent),
2487848b8605Smrg   GLX_FUNCTION(glXQueryContext),
2488848b8605Smrg   GLX_FUNCTION(glXQueryDrawable),
2489848b8605Smrg   GLX_FUNCTION(glXSelectEvent),
2490848b8605Smrg
2491848b8605Smrg#ifndef GLX_USE_APPLEGL
2492848b8605Smrg   /*** GLX_SGI_swap_control ***/
2493848b8605Smrg   GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
2494848b8605Smrg
2495848b8605Smrg   /*** GLX_SGI_video_sync ***/
2496848b8605Smrg   GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
2497848b8605Smrg   GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
2498848b8605Smrg
2499848b8605Smrg   /*** GLX_SGI_make_current_read ***/
2500848b8605Smrg   GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
2501848b8605Smrg   GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
2502848b8605Smrg
2503848b8605Smrg   /*** GLX_EXT_import_context ***/
2504848b8605Smrg   GLX_FUNCTION(glXFreeContextEXT),
2505848b8605Smrg   GLX_FUNCTION(glXGetContextIDEXT),
2506848b8605Smrg   GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
2507848b8605Smrg   GLX_FUNCTION(glXImportContextEXT),
2508848b8605Smrg   GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
2509848b8605Smrg#endif
2510848b8605Smrg
2511848b8605Smrg   /*** GLX_SGIX_fbconfig ***/
2512848b8605Smrg   GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
2513848b8605Smrg   GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
2514848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
2515848b8605Smrg   GLX_FUNCTION(glXCreateContextWithConfigSGIX),
2516848b8605Smrg   GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
2517848b8605Smrg   GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
2518848b8605Smrg
2519848b8605Smrg#ifndef GLX_USE_APPLEGL
2520848b8605Smrg   /*** GLX_SGIX_pbuffer ***/
2521848b8605Smrg   GLX_FUNCTION(glXCreateGLXPbufferSGIX),
2522848b8605Smrg   GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
2523848b8605Smrg   GLX_FUNCTION(glXQueryGLXPbufferSGIX),
2524848b8605Smrg   GLX_FUNCTION(glXSelectEventSGIX),
2525848b8605Smrg   GLX_FUNCTION(glXGetSelectedEventSGIX),
2526848b8605Smrg
2527848b8605Smrg   /*** GLX_MESA_copy_sub_buffer ***/
2528848b8605Smrg   GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
2529848b8605Smrg
2530848b8605Smrg   /*** GLX_MESA_pixmap_colormap ***/
2531848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmapMESA),
2532848b8605Smrg
2533848b8605Smrg   /*** GLX_MESA_release_buffers ***/
2534848b8605Smrg   GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
2535848b8605Smrg
2536848b8605Smrg   /*** GLX_MESA_swap_control ***/
2537848b8605Smrg   GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
2538848b8605Smrg   GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
2539848b8605Smrg#endif
2540848b8605Smrg
2541848b8605Smrg   /*** GLX_ARB_get_proc_address ***/
2542848b8605Smrg   GLX_FUNCTION(glXGetProcAddressARB),
2543848b8605Smrg
2544848b8605Smrg   /*** GLX 1.4 ***/
2545848b8605Smrg   GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
2546848b8605Smrg
2547848b8605Smrg#ifndef GLX_USE_APPLEGL
2548848b8605Smrg   /*** GLX_OML_sync_control ***/
2549848b8605Smrg   GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
2550848b8605Smrg   GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
2551848b8605Smrg   GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
2552848b8605Smrg   GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
2553848b8605Smrg   GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
2554848b8605Smrg
2555848b8605Smrg   /*** GLX_EXT_texture_from_pixmap ***/
2556848b8605Smrg   GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
2557848b8605Smrg   GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
2558848b8605Smrg#endif
2559848b8605Smrg
2560848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_DRM)
2561848b8605Smrg   /*** DRI configuration ***/
2562848b8605Smrg   GLX_FUNCTION(glXGetScreenDriver),
2563848b8605Smrg   GLX_FUNCTION(glXGetDriverConfig),
2564848b8605Smrg#endif
2565848b8605Smrg
2566848b8605Smrg   /*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/
2567848b8605Smrg   GLX_FUNCTION(glXCreateContextAttribsARB),
2568848b8605Smrg
2569848b8605Smrg   /*** GLX_MESA_query_renderer ***/
2570848b8605Smrg   GLX_FUNCTION(glXQueryRendererIntegerMESA),
2571848b8605Smrg   GLX_FUNCTION(glXQueryRendererStringMESA),
2572848b8605Smrg   GLX_FUNCTION(glXQueryCurrentRendererIntegerMESA),
2573848b8605Smrg   GLX_FUNCTION(glXQueryCurrentRendererStringMESA),
2574848b8605Smrg
2575848b8605Smrg   {NULL, NULL}                 /* end of list */
2576848b8605Smrg};
2577848b8605Smrg
2578848b8605Smrgstatic const GLvoid *
2579848b8605Smrgget_glx_proc_address(const char *funcName)
2580848b8605Smrg{
2581848b8605Smrg   GLuint i;
2582848b8605Smrg
2583848b8605Smrg   /* try static functions */
2584848b8605Smrg   for (i = 0; GLX_functions[i].Name; i++) {
2585848b8605Smrg      if (strcmp(GLX_functions[i].Name, funcName) == 0)
2586848b8605Smrg         return GLX_functions[i].Address;
2587848b8605Smrg   }
2588848b8605Smrg
2589848b8605Smrg   return NULL;
2590848b8605Smrg}
2591848b8605Smrg
2592848b8605Smrg/**
2593848b8605Smrg * Get the address of a named GL function.  This is the pre-GLX 1.4 name for
2594848b8605Smrg * \c glXGetProcAddress.
2595848b8605Smrg *
2596848b8605Smrg * \param procName  Name of a GL or GLX function.
2597848b8605Smrg * \returns         A pointer to the named function
2598848b8605Smrg *
2599848b8605Smrg * \sa glXGetProcAddress
2600848b8605Smrg */
2601b8e80941Smrg_GLX_PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
2602848b8605Smrg{
2603848b8605Smrg   typedef void (*gl_function) (void);
2604848b8605Smrg   gl_function f;
2605848b8605Smrg
2606848b8605Smrg
2607848b8605Smrg   /* Search the table of GLX and internal functions first.  If that
2608848b8605Smrg    * fails and the supplied name could be a valid core GL name, try
2609848b8605Smrg    * searching the core GL function table.  This check is done to prevent
2610848b8605Smrg    * DRI based drivers from searching the core GL function table for
2611848b8605Smrg    * internal API functions.
2612848b8605Smrg    */
2613848b8605Smrg   f = (gl_function) get_glx_proc_address((const char *) procName);
2614848b8605Smrg   if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2615848b8605Smrg       && (procName[2] != 'X')) {
2616b8e80941Smrg#ifdef GLX_INDIRECT_RENDERING
2617848b8605Smrg      f = (gl_function) __indirect_get_proc_address((const char *) procName);
2618848b8605Smrg#endif
2619848b8605Smrg      if (!f)
2620848b8605Smrg         f = (gl_function) _glapi_get_proc_address((const char *) procName);
2621848b8605Smrg      if (!f) {
2622848b8605Smrg         struct glx_context *gc = __glXGetCurrentContext();
2623848b8605Smrg
2624848b8605Smrg         if (gc != NULL && gc->vtable->get_proc_address != NULL)
2625848b8605Smrg            f = gc->vtable->get_proc_address((const char *) procName);
2626848b8605Smrg      }
2627848b8605Smrg   }
2628848b8605Smrg   return f;
2629848b8605Smrg}
2630848b8605Smrg
2631848b8605Smrg/**
2632848b8605Smrg * Get the address of a named GL function.  This is the GLX 1.4 name for
2633848b8605Smrg * \c glXGetProcAddressARB.
2634848b8605Smrg *
2635848b8605Smrg * \param procName  Name of a GL or GLX function.
2636848b8605Smrg * \returns         A pointer to the named function
2637848b8605Smrg *
2638848b8605Smrg * \sa glXGetProcAddressARB
2639848b8605Smrg */
2640b8e80941Smrg_GLX_PUBLIC
2641b8e80941SmrgGLX_ALIAS(__GLXextFuncPtr, glXGetProcAddress,
2642b8e80941Smrg          (const GLubyte * procName),
2643b8e80941Smrg          (procName), glXGetProcAddressARB)
2644848b8605Smrg
2645848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2646848b8605Smrg/**
2647848b8605Smrg * Get the unadjusted system time (UST).  Currently, the UST is measured in
2648848b8605Smrg * microseconds since Epoc.  The actual resolution of the UST may vary from
2649848b8605Smrg * system to system, and the units may vary from release to release.
2650848b8605Smrg * Drivers should not call this function directly.  They should instead use
2651848b8605Smrg * \c glXGetProcAddress to obtain a pointer to the function.
2652848b8605Smrg *
2653848b8605Smrg * \param ust Location to store the 64-bit UST
2654848b8605Smrg * \returns Zero on success or a negative errno value on failure.
2655848b8605Smrg *
2656848b8605Smrg * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2657848b8605Smrg *
2658848b8605Smrg * \since Internal API version 20030317.
2659848b8605Smrg */
2660848b8605Smrg_X_HIDDEN int
2661848b8605Smrg__glXGetUST(int64_t * ust)
2662848b8605Smrg{
2663848b8605Smrg   struct timeval tv;
2664848b8605Smrg
2665848b8605Smrg   if (ust == NULL) {
2666848b8605Smrg      return -EFAULT;
2667848b8605Smrg   }
2668848b8605Smrg
2669848b8605Smrg   if (gettimeofday(&tv, NULL) == 0) {
2670848b8605Smrg      ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
2671848b8605Smrg      return 0;
2672848b8605Smrg   }
2673848b8605Smrg   else {
2674848b8605Smrg      return -errno;
2675848b8605Smrg   }
2676848b8605Smrg}
2677848b8605Smrg#endif /* GLX_DIRECT_RENDERING */
2678b8e80941Smrg
2679b8e80941Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2680b8e80941Smrg
2681b8e80941SmrgPUBLIC int
2682b8e80941SmrgMesaGLInteropGLXQueryDeviceInfo(Display *dpy, GLXContext context,
2683b8e80941Smrg                                struct mesa_glinterop_device_info *out)
2684b8e80941Smrg{
2685b8e80941Smrg   struct glx_context *gc = (struct glx_context*)context;
2686b8e80941Smrg   int ret;
2687b8e80941Smrg
2688b8e80941Smrg   __glXLock();
2689b8e80941Smrg
2690b8e80941Smrg   if (!gc || gc->xid == None || !gc->isDirect) {
2691b8e80941Smrg      __glXUnlock();
2692b8e80941Smrg      return MESA_GLINTEROP_INVALID_CONTEXT;
2693b8e80941Smrg   }
2694b8e80941Smrg
2695b8e80941Smrg   if (!gc->vtable->interop_query_device_info) {
2696b8e80941Smrg      __glXUnlock();
2697b8e80941Smrg      return MESA_GLINTEROP_UNSUPPORTED;
2698b8e80941Smrg   }
2699b8e80941Smrg
2700b8e80941Smrg   ret = gc->vtable->interop_query_device_info(gc, out);
2701b8e80941Smrg   __glXUnlock();
2702b8e80941Smrg   return ret;
2703b8e80941Smrg}
2704b8e80941Smrg
2705b8e80941SmrgPUBLIC int
2706b8e80941SmrgMesaGLInteropGLXExportObject(Display *dpy, GLXContext context,
2707b8e80941Smrg                             struct mesa_glinterop_export_in *in,
2708b8e80941Smrg                             struct mesa_glinterop_export_out *out)
2709b8e80941Smrg{
2710b8e80941Smrg   struct glx_context *gc = (struct glx_context*)context;
2711b8e80941Smrg   int ret;
2712b8e80941Smrg
2713b8e80941Smrg   __glXLock();
2714b8e80941Smrg
2715b8e80941Smrg   if (!gc || gc->xid == None || !gc->isDirect) {
2716b8e80941Smrg      __glXUnlock();
2717b8e80941Smrg      return MESA_GLINTEROP_INVALID_CONTEXT;
2718b8e80941Smrg   }
2719b8e80941Smrg
2720b8e80941Smrg   if (!gc->vtable->interop_export_object) {
2721b8e80941Smrg      __glXUnlock();
2722b8e80941Smrg      return MESA_GLINTEROP_UNSUPPORTED;
2723b8e80941Smrg   }
2724b8e80941Smrg
2725b8e80941Smrg   ret = gc->vtable->interop_export_object(gc, in, out);
2726b8e80941Smrg   __glXUnlock();
2727b8e80941Smrg   return ret;
2728b8e80941Smrg}
2729b8e80941Smrg
2730b8e80941Smrg#endif /* defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) */
2731