glxcmds.c revision 848b8605
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"
46848b8605Smrg#else
47848b8605Smrg#include <sys/time.h>
48848b8605Smrg#ifdef XF86VIDMODE
49848b8605Smrg#include <X11/extensions/xf86vmode.h>
50848b8605Smrg#endif
51848b8605Smrg#endif
52848b8605Smrg#endif
53848b8605Smrg
54848b8605Smrg#include <X11/Xlib-xcb.h>
55848b8605Smrg#include <xcb/xcb.h>
56848b8605Smrg#include <xcb/glx.h>
57848b8605Smrg
58848b8605Smrgstatic const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
59848b8605Smrgstatic const char __glXGLXClientVersion[] = "1.4";
60848b8605Smrg
61848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
62848b8605Smrg
63848b8605Smrg/**
64848b8605Smrg * Get the __DRIdrawable for the drawable associated with a GLXContext
65848b8605Smrg *
66848b8605Smrg * \param dpy       The display associated with \c drawable.
67848b8605Smrg * \param drawable  GLXDrawable whose __DRIdrawable part is to be retrieved.
68848b8605Smrg * \param scrn_num  If non-NULL, the drawables screen is stored there
69848b8605Smrg * \returns  A pointer to the context's __DRIdrawable on success, or NULL if
70848b8605Smrg *           the drawable is not associated with a direct-rendering context.
71848b8605Smrg */
72848b8605Smrg_X_HIDDEN __GLXDRIdrawable *
73848b8605SmrgGetGLXDRIDrawable(Display * dpy, GLXDrawable drawable)
74848b8605Smrg{
75848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
76848b8605Smrg   __GLXDRIdrawable *pdraw;
77848b8605Smrg
78848b8605Smrg   if (priv == NULL)
79848b8605Smrg      return NULL;
80848b8605Smrg
81848b8605Smrg   if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0)
82848b8605Smrg      return pdraw;
83848b8605Smrg
84848b8605Smrg   return NULL;
85848b8605Smrg}
86848b8605Smrg
87848b8605Smrg#endif
88848b8605Smrg
89848b8605Smrg_X_HIDDEN struct glx_drawable *
90848b8605SmrgGetGLXDrawable(Display *dpy, GLXDrawable drawable)
91848b8605Smrg{
92848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
93848b8605Smrg   struct glx_drawable *glxDraw;
94848b8605Smrg
95848b8605Smrg   if (priv == NULL)
96848b8605Smrg      return NULL;
97848b8605Smrg
98848b8605Smrg   if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0)
99848b8605Smrg      return glxDraw;
100848b8605Smrg
101848b8605Smrg   return NULL;
102848b8605Smrg}
103848b8605Smrg
104848b8605Smrg_X_HIDDEN int
105848b8605SmrgInitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable,
106848b8605Smrg		GLXDrawable drawable)
107848b8605Smrg{
108848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
109848b8605Smrg
110848b8605Smrg   if (!priv)
111848b8605Smrg      return -1;
112848b8605Smrg
113848b8605Smrg   glxDraw->xDrawable = xDrawable;
114848b8605Smrg   glxDraw->drawable = drawable;
115848b8605Smrg   glxDraw->lastEventSbc = 0;
116848b8605Smrg   glxDraw->eventSbcWrap = 0;
117848b8605Smrg
118848b8605Smrg   return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw);
119848b8605Smrg}
120848b8605Smrg
121848b8605Smrg_X_HIDDEN void
122848b8605SmrgDestroyGLXDrawable(Display *dpy, GLXDrawable drawable)
123848b8605Smrg{
124848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
125848b8605Smrg   struct glx_drawable *glxDraw;
126848b8605Smrg
127848b8605Smrg   if (!priv)
128848b8605Smrg      return;
129848b8605Smrg
130848b8605Smrg   glxDraw = GetGLXDrawable(dpy, drawable);
131848b8605Smrg   __glxHashDelete(priv->glXDrawHash, drawable);
132848b8605Smrg   free(glxDraw);
133848b8605Smrg}
134848b8605Smrg
135848b8605Smrg/**
136848b8605Smrg * Get the GLX per-screen data structure associated with a GLX context.
137848b8605Smrg *
138848b8605Smrg * \param dpy   Display for which the GLX per-screen information is to be
139848b8605Smrg *              retrieved.
140848b8605Smrg * \param scrn  Screen on \c dpy for which the GLX per-screen information is
141848b8605Smrg *              to be retrieved.
142848b8605Smrg * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
143848b8605Smrg *          specify a valid GLX screen, or NULL otherwise.
144848b8605Smrg *
145848b8605Smrg * \todo Should this function validate that \c scrn is within the screen
146848b8605Smrg *       number range for \c dpy?
147848b8605Smrg */
148848b8605Smrg
149848b8605Smrg_X_HIDDEN struct glx_screen *
150848b8605SmrgGetGLXScreenConfigs(Display * dpy, int scrn)
151848b8605Smrg{
152848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
153848b8605Smrg
154848b8605Smrg   return (priv
155848b8605Smrg           && priv->screens !=
156848b8605Smrg           NULL) ? priv->screens[scrn] : NULL;
157848b8605Smrg}
158848b8605Smrg
159848b8605Smrg
160848b8605Smrgstatic int
161848b8605SmrgGetGLXPrivScreenConfig(Display * dpy, int scrn, struct glx_display ** ppriv,
162848b8605Smrg                       struct glx_screen ** ppsc)
163848b8605Smrg{
164848b8605Smrg   /* Initialize the extension, if needed .  This has the added value
165848b8605Smrg    * of initializing/allocating the display private
166848b8605Smrg    */
167848b8605Smrg
168848b8605Smrg   if (dpy == NULL) {
169848b8605Smrg      return GLX_NO_EXTENSION;
170848b8605Smrg   }
171848b8605Smrg
172848b8605Smrg   *ppriv = __glXInitialize(dpy);
173848b8605Smrg   if (*ppriv == NULL) {
174848b8605Smrg      return GLX_NO_EXTENSION;
175848b8605Smrg   }
176848b8605Smrg
177848b8605Smrg   /* Check screen number to see if its valid */
178848b8605Smrg   if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
179848b8605Smrg      return GLX_BAD_SCREEN;
180848b8605Smrg   }
181848b8605Smrg
182848b8605Smrg   /* Check to see if the GL is supported on this screen */
183848b8605Smrg   *ppsc = (*ppriv)->screens[scrn];
184848b8605Smrg   if ((*ppsc)->configs == NULL && (*ppsc)->visuals == NULL) {
185848b8605Smrg      /* No support for GL on this screen regardless of visual */
186848b8605Smrg      return GLX_BAD_VISUAL;
187848b8605Smrg   }
188848b8605Smrg
189848b8605Smrg   return Success;
190848b8605Smrg}
191848b8605Smrg
192848b8605Smrg
193848b8605Smrg/**
194848b8605Smrg * Determine if a \c GLXFBConfig supplied by the application is valid.
195848b8605Smrg *
196848b8605Smrg * \param dpy     Application supplied \c Display pointer.
197848b8605Smrg * \param config  Application supplied \c GLXFBConfig.
198848b8605Smrg *
199848b8605Smrg * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
200848b8605Smrg *          \c struct glx_config structure is returned.  Otherwise, \c NULL
201848b8605Smrg *          is returned.
202848b8605Smrg */
203848b8605Smrgstatic struct glx_config *
204848b8605SmrgValidateGLXFBConfig(Display * dpy, GLXFBConfig fbconfig)
205848b8605Smrg{
206848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
207848b8605Smrg   int num_screens = ScreenCount(dpy);
208848b8605Smrg   unsigned i;
209848b8605Smrg   struct glx_config *config;
210848b8605Smrg
211848b8605Smrg   if (priv != NULL) {
212848b8605Smrg      for (i = 0; i < num_screens; i++) {
213848b8605Smrg	 for (config = priv->screens[i]->configs; config != NULL;
214848b8605Smrg	      config = config->next) {
215848b8605Smrg	    if (config == (struct glx_config *) fbconfig) {
216848b8605Smrg	       return config;
217848b8605Smrg	    }
218848b8605Smrg	 }
219848b8605Smrg      }
220848b8605Smrg   }
221848b8605Smrg
222848b8605Smrg   return NULL;
223848b8605Smrg}
224848b8605Smrg
225848b8605Smrg/**
226848b8605Smrg * Verifies context's GLX_RENDER_TYPE value with config.
227848b8605Smrg *
228848b8605Smrg * \param config GLX FBConfig which will support the returned renderType.
229848b8605Smrg * \param renderType The context render type to be verified.
230848b8605Smrg * \return True if the value of context renderType was approved, or 0 if no
231848b8605Smrg * valid value was found.
232848b8605Smrg */
233848b8605SmrgBool
234848b8605Smrgvalidate_renderType_against_config(const struct glx_config *config,
235848b8605Smrg                                   int renderType)
236848b8605Smrg{
237848b8605Smrg    switch (renderType) {
238848b8605Smrg    case GLX_RGBA_TYPE:
239848b8605Smrg        return (config->renderType & GLX_RGBA_BIT) != 0;
240848b8605Smrg    case GLX_COLOR_INDEX_TYPE:
241848b8605Smrg        return (config->renderType & GLX_COLOR_INDEX_BIT) != 0;
242848b8605Smrg    case GLX_RGBA_FLOAT_TYPE_ARB:
243848b8605Smrg        return (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) != 0;
244848b8605Smrg    case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
245848b8605Smrg        return (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) != 0;
246848b8605Smrg    default:
247848b8605Smrg        break;
248848b8605Smrg    }
249848b8605Smrg    return 0;
250848b8605Smrg}
251848b8605Smrg
252848b8605Smrg_X_HIDDEN Bool
253848b8605Smrgglx_context_init(struct glx_context *gc,
254848b8605Smrg		 struct glx_screen *psc, struct glx_config *config)
255848b8605Smrg{
256848b8605Smrg   gc->majorOpcode = __glXSetupForCommand(psc->display->dpy);
257848b8605Smrg   if (!gc->majorOpcode)
258848b8605Smrg      return False;
259848b8605Smrg
260848b8605Smrg   gc->screen = psc->scr;
261848b8605Smrg   gc->psc = psc;
262848b8605Smrg   gc->config = config;
263848b8605Smrg   gc->isDirect = GL_TRUE;
264848b8605Smrg   gc->currentContextTag = -1;
265848b8605Smrg
266848b8605Smrg   return True;
267848b8605Smrg}
268848b8605Smrg
269848b8605Smrg
270848b8605Smrg/**
271848b8605Smrg * Create a new context.
272848b8605Smrg *
273848b8605Smrg * \param renderType   For FBConfigs, what is the rendering type?
274848b8605Smrg */
275848b8605Smrg
276848b8605Smrgstatic GLXContext
277848b8605SmrgCreateContext(Display *dpy, int generic_id, struct glx_config *config,
278848b8605Smrg              GLXContext shareList_user, Bool allowDirect,
279848b8605Smrg	      unsigned code, int renderType, int screen)
280848b8605Smrg{
281848b8605Smrg   struct glx_context *gc;
282848b8605Smrg   struct glx_screen *psc;
283848b8605Smrg   struct glx_context *shareList = (struct glx_context *) shareList_user;
284848b8605Smrg   if (dpy == NULL)
285848b8605Smrg      return NULL;
286848b8605Smrg
287848b8605Smrg   psc = GetGLXScreenConfigs(dpy, screen);
288848b8605Smrg   if (psc == NULL)
289848b8605Smrg      return NULL;
290848b8605Smrg
291848b8605Smrg   if (generic_id == None)
292848b8605Smrg      return NULL;
293848b8605Smrg
294848b8605Smrg   gc = NULL;
295848b8605Smrg#ifdef GLX_USE_APPLEGL
296848b8605Smrg   gc = applegl_create_context(psc, config, shareList, renderType);
297848b8605Smrg#else
298848b8605Smrg   if (allowDirect && psc->vtable->create_context)
299848b8605Smrg      gc = psc->vtable->create_context(psc, config, shareList, renderType);
300848b8605Smrg   if (!gc)
301848b8605Smrg      gc = indirect_create_context(psc, config, shareList, renderType);
302848b8605Smrg#endif
303848b8605Smrg   if (!gc)
304848b8605Smrg      return NULL;
305848b8605Smrg
306848b8605Smrg   LockDisplay(dpy);
307848b8605Smrg   switch (code) {
308848b8605Smrg   case X_GLXCreateContext: {
309848b8605Smrg      xGLXCreateContextReq *req;
310848b8605Smrg
311848b8605Smrg      /* Send the glXCreateContext request */
312848b8605Smrg      GetReq(GLXCreateContext, req);
313848b8605Smrg      req->reqType = gc->majorOpcode;
314848b8605Smrg      req->glxCode = X_GLXCreateContext;
315848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
316848b8605Smrg      req->visual = generic_id;
317848b8605Smrg      req->screen = screen;
318848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
319848b8605Smrg      req->isDirect = gc->isDirect;
320848b8605Smrg      break;
321848b8605Smrg   }
322848b8605Smrg
323848b8605Smrg   case X_GLXCreateNewContext: {
324848b8605Smrg      xGLXCreateNewContextReq *req;
325848b8605Smrg
326848b8605Smrg      /* Send the glXCreateNewContext request */
327848b8605Smrg      GetReq(GLXCreateNewContext, req);
328848b8605Smrg      req->reqType = gc->majorOpcode;
329848b8605Smrg      req->glxCode = X_GLXCreateNewContext;
330848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
331848b8605Smrg      req->fbconfig = generic_id;
332848b8605Smrg      req->screen = screen;
333848b8605Smrg      req->renderType = renderType;
334848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
335848b8605Smrg      req->isDirect = gc->isDirect;
336848b8605Smrg      break;
337848b8605Smrg   }
338848b8605Smrg
339848b8605Smrg   case X_GLXvop_CreateContextWithConfigSGIX: {
340848b8605Smrg      xGLXVendorPrivateWithReplyReq *vpreq;
341848b8605Smrg      xGLXCreateContextWithConfigSGIXReq *req;
342848b8605Smrg
343848b8605Smrg      /* Send the glXCreateNewContext request */
344848b8605Smrg      GetReqExtra(GLXVendorPrivateWithReply,
345848b8605Smrg		  sz_xGLXCreateContextWithConfigSGIXReq -
346848b8605Smrg		  sz_xGLXVendorPrivateWithReplyReq, vpreq);
347848b8605Smrg      req = (xGLXCreateContextWithConfigSGIXReq *) vpreq;
348848b8605Smrg      req->reqType = gc->majorOpcode;
349848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
350848b8605Smrg      req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
351848b8605Smrg      req->context = gc->xid = XAllocID(dpy);
352848b8605Smrg      req->fbconfig = generic_id;
353848b8605Smrg      req->screen = screen;
354848b8605Smrg      req->renderType = renderType;
355848b8605Smrg      req->shareList = shareList ? shareList->xid : None;
356848b8605Smrg      req->isDirect = gc->isDirect;
357848b8605Smrg      break;
358848b8605Smrg   }
359848b8605Smrg
360848b8605Smrg   default:
361848b8605Smrg      /* What to do here?  This case is the sign of an internal error.  It
362848b8605Smrg       * should never be reachable.
363848b8605Smrg       */
364848b8605Smrg      break;
365848b8605Smrg   }
366848b8605Smrg
367848b8605Smrg   UnlockDisplay(dpy);
368848b8605Smrg   SyncHandle();
369848b8605Smrg
370848b8605Smrg   gc->share_xid = shareList ? shareList->xid : None;
371848b8605Smrg   gc->imported = GL_FALSE;
372848b8605Smrg
373848b8605Smrg   return (GLXContext) gc;
374848b8605Smrg}
375848b8605Smrg
376848b8605Smrg_X_EXPORT GLXContext
377848b8605SmrgglXCreateContext(Display * dpy, XVisualInfo * vis,
378848b8605Smrg                 GLXContext shareList, Bool allowDirect)
379848b8605Smrg{
380848b8605Smrg   struct glx_config *config = NULL;
381848b8605Smrg   int renderType = GLX_RGBA_TYPE;
382848b8605Smrg
383848b8605Smrg#if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL)
384848b8605Smrg   struct glx_screen *const psc = GetGLXScreenConfigs(dpy, vis->screen);
385848b8605Smrg
386848b8605Smrg   if (psc)
387848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
388848b8605Smrg
389848b8605Smrg   if (config == NULL) {
390848b8605Smrg      xError error;
391848b8605Smrg
392848b8605Smrg      error.errorCode = BadValue;
393848b8605Smrg      error.resourceID = vis->visualid;
394848b8605Smrg      error.sequenceNumber = dpy->request;
395848b8605Smrg      error.type = X_Error;
396848b8605Smrg      error.majorCode = __glXSetupForCommand(dpy);
397848b8605Smrg      error.minorCode = X_GLXCreateContext;
398848b8605Smrg      _XError(dpy, &error);
399848b8605Smrg      return None;
400848b8605Smrg   }
401848b8605Smrg
402848b8605Smrg   /* Choose the context render type based on DRI config values.  It is
403848b8605Smrg    * unusual to set this type from config, but we have no other choice, as
404848b8605Smrg    * this old API does not provide renderType parameter.
405848b8605Smrg    */
406848b8605Smrg   if (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) {
407848b8605Smrg       renderType = GLX_RGBA_FLOAT_TYPE_ARB;
408848b8605Smrg   } else if (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) {
409848b8605Smrg       renderType = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT;
410848b8605Smrg   } else if (config->renderType & GLX_RGBA_BIT) {
411848b8605Smrg       renderType = GLX_RGBA_TYPE;
412848b8605Smrg   } else if (config->renderType & GLX_COLOR_INDEX_BIT) {
413848b8605Smrg       renderType = GLX_COLOR_INDEX_TYPE;
414848b8605Smrg   } else if (config->rgbMode) {
415848b8605Smrg       /* If we're here, then renderType is not set correctly.  Let's use a
416848b8605Smrg        * safeguard - any TrueColor or DirectColor mode is RGB mode.  Such
417848b8605Smrg        * default value is needed by old DRI drivers, which didn't set
418848b8605Smrg        * renderType correctly as the value was just ignored.
419848b8605Smrg        */
420848b8605Smrg       renderType = GLX_RGBA_TYPE;
421848b8605Smrg   } else {
422848b8605Smrg       /* Safeguard - only one option left, all non-RGB modes are indexed
423848b8605Smrg        * modes.  Again, this allows drivers with invalid renderType to work
424848b8605Smrg        * properly.
425848b8605Smrg        */
426848b8605Smrg       renderType = GLX_COLOR_INDEX_TYPE;
427848b8605Smrg   }
428848b8605Smrg#endif
429848b8605Smrg
430848b8605Smrg   return CreateContext(dpy, vis->visualid, config, shareList, allowDirect,
431848b8605Smrg                        X_GLXCreateContext, renderType, vis->screen);
432848b8605Smrg}
433848b8605Smrg
434848b8605Smrgstatic void
435848b8605Smrgglx_send_destroy_context(Display *dpy, XID xid)
436848b8605Smrg{
437848b8605Smrg   CARD8 opcode = __glXSetupForCommand(dpy);
438848b8605Smrg   xGLXDestroyContextReq *req;
439848b8605Smrg
440848b8605Smrg   LockDisplay(dpy);
441848b8605Smrg   GetReq(GLXDestroyContext, req);
442848b8605Smrg   req->reqType = opcode;
443848b8605Smrg   req->glxCode = X_GLXDestroyContext;
444848b8605Smrg   req->context = xid;
445848b8605Smrg   UnlockDisplay(dpy);
446848b8605Smrg   SyncHandle();
447848b8605Smrg}
448848b8605Smrg
449848b8605Smrg/*
450848b8605Smrg** Destroy the named context
451848b8605Smrg*/
452848b8605Smrg
453848b8605Smrg_X_EXPORT void
454848b8605SmrgglXDestroyContext(Display * dpy, GLXContext ctx)
455848b8605Smrg{
456848b8605Smrg   struct glx_context *gc = (struct glx_context *) ctx;
457848b8605Smrg
458848b8605Smrg   if (gc == NULL || gc->xid == None)
459848b8605Smrg      return;
460848b8605Smrg
461848b8605Smrg   __glXLock();
462848b8605Smrg   if (!gc->imported)
463848b8605Smrg      glx_send_destroy_context(dpy, gc->xid);
464848b8605Smrg
465848b8605Smrg   if (gc->currentDpy) {
466848b8605Smrg      /* This context is bound to some thread.  According to the man page,
467848b8605Smrg       * we should not actually delete the context until it's unbound.
468848b8605Smrg       * Note that we set gc->xid = None above.  In MakeContextCurrent()
469848b8605Smrg       * we check for that and delete the context there.
470848b8605Smrg       */
471848b8605Smrg      gc->xid = None;
472848b8605Smrg   } else {
473848b8605Smrg      gc->vtable->destroy(gc);
474848b8605Smrg   }
475848b8605Smrg   __glXUnlock();
476848b8605Smrg}
477848b8605Smrg
478848b8605Smrg/*
479848b8605Smrg** Return the major and minor version #s for the GLX extension
480848b8605Smrg*/
481848b8605Smrg_X_EXPORT Bool
482848b8605SmrgglXQueryVersion(Display * dpy, int *major, int *minor)
483848b8605Smrg{
484848b8605Smrg   struct glx_display *priv;
485848b8605Smrg
486848b8605Smrg   /* Init the extension.  This fetches the major and minor version. */
487848b8605Smrg   priv = __glXInitialize(dpy);
488848b8605Smrg   if (!priv)
489848b8605Smrg      return False;
490848b8605Smrg
491848b8605Smrg   if (major)
492848b8605Smrg      *major = priv->majorVersion;
493848b8605Smrg   if (minor)
494848b8605Smrg      *minor = priv->minorVersion;
495848b8605Smrg   return True;
496848b8605Smrg}
497848b8605Smrg
498848b8605Smrg/*
499848b8605Smrg** Query the existance of the GLX extension
500848b8605Smrg*/
501848b8605Smrg_X_EXPORT Bool
502848b8605SmrgglXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
503848b8605Smrg{
504848b8605Smrg   int major_op, erb, evb;
505848b8605Smrg   Bool rv;
506848b8605Smrg
507848b8605Smrg   rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
508848b8605Smrg   if (rv) {
509848b8605Smrg      if (errorBase)
510848b8605Smrg         *errorBase = erb;
511848b8605Smrg      if (eventBase)
512848b8605Smrg         *eventBase = evb;
513848b8605Smrg   }
514848b8605Smrg   return rv;
515848b8605Smrg}
516848b8605Smrg
517848b8605Smrg/*
518848b8605Smrg** Put a barrier in the token stream that forces the GL to finish its
519848b8605Smrg** work before X can proceed.
520848b8605Smrg*/
521848b8605Smrg_X_EXPORT void
522848b8605SmrgglXWaitGL(void)
523848b8605Smrg{
524848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
525848b8605Smrg
526848b8605Smrg   if (gc && gc->vtable->wait_gl)
527848b8605Smrg      gc->vtable->wait_gl(gc);
528848b8605Smrg}
529848b8605Smrg
530848b8605Smrg/*
531848b8605Smrg** Put a barrier in the token stream that forces X to finish its
532848b8605Smrg** work before GL can proceed.
533848b8605Smrg*/
534848b8605Smrg_X_EXPORT void
535848b8605SmrgglXWaitX(void)
536848b8605Smrg{
537848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
538848b8605Smrg
539848b8605Smrg   if (gc && gc->vtable->wait_x)
540848b8605Smrg      gc->vtable->wait_x(gc);
541848b8605Smrg}
542848b8605Smrg
543848b8605Smrg_X_EXPORT void
544848b8605SmrgglXUseXFont(Font font, int first, int count, int listBase)
545848b8605Smrg{
546848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
547848b8605Smrg
548848b8605Smrg   if (gc && gc->vtable->use_x_font)
549848b8605Smrg      gc->vtable->use_x_font(gc, font, first, count, listBase);
550848b8605Smrg}
551848b8605Smrg
552848b8605Smrg/************************************************************************/
553848b8605Smrg
554848b8605Smrg/*
555848b8605Smrg** Copy the source context to the destination context using the
556848b8605Smrg** attribute "mask".
557848b8605Smrg*/
558848b8605Smrg_X_EXPORT void
559848b8605SmrgglXCopyContext(Display * dpy, GLXContext source_user,
560848b8605Smrg	       GLXContext dest_user, unsigned long mask)
561848b8605Smrg{
562848b8605Smrg   struct glx_context *source = (struct glx_context *) source_user;
563848b8605Smrg   struct glx_context *dest = (struct glx_context *) dest_user;
564848b8605Smrg#ifdef GLX_USE_APPLEGL
565848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
566848b8605Smrg   int errorcode;
567848b8605Smrg   bool x11error;
568848b8605Smrg
569848b8605Smrg   if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext,
570848b8605Smrg                             mask, &errorcode, &x11error)) {
571848b8605Smrg      __glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error);
572848b8605Smrg   }
573848b8605Smrg
574848b8605Smrg#else
575848b8605Smrg   xGLXCopyContextReq *req;
576848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
577848b8605Smrg   GLXContextTag tag;
578848b8605Smrg   CARD8 opcode;
579848b8605Smrg
580848b8605Smrg   opcode = __glXSetupForCommand(dpy);
581848b8605Smrg   if (!opcode) {
582848b8605Smrg      return;
583848b8605Smrg   }
584848b8605Smrg
585848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
586848b8605Smrg   if (gc->isDirect) {
587848b8605Smrg      /* NOT_DONE: This does not work yet */
588848b8605Smrg   }
589848b8605Smrg#endif
590848b8605Smrg
591848b8605Smrg   /*
592848b8605Smrg    ** If the source is the current context, send its tag so that the context
593848b8605Smrg    ** can be flushed before the copy.
594848b8605Smrg    */
595848b8605Smrg   if (source == gc && dpy == gc->currentDpy) {
596848b8605Smrg      tag = gc->currentContextTag;
597848b8605Smrg   }
598848b8605Smrg   else {
599848b8605Smrg      tag = 0;
600848b8605Smrg   }
601848b8605Smrg
602848b8605Smrg   /* Send the glXCopyContext request */
603848b8605Smrg   LockDisplay(dpy);
604848b8605Smrg   GetReq(GLXCopyContext, req);
605848b8605Smrg   req->reqType = opcode;
606848b8605Smrg   req->glxCode = X_GLXCopyContext;
607848b8605Smrg   req->source = source ? source->xid : None;
608848b8605Smrg   req->dest = dest ? dest->xid : None;
609848b8605Smrg   req->mask = mask;
610848b8605Smrg   req->contextTag = tag;
611848b8605Smrg   UnlockDisplay(dpy);
612848b8605Smrg   SyncHandle();
613848b8605Smrg#endif /* GLX_USE_APPLEGL */
614848b8605Smrg}
615848b8605Smrg
616848b8605Smrg
617848b8605Smrg/**
618848b8605Smrg * Determine if a context uses direct rendering.
619848b8605Smrg *
620848b8605Smrg * \param dpy        Display where the context was created.
621848b8605Smrg * \param contextID  ID of the context to be tested.
622848b8605Smrg *
623848b8605Smrg * \returns \c True if the context is direct rendering or not.
624848b8605Smrg */
625848b8605Smrgstatic Bool
626848b8605Smrg__glXIsDirect(Display * dpy, GLXContextID contextID)
627848b8605Smrg{
628848b8605Smrg   CARD8 opcode;
629848b8605Smrg   xcb_connection_t *c;
630848b8605Smrg   xcb_generic_error_t *err;
631848b8605Smrg   xcb_glx_is_direct_reply_t *reply;
632848b8605Smrg   Bool is_direct;
633848b8605Smrg
634848b8605Smrg   opcode = __glXSetupForCommand(dpy);
635848b8605Smrg   if (!opcode) {
636848b8605Smrg      return False;
637848b8605Smrg   }
638848b8605Smrg
639848b8605Smrg   c = XGetXCBConnection(dpy);
640848b8605Smrg   reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err);
641848b8605Smrg   is_direct = (reply != NULL && reply->is_direct) ? True : False;
642848b8605Smrg
643848b8605Smrg   if (err != NULL) {
644848b8605Smrg      __glXSendErrorForXcb(dpy, err);
645848b8605Smrg      free(err);
646848b8605Smrg   }
647848b8605Smrg
648848b8605Smrg   free(reply);
649848b8605Smrg
650848b8605Smrg   return is_direct;
651848b8605Smrg}
652848b8605Smrg
653848b8605Smrg/**
654848b8605Smrg * \todo
655848b8605Smrg * Shouldn't this function \b always return \c False when
656848b8605Smrg * \c GLX_DIRECT_RENDERING is not defined?  Do we really need to bother with
657848b8605Smrg * the GLX protocol here at all?
658848b8605Smrg */
659848b8605Smrg_X_EXPORT Bool
660848b8605SmrgglXIsDirect(Display * dpy, GLXContext gc_user)
661848b8605Smrg{
662848b8605Smrg   struct glx_context *gc = (struct glx_context *) gc_user;
663848b8605Smrg
664848b8605Smrg   if (!gc) {
665848b8605Smrg      return False;
666848b8605Smrg   }
667848b8605Smrg   else if (gc->isDirect) {
668848b8605Smrg      return True;
669848b8605Smrg   }
670848b8605Smrg#ifdef GLX_USE_APPLEGL  /* TODO: indirect on darwin */
671848b8605Smrg   return False;
672848b8605Smrg#else
673848b8605Smrg   return __glXIsDirect(dpy, gc->xid);
674848b8605Smrg#endif
675848b8605Smrg}
676848b8605Smrg
677848b8605Smrg_X_EXPORT GLXPixmap
678848b8605SmrgglXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
679848b8605Smrg{
680848b8605Smrg#ifdef GLX_USE_APPLEGL
681848b8605Smrg   int screen = vis->screen;
682848b8605Smrg   struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
683848b8605Smrg   const struct glx_config *config;
684848b8605Smrg
685848b8605Smrg   config = glx_config_find_visual(psc->visuals, vis->visualid);
686848b8605Smrg
687848b8605Smrg   if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config))
688848b8605Smrg      return None;
689848b8605Smrg
690848b8605Smrg   return pixmap;
691848b8605Smrg#else
692848b8605Smrg   xGLXCreateGLXPixmapReq *req;
693848b8605Smrg   struct glx_drawable *glxDraw;
694848b8605Smrg   GLXPixmap xid;
695848b8605Smrg   CARD8 opcode;
696848b8605Smrg
697848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
698848b8605Smrg   struct glx_display *const priv = __glXInitialize(dpy);
699848b8605Smrg
700848b8605Smrg   if (priv == NULL)
701848b8605Smrg      return None;
702848b8605Smrg#endif
703848b8605Smrg
704848b8605Smrg   opcode = __glXSetupForCommand(dpy);
705848b8605Smrg   if (!opcode) {
706848b8605Smrg      return None;
707848b8605Smrg   }
708848b8605Smrg
709848b8605Smrg   glxDraw = malloc(sizeof(*glxDraw));
710848b8605Smrg   if (!glxDraw)
711848b8605Smrg      return None;
712848b8605Smrg
713848b8605Smrg   /* Send the glXCreateGLXPixmap request */
714848b8605Smrg   LockDisplay(dpy);
715848b8605Smrg   GetReq(GLXCreateGLXPixmap, req);
716848b8605Smrg   req->reqType = opcode;
717848b8605Smrg   req->glxCode = X_GLXCreateGLXPixmap;
718848b8605Smrg   req->screen = vis->screen;
719848b8605Smrg   req->visual = vis->visualid;
720848b8605Smrg   req->pixmap = pixmap;
721848b8605Smrg   req->glxpixmap = xid = XAllocID(dpy);
722848b8605Smrg   UnlockDisplay(dpy);
723848b8605Smrg   SyncHandle();
724848b8605Smrg
725848b8605Smrg   if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
726848b8605Smrg      free(glxDraw);
727848b8605Smrg      return None;
728848b8605Smrg   }
729848b8605Smrg
730848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
731848b8605Smrg   do {
732848b8605Smrg      /* FIXME: Maybe delay __DRIdrawable creation until the drawable
733848b8605Smrg       * is actually bound to a context... */
734848b8605Smrg
735848b8605Smrg      __GLXDRIdrawable *pdraw;
736848b8605Smrg      struct glx_screen *psc;
737848b8605Smrg      struct glx_config *config;
738848b8605Smrg
739848b8605Smrg      psc = priv->screens[vis->screen];
740848b8605Smrg      if (psc->driScreen == NULL)
741848b8605Smrg         return xid;
742848b8605Smrg
743848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
744848b8605Smrg      pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, config);
745848b8605Smrg      if (pdraw == NULL) {
746848b8605Smrg         fprintf(stderr, "failed to create pixmap\n");
747848b8605Smrg         xid = None;
748848b8605Smrg         break;
749848b8605Smrg      }
750848b8605Smrg
751848b8605Smrg      if (__glxHashInsert(priv->drawHash, xid, pdraw)) {
752848b8605Smrg         (*pdraw->destroyDrawable) (pdraw);
753848b8605Smrg         xid = None;
754848b8605Smrg         break;
755848b8605Smrg      }
756848b8605Smrg   } while (0);
757848b8605Smrg
758848b8605Smrg   if (xid == None) {
759848b8605Smrg      xGLXDestroyGLXPixmapReq *dreq;
760848b8605Smrg      LockDisplay(dpy);
761848b8605Smrg      GetReq(GLXDestroyGLXPixmap, dreq);
762848b8605Smrg      dreq->reqType = opcode;
763848b8605Smrg      dreq->glxCode = X_GLXDestroyGLXPixmap;
764848b8605Smrg      dreq->glxpixmap = xid;
765848b8605Smrg      UnlockDisplay(dpy);
766848b8605Smrg      SyncHandle();
767848b8605Smrg   }
768848b8605Smrg#endif
769848b8605Smrg
770848b8605Smrg   return xid;
771848b8605Smrg#endif
772848b8605Smrg}
773848b8605Smrg
774848b8605Smrg/*
775848b8605Smrg** Destroy the named pixmap
776848b8605Smrg*/
777848b8605Smrg_X_EXPORT void
778848b8605SmrgglXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
779848b8605Smrg{
780848b8605Smrg#ifdef GLX_USE_APPLEGL
781848b8605Smrg   if(apple_glx_pixmap_destroy(dpy, glxpixmap))
782848b8605Smrg      __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false);
783848b8605Smrg#else
784848b8605Smrg   xGLXDestroyGLXPixmapReq *req;
785848b8605Smrg   CARD8 opcode;
786848b8605Smrg
787848b8605Smrg   opcode = __glXSetupForCommand(dpy);
788848b8605Smrg   if (!opcode) {
789848b8605Smrg      return;
790848b8605Smrg   }
791848b8605Smrg
792848b8605Smrg   /* Send the glXDestroyGLXPixmap request */
793848b8605Smrg   LockDisplay(dpy);
794848b8605Smrg   GetReq(GLXDestroyGLXPixmap, req);
795848b8605Smrg   req->reqType = opcode;
796848b8605Smrg   req->glxCode = X_GLXDestroyGLXPixmap;
797848b8605Smrg   req->glxpixmap = glxpixmap;
798848b8605Smrg   UnlockDisplay(dpy);
799848b8605Smrg   SyncHandle();
800848b8605Smrg
801848b8605Smrg   DestroyGLXDrawable(dpy, glxpixmap);
802848b8605Smrg
803848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
804848b8605Smrg   {
805848b8605Smrg      struct glx_display *const priv = __glXInitialize(dpy);
806848b8605Smrg      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap);
807848b8605Smrg
808848b8605Smrg      if (priv != NULL && pdraw != NULL) {
809848b8605Smrg         (*pdraw->destroyDrawable) (pdraw);
810848b8605Smrg         __glxHashDelete(priv->drawHash, glxpixmap);
811848b8605Smrg      }
812848b8605Smrg   }
813848b8605Smrg#endif
814848b8605Smrg#endif /* GLX_USE_APPLEGL */
815848b8605Smrg}
816848b8605Smrg
817848b8605Smrg_X_EXPORT void
818848b8605SmrgglXSwapBuffers(Display * dpy, GLXDrawable drawable)
819848b8605Smrg{
820848b8605Smrg#ifdef GLX_USE_APPLEGL
821848b8605Smrg   struct glx_context * gc = __glXGetCurrentContext();
822848b8605Smrg   if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
823848b8605Smrg      apple_glx_swap_buffers(gc->driContext);
824848b8605Smrg   } else {
825848b8605Smrg      __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false);
826848b8605Smrg   }
827848b8605Smrg#else
828848b8605Smrg   struct glx_context *gc;
829848b8605Smrg   GLXContextTag tag;
830848b8605Smrg   CARD8 opcode;
831848b8605Smrg   xcb_connection_t *c;
832848b8605Smrg
833848b8605Smrg   gc = __glXGetCurrentContext();
834848b8605Smrg
835848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
836848b8605Smrg   {
837848b8605Smrg      __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
838848b8605Smrg
839848b8605Smrg      if (pdraw != NULL) {
840848b8605Smrg         Bool flush = gc && drawable == gc->currentDrawable;
841848b8605Smrg
842848b8605Smrg         (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0, flush);
843848b8605Smrg         return;
844848b8605Smrg      }
845848b8605Smrg   }
846848b8605Smrg#endif
847848b8605Smrg
848848b8605Smrg   opcode = __glXSetupForCommand(dpy);
849848b8605Smrg   if (!opcode) {
850848b8605Smrg      return;
851848b8605Smrg   }
852848b8605Smrg
853848b8605Smrg   /*
854848b8605Smrg    ** The calling thread may or may not have a current context.  If it
855848b8605Smrg    ** does, send the context tag so the server can do a flush.
856848b8605Smrg    */
857848b8605Smrg   if ((gc != NULL) && (dpy == gc->currentDpy) &&
858848b8605Smrg       ((drawable == gc->currentDrawable)
859848b8605Smrg        || (drawable == gc->currentReadable))) {
860848b8605Smrg      tag = gc->currentContextTag;
861848b8605Smrg   }
862848b8605Smrg   else {
863848b8605Smrg      tag = 0;
864848b8605Smrg   }
865848b8605Smrg
866848b8605Smrg   c = XGetXCBConnection(dpy);
867848b8605Smrg   xcb_glx_swap_buffers(c, tag, drawable);
868848b8605Smrg   xcb_flush(c);
869848b8605Smrg#endif /* GLX_USE_APPLEGL */
870848b8605Smrg}
871848b8605Smrg
872848b8605Smrg
873848b8605Smrg/*
874848b8605Smrg** Return configuration information for the given display, screen and
875848b8605Smrg** visual combination.
876848b8605Smrg*/
877848b8605Smrg_X_EXPORT int
878848b8605SmrgglXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
879848b8605Smrg             int *value_return)
880848b8605Smrg{
881848b8605Smrg   struct glx_display *priv;
882848b8605Smrg   struct glx_screen *psc;
883848b8605Smrg   struct glx_config *config;
884848b8605Smrg   int status;
885848b8605Smrg
886848b8605Smrg   status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc);
887848b8605Smrg   if (status == Success) {
888848b8605Smrg      config = glx_config_find_visual(psc->visuals, vis->visualid);
889848b8605Smrg
890848b8605Smrg      /* Lookup attribute after first finding a match on the visual */
891848b8605Smrg      if (config != NULL) {
892848b8605Smrg	 return glx_config_get(config, attribute, value_return);
893848b8605Smrg      }
894848b8605Smrg
895848b8605Smrg      status = GLX_BAD_VISUAL;
896848b8605Smrg   }
897848b8605Smrg
898848b8605Smrg   /*
899848b8605Smrg    ** If we can't find the config for this visual, this visual is not
900848b8605Smrg    ** supported by the OpenGL implementation on the server.
901848b8605Smrg    */
902848b8605Smrg   if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) {
903848b8605Smrg      *value_return = False;
904848b8605Smrg      status = Success;
905848b8605Smrg   }
906848b8605Smrg
907848b8605Smrg   return status;
908848b8605Smrg}
909848b8605Smrg
910848b8605Smrg/************************************************************************/
911848b8605Smrg
912848b8605Smrgstatic void
913848b8605Smrginit_fbconfig_for_chooser(struct glx_config * config,
914848b8605Smrg                          GLboolean fbconfig_style_tags)
915848b8605Smrg{
916848b8605Smrg   memset(config, 0, sizeof(struct glx_config));
917848b8605Smrg   config->visualID = (XID) GLX_DONT_CARE;
918848b8605Smrg   config->visualType = GLX_DONT_CARE;
919848b8605Smrg
920848b8605Smrg   /* glXChooseFBConfig specifies different defaults for these properties than
921848b8605Smrg    * glXChooseVisual.
922848b8605Smrg    */
923848b8605Smrg   if (fbconfig_style_tags) {
924848b8605Smrg      config->rgbMode = GL_TRUE;
925848b8605Smrg      config->doubleBufferMode = GLX_DONT_CARE;
926848b8605Smrg      config->renderType = GLX_RGBA_BIT;
927848b8605Smrg   }
928848b8605Smrg
929848b8605Smrg   config->drawableType = GLX_WINDOW_BIT;
930848b8605Smrg   config->visualRating = GLX_DONT_CARE;
931848b8605Smrg   config->transparentPixel = GLX_NONE;
932848b8605Smrg   config->transparentRed = GLX_DONT_CARE;
933848b8605Smrg   config->transparentGreen = GLX_DONT_CARE;
934848b8605Smrg   config->transparentBlue = GLX_DONT_CARE;
935848b8605Smrg   config->transparentAlpha = GLX_DONT_CARE;
936848b8605Smrg   config->transparentIndex = GLX_DONT_CARE;
937848b8605Smrg
938848b8605Smrg   config->xRenderable = GLX_DONT_CARE;
939848b8605Smrg   config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE);
940848b8605Smrg
941848b8605Smrg   config->swapMethod = GLX_DONT_CARE;
942848b8605Smrg}
943848b8605Smrg
944848b8605Smrg#define MATCH_DONT_CARE( param )        \
945848b8605Smrg  do {                                  \
946848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)   \
947848b8605Smrg         && (a-> param != b-> param) ) {        \
948848b8605Smrg      return False;                             \
949848b8605Smrg    }                                           \
950848b8605Smrg  } while ( 0 )
951848b8605Smrg
952848b8605Smrg#define MATCH_MINIMUM( param )                  \
953848b8605Smrg  do {                                          \
954848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)	\
955848b8605Smrg         && (a-> param > b-> param) ) {         \
956848b8605Smrg      return False;                             \
957848b8605Smrg    }                                           \
958848b8605Smrg  } while ( 0 )
959848b8605Smrg
960848b8605Smrg#define MATCH_EXACT( param )                    \
961848b8605Smrg  do {                                          \
962848b8605Smrg    if ( a-> param != b-> param) {              \
963848b8605Smrg      return False;                             \
964848b8605Smrg    }                                           \
965848b8605Smrg  } while ( 0 )
966848b8605Smrg
967848b8605Smrg/* Test that all bits from a are contained in b */
968848b8605Smrg#define MATCH_MASK(param)			\
969848b8605Smrg  do {						\
970848b8605Smrg    if ( ((int) a-> param != (int) GLX_DONT_CARE)	\
971848b8605Smrg         && ((a->param & ~b->param) != 0) ) {   \
972848b8605Smrg      return False;				\
973848b8605Smrg    }                                           \
974848b8605Smrg  } while (0);
975848b8605Smrg
976848b8605Smrg/**
977848b8605Smrg * Determine if two GLXFBConfigs are compatible.
978848b8605Smrg *
979848b8605Smrg * \param a  Application specified config to test.
980848b8605Smrg * \param b  Server specified config to test against \c a.
981848b8605Smrg */
982848b8605Smrgstatic Bool
983848b8605Smrgfbconfigs_compatible(const struct glx_config * const a,
984848b8605Smrg                     const struct glx_config * const b)
985848b8605Smrg{
986848b8605Smrg   MATCH_DONT_CARE(doubleBufferMode);
987848b8605Smrg   MATCH_DONT_CARE(visualType);
988848b8605Smrg   MATCH_DONT_CARE(visualRating);
989848b8605Smrg   MATCH_DONT_CARE(xRenderable);
990848b8605Smrg   MATCH_DONT_CARE(fbconfigID);
991848b8605Smrg   MATCH_DONT_CARE(swapMethod);
992848b8605Smrg
993848b8605Smrg   MATCH_MINIMUM(rgbBits);
994848b8605Smrg   MATCH_MINIMUM(numAuxBuffers);
995848b8605Smrg   MATCH_MINIMUM(redBits);
996848b8605Smrg   MATCH_MINIMUM(greenBits);
997848b8605Smrg   MATCH_MINIMUM(blueBits);
998848b8605Smrg   MATCH_MINIMUM(alphaBits);
999848b8605Smrg   MATCH_MINIMUM(depthBits);
1000848b8605Smrg   MATCH_MINIMUM(stencilBits);
1001848b8605Smrg   MATCH_MINIMUM(accumRedBits);
1002848b8605Smrg   MATCH_MINIMUM(accumGreenBits);
1003848b8605Smrg   MATCH_MINIMUM(accumBlueBits);
1004848b8605Smrg   MATCH_MINIMUM(accumAlphaBits);
1005848b8605Smrg   MATCH_MINIMUM(sampleBuffers);
1006848b8605Smrg   MATCH_MINIMUM(maxPbufferWidth);
1007848b8605Smrg   MATCH_MINIMUM(maxPbufferHeight);
1008848b8605Smrg   MATCH_MINIMUM(maxPbufferPixels);
1009848b8605Smrg   MATCH_MINIMUM(samples);
1010848b8605Smrg
1011848b8605Smrg   MATCH_DONT_CARE(stereoMode);
1012848b8605Smrg   MATCH_EXACT(level);
1013848b8605Smrg
1014848b8605Smrg   MATCH_MASK(drawableType);
1015848b8605Smrg   MATCH_MASK(renderType);
1016848b8605Smrg
1017848b8605Smrg   /* There is a bug in a few of the XFree86 DDX drivers.  They contain
1018848b8605Smrg    * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1019848b8605Smrg    * Technically speaking, it is a bug in the DDX driver, but there is
1020848b8605Smrg    * enough of an installed base to work around the problem here.  In any
1021848b8605Smrg    * case, 0 is not a valid value of the transparent type, so we'll treat 0
1022848b8605Smrg    * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1023848b8605Smrg    * 0 from the server to be a match to maintain backward compatibility with
1024848b8605Smrg    * the (broken) drivers.
1025848b8605Smrg    */
1026848b8605Smrg
1027848b8605Smrg   if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) {
1028848b8605Smrg      if (a->transparentPixel == GLX_NONE) {
1029848b8605Smrg         if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0)
1030848b8605Smrg            return False;
1031848b8605Smrg      }
1032848b8605Smrg      else {
1033848b8605Smrg         MATCH_EXACT(transparentPixel);
1034848b8605Smrg      }
1035848b8605Smrg
1036848b8605Smrg      switch (a->transparentPixel) {
1037848b8605Smrg      case GLX_TRANSPARENT_RGB:
1038848b8605Smrg         MATCH_DONT_CARE(transparentRed);
1039848b8605Smrg         MATCH_DONT_CARE(transparentGreen);
1040848b8605Smrg         MATCH_DONT_CARE(transparentBlue);
1041848b8605Smrg         MATCH_DONT_CARE(transparentAlpha);
1042848b8605Smrg         break;
1043848b8605Smrg
1044848b8605Smrg      case GLX_TRANSPARENT_INDEX:
1045848b8605Smrg         MATCH_DONT_CARE(transparentIndex);
1046848b8605Smrg         break;
1047848b8605Smrg
1048848b8605Smrg      default:
1049848b8605Smrg         break;
1050848b8605Smrg      }
1051848b8605Smrg   }
1052848b8605Smrg
1053848b8605Smrg   return True;
1054848b8605Smrg}
1055848b8605Smrg
1056848b8605Smrg
1057848b8605Smrg/* There's some trickly language in the GLX spec about how this is supposed
1058848b8605Smrg * to work.  Basically, if a given component size is either not specified
1059848b8605Smrg * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1060848b8605Smrg * Well, that's really hard to do with the code as-is.  This behavior is
1061848b8605Smrg * closer to correct, but still not technically right.
1062848b8605Smrg */
1063848b8605Smrg#define PREFER_LARGER_OR_ZERO(comp)             \
1064848b8605Smrg  do {                                          \
1065848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1066848b8605Smrg      if ( ((*a)-> comp) == 0 ) {               \
1067848b8605Smrg        return -1;                              \
1068848b8605Smrg      }                                         \
1069848b8605Smrg      else if ( ((*b)-> comp) == 0 ) {          \
1070848b8605Smrg        return 1;                               \
1071848b8605Smrg      }                                         \
1072848b8605Smrg      else {                                    \
1073848b8605Smrg        return ((*b)-> comp) - ((*a)-> comp) ;  \
1074848b8605Smrg      }                                         \
1075848b8605Smrg    }                                           \
1076848b8605Smrg  } while( 0 )
1077848b8605Smrg
1078848b8605Smrg#define PREFER_LARGER(comp)                     \
1079848b8605Smrg  do {                                          \
1080848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1081848b8605Smrg      return ((*b)-> comp) - ((*a)-> comp) ;    \
1082848b8605Smrg    }                                           \
1083848b8605Smrg  } while( 0 )
1084848b8605Smrg
1085848b8605Smrg#define PREFER_SMALLER(comp)                    \
1086848b8605Smrg  do {                                          \
1087848b8605Smrg    if ( ((*a)-> comp) != ((*b)-> comp) ) {     \
1088848b8605Smrg      return ((*a)-> comp) - ((*b)-> comp) ;    \
1089848b8605Smrg    }                                           \
1090848b8605Smrg  } while( 0 )
1091848b8605Smrg
1092848b8605Smrg/**
1093848b8605Smrg * Compare two GLXFBConfigs.  This function is intended to be used as the
1094848b8605Smrg * compare function passed in to qsort.
1095848b8605Smrg *
1096848b8605Smrg * \returns If \c a is a "better" config, according to the specification of
1097848b8605Smrg *          SGIX_fbconfig, a number less than zero is returned.  If \c b is
1098848b8605Smrg *          better, then a number greater than zero is return.  If both are
1099848b8605Smrg *          equal, zero is returned.
1100848b8605Smrg * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1101848b8605Smrg */
1102848b8605Smrgstatic int
1103848b8605Smrgfbconfig_compare(struct glx_config **a, struct glx_config **b)
1104848b8605Smrg{
1105848b8605Smrg   /* The order of these comparisons must NOT change.  It is defined by
1106848b8605Smrg    * the GLX 1.4 specification.
1107848b8605Smrg    */
1108848b8605Smrg
1109848b8605Smrg   PREFER_SMALLER(visualSelectGroup);
1110848b8605Smrg
1111848b8605Smrg   /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1112848b8605Smrg    * GLX_NON_CONFORMANT_CONFIG.  It just so happens that this is the
1113848b8605Smrg    * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1114848b8605Smrg    */
1115848b8605Smrg   PREFER_SMALLER(visualRating);
1116848b8605Smrg
1117848b8605Smrg   /* This isn't quite right.  It is supposed to compare the sum of the
1118848b8605Smrg    * components the user specifically set minimums for.
1119848b8605Smrg    */
1120848b8605Smrg   PREFER_LARGER_OR_ZERO(redBits);
1121848b8605Smrg   PREFER_LARGER_OR_ZERO(greenBits);
1122848b8605Smrg   PREFER_LARGER_OR_ZERO(blueBits);
1123848b8605Smrg   PREFER_LARGER_OR_ZERO(alphaBits);
1124848b8605Smrg
1125848b8605Smrg   PREFER_SMALLER(rgbBits);
1126848b8605Smrg
1127848b8605Smrg   if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) {
1128848b8605Smrg      /* Prefer single-buffer.
1129848b8605Smrg       */
1130848b8605Smrg      return (!(*a)->doubleBufferMode) ? -1 : 1;
1131848b8605Smrg   }
1132848b8605Smrg
1133848b8605Smrg   PREFER_SMALLER(numAuxBuffers);
1134848b8605Smrg
1135848b8605Smrg   PREFER_SMALLER(sampleBuffers);
1136848b8605Smrg   PREFER_SMALLER(samples);
1137848b8605Smrg
1138848b8605Smrg   PREFER_LARGER_OR_ZERO(depthBits);
1139848b8605Smrg   PREFER_SMALLER(stencilBits);
1140848b8605Smrg
1141848b8605Smrg   /* This isn't quite right.  It is supposed to compare the sum of the
1142848b8605Smrg    * components the user specifically set minimums for.
1143848b8605Smrg    */
1144848b8605Smrg   PREFER_LARGER_OR_ZERO(accumRedBits);
1145848b8605Smrg   PREFER_LARGER_OR_ZERO(accumGreenBits);
1146848b8605Smrg   PREFER_LARGER_OR_ZERO(accumBlueBits);
1147848b8605Smrg   PREFER_LARGER_OR_ZERO(accumAlphaBits);
1148848b8605Smrg
1149848b8605Smrg   PREFER_SMALLER(visualType);
1150848b8605Smrg
1151848b8605Smrg   /* None of the pbuffer or fbconfig specs say that this comparison needs
1152848b8605Smrg    * to happen at all, but it seems like it should.
1153848b8605Smrg    */
1154848b8605Smrg   PREFER_LARGER(maxPbufferWidth);
1155848b8605Smrg   PREFER_LARGER(maxPbufferHeight);
1156848b8605Smrg   PREFER_LARGER(maxPbufferPixels);
1157848b8605Smrg
1158848b8605Smrg   return 0;
1159848b8605Smrg}
1160848b8605Smrg
1161848b8605Smrg
1162848b8605Smrg/**
1163848b8605Smrg * Selects and sorts a subset of the supplied configs based on the attributes.
1164848b8605Smrg * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1165848b8605Smrg * and \c glXChooseFBConfigSGIX.
1166848b8605Smrg *
1167848b8605Smrg * \param configs   Array of pointers to possible configs.  The elements of
1168848b8605Smrg *                  this array that do not meet the criteria will be set to
1169848b8605Smrg *                  NULL.  The remaining elements will be sorted according to
1170848b8605Smrg *                  the various visual / FBConfig selection rules.
1171848b8605Smrg * \param num_configs  Number of elements in the \c configs array.
1172848b8605Smrg * \param attribList   Attributes used select from \c configs.  This array is
1173848b8605Smrg *                     terminated by a \c None tag.  The array can either take
1174848b8605Smrg *                     the form expected by \c glXChooseVisual (where boolean
1175848b8605Smrg *                     tags do not have a value) or by \c glXChooseFBConfig
1176848b8605Smrg *                     (where every tag has a value).
1177848b8605Smrg * \param fbconfig_style_tags  Selects whether \c attribList is in
1178848b8605Smrg *                             \c glXChooseVisual style or
1179848b8605Smrg *                             \c glXChooseFBConfig style.
1180848b8605Smrg * \returns The number of valid elements left in \c configs.
1181848b8605Smrg *
1182848b8605Smrg * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1183848b8605Smrg */
1184848b8605Smrgstatic int
1185848b8605Smrgchoose_visual(struct glx_config ** configs, int num_configs,
1186848b8605Smrg              const int *attribList, GLboolean fbconfig_style_tags)
1187848b8605Smrg{
1188848b8605Smrg   struct glx_config test_config;
1189848b8605Smrg   int base;
1190848b8605Smrg   int i;
1191848b8605Smrg
1192848b8605Smrg   /* This is a fairly direct implementation of the selection method
1193848b8605Smrg    * described by GLX_SGIX_fbconfig.  Start by culling out all the
1194848b8605Smrg    * configs that are not compatible with the selected parameter
1195848b8605Smrg    * list.
1196848b8605Smrg    */
1197848b8605Smrg
1198848b8605Smrg   init_fbconfig_for_chooser(&test_config, fbconfig_style_tags);
1199848b8605Smrg   __glXInitializeVisualConfigFromTags(&test_config, 512,
1200848b8605Smrg                                       (const INT32 *) attribList,
1201848b8605Smrg                                       GL_TRUE, fbconfig_style_tags);
1202848b8605Smrg
1203848b8605Smrg   base = 0;
1204848b8605Smrg   for (i = 0; i < num_configs; i++) {
1205848b8605Smrg      if (fbconfigs_compatible(&test_config, configs[i])) {
1206848b8605Smrg         configs[base] = configs[i];
1207848b8605Smrg         base++;
1208848b8605Smrg      }
1209848b8605Smrg   }
1210848b8605Smrg
1211848b8605Smrg   if (base == 0) {
1212848b8605Smrg      return 0;
1213848b8605Smrg   }
1214848b8605Smrg
1215848b8605Smrg   if (base < num_configs) {
1216848b8605Smrg      (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base));
1217848b8605Smrg   }
1218848b8605Smrg
1219848b8605Smrg   /* After the incompatible configs are removed, the resulting
1220848b8605Smrg    * list is sorted according to the rules set out in the various
1221848b8605Smrg    * specifications.
1222848b8605Smrg    */
1223848b8605Smrg
1224848b8605Smrg   qsort(configs, base, sizeof(struct glx_config *),
1225848b8605Smrg         (int (*)(const void *, const void *)) fbconfig_compare);
1226848b8605Smrg   return base;
1227848b8605Smrg}
1228848b8605Smrg
1229848b8605Smrg
1230848b8605Smrg
1231848b8605Smrg
1232848b8605Smrg/*
1233848b8605Smrg** Return the visual that best matches the template.  Return None if no
1234848b8605Smrg** visual matches the template.
1235848b8605Smrg*/
1236848b8605Smrg_X_EXPORT XVisualInfo *
1237848b8605SmrgglXChooseVisual(Display * dpy, int screen, int *attribList)
1238848b8605Smrg{
1239848b8605Smrg   XVisualInfo *visualList = NULL;
1240848b8605Smrg   struct glx_display *priv;
1241848b8605Smrg   struct glx_screen *psc;
1242848b8605Smrg   struct glx_config test_config;
1243848b8605Smrg   struct glx_config *config;
1244848b8605Smrg   struct glx_config *best_config = NULL;
1245848b8605Smrg
1246848b8605Smrg   /*
1247848b8605Smrg    ** Get a list of all visuals, return if list is empty
1248848b8605Smrg    */
1249848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1250848b8605Smrg      return None;
1251848b8605Smrg   }
1252848b8605Smrg
1253848b8605Smrg
1254848b8605Smrg   /*
1255848b8605Smrg    ** Build a template from the defaults and the attribute list
1256848b8605Smrg    ** Free visual list and return if an unexpected token is encountered
1257848b8605Smrg    */
1258848b8605Smrg   init_fbconfig_for_chooser(&test_config, GL_FALSE);
1259848b8605Smrg   __glXInitializeVisualConfigFromTags(&test_config, 512,
1260848b8605Smrg                                       (const INT32 *) attribList,
1261848b8605Smrg                                       GL_TRUE, GL_FALSE);
1262848b8605Smrg
1263848b8605Smrg   /*
1264848b8605Smrg    ** Eliminate visuals that don't meet minimum requirements
1265848b8605Smrg    ** Compute a score for those that do
1266848b8605Smrg    ** Remember which visual, if any, got the highest score
1267848b8605Smrg    ** If no visual is acceptable, return None
1268848b8605Smrg    ** Otherwise, create an XVisualInfo list with just the selected X visual
1269848b8605Smrg    ** and return this.
1270848b8605Smrg    */
1271848b8605Smrg   for (config = psc->visuals; config != NULL; config = config->next) {
1272848b8605Smrg      if (fbconfigs_compatible(&test_config, config)
1273848b8605Smrg          && ((best_config == NULL) ||
1274848b8605Smrg              (fbconfig_compare (&config, &best_config) < 0))) {
1275848b8605Smrg         XVisualInfo visualTemplate;
1276848b8605Smrg         XVisualInfo *newList;
1277848b8605Smrg         int i;
1278848b8605Smrg
1279848b8605Smrg         visualTemplate.screen = screen;
1280848b8605Smrg         visualTemplate.visualid = config->visualID;
1281848b8605Smrg         newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
1282848b8605Smrg                                  &visualTemplate, &i);
1283848b8605Smrg
1284848b8605Smrg         if (newList) {
1285848b8605Smrg            free(visualList);
1286848b8605Smrg            visualList = newList;
1287848b8605Smrg            best_config = config;
1288848b8605Smrg         }
1289848b8605Smrg      }
1290848b8605Smrg   }
1291848b8605Smrg
1292848b8605Smrg#ifdef GLX_USE_APPLEGL
1293848b8605Smrg   if(visualList && getenv("LIBGL_DUMP_VISUALID")) {
1294848b8605Smrg      printf("visualid 0x%lx\n", visualList[0].visualid);
1295848b8605Smrg   }
1296848b8605Smrg#endif
1297848b8605Smrg
1298848b8605Smrg   return visualList;
1299848b8605Smrg}
1300848b8605Smrg
1301848b8605Smrg
1302848b8605Smrg_X_EXPORT const char *
1303848b8605SmrgglXQueryExtensionsString(Display * dpy, int screen)
1304848b8605Smrg{
1305848b8605Smrg   struct glx_screen *psc;
1306848b8605Smrg   struct glx_display *priv;
1307848b8605Smrg
1308848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1309848b8605Smrg      return NULL;
1310848b8605Smrg   }
1311848b8605Smrg
1312848b8605Smrg   if (!psc->effectiveGLXexts) {
1313848b8605Smrg      if (!psc->serverGLXexts) {
1314848b8605Smrg         psc->serverGLXexts =
1315848b8605Smrg            __glXQueryServerString(dpy, priv->majorOpcode, screen,
1316848b8605Smrg                                   GLX_EXTENSIONS);
1317848b8605Smrg      }
1318848b8605Smrg
1319848b8605Smrg      __glXCalculateUsableExtensions(psc,
1320848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
1321848b8605Smrg                                     (psc->driScreen != NULL),
1322848b8605Smrg#else
1323848b8605Smrg                                     GL_FALSE,
1324848b8605Smrg#endif
1325848b8605Smrg                                     priv->minorVersion);
1326848b8605Smrg   }
1327848b8605Smrg
1328848b8605Smrg   return psc->effectiveGLXexts;
1329848b8605Smrg}
1330848b8605Smrg
1331848b8605Smrg_X_EXPORT const char *
1332848b8605SmrgglXGetClientString(Display * dpy, int name)
1333848b8605Smrg{
1334848b8605Smrg   (void) dpy;
1335848b8605Smrg
1336848b8605Smrg   switch (name) {
1337848b8605Smrg   case GLX_VENDOR:
1338848b8605Smrg      return (__glXGLXClientVendorName);
1339848b8605Smrg   case GLX_VERSION:
1340848b8605Smrg      return (__glXGLXClientVersion);
1341848b8605Smrg   case GLX_EXTENSIONS:
1342848b8605Smrg      return (__glXGetClientExtensions());
1343848b8605Smrg   default:
1344848b8605Smrg      return NULL;
1345848b8605Smrg   }
1346848b8605Smrg}
1347848b8605Smrg
1348848b8605Smrg_X_EXPORT const char *
1349848b8605SmrgglXQueryServerString(Display * dpy, int screen, int name)
1350848b8605Smrg{
1351848b8605Smrg   struct glx_screen *psc;
1352848b8605Smrg   struct glx_display *priv;
1353848b8605Smrg   const char **str;
1354848b8605Smrg
1355848b8605Smrg
1356848b8605Smrg   if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) {
1357848b8605Smrg      return NULL;
1358848b8605Smrg   }
1359848b8605Smrg
1360848b8605Smrg   switch (name) {
1361848b8605Smrg   case GLX_VENDOR:
1362848b8605Smrg      str = &priv->serverGLXvendor;
1363848b8605Smrg      break;
1364848b8605Smrg   case GLX_VERSION:
1365848b8605Smrg      str = &priv->serverGLXversion;
1366848b8605Smrg      break;
1367848b8605Smrg   case GLX_EXTENSIONS:
1368848b8605Smrg      str = &psc->serverGLXexts;
1369848b8605Smrg      break;
1370848b8605Smrg   default:
1371848b8605Smrg      return NULL;
1372848b8605Smrg   }
1373848b8605Smrg
1374848b8605Smrg   if (*str == NULL) {
1375848b8605Smrg      *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
1376848b8605Smrg   }
1377848b8605Smrg
1378848b8605Smrg   return *str;
1379848b8605Smrg}
1380848b8605Smrg
1381848b8605Smrg
1382848b8605Smrg/*
1383848b8605Smrg** EXT_import_context
1384848b8605Smrg*/
1385848b8605Smrg
1386848b8605Smrg_X_EXPORT Display *
1387848b8605SmrgglXGetCurrentDisplay(void)
1388848b8605Smrg{
1389848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1390848b8605Smrg   if (NULL == gc)
1391848b8605Smrg      return NULL;
1392848b8605Smrg   return gc->currentDpy;
1393848b8605Smrg}
1394848b8605Smrg
1395848b8605Smrg_X_EXPORT
1396848b8605SmrgGLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1397848b8605Smrg          glXGetCurrentDisplay)
1398848b8605Smrg
1399848b8605Smrg#ifndef GLX_USE_APPLEGL
1400848b8605Smrg_X_EXPORT GLXContext
1401848b8605SmrgglXImportContextEXT(Display *dpy, GLXContextID contextID)
1402848b8605Smrg{
1403848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
1404848b8605Smrg   struct glx_screen *psc = NULL;
1405848b8605Smrg   xGLXQueryContextReply reply;
1406848b8605Smrg   CARD8 opcode;
1407848b8605Smrg   struct glx_context *ctx;
1408848b8605Smrg
1409848b8605Smrg   /* This GLX implementation knows about 5 different properties, so
1410848b8605Smrg    * allow the server to send us one of each.
1411848b8605Smrg    */
1412848b8605Smrg   int propList[5 * 2], *pProp, nPropListBytes;
1413848b8605Smrg   int numProps;
1414848b8605Smrg   int i, renderType;
1415848b8605Smrg   XID share;
1416848b8605Smrg   struct glx_config *mode;
1417848b8605Smrg   uint32_t fbconfigID = 0;
1418848b8605Smrg   uint32_t visualID = 0;
1419848b8605Smrg   uint32_t screen = 0;
1420848b8605Smrg   Bool got_screen = False;
1421848b8605Smrg
1422848b8605Smrg   if (priv == NULL)
1423848b8605Smrg      return NULL;
1424848b8605Smrg
1425848b8605Smrg   /* The GLX_EXT_import_context spec says:
1426848b8605Smrg    *
1427848b8605Smrg    *     "If <contextID> does not refer to a valid context, then a BadContext
1428848b8605Smrg    *     error is generated; if <contextID> refers to direct rendering
1429848b8605Smrg    *     context then no error is generated but glXImportContextEXT returns
1430848b8605Smrg    *     NULL."
1431848b8605Smrg    *
1432848b8605Smrg    * If contextID is None, generate BadContext on the client-side.  Other
1433848b8605Smrg    * sorts of invalid contexts will be detected by the server in the
1434848b8605Smrg    * __glXIsDirect call.
1435848b8605Smrg    */
1436848b8605Smrg   if (contextID == None) {
1437848b8605Smrg      __glXSendError(dpy, GLXBadContext, contextID, X_GLXIsDirect, false);
1438848b8605Smrg      return NULL;
1439848b8605Smrg   }
1440848b8605Smrg
1441848b8605Smrg   if (__glXIsDirect(dpy, contextID))
1442848b8605Smrg      return NULL;
1443848b8605Smrg
1444848b8605Smrg   opcode = __glXSetupForCommand(dpy);
1445848b8605Smrg   if (!opcode)
1446848b8605Smrg      return 0;
1447848b8605Smrg
1448848b8605Smrg   /* Send the glXQueryContextInfoEXT request */
1449848b8605Smrg   LockDisplay(dpy);
1450848b8605Smrg
1451848b8605Smrg   if (priv->majorVersion > 1 || priv->minorVersion >= 3) {
1452848b8605Smrg      xGLXQueryContextReq *req;
1453848b8605Smrg
1454848b8605Smrg      GetReq(GLXQueryContext, req);
1455848b8605Smrg
1456848b8605Smrg      req->reqType = opcode;
1457848b8605Smrg      req->glxCode = X_GLXQueryContext;
1458848b8605Smrg      req->context = contextID;
1459848b8605Smrg   }
1460848b8605Smrg   else {
1461848b8605Smrg      xGLXVendorPrivateReq *vpreq;
1462848b8605Smrg      xGLXQueryContextInfoEXTReq *req;
1463848b8605Smrg
1464848b8605Smrg      GetReqExtra(GLXVendorPrivate,
1465848b8605Smrg		  sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1466848b8605Smrg		  vpreq);
1467848b8605Smrg      req = (xGLXQueryContextInfoEXTReq *) vpreq;
1468848b8605Smrg      req->reqType = opcode;
1469848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
1470848b8605Smrg      req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1471848b8605Smrg      req->context = contextID;
1472848b8605Smrg   }
1473848b8605Smrg
1474848b8605Smrg   _XReply(dpy, (xReply *) & reply, 0, False);
1475848b8605Smrg
1476848b8605Smrg   if (reply.n <= __GLX_MAX_CONTEXT_PROPS)
1477848b8605Smrg      nPropListBytes = reply.n * 2 * sizeof propList[0];
1478848b8605Smrg   else
1479848b8605Smrg      nPropListBytes = 0;
1480848b8605Smrg   _XRead(dpy, (char *) propList, nPropListBytes);
1481848b8605Smrg   UnlockDisplay(dpy);
1482848b8605Smrg   SyncHandle();
1483848b8605Smrg
1484848b8605Smrg   numProps = nPropListBytes / (2 * sizeof(propList[0]));
1485848b8605Smrg   share = None;
1486848b8605Smrg   mode = NULL;
1487848b8605Smrg   renderType = GLX_RGBA_TYPE; /* By default, assume RGBA context */
1488848b8605Smrg   pProp = propList;
1489848b8605Smrg
1490848b8605Smrg   for (i = 0, pProp = propList; i < numProps; i++, pProp += 2)
1491848b8605Smrg      switch (pProp[0]) {
1492848b8605Smrg      case GLX_SCREEN:
1493848b8605Smrg	 screen = pProp[1];
1494848b8605Smrg	 got_screen = True;
1495848b8605Smrg	 break;
1496848b8605Smrg      case GLX_SHARE_CONTEXT_EXT:
1497848b8605Smrg	 share = pProp[1];
1498848b8605Smrg	 break;
1499848b8605Smrg      case GLX_VISUAL_ID_EXT:
1500848b8605Smrg	 visualID = pProp[1];
1501848b8605Smrg	 break;
1502848b8605Smrg      case GLX_FBCONFIG_ID:
1503848b8605Smrg	 fbconfigID = pProp[1];
1504848b8605Smrg	 break;
1505848b8605Smrg      case GLX_RENDER_TYPE:
1506848b8605Smrg	 renderType = pProp[1];
1507848b8605Smrg	 break;
1508848b8605Smrg      }
1509848b8605Smrg
1510848b8605Smrg   if (!got_screen)
1511848b8605Smrg      return NULL;
1512848b8605Smrg
1513848b8605Smrg   psc = GetGLXScreenConfigs(dpy, screen);
1514848b8605Smrg   if (psc == NULL)
1515848b8605Smrg      return NULL;
1516848b8605Smrg
1517848b8605Smrg   if (fbconfigID != 0) {
1518848b8605Smrg      mode = glx_config_find_fbconfig(psc->configs, fbconfigID);
1519848b8605Smrg   } else if (visualID != 0) {
1520848b8605Smrg      mode = glx_config_find_visual(psc->visuals, visualID);
1521848b8605Smrg   }
1522848b8605Smrg
1523848b8605Smrg   if (mode == NULL)
1524848b8605Smrg      return NULL;
1525848b8605Smrg
1526848b8605Smrg   ctx = indirect_create_context(psc, mode, NULL, renderType);
1527848b8605Smrg   if (ctx == NULL)
1528848b8605Smrg      return NULL;
1529848b8605Smrg
1530848b8605Smrg   ctx->xid = contextID;
1531848b8605Smrg   ctx->imported = GL_TRUE;
1532848b8605Smrg   ctx->share_xid = share;
1533848b8605Smrg
1534848b8605Smrg   return (GLXContext) ctx;
1535848b8605Smrg}
1536848b8605Smrg
1537848b8605Smrg#endif
1538848b8605Smrg
1539848b8605Smrg_X_EXPORT int
1540848b8605SmrgglXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value)
1541848b8605Smrg{
1542848b8605Smrg   struct glx_context *ctx = (struct glx_context *) ctx_user;
1543848b8605Smrg
1544848b8605Smrg   switch (attribute) {
1545848b8605Smrg      case GLX_SHARE_CONTEXT_EXT:
1546848b8605Smrg      *value = ctx->share_xid;
1547848b8605Smrg      break;
1548848b8605Smrg   case GLX_VISUAL_ID_EXT:
1549848b8605Smrg      *value = ctx->config ? ctx->config->visualID : None;
1550848b8605Smrg      break;
1551848b8605Smrg   case GLX_SCREEN:
1552848b8605Smrg      *value = ctx->screen;
1553848b8605Smrg      break;
1554848b8605Smrg   case GLX_FBCONFIG_ID:
1555848b8605Smrg      *value = ctx->config ? ctx->config->fbconfigID : None;
1556848b8605Smrg      break;
1557848b8605Smrg   case GLX_RENDER_TYPE:
1558848b8605Smrg      *value = ctx->renderType;
1559848b8605Smrg      break;
1560848b8605Smrg   default:
1561848b8605Smrg      return GLX_BAD_ATTRIBUTE;
1562848b8605Smrg   }
1563848b8605Smrg   return Success;
1564848b8605Smrg}
1565848b8605Smrg
1566848b8605Smrg_X_EXPORT
1567848b8605SmrgGLX_ALIAS(int, glXQueryContextInfoEXT,
1568848b8605Smrg          (Display * dpy, GLXContext ctx, int attribute, int *value),
1569848b8605Smrg          (dpy, ctx, attribute, value), glXQueryContext)
1570848b8605Smrg
1571848b8605Smrg_X_EXPORT GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
1572848b8605Smrg{
1573848b8605Smrg   struct glx_context *ctx = (struct glx_context *) ctx_user;
1574848b8605Smrg
1575848b8605Smrg   return (ctx == NULL) ? None : ctx->xid;
1576848b8605Smrg}
1577848b8605Smrg
1578848b8605Smrg_X_EXPORT void
1579848b8605SmrgglXFreeContextEXT(Display *dpy, GLXContext ctx)
1580848b8605Smrg{
1581848b8605Smrg   struct glx_context *gc = (struct glx_context *) ctx;
1582848b8605Smrg
1583848b8605Smrg   if (gc == NULL || gc->xid == None)
1584848b8605Smrg      return;
1585848b8605Smrg
1586848b8605Smrg   /* The GLX_EXT_import_context spec says:
1587848b8605Smrg    *
1588848b8605Smrg    *     "glXFreeContext does not free the server-side context information or
1589848b8605Smrg    *     the XID associated with the server-side context."
1590848b8605Smrg    *
1591848b8605Smrg    * Don't send any protocol.  Just destroy the client-side tracking of the
1592848b8605Smrg    * context.  Also, only release the context structure if it's not current.
1593848b8605Smrg    */
1594848b8605Smrg   __glXLock();
1595848b8605Smrg   if (gc->currentDpy) {
1596848b8605Smrg      gc->xid = None;
1597848b8605Smrg   } else {
1598848b8605Smrg      gc->vtable->destroy(gc);
1599848b8605Smrg   }
1600848b8605Smrg   __glXUnlock();
1601848b8605Smrg}
1602848b8605Smrg
1603848b8605Smrg_X_EXPORT GLXFBConfig *
1604848b8605SmrgglXChooseFBConfig(Display * dpy, int screen,
1605848b8605Smrg                  const int *attribList, int *nitems)
1606848b8605Smrg{
1607848b8605Smrg   struct glx_config **config_list;
1608848b8605Smrg   int list_size;
1609848b8605Smrg
1610848b8605Smrg
1611848b8605Smrg   config_list = (struct glx_config **)
1612848b8605Smrg      glXGetFBConfigs(dpy, screen, &list_size);
1613848b8605Smrg
1614848b8605Smrg   if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
1615848b8605Smrg      list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
1616848b8605Smrg      if (list_size == 0) {
1617848b8605Smrg         free(config_list);
1618848b8605Smrg         config_list = NULL;
1619848b8605Smrg      }
1620848b8605Smrg   }
1621848b8605Smrg
1622848b8605Smrg   *nitems = list_size;
1623848b8605Smrg   return (GLXFBConfig *) config_list;
1624848b8605Smrg}
1625848b8605Smrg
1626848b8605Smrg
1627848b8605Smrg_X_EXPORT GLXContext
1628848b8605SmrgglXCreateNewContext(Display * dpy, GLXFBConfig fbconfig,
1629848b8605Smrg                    int renderType, GLXContext shareList, Bool allowDirect)
1630848b8605Smrg{
1631848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1632848b8605Smrg
1633848b8605Smrg   return CreateContext(dpy, config->fbconfigID, config, shareList,
1634848b8605Smrg			allowDirect, X_GLXCreateNewContext, renderType,
1635848b8605Smrg			config->screen);
1636848b8605Smrg}
1637848b8605Smrg
1638848b8605Smrg
1639848b8605Smrg_X_EXPORT GLXDrawable
1640848b8605SmrgglXGetCurrentReadDrawable(void)
1641848b8605Smrg{
1642848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1643848b8605Smrg
1644848b8605Smrg   return gc->currentReadable;
1645848b8605Smrg}
1646848b8605Smrg
1647848b8605Smrg
1648848b8605Smrg_X_EXPORT GLXFBConfig *
1649848b8605SmrgglXGetFBConfigs(Display * dpy, int screen, int *nelements)
1650848b8605Smrg{
1651848b8605Smrg   struct glx_display *priv = __glXInitialize(dpy);
1652848b8605Smrg   struct glx_config **config_list = NULL;
1653848b8605Smrg   struct glx_config *config;
1654848b8605Smrg   unsigned num_configs = 0;
1655848b8605Smrg   int i;
1656848b8605Smrg
1657848b8605Smrg   *nelements = 0;
1658848b8605Smrg   if (priv && (priv->screens != NULL)
1659848b8605Smrg       && (screen >= 0) && (screen <= ScreenCount(dpy))
1660848b8605Smrg       && (priv->screens[screen]->configs != NULL)
1661848b8605Smrg       && (priv->screens[screen]->configs->fbconfigID
1662848b8605Smrg	   != (int) GLX_DONT_CARE)) {
1663848b8605Smrg
1664848b8605Smrg      for (config = priv->screens[screen]->configs; config != NULL;
1665848b8605Smrg           config = config->next) {
1666848b8605Smrg         if (config->fbconfigID != (int) GLX_DONT_CARE) {
1667848b8605Smrg            num_configs++;
1668848b8605Smrg         }
1669848b8605Smrg      }
1670848b8605Smrg
1671848b8605Smrg      config_list = malloc(num_configs * sizeof *config_list);
1672848b8605Smrg      if (config_list != NULL) {
1673848b8605Smrg         *nelements = num_configs;
1674848b8605Smrg         i = 0;
1675848b8605Smrg         for (config = priv->screens[screen]->configs; config != NULL;
1676848b8605Smrg              config = config->next) {
1677848b8605Smrg            if (config->fbconfigID != (int) GLX_DONT_CARE) {
1678848b8605Smrg               config_list[i] = config;
1679848b8605Smrg               i++;
1680848b8605Smrg            }
1681848b8605Smrg         }
1682848b8605Smrg      }
1683848b8605Smrg   }
1684848b8605Smrg
1685848b8605Smrg   return (GLXFBConfig *) config_list;
1686848b8605Smrg}
1687848b8605Smrg
1688848b8605Smrg
1689848b8605Smrg_X_EXPORT int
1690848b8605SmrgglXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig,
1691848b8605Smrg                     int attribute, int *value)
1692848b8605Smrg{
1693848b8605Smrg   struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig);
1694848b8605Smrg
1695848b8605Smrg   if (config == NULL)
1696848b8605Smrg      return GLXBadFBConfig;
1697848b8605Smrg
1698848b8605Smrg   return glx_config_get(config, attribute, value);
1699848b8605Smrg}
1700848b8605Smrg
1701848b8605Smrg
1702848b8605Smrg_X_EXPORT XVisualInfo *
1703848b8605SmrgglXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig)
1704848b8605Smrg{
1705848b8605Smrg   XVisualInfo visualTemplate;
1706848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1707848b8605Smrg   int count;
1708848b8605Smrg
1709848b8605Smrg   /*
1710848b8605Smrg    ** Get a list of all visuals, return if list is empty
1711848b8605Smrg    */
1712848b8605Smrg   visualTemplate.visualid = config->visualID;
1713848b8605Smrg   return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count);
1714848b8605Smrg}
1715848b8605Smrg
1716848b8605Smrg#ifndef GLX_USE_APPLEGL
1717848b8605Smrg/*
1718848b8605Smrg** GLX_SGI_swap_control
1719848b8605Smrg*/
1720848b8605Smrgstatic int
1721848b8605Smrg__glXSwapIntervalSGI(int interval)
1722848b8605Smrg{
1723848b8605Smrg   xGLXVendorPrivateReq *req;
1724848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1725848b8605Smrg   struct glx_screen *psc;
1726848b8605Smrg   Display *dpy;
1727848b8605Smrg   CARD32 *interval_ptr;
1728848b8605Smrg   CARD8 opcode;
1729848b8605Smrg
1730848b8605Smrg   if (gc == NULL) {
1731848b8605Smrg      return GLX_BAD_CONTEXT;
1732848b8605Smrg   }
1733848b8605Smrg
1734848b8605Smrg   if (interval <= 0) {
1735848b8605Smrg      return GLX_BAD_VALUE;
1736848b8605Smrg   }
1737848b8605Smrg
1738848b8605Smrg   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1739848b8605Smrg
1740848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1741848b8605Smrg   if (gc->isDirect && psc && psc->driScreen &&
1742848b8605Smrg          psc->driScreen->setSwapInterval) {
1743848b8605Smrg      __GLXDRIdrawable *pdraw =
1744848b8605Smrg	 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1745848b8605Smrg      psc->driScreen->setSwapInterval(pdraw, interval);
1746848b8605Smrg      return 0;
1747848b8605Smrg   }
1748848b8605Smrg#endif
1749848b8605Smrg
1750848b8605Smrg   dpy = gc->currentDpy;
1751848b8605Smrg   opcode = __glXSetupForCommand(dpy);
1752848b8605Smrg   if (!opcode) {
1753848b8605Smrg      return 0;
1754848b8605Smrg   }
1755848b8605Smrg
1756848b8605Smrg   /* Send the glXSwapIntervalSGI request */
1757848b8605Smrg   LockDisplay(dpy);
1758848b8605Smrg   GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req);
1759848b8605Smrg   req->reqType = opcode;
1760848b8605Smrg   req->glxCode = X_GLXVendorPrivate;
1761848b8605Smrg   req->vendorCode = X_GLXvop_SwapIntervalSGI;
1762848b8605Smrg   req->contextTag = gc->currentContextTag;
1763848b8605Smrg
1764848b8605Smrg   interval_ptr = (CARD32 *) (req + 1);
1765848b8605Smrg   *interval_ptr = interval;
1766848b8605Smrg
1767848b8605Smrg   UnlockDisplay(dpy);
1768848b8605Smrg   SyncHandle();
1769848b8605Smrg   XFlush(dpy);
1770848b8605Smrg
1771848b8605Smrg   return 0;
1772848b8605Smrg}
1773848b8605Smrg
1774848b8605Smrg
1775848b8605Smrg/*
1776848b8605Smrg** GLX_MESA_swap_control
1777848b8605Smrg*/
1778848b8605Smrgstatic int
1779848b8605Smrg__glXSwapIntervalMESA(unsigned int interval)
1780848b8605Smrg{
1781848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1782848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1783848b8605Smrg
1784848b8605Smrg   if (gc != NULL && gc->isDirect) {
1785848b8605Smrg      struct glx_screen *psc;
1786848b8605Smrg
1787848b8605Smrg      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1788848b8605Smrg      if (psc && psc->driScreen && psc->driScreen->setSwapInterval) {
1789848b8605Smrg         __GLXDRIdrawable *pdraw =
1790848b8605Smrg	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1791848b8605Smrg	 return psc->driScreen->setSwapInterval(pdraw, interval);
1792848b8605Smrg      }
1793848b8605Smrg   }
1794848b8605Smrg#endif
1795848b8605Smrg
1796848b8605Smrg   return GLX_BAD_CONTEXT;
1797848b8605Smrg}
1798848b8605Smrg
1799848b8605Smrg
1800848b8605Smrgstatic int
1801848b8605Smrg__glXGetSwapIntervalMESA(void)
1802848b8605Smrg{
1803848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1804848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1805848b8605Smrg
1806848b8605Smrg   if (gc != NULL && gc->isDirect) {
1807848b8605Smrg      struct glx_screen *psc;
1808848b8605Smrg
1809848b8605Smrg      psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1810848b8605Smrg      if (psc && psc->driScreen && psc->driScreen->getSwapInterval) {
1811848b8605Smrg         __GLXDRIdrawable *pdraw =
1812848b8605Smrg	    GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1813848b8605Smrg	 return psc->driScreen->getSwapInterval(pdraw);
1814848b8605Smrg      }
1815848b8605Smrg   }
1816848b8605Smrg#endif
1817848b8605Smrg
1818848b8605Smrg   return 0;
1819848b8605Smrg}
1820848b8605Smrg
1821848b8605Smrg
1822848b8605Smrg/*
1823848b8605Smrg** GLX_SGI_video_sync
1824848b8605Smrg*/
1825848b8605Smrgstatic int
1826848b8605Smrg__glXGetVideoSyncSGI(unsigned int *count)
1827848b8605Smrg{
1828848b8605Smrg   int64_t ust, msc, sbc;
1829848b8605Smrg   int ret;
1830848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1831848b8605Smrg   struct glx_screen *psc;
1832848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1833848b8605Smrg   __GLXDRIdrawable *pdraw;
1834848b8605Smrg#endif
1835848b8605Smrg
1836848b8605Smrg   if (!gc)
1837848b8605Smrg      return GLX_BAD_CONTEXT;
1838848b8605Smrg
1839848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1840848b8605Smrg   if (!gc->isDirect)
1841848b8605Smrg      return GLX_BAD_CONTEXT;
1842848b8605Smrg#endif
1843848b8605Smrg
1844848b8605Smrg   psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen);
1845848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1846848b8605Smrg   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1847848b8605Smrg#endif
1848848b8605Smrg
1849848b8605Smrg   /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1850848b8605Smrg    * FIXME: there should be a GLX encoding for this call.  I can find no
1851848b8605Smrg    * FIXME: documentation for the GLX encoding.
1852848b8605Smrg    */
1853848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1854848b8605Smrg   if (psc && psc->driScreen && psc->driScreen->getDrawableMSC) {
1855848b8605Smrg      ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc);
1856848b8605Smrg      *count = (unsigned) msc;
1857848b8605Smrg      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
1858848b8605Smrg   }
1859848b8605Smrg#endif
1860848b8605Smrg
1861848b8605Smrg   return GLX_BAD_CONTEXT;
1862848b8605Smrg}
1863848b8605Smrg
1864848b8605Smrgstatic int
1865848b8605Smrg__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
1866848b8605Smrg{
1867848b8605Smrg   struct glx_context *gc = __glXGetCurrentContext();
1868848b8605Smrg   struct glx_screen *psc;
1869848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1870848b8605Smrg   __GLXDRIdrawable *pdraw;
1871848b8605Smrg#endif
1872848b8605Smrg   int64_t ust, msc, sbc;
1873848b8605Smrg   int ret;
1874848b8605Smrg
1875848b8605Smrg   if (divisor <= 0 || remainder < 0)
1876848b8605Smrg      return GLX_BAD_VALUE;
1877848b8605Smrg
1878848b8605Smrg   if (!gc)
1879848b8605Smrg      return GLX_BAD_CONTEXT;
1880848b8605Smrg
1881848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1882848b8605Smrg   if (!gc->isDirect)
1883848b8605Smrg      return GLX_BAD_CONTEXT;
1884848b8605Smrg#endif
1885848b8605Smrg
1886848b8605Smrg   psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen);
1887848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1888848b8605Smrg   pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
1889848b8605Smrg#endif
1890848b8605Smrg
1891848b8605Smrg#ifdef GLX_DIRECT_RENDERING
1892848b8605Smrg   if (psc && psc->driScreen && psc->driScreen->waitForMSC) {
1893848b8605Smrg      ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc,
1894848b8605Smrg				       &sbc);
1895848b8605Smrg      *count = (unsigned) msc;
1896848b8605Smrg      return (ret == True) ? 0 : GLX_BAD_CONTEXT;
1897848b8605Smrg   }
1898848b8605Smrg#endif
1899848b8605Smrg
1900848b8605Smrg   return GLX_BAD_CONTEXT;
1901848b8605Smrg}
1902848b8605Smrg
1903848b8605Smrg#endif /* GLX_USE_APPLEGL */
1904848b8605Smrg
1905848b8605Smrg/*
1906848b8605Smrg** GLX_SGIX_fbconfig
1907848b8605Smrg** Many of these functions are aliased to GLX 1.3 entry points in the
1908848b8605Smrg** GLX_functions table.
1909848b8605Smrg*/
1910848b8605Smrg
1911848b8605Smrg_X_EXPORT
1912848b8605SmrgGLX_ALIAS(int, glXGetFBConfigAttribSGIX,
1913848b8605Smrg          (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
1914848b8605Smrg          (dpy, config, attribute, value), glXGetFBConfigAttrib)
1915848b8605Smrg
1916848b8605Smrg_X_EXPORT GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
1917848b8605Smrg                 (Display * dpy, int screen, int *attrib_list,
1918848b8605Smrg                  int *nelements), (dpy, screen, attrib_list, nelements),
1919848b8605Smrg                 glXChooseFBConfig)
1920848b8605Smrg
1921848b8605Smrg_X_EXPORT GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
1922848b8605Smrg                 (Display * dpy, GLXFBConfigSGIX config),
1923848b8605Smrg                 (dpy, config), glXGetVisualFromFBConfig)
1924848b8605Smrg
1925848b8605Smrg_X_EXPORT GLXPixmap
1926848b8605SmrgglXCreateGLXPixmapWithConfigSGIX(Display * dpy,
1927848b8605Smrg                                 GLXFBConfigSGIX fbconfig,
1928848b8605Smrg                                 Pixmap pixmap)
1929848b8605Smrg{
1930848b8605Smrg#ifndef GLX_USE_APPLEGL
1931848b8605Smrg   xGLXVendorPrivateWithReplyReq *vpreq;
1932848b8605Smrg   xGLXCreateGLXPixmapWithConfigSGIXReq *req;
1933848b8605Smrg   GLXPixmap xid = None;
1934848b8605Smrg   CARD8 opcode;
1935848b8605Smrg   struct glx_screen *psc;
1936848b8605Smrg#endif
1937848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1938848b8605Smrg
1939848b8605Smrg
1940848b8605Smrg   if ((dpy == NULL) || (config == NULL)) {
1941848b8605Smrg      return None;
1942848b8605Smrg   }
1943848b8605Smrg#ifdef GLX_USE_APPLEGL
1944848b8605Smrg   if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config))
1945848b8605Smrg      return None;
1946848b8605Smrg   return pixmap;
1947848b8605Smrg#else
1948848b8605Smrg
1949848b8605Smrg   psc = GetGLXScreenConfigs(dpy, config->screen);
1950848b8605Smrg   if ((psc != NULL)
1951848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
1952848b8605Smrg      opcode = __glXSetupForCommand(dpy);
1953848b8605Smrg      if (!opcode) {
1954848b8605Smrg         return None;
1955848b8605Smrg      }
1956848b8605Smrg
1957848b8605Smrg      /* Send the glXCreateGLXPixmapWithConfigSGIX request */
1958848b8605Smrg      LockDisplay(dpy);
1959848b8605Smrg      GetReqExtra(GLXVendorPrivateWithReply,
1960848b8605Smrg                  sz_xGLXCreateGLXPixmapWithConfigSGIXReq -
1961848b8605Smrg                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
1962848b8605Smrg      req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq;
1963848b8605Smrg      req->reqType = opcode;
1964848b8605Smrg      req->glxCode = X_GLXVendorPrivateWithReply;
1965848b8605Smrg      req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
1966848b8605Smrg      req->screen = config->screen;
1967848b8605Smrg      req->fbconfig = config->fbconfigID;
1968848b8605Smrg      req->pixmap = pixmap;
1969848b8605Smrg      req->glxpixmap = xid = XAllocID(dpy);
1970848b8605Smrg      UnlockDisplay(dpy);
1971848b8605Smrg      SyncHandle();
1972848b8605Smrg   }
1973848b8605Smrg
1974848b8605Smrg   return xid;
1975848b8605Smrg#endif
1976848b8605Smrg}
1977848b8605Smrg
1978848b8605Smrg_X_EXPORT GLXContext
1979848b8605SmrgglXCreateContextWithConfigSGIX(Display * dpy,
1980848b8605Smrg                               GLXFBConfigSGIX fbconfig, int renderType,
1981848b8605Smrg                               GLXContext shareList, Bool allowDirect)
1982848b8605Smrg{
1983848b8605Smrg   GLXContext gc = NULL;
1984848b8605Smrg   struct glx_config *config = (struct glx_config *) fbconfig;
1985848b8605Smrg   struct glx_screen *psc;
1986848b8605Smrg
1987848b8605Smrg
1988848b8605Smrg   if ((dpy == NULL) || (config == NULL)) {
1989848b8605Smrg      return None;
1990848b8605Smrg   }
1991848b8605Smrg
1992848b8605Smrg   psc = GetGLXScreenConfigs(dpy, config->screen);
1993848b8605Smrg   if ((psc != NULL)
1994848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) {
1995848b8605Smrg      gc = CreateContext(dpy, config->fbconfigID, config, shareList,
1996848b8605Smrg                         allowDirect,
1997848b8605Smrg			 X_GLXvop_CreateContextWithConfigSGIX, renderType,
1998848b8605Smrg			 config->screen);
1999848b8605Smrg   }
2000848b8605Smrg
2001848b8605Smrg   return gc;
2002848b8605Smrg}
2003848b8605Smrg
2004848b8605Smrg
2005848b8605Smrg_X_EXPORT GLXFBConfigSGIX
2006848b8605SmrgglXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
2007848b8605Smrg{
2008848b8605Smrg   struct glx_display *priv;
2009848b8605Smrg   struct glx_screen *psc = NULL;
2010848b8605Smrg
2011848b8605Smrg   if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success)
2012848b8605Smrg       && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
2013848b8605Smrg       && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
2014848b8605Smrg      return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs,
2015848b8605Smrg						      vis->visualid);
2016848b8605Smrg   }
2017848b8605Smrg
2018848b8605Smrg   return NULL;
2019848b8605Smrg}
2020848b8605Smrg
2021848b8605Smrg#ifndef GLX_USE_APPLEGL
2022848b8605Smrg/*
2023848b8605Smrg** GLX_SGIX_swap_group
2024848b8605Smrg*/
2025848b8605Smrgstatic void
2026848b8605Smrg__glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable,
2027848b8605Smrg                       GLXDrawable member)
2028848b8605Smrg{
2029848b8605Smrg   (void) dpy;
2030848b8605Smrg   (void) drawable;
2031848b8605Smrg   (void) member;
2032848b8605Smrg}
2033848b8605Smrg
2034848b8605Smrg
2035848b8605Smrg/*
2036848b8605Smrg** GLX_SGIX_swap_barrier
2037848b8605Smrg*/
2038848b8605Smrgstatic void
2039848b8605Smrg__glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier)
2040848b8605Smrg{
2041848b8605Smrg   (void) dpy;
2042848b8605Smrg   (void) drawable;
2043848b8605Smrg   (void) barrier;
2044848b8605Smrg}
2045848b8605Smrg
2046848b8605Smrgstatic Bool
2047848b8605Smrg__glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max)
2048848b8605Smrg{
2049848b8605Smrg   (void) dpy;
2050848b8605Smrg   (void) screen;
2051848b8605Smrg   (void) max;
2052848b8605Smrg   return False;
2053848b8605Smrg}
2054848b8605Smrg
2055848b8605Smrg
2056848b8605Smrg/*
2057848b8605Smrg** GLX_OML_sync_control
2058848b8605Smrg*/
2059848b8605Smrgstatic Bool
2060848b8605Smrg__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable,
2061848b8605Smrg                      int64_t * ust, int64_t * msc, int64_t * sbc)
2062848b8605Smrg{
2063848b8605Smrg   struct glx_display * const priv = __glXInitialize(dpy);
2064848b8605Smrg   int ret;
2065848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2066848b8605Smrg   __GLXDRIdrawable *pdraw;
2067848b8605Smrg#endif
2068848b8605Smrg   struct glx_screen *psc;
2069848b8605Smrg
2070848b8605Smrg   if (!priv)
2071848b8605Smrg      return False;
2072848b8605Smrg
2073848b8605Smrg#ifdef GLX_DIRECT_RENDERING
2074848b8605Smrg   pdraw = GetGLXDRIDrawable(dpy, drawable);
2075848b8605Smrg   psc = pdraw ? pdraw->psc : NULL;
2076848b8605Smrg   if (pdraw && psc->driScreen->getDrawableMSC) {
2077848b8605Smrg      ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc);
2078848b8605Smrg      return ret;
2079848b8605Smrg   }
2080848b8605Smrg#endif
2081848b8605Smrg
2082848b8605Smrg   return False;
2083848b8605Smrg}
2084848b8605Smrg
2085848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2086848b8605Smrg_X_HIDDEN GLboolean
2087848b8605Smrg__glxGetMscRate(struct glx_screen *psc,
2088848b8605Smrg		int32_t * numerator, int32_t * denominator)
2089848b8605Smrg{
2090848b8605Smrg#ifdef XF86VIDMODE
2091848b8605Smrg   XF86VidModeModeLine mode_line;
2092848b8605Smrg   int dot_clock;
2093848b8605Smrg   int i;
2094848b8605Smrg
2095848b8605Smrg   if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2096848b8605Smrg       XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) {
2097848b8605Smrg      unsigned n = dot_clock * 1000;
2098848b8605Smrg      unsigned d = mode_line.vtotal * mode_line.htotal;
2099848b8605Smrg
2100848b8605Smrg# define V_INTERLACE 0x010
2101848b8605Smrg# define V_DBLSCAN   0x020
2102848b8605Smrg
2103848b8605Smrg      if (mode_line.flags & V_INTERLACE)
2104848b8605Smrg         n *= 2;
2105848b8605Smrg      else if (mode_line.flags & V_DBLSCAN)
2106848b8605Smrg         d *= 2;
2107848b8605Smrg
2108848b8605Smrg      /* The OML_sync_control spec requires that if the refresh rate is a
2109848b8605Smrg       * whole number, that the returned numerator be equal to the refresh
2110848b8605Smrg       * rate and the denominator be 1.
2111848b8605Smrg       */
2112848b8605Smrg
2113848b8605Smrg      if (n % d == 0) {
2114848b8605Smrg         n /= d;
2115848b8605Smrg         d = 1;
2116848b8605Smrg      }
2117848b8605Smrg      else {
2118848b8605Smrg         static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2119848b8605Smrg
2120848b8605Smrg         /* This is a poor man's way to reduce a fraction.  It's far from
2121848b8605Smrg          * perfect, but it will work well enough for this situation.
2122848b8605Smrg          */
2123848b8605Smrg
2124848b8605Smrg         for (i = 0; f[i] != 0; i++) {
2125848b8605Smrg            while (n % f[i] == 0 && d % f[i] == 0) {
2126848b8605Smrg               d /= f[i];
2127848b8605Smrg               n /= f[i];
2128848b8605Smrg            }
2129848b8605Smrg         }
2130848b8605Smrg      }
2131848b8605Smrg
2132848b8605Smrg      *numerator = n;
2133848b8605Smrg      *denominator = d;
2134848b8605Smrg
2135848b8605Smrg      return True;
2136848b8605Smrg   }
2137848b8605Smrg   else
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{
2164848b8605Smrg#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
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
2191848b8605Smrg   if (!gc) /* 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
2321848b8605Smrg_X_EXPORT 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();
2371848b8605Smrg   if ((gc != NULL) && (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
2410848b8605Smrg   if (gc == NULL || 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
2421848b8605Smrg   if (gc == NULL || 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 * \c strdup is actually not a standard ANSI C or POSIX routine.
2433848b8605Smrg * Irix will not define it if ANSI mode is in effect.
2434848b8605Smrg *
2435848b8605Smrg * \sa strdup
2436848b8605Smrg */
2437848b8605Smrg_X_HIDDEN char *
2438848b8605Smrg__glXstrdup(const char *str)
2439848b8605Smrg{
2440848b8605Smrg   char *copy;
2441848b8605Smrg   copy = malloc(strlen(str) + 1);
2442848b8605Smrg   if (!copy)
2443848b8605Smrg      return NULL;
2444848b8605Smrg   strcpy(copy, str);
2445848b8605Smrg   return copy;
2446848b8605Smrg}
2447848b8605Smrg
2448848b8605Smrg/*
2449848b8605Smrg** glXGetProcAddress support
2450848b8605Smrg*/
2451848b8605Smrg
2452848b8605Smrgstruct name_address_pair
2453848b8605Smrg{
2454848b8605Smrg   const char *Name;
2455848b8605Smrg   GLvoid *Address;
2456848b8605Smrg};
2457848b8605Smrg
2458848b8605Smrg#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2459848b8605Smrg#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2460848b8605Smrg
2461848b8605Smrgstatic const struct name_address_pair GLX_functions[] = {
2462848b8605Smrg   /*** GLX_VERSION_1_0 ***/
2463848b8605Smrg   GLX_FUNCTION(glXChooseVisual),
2464848b8605Smrg   GLX_FUNCTION(glXCopyContext),
2465848b8605Smrg   GLX_FUNCTION(glXCreateContext),
2466848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmap),
2467848b8605Smrg   GLX_FUNCTION(glXDestroyContext),
2468848b8605Smrg   GLX_FUNCTION(glXDestroyGLXPixmap),
2469848b8605Smrg   GLX_FUNCTION(glXGetConfig),
2470848b8605Smrg   GLX_FUNCTION(glXGetCurrentContext),
2471848b8605Smrg   GLX_FUNCTION(glXGetCurrentDrawable),
2472848b8605Smrg   GLX_FUNCTION(glXIsDirect),
2473848b8605Smrg   GLX_FUNCTION(glXMakeCurrent),
2474848b8605Smrg   GLX_FUNCTION(glXQueryExtension),
2475848b8605Smrg   GLX_FUNCTION(glXQueryVersion),
2476848b8605Smrg   GLX_FUNCTION(glXSwapBuffers),
2477848b8605Smrg   GLX_FUNCTION(glXUseXFont),
2478848b8605Smrg   GLX_FUNCTION(glXWaitGL),
2479848b8605Smrg   GLX_FUNCTION(glXWaitX),
2480848b8605Smrg
2481848b8605Smrg   /*** GLX_VERSION_1_1 ***/
2482848b8605Smrg   GLX_FUNCTION(glXGetClientString),
2483848b8605Smrg   GLX_FUNCTION(glXQueryExtensionsString),
2484848b8605Smrg   GLX_FUNCTION(glXQueryServerString),
2485848b8605Smrg
2486848b8605Smrg   /*** GLX_VERSION_1_2 ***/
2487848b8605Smrg   GLX_FUNCTION(glXGetCurrentDisplay),
2488848b8605Smrg
2489848b8605Smrg   /*** GLX_VERSION_1_3 ***/
2490848b8605Smrg   GLX_FUNCTION(glXChooseFBConfig),
2491848b8605Smrg   GLX_FUNCTION(glXCreateNewContext),
2492848b8605Smrg   GLX_FUNCTION(glXCreatePbuffer),
2493848b8605Smrg   GLX_FUNCTION(glXCreatePixmap),
2494848b8605Smrg   GLX_FUNCTION(glXCreateWindow),
2495848b8605Smrg   GLX_FUNCTION(glXDestroyPbuffer),
2496848b8605Smrg   GLX_FUNCTION(glXDestroyPixmap),
2497848b8605Smrg   GLX_FUNCTION(glXDestroyWindow),
2498848b8605Smrg   GLX_FUNCTION(glXGetCurrentReadDrawable),
2499848b8605Smrg   GLX_FUNCTION(glXGetFBConfigAttrib),
2500848b8605Smrg   GLX_FUNCTION(glXGetFBConfigs),
2501848b8605Smrg   GLX_FUNCTION(glXGetSelectedEvent),
2502848b8605Smrg   GLX_FUNCTION(glXGetVisualFromFBConfig),
2503848b8605Smrg   GLX_FUNCTION(glXMakeContextCurrent),
2504848b8605Smrg   GLX_FUNCTION(glXQueryContext),
2505848b8605Smrg   GLX_FUNCTION(glXQueryDrawable),
2506848b8605Smrg   GLX_FUNCTION(glXSelectEvent),
2507848b8605Smrg
2508848b8605Smrg#ifndef GLX_USE_APPLEGL
2509848b8605Smrg   /*** GLX_SGI_swap_control ***/
2510848b8605Smrg   GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI),
2511848b8605Smrg
2512848b8605Smrg   /*** GLX_SGI_video_sync ***/
2513848b8605Smrg   GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI),
2514848b8605Smrg   GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI),
2515848b8605Smrg
2516848b8605Smrg   /*** GLX_SGI_make_current_read ***/
2517848b8605Smrg   GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent),
2518848b8605Smrg   GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable),
2519848b8605Smrg
2520848b8605Smrg   /*** GLX_EXT_import_context ***/
2521848b8605Smrg   GLX_FUNCTION(glXFreeContextEXT),
2522848b8605Smrg   GLX_FUNCTION(glXGetContextIDEXT),
2523848b8605Smrg   GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay),
2524848b8605Smrg   GLX_FUNCTION(glXImportContextEXT),
2525848b8605Smrg   GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext),
2526848b8605Smrg#endif
2527848b8605Smrg
2528848b8605Smrg   /*** GLX_SGIX_fbconfig ***/
2529848b8605Smrg   GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib),
2530848b8605Smrg   GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig),
2531848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX),
2532848b8605Smrg   GLX_FUNCTION(glXCreateContextWithConfigSGIX),
2533848b8605Smrg   GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig),
2534848b8605Smrg   GLX_FUNCTION(glXGetFBConfigFromVisualSGIX),
2535848b8605Smrg
2536848b8605Smrg#ifndef GLX_USE_APPLEGL
2537848b8605Smrg   /*** GLX_SGIX_pbuffer ***/
2538848b8605Smrg   GLX_FUNCTION(glXCreateGLXPbufferSGIX),
2539848b8605Smrg   GLX_FUNCTION(glXDestroyGLXPbufferSGIX),
2540848b8605Smrg   GLX_FUNCTION(glXQueryGLXPbufferSGIX),
2541848b8605Smrg   GLX_FUNCTION(glXSelectEventSGIX),
2542848b8605Smrg   GLX_FUNCTION(glXGetSelectedEventSGIX),
2543848b8605Smrg
2544848b8605Smrg   /*** GLX_SGIX_swap_group ***/
2545848b8605Smrg   GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX),
2546848b8605Smrg
2547848b8605Smrg   /*** GLX_SGIX_swap_barrier ***/
2548848b8605Smrg   GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX),
2549848b8605Smrg   GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX),
2550848b8605Smrg
2551848b8605Smrg   /*** GLX_MESA_copy_sub_buffer ***/
2552848b8605Smrg   GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA),
2553848b8605Smrg
2554848b8605Smrg   /*** GLX_MESA_pixmap_colormap ***/
2555848b8605Smrg   GLX_FUNCTION(glXCreateGLXPixmapMESA),
2556848b8605Smrg
2557848b8605Smrg   /*** GLX_MESA_release_buffers ***/
2558848b8605Smrg   GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA),
2559848b8605Smrg
2560848b8605Smrg   /*** GLX_MESA_swap_control ***/
2561848b8605Smrg   GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA),
2562848b8605Smrg   GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA),
2563848b8605Smrg#endif
2564848b8605Smrg
2565848b8605Smrg   /*** GLX_ARB_get_proc_address ***/
2566848b8605Smrg   GLX_FUNCTION(glXGetProcAddressARB),
2567848b8605Smrg
2568848b8605Smrg   /*** GLX 1.4 ***/
2569848b8605Smrg   GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB),
2570848b8605Smrg
2571848b8605Smrg#ifndef GLX_USE_APPLEGL
2572848b8605Smrg   /*** GLX_OML_sync_control ***/
2573848b8605Smrg   GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML),
2574848b8605Smrg   GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML),
2575848b8605Smrg   GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML),
2576848b8605Smrg   GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML),
2577848b8605Smrg   GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML),
2578848b8605Smrg
2579848b8605Smrg   /*** GLX_EXT_texture_from_pixmap ***/
2580848b8605Smrg   GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT),
2581848b8605Smrg   GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT),
2582848b8605Smrg#endif
2583848b8605Smrg
2584848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_DRM)
2585848b8605Smrg   /*** DRI configuration ***/
2586848b8605Smrg   GLX_FUNCTION(glXGetScreenDriver),
2587848b8605Smrg   GLX_FUNCTION(glXGetDriverConfig),
2588848b8605Smrg#endif
2589848b8605Smrg
2590848b8605Smrg   /*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/
2591848b8605Smrg   GLX_FUNCTION(glXCreateContextAttribsARB),
2592848b8605Smrg
2593848b8605Smrg   /*** GLX_MESA_query_renderer ***/
2594848b8605Smrg   GLX_FUNCTION(glXQueryRendererIntegerMESA),
2595848b8605Smrg   GLX_FUNCTION(glXQueryRendererStringMESA),
2596848b8605Smrg   GLX_FUNCTION(glXQueryCurrentRendererIntegerMESA),
2597848b8605Smrg   GLX_FUNCTION(glXQueryCurrentRendererStringMESA),
2598848b8605Smrg
2599848b8605Smrg   {NULL, NULL}                 /* end of list */
2600848b8605Smrg};
2601848b8605Smrg
2602848b8605Smrgstatic const GLvoid *
2603848b8605Smrgget_glx_proc_address(const char *funcName)
2604848b8605Smrg{
2605848b8605Smrg   GLuint i;
2606848b8605Smrg
2607848b8605Smrg   /* try static functions */
2608848b8605Smrg   for (i = 0; GLX_functions[i].Name; i++) {
2609848b8605Smrg      if (strcmp(GLX_functions[i].Name, funcName) == 0)
2610848b8605Smrg         return GLX_functions[i].Address;
2611848b8605Smrg   }
2612848b8605Smrg
2613848b8605Smrg   return NULL;
2614848b8605Smrg}
2615848b8605Smrg
2616848b8605Smrg/**
2617848b8605Smrg * Get the address of a named GL function.  This is the pre-GLX 1.4 name for
2618848b8605Smrg * \c glXGetProcAddress.
2619848b8605Smrg *
2620848b8605Smrg * \param procName  Name of a GL or GLX function.
2621848b8605Smrg * \returns         A pointer to the named function
2622848b8605Smrg *
2623848b8605Smrg * \sa glXGetProcAddress
2624848b8605Smrg */
2625848b8605Smrg_X_EXPORT void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
2626848b8605Smrg{
2627848b8605Smrg   typedef void (*gl_function) (void);
2628848b8605Smrg   gl_function f;
2629848b8605Smrg
2630848b8605Smrg
2631848b8605Smrg   /* Search the table of GLX and internal functions first.  If that
2632848b8605Smrg    * fails and the supplied name could be a valid core GL name, try
2633848b8605Smrg    * searching the core GL function table.  This check is done to prevent
2634848b8605Smrg    * DRI based drivers from searching the core GL function table for
2635848b8605Smrg    * internal API functions.
2636848b8605Smrg    */
2637848b8605Smrg   f = (gl_function) get_glx_proc_address((const char *) procName);
2638848b8605Smrg   if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2639848b8605Smrg       && (procName[2] != 'X')) {
2640848b8605Smrg#ifdef GLX_SHARED_GLAPI
2641848b8605Smrg      f = (gl_function) __indirect_get_proc_address((const char *) procName);
2642848b8605Smrg#endif
2643848b8605Smrg      if (!f)
2644848b8605Smrg         f = (gl_function) _glapi_get_proc_address((const char *) procName);
2645848b8605Smrg      if (!f) {
2646848b8605Smrg         struct glx_context *gc = __glXGetCurrentContext();
2647848b8605Smrg
2648848b8605Smrg         if (gc != NULL && gc->vtable->get_proc_address != NULL)
2649848b8605Smrg            f = gc->vtable->get_proc_address((const char *) procName);
2650848b8605Smrg      }
2651848b8605Smrg   }
2652848b8605Smrg   return f;
2653848b8605Smrg}
2654848b8605Smrg
2655848b8605Smrg/**
2656848b8605Smrg * Get the address of a named GL function.  This is the GLX 1.4 name for
2657848b8605Smrg * \c glXGetProcAddressARB.
2658848b8605Smrg *
2659848b8605Smrg * \param procName  Name of a GL or GLX function.
2660848b8605Smrg * \returns         A pointer to the named function
2661848b8605Smrg *
2662848b8605Smrg * \sa glXGetProcAddressARB
2663848b8605Smrg */
2664848b8605Smrg_X_EXPORT void (*glXGetProcAddress(const GLubyte * procName)) (void)
2665848b8605Smrg#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
2666848b8605Smrg   __attribute__ ((alias("glXGetProcAddressARB")));
2667848b8605Smrg#else
2668848b8605Smrg{
2669848b8605Smrg   return glXGetProcAddressARB(procName);
2670848b8605Smrg}
2671848b8605Smrg#endif /* __GNUC__ */
2672848b8605Smrg
2673848b8605Smrg
2674848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
2675848b8605Smrg/**
2676848b8605Smrg * Get the unadjusted system time (UST).  Currently, the UST is measured in
2677848b8605Smrg * microseconds since Epoc.  The actual resolution of the UST may vary from
2678848b8605Smrg * system to system, and the units may vary from release to release.
2679848b8605Smrg * Drivers should not call this function directly.  They should instead use
2680848b8605Smrg * \c glXGetProcAddress to obtain a pointer to the function.
2681848b8605Smrg *
2682848b8605Smrg * \param ust Location to store the 64-bit UST
2683848b8605Smrg * \returns Zero on success or a negative errno value on failure.
2684848b8605Smrg *
2685848b8605Smrg * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2686848b8605Smrg *
2687848b8605Smrg * \since Internal API version 20030317.
2688848b8605Smrg */
2689848b8605Smrg_X_HIDDEN int
2690848b8605Smrg__glXGetUST(int64_t * ust)
2691848b8605Smrg{
2692848b8605Smrg   struct timeval tv;
2693848b8605Smrg
2694848b8605Smrg   if (ust == NULL) {
2695848b8605Smrg      return -EFAULT;
2696848b8605Smrg   }
2697848b8605Smrg
2698848b8605Smrg   if (gettimeofday(&tv, NULL) == 0) {
2699848b8605Smrg      ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
2700848b8605Smrg      return 0;
2701848b8605Smrg   }
2702848b8605Smrg   else {
2703848b8605Smrg      return -errno;
2704848b8605Smrg   }
2705848b8605Smrg}
2706848b8605Smrg#endif /* GLX_DIRECT_RENDERING */
2707