blob: c68b6ac4efef75bec5d2197e9737d3f64722a1d6 [file] [log] [blame]
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001/*
Adam Jacksondc8058c2008-09-19 17:16:53 -04002 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +000030
31/**
32 * \file glxcmds.c
33 * Client-side GLX interface.
34 */
35
Adam Jacksoncb3610e2004-10-25 21:09:16 +000036#include "glxclient.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000037#include "glapi.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000038#include "glxextensions.h"
39#include "glcontextmodes.h"
George Sapountzisdf04ffb2008-04-18 17:28:34 +030040
41#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +000042#include <sys/time.h>
George Sapountzisdf04ffb2008-04-18 17:28:34 +030043#include <X11/extensions/xf86vmode.h>
44#include "xf86dri.h"
45#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +000046
RALOVICH, Kristóf9c7aaa72008-11-04 10:59:39 +010047#if defined(USE_XCB)
48#include <X11/Xlib-xcb.h>
49#include <xcb/xcb.h>
50#include <xcb/glx.h>
51#endif
52
Adam Jacksoncb3610e2004-10-25 21:09:16 +000053static const char __glXGLXClientVendorName[] = "SGI";
54static const char __glXGLXClientVersion[] = "1.4";
55
56
Adam Jacksoncb3610e2004-10-25 21:09:16 +000057/****************************************************************************/
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050058
59#ifdef GLX_DIRECT_RENDERING
60
61static Bool windowExistsFlag;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040062static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050063{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040064 if (xerr->error_code == BadWindow) {
65 windowExistsFlag = GL_FALSE;
66 }
67 return 0;
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050068}
69
70/**
71 * Find drawables in the local hash that have been destroyed on the
72 * server.
73 *
74 * \param dpy Display to destroy drawables for
75 * \param screen Screen number to destroy drawables for
76 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040077static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050078{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040079 XID draw;
80 __GLXDRIdrawable *pdraw;
81 XWindowAttributes xwa;
82 int (*oldXErrorHandler)(Display *, XErrorEvent *);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050083
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040084 /* Set no-op error handler so Xlib doesn't bail out if the windows
85 * has alreay been destroyed on the server. */
86 XSync(dpy, GL_FALSE);
87 oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050088
Kristian Høgsberg77c7f902008-10-14 23:07:42 -040089 if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) {
90 do {
91 windowExistsFlag = GL_TRUE;
92 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
93 if (!windowExistsFlag) {
94 /* Destroy the local drawable data, if the drawable no
95 longer exists in the Xserver */
96 (*pdraw->destroyDrawable)(pdraw);
97 __glxHashDelete(sc->drawHash, draw);
98 }
99 } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1);
100 }
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500101
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400102 XSync(dpy, GL_FALSE);
103 XSetErrorHandler(oldXErrorHandler);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500104}
105
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400106extern __GLXDRIdrawable *
107GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num);
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400108
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000109/**
110 * Get the __DRIdrawable for the drawable associated with a GLXContext
111 *
112 * \param dpy The display associated with \c drawable.
113 * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500114 * \param scrn_num If non-NULL, the drawables screen is stored there
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000115 * \returns A pointer to the context's __DRIdrawable on success, or NULL if
116 * the drawable is not associated with a direct-rendering context.
117 */
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400118_X_HIDDEN __GLXDRIdrawable *
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400119GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000120{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400121 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
122 __GLXDRIdrawable *pdraw;
123 const unsigned screen_count = ScreenCount(dpy);
124 unsigned i;
125 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000126
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400127 if (priv == NULL)
128 return NULL;
129
130 for (i = 0; i < screen_count; i++) {
131 psc = &priv->screenConfigs[i];
132 if (psc->drawHash == NULL)
133 continue;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -0400134
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400135 if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) {
136 if (scrn_num != NULL)
137 *scrn_num = i;
138 return pdraw;
139 }
140 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000141
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400142 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000143}
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500144
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000145#endif
146
147
148/**
149 * Get the GLX per-screen data structure associated with a GLX context.
150 *
151 * \param dpy Display for which the GLX per-screen information is to be
152 * retrieved.
153 * \param scrn Screen on \c dpy for which the GLX per-screen information is
154 * to be retrieved.
155 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
156 * specify a valid GLX screen, or NULL otherwise.
157 *
158 * \todo Should this function validate that \c scrn is within the screen
159 * number range for \c dpy?
160 */
161
162static __GLXscreenConfigs *
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400163GetGLXScreenConfigs(Display *dpy, int scrn)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000164{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400165 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000166
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400167 return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000168}
169
170
171static int
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400172GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv,
173 __GLXscreenConfigs ** ppsc )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000174{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400175 /* Initialize the extension, if needed . This has the added value
176 * of initializing/allocating the display private
177 */
178
179 if ( dpy == NULL ) {
180 return GLX_NO_EXTENSION;
181 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000182
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400183 *ppriv = __glXInitialize(dpy);
184 if ( *ppriv == NULL ) {
185 return GLX_NO_EXTENSION;
186 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000187
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400188 /* Check screen number to see if its valid */
189 if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
190 return GLX_BAD_SCREEN;
191 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000192
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400193 /* Check to see if the GL is supported on this screen */
194 *ppsc = &((*ppriv)->screenConfigs[scrn]);
195 if ( (*ppsc)->configs == NULL ) {
196 /* No support for GL on this screen regardless of visual */
197 return GLX_BAD_VISUAL;
198 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000199
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400200 return Success;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000201}
202
203
204/**
205 * Determine if a \c GLXFBConfig supplied by the application is valid.
206 *
207 * \param dpy Application supplied \c Display pointer.
208 * \param config Application supplied \c GLXFBConfig.
209 *
210 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
211 * \c __GLcontextModes structure is returned. Otherwise, \c NULL
212 * is returned.
213 */
214static __GLcontextModes *
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400215ValidateGLXFBConfig( Display * dpy, GLXFBConfig config )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000216{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400217 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
218 const unsigned num_screens = ScreenCount(dpy);
219 unsigned i;
220 const __GLcontextModes * modes;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000221
222
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400223 if ( priv != NULL ) {
224 for ( i = 0 ; i < num_screens ; i++ ) {
225 for ( modes = priv->screenConfigs[i].configs
226 ; modes != NULL
227 ; modes = modes->next ) {
228 if ( modes == (__GLcontextModes *) config ) {
229 return (__GLcontextModes *) config;
230 }
231 }
232 }
233 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000234
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400235 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000236}
237
238
239/**
240 * \todo It should be possible to move the allocate of \c client_state_private
241 * later in the function for direct-rendering contexts. Direct-rendering
242 * contexts don't need to track client state, so they don't need that memory
243 * at all.
244 *
245 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
246 * function called \c __glXAllocateClientState that allocates the memory and
247 * does all the initialization (including the pixel pack / unpack).
248 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400249static
250GLXContext AllocateGLXContext( Display *dpy )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000251{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400252 GLXContext gc;
253 int bufSize;
254 CARD8 opcode;
255 __GLXattribute *state;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000256
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400257 if (!dpy)
258 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000259
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400260 opcode = __glXSetupForCommand(dpy);
261 if (!opcode) {
262 return NULL;
263 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000264
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400265 /* Allocate our context record */
266 gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
267 if (!gc) {
268 /* Out of memory */
269 return NULL;
270 }
271 memset(gc, 0, sizeof(struct __GLXcontextRec));
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000272
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400273 state = Xmalloc(sizeof(struct __GLXattributeRec));
274 if (state == NULL) {
275 /* Out of memory */
276 Xfree(gc);
277 return NULL;
278 }
279 gc->client_state_private = state;
280 memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
281 state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000282
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400283 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000284 ** Create a temporary buffer to hold GLX rendering commands. The size
285 ** of the buffer is selected so that the maximum number of GLX rendering
286 ** commands can fit in a single X packet and still have room in the X
287 ** packet for the GLXRenderReq header.
288 */
289
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400290 bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
291 gc->buf = (GLubyte *) Xmalloc(bufSize);
292 if (!gc->buf) {
293 Xfree(gc->client_state_private);
294 Xfree(gc);
295 return NULL;
296 }
297 gc->bufSize = bufSize;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000298
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400299 /* Fill in the new context */
300 gc->renderMode = GL_RENDER;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000301
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400302 state->storePack.alignment = 4;
303 state->storeUnpack.alignment = 4;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000304
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400305 gc->attributes.stackPointer = &gc->attributes.stack[0];
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000306
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400307 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000308 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
309 ** Other code uses the fastImageUnpack bit, but it is never set
310 ** to GL_TRUE.
311 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400312 gc->fastImageUnpack = GL_FALSE;
313 gc->fillImage = __glFillImage;
314 gc->pc = gc->buf;
315 gc->bufEnd = gc->buf + bufSize;
316 gc->isDirect = GL_FALSE;
317 if (__glXDebug) {
318 /*
319 ** Set limit register so that there will be one command per packet
320 */
321 gc->limit = gc->buf;
322 } else {
323 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
324 }
325 gc->createDpy = dpy;
326 gc->majorOpcode = opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000327
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400328 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000329 ** Constrain the maximum drawing command size allowed to be
330 ** transfered using the X_GLXRender protocol request. First
331 ** constrain by a software limit, then constrain by the protocl
332 ** limit.
333 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400334 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
335 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
336 }
337 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
338 bufSize = __GLX_MAX_RENDER_CMD_SIZE;
339 }
340 gc->maxSmallRenderCommandSize = bufSize;
341 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000342}
343
344
345/**
346 * Create a new context. Exactly one of \c vis and \c fbconfig should be
347 * non-NULL.
348 *
349 * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or
350 * SGIX_fbconfig protocol be used?
351 * \param renderType For FBConfigs, what is the rendering type?
352 */
353
354static GLXContext
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400355CreateContext(Display *dpy, XVisualInfo *vis,
356 const __GLcontextModes * const fbconfig,
357 GLXContext shareList,
358 Bool allowDirect, GLXContextID contextID,
359 Bool use_glx_1_3, int renderType)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000360{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400361 GLXContext gc;
Kristian Høgsberg37311592008-03-10 17:59:46 -0400362#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400363 int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
364 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
Kristian Høgsberg37311592008-03-10 17:59:46 -0400365#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000366
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400367 if ( dpy == NULL )
368 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000369
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400370 gc = AllocateGLXContext(dpy);
371 if (!gc)
372 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000373
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400374 if (None == contextID) {
375 if ( (vis == NULL) && (fbconfig == NULL) )
376 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000377
378#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400379 if (allowDirect && psc->driScreen) {
380 const __GLcontextModes * mode;
Kristian Høgsberg8e66c3d2007-11-05 17:02:03 -0500381
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400382 if (fbconfig == NULL) {
383 mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
384 if (mode == NULL) {
385 xError error;
Kristian Høgsberg8e66c3d2007-11-05 17:02:03 -0500386
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400387 error.errorCode = BadValue;
388 error.resourceID = vis->visualid;
389 error.sequenceNumber = dpy->request;
390 error.type = X_Error;
391 error.majorCode = gc->majorOpcode;
392 error.minorCode = X_GLXCreateContext;
393 _XError(dpy, &error);
394 return None;
395 }
396 }
397 else {
398 mode = fbconfig;
399 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000400
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400401 gc->driContext = psc->driScreen->createContext(psc, mode, gc,
402 shareList,
403 renderType);
404 if (gc->driContext != NULL) {
405 gc->screen = mode->screen;
406 gc->psc = psc;
407 gc->mode = mode;
408 gc->isDirect = GL_TRUE;
409 }
410 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000411#endif
412
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400413 LockDisplay(dpy);
414 if ( fbconfig == NULL ) {
415 xGLXCreateContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000416
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400417 /* Send the glXCreateContext request */
418 GetReq(GLXCreateContext,req);
419 req->reqType = gc->majorOpcode;
420 req->glxCode = X_GLXCreateContext;
421 req->context = gc->xid = XAllocID(dpy);
422 req->visual = vis->visualid;
423 req->screen = vis->screen;
424 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700425#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400426 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700427#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400428 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700429#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400430 }
431 else if ( use_glx_1_3 ) {
432 xGLXCreateNewContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000433
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400434 /* Send the glXCreateNewContext request */
435 GetReq(GLXCreateNewContext,req);
436 req->reqType = gc->majorOpcode;
437 req->glxCode = X_GLXCreateNewContext;
438 req->context = gc->xid = XAllocID(dpy);
439 req->fbconfig = fbconfig->fbconfigID;
440 req->screen = fbconfig->screen;
441 req->renderType = renderType;
442 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700443#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400444 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700445#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400446 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700447#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400448 }
449 else {
450 xGLXVendorPrivateWithReplyReq *vpreq;
451 xGLXCreateContextWithConfigSGIXReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000452
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400453 /* Send the glXCreateNewContext request */
454 GetReqExtra(GLXVendorPrivateWithReply,
455 sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
456 req = (xGLXCreateContextWithConfigSGIXReq *)vpreq;
457 req->reqType = gc->majorOpcode;
458 req->glxCode = X_GLXVendorPrivateWithReply;
459 req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
460 req->context = gc->xid = XAllocID(dpy);
461 req->fbconfig = fbconfig->fbconfigID;
462 req->screen = fbconfig->screen;
463 req->renderType = renderType;
464 req->shareList = shareList ? shareList->xid : None;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700465#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400466 req->isDirect = gc->driContext != NULL;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700467#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400468 req->isDirect = 0;
Jeremy Huddleston919ec222008-08-08 02:52:10 -0700469#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400470 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000471
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400472 UnlockDisplay(dpy);
473 SyncHandle();
474 gc->imported = GL_FALSE;
475 }
476 else {
477 gc->xid = contextID;
478 gc->imported = GL_TRUE;
479 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000480
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400481 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000482}
483
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400484PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,
485 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000486{
487 return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400488 False, 0);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000489}
490
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400491_X_HIDDEN void __glXFreeContext(__GLXcontext *gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000492{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400493 if (gc->vendor) XFree((char *) gc->vendor);
494 if (gc->renderer) XFree((char *) gc->renderer);
495 if (gc->version) XFree((char *) gc->version);
496 if (gc->extensions) XFree((char *) gc->extensions);
497 __glFreeAttributeState(gc);
498 XFree((char *) gc->buf);
499 Xfree((char *) gc->client_state_private);
500 XFree((char *) gc);
501
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000502}
503
504/*
505** Destroy the named context
506*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400507static void
508DestroyContext(Display *dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000509{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400510 xGLXDestroyContextReq *req;
511 GLXContextID xid;
512 CARD8 opcode;
513 GLboolean imported;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000514
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400515 opcode = __glXSetupForCommand(dpy);
516 if (!opcode || !gc) {
517 return;
518 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000519
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400520 __glXLock();
521 xid = gc->xid;
522 imported = gc->imported;
523 gc->xid = None;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000524
525#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400526 /* Destroy the direct rendering context */
527 if (gc->driContext) {
528 (*gc->driContext->destroyContext)(gc->driContext, gc->psc, dpy);
529 gc->driContext = NULL;
530 GarbageCollectDRIDrawables(dpy, gc->psc);
531 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000532#endif
533
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400534 __glXFreeVertexArrayState(gc);
Kristof Raloviche2060342008-08-20 15:18:38 -0600535
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400536 if (gc->currentDpy) {
537 /* Have to free later cuz it's in use now */
538 __glXUnlock();
539 } else {
540 /* Destroy the handle if not current to anybody */
541 __glXUnlock();
542 __glXFreeContext(gc);
543 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000544
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400545 if (!imported) {
546 /*
547 ** This dpy also created the server side part of the context.
548 ** Send the glXDestroyContext request.
549 */
550 LockDisplay(dpy);
551 GetReq(GLXDestroyContext,req);
552 req->reqType = opcode;
553 req->glxCode = X_GLXDestroyContext;
554 req->context = xid;
555 UnlockDisplay(dpy);
556 SyncHandle();
557 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000558}
Adam Jackson489ccef2004-12-15 17:18:06 +0000559
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400560PUBLIC void glXDestroyContext(Display *dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000561{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400562 DestroyContext(dpy, gc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000563}
564
565/*
566** Return the major and minor version #s for the GLX extension
567*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400568PUBLIC Bool glXQueryVersion(Display *dpy, int *major, int *minor)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000569{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400570 __GLXdisplayPrivate *priv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000571
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400572 /* Init the extension. This fetches the major and minor version. */
573 priv = __glXInitialize(dpy);
574 if (!priv) return GL_FALSE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000575
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400576 if (major) *major = priv->majorVersion;
577 if (minor) *minor = priv->minorVersion;
578 return GL_TRUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000579}
580
581/*
582** Query the existance of the GLX extension
583*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400584PUBLIC Bool glXQueryExtension(Display *dpy, int *errorBase, int *eventBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000585{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400586 int major_op, erb, evb;
587 Bool rv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000588
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400589 rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
590 if (rv) {
591 if (errorBase) *errorBase = erb;
592 if (eventBase) *eventBase = evb;
593 }
594 return rv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000595}
596
597/*
598** Put a barrier in the token stream that forces the GL to finish its
599** work before X can proceed.
600*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400601PUBLIC void glXWaitGL(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000602{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400603 xGLXWaitGLReq *req;
604 GLXContext gc = __glXGetCurrentContext();
605 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000606
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400607 if (!dpy) return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000608
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400609 /* Flush any pending commands out */
610 __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000611
612#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400613 if (gc->driContext) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000614/* This bit of ugliness unwraps the glFinish function */
615#ifdef glFinish
616#undef glFinish
617#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400618 glFinish();
619 return;
620 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000621#endif
622
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400623 /* Send the glXWaitGL request */
624 LockDisplay(dpy);
625 GetReq(GLXWaitGL,req);
626 req->reqType = gc->majorOpcode;
627 req->glxCode = X_GLXWaitGL;
628 req->contextTag = gc->currentContextTag;
629 UnlockDisplay(dpy);
630 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000631}
632
633/*
634** Put a barrier in the token stream that forces X to finish its
635** work before GL can proceed.
636*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400637PUBLIC void glXWaitX(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000638{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400639 xGLXWaitXReq *req;
640 GLXContext gc = __glXGetCurrentContext();
641 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000642
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400643 if (!dpy) return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000644
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400645 /* Flush any pending commands out */
646 __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000647
648#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400649 if (gc->driContext) {
650 XSync(dpy, False);
651 return;
652 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000653#endif
654
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400655 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000656 ** Send the glXWaitX request.
657 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400658 LockDisplay(dpy);
659 GetReq(GLXWaitX,req);
660 req->reqType = gc->majorOpcode;
661 req->glxCode = X_GLXWaitX;
662 req->contextTag = gc->currentContextTag;
663 UnlockDisplay(dpy);
664 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000665}
666
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400667PUBLIC void glXUseXFont(Font font, int first, int count, int listBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000668{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400669 xGLXUseXFontReq *req;
670 GLXContext gc = __glXGetCurrentContext();
671 Display *dpy = gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000672
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400673 if (!dpy) return;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000674
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400675 /* Flush any pending commands out */
676 (void) __glXFlushRenderBuffer(gc, gc->pc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000677
678#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400679 if (gc->driContext) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000680 DRI_glXUseXFont(font, first, count, listBase);
681 return;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400682 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000683#endif
684
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400685 /* Send the glXUseFont request */
686 LockDisplay(dpy);
687 GetReq(GLXUseXFont,req);
688 req->reqType = gc->majorOpcode;
689 req->glxCode = X_GLXUseXFont;
690 req->contextTag = gc->currentContextTag;
691 req->font = font;
692 req->first = first;
693 req->count = count;
694 req->listBase = listBase;
695 UnlockDisplay(dpy);
696 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000697}
698
699/************************************************************************/
700
701/*
702** Copy the source context to the destination context using the
703** attribute "mask".
704*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400705PUBLIC void glXCopyContext(Display *dpy, GLXContext source,
706 GLXContext dest, unsigned long mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000707{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400708 xGLXCopyContextReq *req;
709 GLXContext gc = __glXGetCurrentContext();
710 GLXContextTag tag;
711 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000712
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400713 opcode = __glXSetupForCommand(dpy);
714 if (!opcode) {
715 return;
716 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000717
718#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400719 if (gc->driContext) {
720 /* NOT_DONE: This does not work yet */
721 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000722#endif
723
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400724 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000725 ** If the source is the current context, send its tag so that the context
726 ** can be flushed before the copy.
727 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400728 if (source == gc && dpy == gc->currentDpy) {
729 tag = gc->currentContextTag;
730 } else {
731 tag = 0;
732 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000733
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400734 /* Send the glXCopyContext request */
735 LockDisplay(dpy);
736 GetReq(GLXCopyContext,req);
737 req->reqType = opcode;
738 req->glxCode = X_GLXCopyContext;
739 req->source = source ? source->xid : None;
740 req->dest = dest ? dest->xid : None;
741 req->mask = mask;
742 req->contextTag = tag;
743 UnlockDisplay(dpy);
744 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000745}
746
747
748/**
749 * Determine if a context uses direct rendering.
750 *
751 * \param dpy Display where the context was created.
752 * \param contextID ID of the context to be tested.
753 *
754 * \returns \c GL_TRUE if the context is direct rendering or not.
755 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400756static Bool __glXIsDirect(Display *dpy, GLXContextID contextID)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000757{
RALOVICH, Kristóf9c7aaa72008-11-04 10:59:39 +0100758#if !defined(USE_XCB)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400759 xGLXIsDirectReq *req;
760 xGLXIsDirectReply reply;
RALOVICH, Kristóf9c7aaa72008-11-04 10:59:39 +0100761#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400762 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000763
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400764 opcode = __glXSetupForCommand(dpy);
765 if (!opcode) {
766 return GL_FALSE;
767 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000768
RALOVICH, Kristóf9c7aaa72008-11-04 10:59:39 +0100769#ifdef USE_XCB
770 xcb_connection_t* c = XGetXCBConnection(dpy);
771 xcb_glx_is_direct_reply_t* reply =
772 xcb_glx_is_direct_reply(c,
773 xcb_glx_is_direct(c, contextID),
774 NULL);
775
776 const Bool is_direct = reply->is_direct ? True : False;
777 free(reply);
778
779 return is_direct;
780#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400781 /* Send the glXIsDirect request */
782 LockDisplay(dpy);
783 GetReq(GLXIsDirect,req);
784 req->reqType = opcode;
785 req->glxCode = X_GLXIsDirect;
786 req->context = contextID;
787 _XReply(dpy, (xReply*) &reply, 0, False);
788 UnlockDisplay(dpy);
789 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000790
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400791 return reply.isDirect;
RALOVICH, Kristóf9c7aaa72008-11-04 10:59:39 +0100792#endif /* USE_XCB */
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000793}
794
Ian Romanickc39bf5e2005-07-24 06:29:14 +0000795/**
796 * \todo
797 * Shouldn't this function \b always return \c GL_FALSE when
798 * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with
799 * the GLX protocol here at all?
800 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400801PUBLIC Bool glXIsDirect(Display *dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000802{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400803 if (!gc) {
804 return GL_FALSE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000805#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400806 } else if (gc->driContext) {
807 return GL_TRUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000808#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400809 }
810 return __glXIsDirect(dpy, gc->xid);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000811}
812
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400813PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis,
814 Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000815{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400816 xGLXCreateGLXPixmapReq *req;
817 GLXPixmap xid;
818 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000819
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400820 opcode = __glXSetupForCommand(dpy);
821 if (!opcode) {
822 return None;
823 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000824
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400825 /* Send the glXCreateGLXPixmap request */
826 LockDisplay(dpy);
827 GetReq(GLXCreateGLXPixmap,req);
828 req->reqType = opcode;
829 req->glxCode = X_GLXCreateGLXPixmap;
830 req->screen = vis->screen;
831 req->visual = vis->visualid;
832 req->pixmap = pixmap;
833 req->glxpixmap = xid = XAllocID(dpy);
834 UnlockDisplay(dpy);
835 SyncHandle();
836 return xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000837}
838
839/*
840** Destroy the named pixmap
841*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400842PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap glxpixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000843{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400844 xGLXDestroyGLXPixmapReq *req;
845 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000846
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400847 opcode = __glXSetupForCommand(dpy);
848 if (!opcode) {
849 return;
850 }
851
852 /* Send the glXDestroyGLXPixmap request */
853 LockDisplay(dpy);
854 GetReq(GLXDestroyGLXPixmap,req);
855 req->reqType = opcode;
856 req->glxCode = X_GLXDestroyGLXPixmap;
857 req->glxpixmap = glxpixmap;
858 UnlockDisplay(dpy);
859 SyncHandle();
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000860}
861
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400862PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000863{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400864 GLXContext gc;
865 GLXContextTag tag;
866 CARD8 opcode;
Brian Paulb7f802e2009-01-18 09:59:07 -0700867#ifdef USE_XCB
868 xcb_connection_t *c;
869#else
870 xGLXSwapBuffersReq *req;
871#endif
872
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000873#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400874 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000875
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400876 if (pdraw != NULL) {
877 glFlush();
878 (*pdraw->psc->driScreen->swapBuffers)(pdraw);
879 return;
880 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000881#endif
882
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400883 opcode = __glXSetupForCommand(dpy);
884 if (!opcode) {
885 return;
886 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000887
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400888 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000889 ** The calling thread may or may not have a current context. If it
890 ** does, send the context tag so the server can do a flush.
891 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400892 gc = __glXGetCurrentContext();
893 if ((gc != NULL) && (dpy == gc->currentDpy) &&
894 ((drawable == gc->currentDrawable) || (drawable == gc->currentReadable)) ) {
895 tag = gc->currentContextTag;
896 } else {
897 tag = 0;
898 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000899
RALOVICH, Kristófff3fa922008-11-04 17:30:21 +0100900#ifdef USE_XCB
Brian Paulb7f802e2009-01-18 09:59:07 -0700901 c = XGetXCBConnection(dpy);
RALOVICH, Kristófff3fa922008-11-04 17:30:21 +0100902 xcb_glx_swap_buffers(c, tag, drawable);
903 xcb_flush(c);
904#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400905 /* Send the glXSwapBuffers request */
906 LockDisplay(dpy);
907 GetReq(GLXSwapBuffers,req);
908 req->reqType = opcode;
909 req->glxCode = X_GLXSwapBuffers;
910 req->drawable = drawable;
911 req->contextTag = tag;
912 UnlockDisplay(dpy);
913 SyncHandle();
914 XFlush(dpy);
RALOVICH, Kristófff3fa922008-11-04 17:30:21 +0100915#endif /* USE_XCB */
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000916}
917
918
919/*
920** Return configuration information for the given display, screen and
921** visual combination.
922*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400923PUBLIC int glXGetConfig(Display *dpy, XVisualInfo *vis, int attribute,
924 int *value_return)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000925{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400926 __GLXdisplayPrivate *priv;
927 __GLXscreenConfigs *psc;
928 __GLcontextModes *modes;
929 int status;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000930
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400931 status = GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc );
932 if ( status == Success ) {
933 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000934
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400935 /* Lookup attribute after first finding a match on the visual */
936 if ( modes != NULL ) {
937 return _gl_get_context_mode_data( modes, attribute, value_return );
938 }
939
940 status = GLX_BAD_VISUAL;
941 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000942
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400943 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000944 ** If we can't find the config for this visual, this visual is not
945 ** supported by the OpenGL implementation on the server.
946 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400947 if ( (status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL) ) {
948 *value_return = GL_FALSE;
949 status = Success;
950 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000951
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400952 return status;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000953}
954
955/************************************************************************/
956
957static void
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400958init_fbconfig_for_chooser( __GLcontextModes * config,
959 GLboolean fbconfig_style_tags )
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000960{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400961 memset( config, 0, sizeof( __GLcontextModes ) );
962 config->visualID = (XID) GLX_DONT_CARE;
963 config->visualType = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000964
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400965 /* glXChooseFBConfig specifies different defaults for these two than
966 * glXChooseVisual.
967 */
968 if ( fbconfig_style_tags ) {
969 config->rgbMode = GL_TRUE;
970 config->doubleBufferMode = GLX_DONT_CARE;
971 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000972
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400973 config->visualRating = GLX_DONT_CARE;
974 config->transparentPixel = GLX_NONE;
975 config->transparentRed = GLX_DONT_CARE;
976 config->transparentGreen = GLX_DONT_CARE;
977 config->transparentBlue = GLX_DONT_CARE;
978 config->transparentAlpha = GLX_DONT_CARE;
979 config->transparentIndex = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000980
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400981 config->drawableType = GLX_WINDOW_BIT;
982 config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
983 config->xRenderable = GLX_DONT_CARE;
984 config->fbconfigID = (GLXFBConfigID)(GLX_DONT_CARE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000985
Kristian Høgsberg77c7f902008-10-14 23:07:42 -0400986 config->swapMethod = GLX_DONT_CARE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000987}
988
989#define MATCH_DONT_CARE( param ) \
990 do { \
991 if ( (a-> param != GLX_DONT_CARE) \
992 && (a-> param != b-> param) ) { \
993 return False; \
994 } \
995 } while ( 0 )
996
997#define MATCH_MINIMUM( param ) \
998 do { \
999 if ( (a-> param != GLX_DONT_CARE) \
1000 && (a-> param > b-> param) ) { \
1001 return False; \
1002 } \
1003 } while ( 0 )
1004
1005#define MATCH_EXACT( param ) \
1006 do { \
1007 if ( a-> param != b-> param) { \
1008 return False; \
1009 } \
1010 } while ( 0 )
1011
1012/**
1013 * Determine if two GLXFBConfigs are compatible.
1014 *
1015 * \param a Application specified config to test.
1016 * \param b Server specified config to test against \c a.
1017 */
1018static Bool
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001019fbconfigs_compatible( const __GLcontextModes * const a,
1020 const __GLcontextModes * const b )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001021{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001022 MATCH_DONT_CARE( doubleBufferMode );
1023 MATCH_DONT_CARE( visualType );
1024 MATCH_DONT_CARE( visualRating );
1025 MATCH_DONT_CARE( xRenderable );
1026 MATCH_DONT_CARE( fbconfigID );
1027 MATCH_DONT_CARE( swapMethod );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001028
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001029 MATCH_MINIMUM( rgbBits );
1030 MATCH_MINIMUM( numAuxBuffers );
1031 MATCH_MINIMUM( redBits );
1032 MATCH_MINIMUM( greenBits );
1033 MATCH_MINIMUM( blueBits );
1034 MATCH_MINIMUM( alphaBits );
1035 MATCH_MINIMUM( depthBits );
1036 MATCH_MINIMUM( stencilBits );
1037 MATCH_MINIMUM( accumRedBits );
1038 MATCH_MINIMUM( accumGreenBits );
1039 MATCH_MINIMUM( accumBlueBits );
1040 MATCH_MINIMUM( accumAlphaBits );
1041 MATCH_MINIMUM( sampleBuffers );
1042 MATCH_MINIMUM( maxPbufferWidth );
1043 MATCH_MINIMUM( maxPbufferHeight );
1044 MATCH_MINIMUM( maxPbufferPixels );
1045 MATCH_MINIMUM( samples );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001046
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001047 MATCH_DONT_CARE( stereoMode );
1048 MATCH_EXACT( level );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001049
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001050 if ( ((a->drawableType & b->drawableType) == 0)
1051 || ((a->renderType & b->renderType) == 0) ) {
1052 return False;
1053 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001054
1055
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001056 /* There is a bug in a few of the XFree86 DDX drivers. They contain
1057 * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1058 * Technically speaking, it is a bug in the DDX driver, but there is
1059 * enough of an installed base to work around the problem here. In any
1060 * case, 0 is not a valid value of the transparent type, so we'll treat 0
1061 * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1062 * 0 from the server to be a match to maintain backward compatibility with
1063 * the (broken) drivers.
1064 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001065
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001066 if ( a->transparentPixel != GLX_DONT_CARE
1067 && a->transparentPixel != 0 ) {
1068 if ( a->transparentPixel == GLX_NONE ) {
1069 if ( b->transparentPixel != GLX_NONE && b->transparentPixel != 0 )
1070 return False;
1071 } else {
1072 MATCH_EXACT( transparentPixel );
1073 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001074
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001075 switch ( a->transparentPixel ) {
1076 case GLX_TRANSPARENT_RGB:
1077 MATCH_DONT_CARE( transparentRed );
1078 MATCH_DONT_CARE( transparentGreen );
1079 MATCH_DONT_CARE( transparentBlue );
1080 MATCH_DONT_CARE( transparentAlpha );
1081 break;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001082
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001083 case GLX_TRANSPARENT_INDEX:
1084 MATCH_DONT_CARE( transparentIndex );
1085 break;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001086
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001087 default:
1088 break;
1089 }
1090 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001091
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001092 return True;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001093}
1094
1095
1096/* There's some trickly language in the GLX spec about how this is supposed
1097 * to work. Basically, if a given component size is either not specified
1098 * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1099 * Well, that's really hard to do with the code as-is. This behavior is
1100 * closer to correct, but still not technically right.
1101 */
1102#define PREFER_LARGER_OR_ZERO(comp) \
1103 do { \
1104 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1105 if ( ((*a)-> comp) == 0 ) { \
1106 return -1; \
1107 } \
1108 else if ( ((*b)-> comp) == 0 ) { \
1109 return 1; \
1110 } \
1111 else { \
1112 return ((*b)-> comp) - ((*a)-> comp) ; \
1113 } \
1114 } \
1115 } while( 0 )
1116
1117#define PREFER_LARGER(comp) \
1118 do { \
1119 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1120 return ((*b)-> comp) - ((*a)-> comp) ; \
1121 } \
1122 } while( 0 )
1123
1124#define PREFER_SMALLER(comp) \
1125 do { \
1126 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1127 return ((*a)-> comp) - ((*b)-> comp) ; \
1128 } \
1129 } while( 0 )
1130
1131/**
1132 * Compare two GLXFBConfigs. This function is intended to be used as the
1133 * compare function passed in to qsort.
1134 *
1135 * \returns If \c a is a "better" config, according to the specification of
1136 * SGIX_fbconfig, a number less than zero is returned. If \c b is
1137 * better, then a number greater than zero is return. If both are
1138 * equal, zero is returned.
1139 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1140 */
1141static int
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001142fbconfig_compare( const __GLcontextModes * const * const a,
1143 const __GLcontextModes * const * const b )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001144{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001145 /* The order of these comparisons must NOT change. It is defined by
1146 * the GLX 1.3 spec and ARB_multisample.
1147 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001148
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001149 PREFER_SMALLER( visualSelectGroup );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001150
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001151 /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1152 * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
1153 * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1154 */
1155 PREFER_SMALLER( visualRating );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001156
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001157 /* This isn't quite right. It is supposed to compare the sum of the
1158 * components the user specifically set minimums for.
1159 */
1160 PREFER_LARGER_OR_ZERO( redBits );
1161 PREFER_LARGER_OR_ZERO( greenBits );
1162 PREFER_LARGER_OR_ZERO( blueBits );
1163 PREFER_LARGER_OR_ZERO( alphaBits );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001164
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001165 PREFER_SMALLER( rgbBits );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001166
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001167 if ( ((*a)->doubleBufferMode != (*b)->doubleBufferMode) ) {
1168 /* Prefer single-buffer.
1169 */
1170 return ( !(*a)->doubleBufferMode ) ? -1 : 1;
1171 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001172
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001173 PREFER_SMALLER( numAuxBuffers );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001174
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001175 PREFER_LARGER_OR_ZERO( depthBits );
1176 PREFER_SMALLER( stencilBits );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001177
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001178 /* This isn't quite right. It is supposed to compare the sum of the
1179 * components the user specifically set minimums for.
1180 */
1181 PREFER_LARGER_OR_ZERO( accumRedBits );
1182 PREFER_LARGER_OR_ZERO( accumGreenBits );
1183 PREFER_LARGER_OR_ZERO( accumBlueBits );
1184 PREFER_LARGER_OR_ZERO( accumAlphaBits );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001185
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001186 PREFER_SMALLER( visualType );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001187
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001188 /* None of the multisample specs say where this comparison should happen,
1189 * so I put it near the end.
1190 */
1191 PREFER_SMALLER( sampleBuffers );
1192 PREFER_SMALLER( samples );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001193
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001194 /* None of the pbuffer or fbconfig specs say that this comparison needs
1195 * to happen at all, but it seems like it should.
1196 */
1197 PREFER_LARGER( maxPbufferWidth );
1198 PREFER_LARGER( maxPbufferHeight );
1199 PREFER_LARGER( maxPbufferPixels );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001200
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001201 return 0;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001202}
1203
1204
1205/**
1206 * Selects and sorts a subset of the supplied configs based on the attributes.
1207 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1208 * and \c glXChooseFBConfigSGIX.
1209 *
1210 * \param configs Array of pointers to possible configs. The elements of
1211 * this array that do not meet the criteria will be set to
1212 * NULL. The remaining elements will be sorted according to
1213 * the various visual / FBConfig selection rules.
1214 * \param num_configs Number of elements in the \c configs array.
1215 * \param attribList Attributes used select from \c configs. This array is
1216 * terminated by a \c None tag. The array can either take
1217 * the form expected by \c glXChooseVisual (where boolean
1218 * tags do not have a value) or by \c glXChooseFBConfig
1219 * (where every tag has a value).
1220 * \param fbconfig_style_tags Selects whether \c attribList is in
1221 * \c glXChooseVisual style or
1222 * \c glXChooseFBConfig style.
1223 * \returns The number of valid elements left in \c configs.
1224 *
1225 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1226 */
1227static int
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001228choose_visual( __GLcontextModes ** configs, int num_configs,
1229 const int *attribList, GLboolean fbconfig_style_tags )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001230{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001231 __GLcontextModes test_config;
1232 int base;
1233 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001234
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001235 /* This is a fairly direct implementation of the selection method
1236 * described by GLX_SGIX_fbconfig. Start by culling out all the
1237 * configs that are not compatible with the selected parameter
1238 * list.
1239 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001240
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001241 init_fbconfig_for_chooser( & test_config, fbconfig_style_tags );
1242 __glXInitializeVisualConfigFromTags( & test_config, 512,
1243 (const INT32 *) attribList,
1244 GL_TRUE, fbconfig_style_tags );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001245
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001246 base = 0;
1247 for ( i = 0 ; i < num_configs ; i++ ) {
1248 if ( fbconfigs_compatible( & test_config, configs[i] ) ) {
1249 configs[ base ] = configs[ i ];
1250 base++;
1251 }
1252 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001253
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001254 if ( base == 0 ) {
1255 return 0;
1256 }
1257
1258 if ( base < num_configs ) {
1259 (void) memset( & configs[ base ], 0,
1260 sizeof( void * ) * (num_configs - base) );
1261 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001262
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001263 /* After the incompatible configs are removed, the resulting
1264 * list is sorted according to the rules set out in the various
1265 * specifications.
1266 */
1267
1268 qsort( configs, base, sizeof( __GLcontextModes * ),
1269 (int (*)(const void*, const void*)) fbconfig_compare );
1270 return base;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001271}
1272
1273
1274
1275
1276/*
1277** Return the visual that best matches the template. Return None if no
1278** visual matches the template.
1279*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001280PUBLIC XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001281{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001282 XVisualInfo *visualList = NULL;
1283 __GLXdisplayPrivate *priv;
1284 __GLXscreenConfigs *psc;
1285 __GLcontextModes test_config;
1286 __GLcontextModes *modes;
1287 const __GLcontextModes *best_config = NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001288
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001289 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001290 ** Get a list of all visuals, return if list is empty
1291 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001292 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1293 return None;
1294 }
1295
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001296
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001297 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001298 ** Build a template from the defaults and the attribute list
1299 ** Free visual list and return if an unexpected token is encountered
1300 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001301 init_fbconfig_for_chooser( & test_config, GL_FALSE );
1302 __glXInitializeVisualConfigFromTags( & test_config, 512,
1303 (const INT32 *) attribList,
1304 GL_TRUE, GL_FALSE );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001305
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001306 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001307 ** Eliminate visuals that don't meet minimum requirements
1308 ** Compute a score for those that do
1309 ** Remember which visual, if any, got the highest score
1310 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001311 for ( modes = psc->visuals ; modes != NULL ; modes = modes->next ) {
1312 if ( fbconfigs_compatible( & test_config, modes )
1313 && ((best_config == NULL)
1314 || (fbconfig_compare( (const __GLcontextModes * const * const)&modes, &best_config ) < 0)) ) {
1315 best_config = modes;
1316 }
1317 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001318
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001319 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001320 ** If no visual is acceptable, return None
1321 ** Otherwise, create an XVisualInfo list with just the selected X visual
1322 ** and return this.
1323 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001324 if (best_config != NULL) {
1325 XVisualInfo visualTemplate;
1326 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001327
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001328 visualTemplate.screen = screen;
1329 visualTemplate.visualid = best_config->visualID;
1330 visualList = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask,
1331 &visualTemplate, &i );
1332 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001333
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001334 return visualList;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001335}
1336
1337
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001338PUBLIC const char *glXQueryExtensionsString( Display *dpy, int screen )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001339{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001340 __GLXscreenConfigs *psc;
1341 __GLXdisplayPrivate *priv;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001342
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001343 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1344 return NULL;
1345 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001346
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001347 if (!psc->effectiveGLXexts) {
1348 if (!psc->serverGLXexts) {
RALOVICH, Kristóf9c98e352008-11-03 18:32:20 +01001349 psc->serverGLXexts =
RALOVICH, Kristóf6d1d1572008-11-04 11:31:53 +01001350 __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001351 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001352
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001353 __glXCalculateUsableExtensions(psc,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001354#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001355 (psc->driScreen != NULL),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001356#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001357 GL_FALSE,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001358#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001359 priv->minorVersion);
1360 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001361
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001362 return psc->effectiveGLXexts;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001363}
1364
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001365PUBLIC const char *glXGetClientString( Display *dpy, int name )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001366{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001367 switch(name) {
1368 case GLX_VENDOR:
1369 return (__glXGLXClientVendorName);
1370 case GLX_VERSION:
1371 return (__glXGLXClientVersion);
1372 case GLX_EXTENSIONS:
1373 return (__glXGetClientExtensions());
1374 default:
1375 return NULL;
1376 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001377}
1378
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001379PUBLIC const char *glXQueryServerString( Display *dpy, int screen, int name )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001380{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001381 __GLXscreenConfigs *psc;
1382 __GLXdisplayPrivate *priv;
1383 const char ** str;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001384
1385
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001386 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1387 return NULL;
1388 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001389
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001390 switch(name) {
1391 case GLX_VENDOR:
1392 str = & priv->serverGLXvendor;
1393 break;
1394 case GLX_VERSION:
1395 str = & priv->serverGLXversion;
1396 break;
1397 case GLX_EXTENSIONS:
1398 str = & psc->serverGLXexts;
1399 break;
1400 default:
1401 return NULL;
1402 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001403
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001404 if ( *str == NULL ) {
RALOVICH, Kristóf6d1d1572008-11-04 11:31:53 +01001405 *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001406 }
1407
1408 return *str;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001409}
1410
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001411void __glXClientInfo ( Display *dpy, int opcode )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001412{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001413 char * ext_str = __glXGetClientGLExtensionString();
RALOVICH, Kristóf66db1b62008-11-04 12:41:55 +01001414 int size = strlen( ext_str ) + 1;
1415
1416#ifdef USE_XCB
1417 xcb_connection_t *c = XGetXCBConnection(dpy);
1418 xcb_glx_client_info(c,
1419 GLX_MAJOR_VERSION,
1420 GLX_MINOR_VERSION,
1421 size,
1422 (const uint8_t *)ext_str);
1423#else
1424 xGLXClientInfoReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001425
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001426 /* Send the glXClientInfo request */
1427 LockDisplay(dpy);
1428 GetReq(GLXClientInfo,req);
1429 req->reqType = opcode;
1430 req->glxCode = X_GLXClientInfo;
1431 req->major = GLX_MAJOR_VERSION;
1432 req->minor = GLX_MINOR_VERSION;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001433
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001434 req->length += (size + 3) >> 2;
1435 req->numbytes = size;
1436 Data(dpy, ext_str, size);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001437
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001438 UnlockDisplay(dpy);
1439 SyncHandle();
RALOVICH, Kristóf66db1b62008-11-04 12:41:55 +01001440#endif /* USE_XCB */
1441
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001442 Xfree( ext_str );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001443}
1444
1445
1446/*
1447** EXT_import_context
1448*/
1449
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001450PUBLIC Display *glXGetCurrentDisplay(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001451{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001452 GLXContext gc = __glXGetCurrentContext();
1453 if (NULL == gc) return NULL;
1454 return gc->currentDpy;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001455}
1456
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001457PUBLIC GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
1458 glXGetCurrentDisplay)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001459
1460/**
1461 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
1462 * to the X-server.
1463 *
1464 * \param dpy Display where \c ctx was created.
1465 * \param ctx Context to query.
1466 * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid,
1467 * or zero if the request failed due to internal problems (i.e.,
1468 * unable to allocate temporary memory, etc.)
1469 *
1470 * \note
1471 * This function dynamically determines whether to use the EXT_import_context
1472 * version of the protocol or the GLX 1.3 version of the protocol.
1473 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001474static int __glXQueryContextInfo(Display *dpy, GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001475{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001476 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1477 xGLXQueryContextReply reply;
1478 CARD8 opcode;
1479 GLuint numValues;
1480 int retval;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001481
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001482 if (ctx == NULL) {
1483 return GLX_BAD_CONTEXT;
1484 }
1485 opcode = __glXSetupForCommand(dpy);
1486 if (!opcode) {
1487 return 0;
1488 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001489
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001490 /* Send the glXQueryContextInfoEXT request */
1491 LockDisplay(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001492
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001493 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
1494 xGLXQueryContextReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001495
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001496 GetReq(GLXQueryContext, req);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001497
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001498 req->reqType = opcode;
1499 req->glxCode = X_GLXQueryContext;
1500 req->context = (unsigned int)(ctx->xid);
1501 }
1502 else {
1503 xGLXVendorPrivateReq *vpreq;
1504 xGLXQueryContextInfoEXTReq *req;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001505
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001506 GetReqExtra( GLXVendorPrivate,
1507 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1508 vpreq );
1509 req = (xGLXQueryContextInfoEXTReq *)vpreq;
1510 req->reqType = opcode;
1511 req->glxCode = X_GLXVendorPrivateWithReply;
1512 req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1513 req->context = (unsigned int)(ctx->xid);
1514 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001515
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001516 _XReply(dpy, (xReply*) &reply, 0, False);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001517
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001518 numValues = reply.n;
1519 if (numValues == 0)
1520 retval = Success;
1521 else if (numValues > __GLX_MAX_CONTEXT_PROPS)
1522 retval = 0;
1523 else
1524 {
1525 int *propList, *pProp;
1526 int nPropListBytes;
1527 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001528
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001529 nPropListBytes = numValues << 3;
1530 propList = (int *) Xmalloc(nPropListBytes);
1531 if (NULL == propList) {
1532 retval = 0;
1533 } else {
1534 _XRead(dpy, (char *)propList, nPropListBytes);
1535 pProp = propList;
1536 for (i=0; i < numValues; i++) {
1537 switch (*pProp++) {
1538 case GLX_SHARE_CONTEXT_EXT:
1539 ctx->share_xid = *pProp++;
1540 break;
1541 case GLX_VISUAL_ID_EXT:
1542 ctx->mode =
1543 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
1544 break;
1545 case GLX_SCREEN:
1546 ctx->screen = *pProp++;
1547 break;
1548 case GLX_FBCONFIG_ID:
1549 ctx->mode =
1550 _gl_context_modes_find_fbconfig(ctx->psc->configs, *pProp++);
1551 break;
1552 case GLX_RENDER_TYPE:
1553 ctx->renderType = *pProp++;
1554 break;
1555 default:
1556 pProp++;
1557 continue;
1558 }
1559 }
1560 Xfree((char *)propList);
1561 retval = Success;
1562 }
1563 }
1564 UnlockDisplay(dpy);
1565 SyncHandle();
1566 return retval;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001567}
1568
Adam Jackson489ccef2004-12-15 17:18:06 +00001569PUBLIC int
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001570glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001571{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001572 int retVal;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001573
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001574 /* get the information from the server if we don't have it already */
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001575#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001576 if (!ctx->driContext && (ctx->mode == NULL)) {
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001577#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001578 if (ctx->mode == NULL) {
Jeremy Huddleston919ec222008-08-08 02:52:10 -07001579#endif
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001580 retVal = __glXQueryContextInfo(dpy, ctx);
1581 if (Success != retVal) return retVal;
1582 }
1583 switch (attribute) {
1584 case GLX_SHARE_CONTEXT_EXT:
1585 *value = (int)(ctx->share_xid);
1586 break;
1587 case GLX_VISUAL_ID_EXT:
1588 *value = ctx->mode ? ctx->mode->visualID : None;
1589 break;
1590 case GLX_SCREEN:
1591 *value = (int)(ctx->screen);
1592 break;
1593 case GLX_FBCONFIG_ID:
1594 *value = ctx->mode ? ctx->mode->fbconfigID : None;
1595 break;
1596 case GLX_RENDER_TYPE:
1597 *value = (int)(ctx->renderType);
1598 break;
1599 default:
1600 return GLX_BAD_ATTRIBUTE;
1601 }
1602 return Success;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001603}
1604
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001605PUBLIC GLX_ALIAS( int, glXQueryContextInfoEXT,
1606 (Display *dpy, GLXContext ctx, int attribute, int *value),
1607 (dpy, ctx, attribute, value),
1608 glXQueryContext )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001609
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001610PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001611{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001612 return ctx->xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001613}
1614
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001615PUBLIC GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001616{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001617 GLXContext ctx;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001618
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001619 if (contextID == None) {
1620 return NULL;
1621 }
1622 if (__glXIsDirect(dpy, contextID)) {
1623 return NULL;
1624 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001625
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001626 ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
1627 if (NULL != ctx) {
1628 if (Success != __glXQueryContextInfo(dpy, ctx)) {
1629 return NULL;
1630 }
1631 }
1632 return ctx;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001633}
1634
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001635PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001636{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001637 DestroyContext(dpy, ctx);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001638}
1639
1640
1641
1642/*
1643 * GLX 1.3 functions - these are just stubs for now!
1644 */
1645
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001646PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
1647 const int *attribList, int *nitems)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001648{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001649 __GLcontextModes ** config_list;
1650 int list_size;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001651
1652
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001653 config_list = (__GLcontextModes **)
1654 glXGetFBConfigs( dpy, screen, & list_size );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001655
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001656 if ( (config_list != NULL) && (list_size > 0) && (attribList != NULL) ) {
1657 list_size = choose_visual( config_list, list_size, attribList,
1658 GL_TRUE );
1659 if ( list_size == 0 ) {
1660 XFree( config_list );
1661 config_list = NULL;
1662 }
1663 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001664
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001665 *nitems = list_size;
1666 return (GLXFBConfig *) config_list;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001667}
1668
1669
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001670PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config,
1671 int renderType, GLXContext shareList,
1672 Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001673{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001674 return CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
1675 allowDirect, None, True, renderType );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001676}
1677
1678
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001679PUBLIC GLXDrawable glXGetCurrentReadDrawable(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001680{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001681 GLXContext gc = __glXGetCurrentContext();
1682 return gc->currentReadable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001683}
1684
1685
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001686PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001687{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001688 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1689 __GLcontextModes ** config = NULL;
1690 int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001691
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001692 *nelements = 0;
1693 if ( (priv->screenConfigs != NULL)
1694 && (screen >= 0) && (screen <= ScreenCount(dpy))
1695 && (priv->screenConfigs[screen].configs != NULL)
1696 && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE) ) {
1697 unsigned num_configs = 0;
1698 __GLcontextModes * modes;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001699
1700
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001701 for ( modes = priv->screenConfigs[screen].configs
1702 ; modes != NULL
1703 ; modes = modes->next ) {
1704 if ( modes->fbconfigID != GLX_DONT_CARE ) {
1705 num_configs++;
1706 }
1707 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001708
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001709 config = (__GLcontextModes **) Xmalloc( sizeof(__GLcontextModes *)
1710 * num_configs );
1711 if ( config != NULL ) {
1712 *nelements = num_configs;
1713 i = 0;
1714 for ( modes = priv->screenConfigs[screen].configs
1715 ; modes != NULL
1716 ; modes = modes->next ) {
1717 if ( modes->fbconfigID != GLX_DONT_CARE ) {
1718 config[i] = modes;
1719 i++;
1720 }
1721 }
1722 }
1723 }
1724 return (GLXFBConfig *) config;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001725}
1726
1727
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001728PUBLIC int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
1729 int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001730{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001731 __GLcontextModes * const modes = ValidateGLXFBConfig( dpy, config );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001732
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001733 return (modes != NULL)
1734 ? _gl_get_context_mode_data( modes, attribute, value )
1735 : GLXBadFBConfig;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001736}
1737
1738
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001739PUBLIC XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001740{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001741 XVisualInfo visualTemplate;
1742 __GLcontextModes * fbconfig = (__GLcontextModes *) config;
1743 int count;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001744
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001745 /*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001746 ** Get a list of all visuals, return if list is empty
1747 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001748 visualTemplate.visualid = fbconfig->visualID;
1749 return XGetVisualInfo(dpy,VisualIDMask,&visualTemplate,&count);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001750}
1751
1752
1753/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001754** GLX_SGI_swap_control
1755*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001756static int __glXSwapIntervalSGI(int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001757{
1758 xGLXVendorPrivateReq *req;
1759 GLXContext gc = __glXGetCurrentContext();
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001760 Display * dpy;
1761 CARD32 * interval_ptr;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001762 CARD8 opcode;
1763
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001764 if ( gc == NULL ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001765 return GLX_BAD_CONTEXT;
1766 }
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001767
1768 if ( interval <= 0 ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001769 return GLX_BAD_VALUE;
1770 }
1771
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001772#ifdef __DRI_SWAP_CONTROL
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001773 if (gc->driContext) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001774 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1775 gc->screen );
1776 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(gc->currentDpy,
1777 gc->currentDrawable,
1778 NULL);
1779 if (psc->swapControl != NULL && pdraw != NULL) {
1780 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1781 return 0;
1782 }
1783 else {
1784 return GLX_BAD_CONTEXT;
1785 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001786 }
1787#endif
1788 dpy = gc->currentDpy;
1789 opcode = __glXSetupForCommand(dpy);
1790 if (!opcode) {
1791 return 0;
1792 }
1793
1794 /* Send the glXSwapIntervalSGI request */
1795 LockDisplay(dpy);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001796 GetReqExtra(GLXVendorPrivate,sizeof(CARD32),req);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001797 req->reqType = opcode;
1798 req->glxCode = X_GLXVendorPrivate;
1799 req->vendorCode = X_GLXvop_SwapIntervalSGI;
1800 req->contextTag = gc->currentContextTag;
1801
Ian Romanicka70d5642006-08-30 23:15:02 +00001802 interval_ptr = (CARD32 *) (req + 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001803 *interval_ptr = interval;
1804
1805 UnlockDisplay(dpy);
1806 SyncHandle();
1807 XFlush(dpy);
1808
1809 return 0;
1810}
1811
1812
1813/*
1814** GLX_MESA_swap_control
1815*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001816static int __glXSwapIntervalMESA(unsigned int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001817{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001818#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001819 GLXContext gc = __glXGetCurrentContext();
1820
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001821 if ( interval < 0 ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001822 return GLX_BAD_VALUE;
1823 }
1824
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001825 if (gc != NULL && gc->driContext) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001826 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1827 gc->screen );
1828
1829 if ( (psc != NULL) && (psc->driScreen != NULL) ) {
1830 __GLXDRIdrawable *pdraw =
1831 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1832 if (psc->swapControl != NULL && pdraw != NULL) {
1833 psc->swapControl->setSwapInterval(pdraw->driDrawable, interval);
1834 return 0;
1835 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001836 }
1837 }
1838#else
1839 (void) interval;
1840#endif
1841
1842 return GLX_BAD_CONTEXT;
1843}
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001844
Brian Paul841a8232006-03-09 16:25:46 +00001845
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001846static int __glXGetSwapIntervalMESA(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001847{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001848#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001849 GLXContext gc = __glXGetCurrentContext();
1850
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001851 if (gc != NULL && gc->driContext) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001852 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1853 gc->screen );
1854
1855 if ( (psc != NULL) && (psc->driScreen != NULL) ) {
1856 __GLXDRIdrawable *pdraw =
1857 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1858 if (psc->swapControl != NULL && pdraw != NULL) {
1859 return psc->swapControl->getSwapInterval(pdraw->driDrawable);
1860 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001861 }
1862 }
1863#endif
1864
1865 return 0;
1866}
1867
1868
1869/*
1870** GLX_MESA_swap_frame_usage
1871*/
1872
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001873static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001874{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001875 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001876#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001877 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001878 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001879 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001880
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001881 if (pdraw != NULL && psc->frameTracking != NULL)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001882 status = psc->frameTracking->frameTracking(pdraw->driDrawable, GL_TRUE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001883#else
1884 (void) dpy;
1885 (void) drawable;
1886#endif
1887 return status;
1888}
1889
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001890
1891static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001892{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001893 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001894#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001895 int screen;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001896 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001897 __GLXscreenConfigs *psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001898
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001899 if (pdraw != NULL && psc->frameTracking != NULL)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001900 status = psc->frameTracking->frameTracking(pdraw->driDrawable,
1901 GL_FALSE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001902#else
1903 (void) dpy;
1904 (void) drawable;
1905#endif
1906 return status;
1907}
1908
1909
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001910static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable,
1911 GLfloat *usage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001912{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001913 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001914#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001915 int screen;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001916 __GLXDRIdrawable * const pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
1917 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001918
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001919 if (pdraw != NULL && psc->frameTracking != NULL) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001920 int64_t sbc, missedFrames;
1921 float lastMissedUsage;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001922
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001923 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
1924 &sbc,
1925 &missedFrames,
1926 &lastMissedUsage,
1927 usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001928 }
1929#else
1930 (void) dpy;
1931 (void) drawable;
1932 (void) usage;
1933#endif
1934 return status;
1935}
1936
1937
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001938static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable,
1939 int64_t *sbc, int64_t *missedFrames,
1940 GLfloat *lastMissedUsage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001941{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001942 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001943#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001944 int screen;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001945 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, & screen);
1946 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001947
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001948 if (pdraw != NULL && psc->frameTracking != NULL) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001949 float usage;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001950
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04001951 status = psc->frameTracking->queryFrameTracking(pdraw->driDrawable,
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001952 sbc, missedFrames,
1953 lastMissedUsage, &usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001954 }
1955#else
1956 (void) dpy;
1957 (void) drawable;
1958 (void) sbc;
1959 (void) missedFrames;
1960 (void) lastMissedUsage;
1961#endif
1962 return status;
1963}
1964
1965
1966/*
1967** GLX_SGI_video_sync
1968*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001969static int __glXGetVideoSyncSGI(unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001970{
1971 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1972 * FIXME: there should be a GLX encoding for this call. I can find no
1973 * FIXME: documentation for the GLX encoding.
1974 */
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04001975#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001976 GLXContext gc = __glXGetCurrentContext();
1977
1978
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05001979 if (gc != NULL && gc->driContext) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001980 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1981 gc->screen );
1982 if ( psc->msc && psc->driScreen ) {
1983 __GLXDRIdrawable *pdraw =
1984 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1985 int64_t temp;
1986 int ret;
1987
1988 ret = (*psc->msc->getDrawableMSC)(psc->__driScreen,
1989 pdraw->driDrawable, &temp);
1990 *count = (unsigned) temp;
Kristian Høgsberg6e8d21d2008-02-25 16:14:37 -05001991
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001992 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001993 }
1994 }
1995#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04001996 (void) count;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001997#endif
1998 return GLX_BAD_CONTEXT;
1999}
2000
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002001static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002002{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002003#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002004 GLXContext gc = __glXGetCurrentContext();
2005
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002006 if ( divisor <= 0 || remainder < 0 )
2007 return GLX_BAD_VALUE;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002008
Kristian Høgsberg020c64b2008-03-08 21:57:29 -05002009 if (gc != NULL && gc->driContext) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002010 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
2011 gc->screen );
2012 if (psc->msc != NULL && psc->driScreen ) {
2013 __GLXDRIdrawable *pdraw =
2014 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
2015 int ret;
2016 int64_t msc;
2017 int64_t sbc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002018
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002019 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, 0,
2020 divisor, remainder, &msc, &sbc);
2021 *count = (unsigned) msc;
2022 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002023 }
2024 }
2025#else
2026 (void) count;
2027#endif
2028 return GLX_BAD_CONTEXT;
2029}
2030
2031
2032/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002033** GLX_SGIX_fbconfig
2034** Many of these functions are aliased to GLX 1.3 entry points in the
2035** GLX_functions table.
2036*/
2037
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002038PUBLIC GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
2039 (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value),
2040 (dpy, config, attribute, value),
2041 glXGetFBConfigAttrib)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002042
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002043PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
2044 (Display *dpy, int screen, int *attrib_list, int *nelements),
2045 (dpy, screen, attrib_list, nelements),
2046 glXChooseFBConfig)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002047
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002048PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
2049 (Display * dpy, GLXFBConfigSGIX config),
2050 (dpy, config),
2051 glXGetVisualFromFBConfig)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002052
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002053PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy,
2054 GLXFBConfigSGIX config, Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002055{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002056 xGLXVendorPrivateWithReplyReq *vpreq;
2057 xGLXCreateGLXPixmapWithConfigSGIXReq *req;
2058 GLXPixmap xid = None;
2059 CARD8 opcode;
2060 const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
2061 __GLXscreenConfigs * psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002062
2063
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002064 if ( (dpy == NULL) || (config == NULL) ) {
2065 return None;
2066 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002067
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002068 psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
2069 if ( (psc != NULL)
2070 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
2071 opcode = __glXSetupForCommand(dpy);
2072 if (!opcode) {
2073 return None;
2074 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002075
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002076 /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2077 LockDisplay(dpy);
2078 GetReqExtra(GLXVendorPrivateWithReply,
2079 sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
2080 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq;
2081 req->reqType = opcode;
2082 req->glxCode = X_GLXVendorPrivateWithReply;
2083 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2084 req->screen = fbconfig->screen;
2085 req->fbconfig = fbconfig->fbconfigID;
2086 req->pixmap = pixmap;
2087 req->glxpixmap = xid = XAllocID(dpy);
2088 UnlockDisplay(dpy);
2089 SyncHandle();
2090 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002091
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002092 return xid;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002093}
2094
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002095PUBLIC GLXContext glXCreateContextWithConfigSGIX(Display *dpy,
2096 GLXFBConfigSGIX config, int renderType,
2097 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002098{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002099 GLXContext gc = NULL;
2100 const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
2101 __GLXscreenConfigs * psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002102
2103
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002104 if ( (dpy == NULL) || (config == NULL) ) {
2105 return None;
2106 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002107
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002108 psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
2109 if ( (psc != NULL)
2110 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
2111 gc = CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
2112 allowDirect, None, False, renderType );
2113 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002114
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002115 return gc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002116}
2117
2118
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002119PUBLIC GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy,
2120 XVisualInfo *vis)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002121{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002122 __GLXdisplayPrivate *priv;
2123 __GLXscreenConfigs *psc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002124
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002125 if ( (GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc ) != Success)
2126 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit )
2127 && (psc->configs->fbconfigID != GLX_DONT_CARE) ) {
2128 return (GLXFBConfigSGIX) _gl_context_modes_find_visual( psc->configs,
2129 vis->visualid );
2130 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002131
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002132 return NULL;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002133}
2134
2135
2136/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002137** GLX_SGIX_swap_group
2138*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002139static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable,
2140 GLXDrawable member)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002141{
2142 (void) dpy;
2143 (void) drawable;
2144 (void) member;
2145}
2146
2147
2148/*
2149** GLX_SGIX_swap_barrier
2150*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002151static void __glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable,
2152 int barrier)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002153{
2154 (void) dpy;
2155 (void) drawable;
2156 (void) barrier;
2157}
2158
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002159static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002160{
2161 (void) dpy;
2162 (void) screen;
2163 (void) max;
2164 return False;
2165}
2166
2167
2168/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002169** GLX_OML_sync_control
2170*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002171static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
2172 int64_t *ust, int64_t *msc, int64_t *sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002173{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002174#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002175 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002176
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002177 if ( priv != NULL ) {
2178 int i;
2179 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &i);
2180 __GLXscreenConfigs * const psc = &priv->screenConfigs[i];
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002181
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002182 assert( (pdraw == NULL) || (i != -1) );
2183 return ( (pdraw && psc->sbc && psc->msc)
2184 && ((*psc->msc->getMSC)(psc->driScreen, msc) == 0)
2185 && ((*psc->sbc->getSBC)(pdraw->driDrawable, sbc) == 0)
2186 && (__glXGetUST(ust) == 0) );
2187 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002188#else
2189 (void) dpy;
2190 (void) drawable;
2191 (void) ust;
2192 (void) msc;
2193 (void) sbc;
2194#endif
2195 return False;
2196}
2197
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002198#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg3d28a262008-03-08 22:28:01 -05002199_X_HIDDEN GLboolean
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002200__driGetMscRateOML(__DRIdrawable *draw,
2201 int32_t *numerator, int32_t *denominator, void *private)
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002202{
2203#ifdef XF86VIDMODE
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002204 __GLXscreenConfigs *psc;
2205 XF86VidModeModeLine mode_line;
2206 int dot_clock;
2207 int i;
2208 __GLXDRIdrawable *glxDraw = private;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002209
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002210 psc = glxDraw->psc;
2211 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2212 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line) ) {
2213 unsigned n = dot_clock * 1000;
2214 unsigned d = mode_line.vtotal * mode_line.htotal;
2215
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002216# define V_INTERLACE 0x010
2217# define V_DBLSCAN 0x020
2218
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002219 if (mode_line.flags & V_INTERLACE)
2220 n *= 2;
2221 else if (mode_line.flags & V_DBLSCAN)
2222 d *= 2;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002223
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002224 /* The OML_sync_control spec requires that if the refresh rate is a
2225 * whole number, that the returned numerator be equal to the refresh
2226 * rate and the denominator be 1.
2227 */
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002228
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002229 if (n % d == 0) {
2230 n /= d;
2231 d = 1;
2232 }
2233 else {
2234 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002235
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002236 /* This is a poor man's way to reduce a fraction. It's far from
2237 * perfect, but it will work well enough for this situation.
2238 */
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002239
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002240 for (i = 0; f[i] != 0; i++) {
2241 while (n % f[i] == 0 && d % f[i] == 0) {
2242 d /= f[i];
2243 n /= f[i];
2244 }
2245 }
2246 }
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002247
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002248 *numerator = n;
2249 *denominator = d;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002250
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002251 return True;
2252 }
2253 else
2254 return False;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002255#else
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002256 return False;
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002257#endif
2258}
2259#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002260
2261/**
2262 * Determine the refresh rate of the specified drawable and display.
2263 *
2264 * \param dpy Display whose refresh rate is to be determined.
2265 * \param drawable Drawable whose refresh rate is to be determined.
2266 * \param numerator Numerator of the refresh rate.
2267 * \param demoninator Denominator of the refresh rate.
2268 * \return If the refresh rate for the specified display and drawable could
2269 * be calculated, True is returned. Otherwise False is returned.
2270 *
2271 * \note This function is implemented entirely client-side. A lot of other
2272 * functionality is required to export GLX_OML_sync_control, so on
2273 * XFree86 this function can be called for direct-rendering contexts
2274 * when GLX_OML_sync_control appears in the client extension string.
2275 */
2276
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002277_X_HIDDEN GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
2278 int32_t * numerator,
2279 int32_t * denominator)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002280{
2281#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002282 __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable, NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002283
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002284 if (draw == NULL)
2285 return False;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002286
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002287 return __driGetMscRateOML(draw->driDrawable, numerator, denominator, draw);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002288#else
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002289 (void) dpy;
2290 (void) drawable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002291 (void) numerator;
2292 (void) denominator;
2293#endif
2294 return False;
2295}
2296
2297
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002298static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
2299 int64_t target_msc, int64_t divisor,
2300 int64_t remainder)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002301{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002302#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002303 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002304 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002305 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002306
2307 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2308 * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2309 * of -1 if the function failed because of errors detected in the input
2310 * parameters"
2311 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002312 if ( divisor < 0 || remainder < 0 || target_msc < 0 )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002313 return -1;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002314 if ( divisor > 0 && remainder >= divisor )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002315 return -1;
2316
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002317 if (pdraw != NULL && psc->counters != NULL)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002318 return (*psc->sbc->swapBuffersMSC)(pdraw->driDrawable, target_msc,
2319 divisor, remainder);
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002320
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002321#else
2322 (void) dpy;
2323 (void) drawable;
2324 (void) target_msc;
2325 (void) divisor;
2326 (void) remainder;
2327#endif
2328 return 0;
2329}
2330
2331
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002332static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2333 int64_t target_msc, int64_t divisor,
2334 int64_t remainder, int64_t *ust,
2335 int64_t *msc, int64_t *sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002336{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002337#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002338 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002339 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002340 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2341 int ret;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002342
2343 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2344 * error", but the return type in the spec is Bool.
2345 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002346 if ( divisor < 0 || remainder < 0 || target_msc < 0 )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002347 return False;
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002348 if ( divisor > 0 && remainder >= divisor )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002349 return False;
2350
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002351 if (pdraw != NULL && psc->msc != NULL) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002352 ret = (*psc->msc->waitForMSC)(pdraw->driDrawable, target_msc,
2353 divisor, remainder, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002354
2355 /* __glXGetUST returns zero on success and non-zero on failure.
2356 * This function returns True on success and False on failure.
2357 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002358 return ( (ret == 0) && (__glXGetUST( ust ) == 0) );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002359 }
2360#else
2361 (void) dpy;
2362 (void) drawable;
2363 (void) target_msc;
2364 (void) divisor;
2365 (void) remainder;
2366 (void) ust;
2367 (void) msc;
2368 (void) sbc;
2369#endif
2370 return False;
2371}
2372
2373
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002374static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2375 int64_t target_sbc, int64_t *ust,
2376 int64_t *msc, int64_t *sbc )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002377{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002378#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002379 int screen;
Kristian Høgsberge82dd8c2008-03-26 19:26:59 -04002380 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002381 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2382 int ret;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002383
2384 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2385 * error", but the return type in the spec is Bool.
2386 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002387 if ( target_sbc < 0 )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002388 return False;
2389
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002390 if (pdraw != NULL && psc->sbc != NULL) {
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002391 ret = (*psc->sbc->waitForSBC)(pdraw->driDrawable, target_sbc, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002392
2393 /* __glXGetUST returns zero on success and non-zero on failure.
2394 * This function returns True on success and False on failure.
2395 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002396 return( (ret == 0) && (__glXGetUST( ust ) == 0) );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002397 }
2398#else
2399 (void) dpy;
2400 (void) drawable;
2401 (void) target_sbc;
2402 (void) ust;
2403 (void) msc;
2404 (void) sbc;
2405#endif
2406 return False;
2407}
2408
2409
2410/**
2411 * GLX_MESA_allocate_memory
2412 */
2413/*@{*/
2414
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002415PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn,
2416 size_t size, float readFreq,
2417 float writeFreq, float priority)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002418{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002419#ifdef __DRI_ALLOCATE
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002420 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002421
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002422 if (psc && psc->allocate)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002423 return (*psc->allocate->allocateMemory)(psc->__driScreen, size,
2424 readFreq, writeFreq, priority);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002425
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002426#else
2427 (void) dpy;
2428 (void) scrn;
2429 (void) size;
2430 (void) readFreq;
2431 (void) writeFreq;
2432 (void) priority;
2433#endif /* GLX_DIRECT_RENDERING */
2434
2435 return NULL;
2436}
2437
2438
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002439PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002440{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002441#ifdef __DRI_ALLOCATE
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002442 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002443
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002444 if (psc && psc->allocate)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002445 (*psc->allocate->freeMemory)(psc->__driScreen, pointer);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002446
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002447#else
2448 (void) dpy;
2449 (void) scrn;
2450 (void) pointer;
2451#endif /* GLX_DIRECT_RENDERING */
2452}
2453
2454
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002455PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
2456 const void *pointer )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002457{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002458#ifdef __DRI_ALLOCATE
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002459 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002460
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002461 if (psc && psc->allocate)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002462 return (*psc->allocate->memoryOffset)(psc->__driScreen, pointer);
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002463
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002464#else
2465 (void) dpy;
2466 (void) scrn;
2467 (void) pointer;
2468#endif /* GLX_DIRECT_RENDERING */
2469
2470 return ~0L;
2471}
2472/*@}*/
2473
2474
2475/**
2476 * Mesa extension stubs. These will help reduce portability problems.
2477 */
2478/*@{*/
2479
2480/**
2481 * Release all buffers associated with the specified GLX drawable.
2482 *
2483 * \todo
2484 * This function was intended for stand-alone Mesa. The issue there is that
2485 * the library doesn't get any notification when a window is closed. In
2486 * DRI there is a similar but slightly different issue. When GLX 1.3 is
2487 * supported, there are 3 different functions to destroy a drawable. It
2488 * should be possible to create GLX protocol (or have it determine which
2489 * protocol to use based on the type of the drawable) to have one function
2490 * do the work of 3. For the direct-rendering case, this function could
2491 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2492 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2493 * would need to be used. This really should be done as part of the new DRI
2494 * interface work.
2495 *
2496 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2497 * __driGarbageCollectDrawables
2498 * glXDestroyGLXPixmap
2499 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2500 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2501 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002502static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002503{
2504 (void) dpy;
2505 (void) d;
2506 return False;
2507}
2508
2509
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002510PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
2511 Pixmap pixmap, Colormap cmap )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002512{
2513 (void) dpy;
2514 (void) visual;
2515 (void) pixmap;
2516 (void) cmap;
2517 return 0;
2518}
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002519/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002520
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002521
2522/**
2523 * GLX_MESA_copy_sub_buffer
2524 */
Brian Paulf2ad1b62006-03-31 15:48:04 +00002525#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002526static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
2527 int x, int y, int width, int height)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002528{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002529 xGLXVendorPrivateReq *req;
2530 GLXContext gc;
2531 GLXContextTag tag;
2532 CARD32 *drawable_ptr;
2533 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2534 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002535
Kristian Høgsbergac3e8382007-05-15 15:17:30 -04002536#ifdef __DRI_COPY_SUB_BUFFER
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002537 int screen;
2538 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen);
2539 if ( pdraw != NULL ) {
Kristian Høgsberg48308092008-10-11 20:41:14 -04002540 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
2541 if (psc->driScreen->copySubBuffer != NULL) {
Kristian Høgsberge1fbb302008-11-12 15:24:45 -05002542 glFlush();
Kristian Høgsberg48308092008-10-11 20:41:14 -04002543 (*psc->driScreen->copySubBuffer)(pdraw, x, y, width, height);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002544 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002545
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002546 return;
2547 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002548#endif
2549
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002550 opcode = __glXSetupForCommand(dpy);
2551 if (!opcode)
2552 return;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002553
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002554 /*
Brian Paulf2ad1b62006-03-31 15:48:04 +00002555 ** The calling thread may or may not have a current context. If it
2556 ** does, send the context tag so the server can do a flush.
2557 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002558 gc = __glXGetCurrentContext();
2559 if ((gc != NULL) && (dpy == gc->currentDpy) &&
2560 ((drawable == gc->currentDrawable) ||
2561 (drawable == gc->currentReadable)) ) {
2562 tag = gc->currentContextTag;
2563 } else {
2564 tag = 0;
2565 }
Brian Paulf2ad1b62006-03-31 15:48:04 +00002566
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002567 LockDisplay(dpy);
2568 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4,req);
2569 req->reqType = opcode;
2570 req->glxCode = X_GLXVendorPrivate;
2571 req->vendorCode = X_GLXvop_CopySubBufferMESA;
2572 req->contextTag = tag;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002573
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002574 drawable_ptr = (CARD32 *) (req + 1);
2575 x_ptr = (INT32 *) (drawable_ptr + 1);
2576 y_ptr = (INT32 *) (drawable_ptr + 2);
2577 w_ptr = (INT32 *) (drawable_ptr + 3);
2578 h_ptr = (INT32 *) (drawable_ptr + 4);
Brian Paulf2ad1b62006-03-31 15:48:04 +00002579
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002580 *drawable_ptr = drawable;
2581 *x_ptr = x;
2582 *y_ptr = y;
2583 *w_ptr = width;
2584 *h_ptr = height;
Brian Paulf2ad1b62006-03-31 15:48:04 +00002585
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002586 UnlockDisplay(dpy);
2587 SyncHandle();
Brian Paulf2ad1b62006-03-31 15:48:04 +00002588}
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002589
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002590
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002591/**
2592 * GLX_EXT_texture_from_pixmap
2593 */
2594/*@{*/
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002595static void __glXBindTexImageEXT(Display *dpy,
2596 GLXDrawable drawable,
2597 int buffer,
2598 const int *attrib_list)
Brian Paul42725d62006-02-07 00:39:56 +00002599{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002600 xGLXVendorPrivateReq *req;
2601 GLXContext gc = __glXGetCurrentContext();
2602 CARD32 *drawable_ptr;
2603 INT32 *buffer_ptr;
2604 CARD32 *num_attrib_ptr;
2605 CARD32 *attrib_ptr;
2606 CARD8 opcode;
2607 unsigned int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002608
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002609 if (gc == NULL)
2610 return;
Brian Paul42725d62006-02-07 00:39:56 +00002611
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002612 i = 0;
2613 if (attrib_list) {
2614 while (attrib_list[i * 2] != None)
2615 i++;
2616 }
2617
Brian Paul42725d62006-02-07 00:39:56 +00002618#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002619 if (gc->driContext) {
2620 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002621
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002622 if (pdraw != NULL)
2623 (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext,
2624 pdraw->textureTarget,
2625 pdraw->driDrawable);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002626
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002627 return;
2628 }
Brian Paul42725d62006-02-07 00:39:56 +00002629#endif
2630
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002631 opcode = __glXSetupForCommand(dpy);
2632 if (!opcode)
2633 return;
Brian Paul42725d62006-02-07 00:39:56 +00002634
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002635 LockDisplay(dpy);
2636 GetReqExtra(GLXVendorPrivate, 12 + 8 * i,req);
2637 req->reqType = opcode;
2638 req->glxCode = X_GLXVendorPrivate;
2639 req->vendorCode = X_GLXvop_BindTexImageEXT;
2640 req->contextTag = gc->currentContextTag;
Brian Paul42725d62006-02-07 00:39:56 +00002641
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002642 drawable_ptr = (CARD32 *) (req + 1);
2643 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2644 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2645 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
Brian Paul42725d62006-02-07 00:39:56 +00002646
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002647 *drawable_ptr = drawable;
2648 *buffer_ptr = buffer;
2649 *num_attrib_ptr = (CARD32) i;
Brian Paul42725d62006-02-07 00:39:56 +00002650
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002651 i = 0;
2652 if (attrib_list) {
2653 while (attrib_list[i * 2] != None)
2654 {
2655 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2656 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2657 i++;
2658 }
2659 }
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002660
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002661 UnlockDisplay(dpy);
2662 SyncHandle();
Brian Paul42725d62006-02-07 00:39:56 +00002663}
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002664
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002665static void __glXReleaseTexImageEXT(Display *dpy,
2666 GLXDrawable drawable,
2667 int buffer)
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002668{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002669 xGLXVendorPrivateReq *req;
2670 GLXContext gc = __glXGetCurrentContext();
2671 CARD32 *drawable_ptr;
2672 INT32 *buffer_ptr;
2673 CARD8 opcode;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002674
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002675 if (gc == NULL)
2676 return;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002677
2678#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002679 if (gc->driContext)
2680 return;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002681#endif
2682
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002683 opcode = __glXSetupForCommand(dpy);
2684 if (!opcode)
2685 return;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002686
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002687 LockDisplay(dpy);
2688 GetReqExtra(GLXVendorPrivate, sizeof(CARD32)+sizeof(INT32),req);
2689 req->reqType = opcode;
2690 req->glxCode = X_GLXVendorPrivate;
2691 req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
2692 req->contextTag = gc->currentContextTag;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002693
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002694 drawable_ptr = (CARD32 *) (req + 1);
2695 buffer_ptr = (INT32 *) (drawable_ptr + 1);
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002696
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002697 *drawable_ptr = drawable;
2698 *buffer_ptr = buffer;
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002699
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002700 UnlockDisplay(dpy);
2701 SyncHandle();
RALOVICH, Kristóf12933562008-10-13 14:06:30 +02002702}
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002703/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002704
2705/**
2706 * \c strdup is actually not a standard ANSI C or POSIX routine.
2707 * Irix will not define it if ANSI mode is in effect.
2708 *
2709 * \sa strdup
2710 */
Kristian Høgsberg3d28a262008-03-08 22:28:01 -05002711_X_HIDDEN char *
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002712__glXstrdup(const char *str)
2713{
2714 char *copy;
2715 copy = (char *) Xmalloc(strlen(str) + 1);
2716 if (!copy)
2717 return NULL;
2718 strcpy(copy, str);
2719 return copy;
2720}
2721
2722/*
2723** glXGetProcAddress support
2724*/
2725
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002726struct name_address_pair {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002727 const char *Name;
2728 GLvoid *Address;
2729};
2730
2731#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2732#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2733
2734static const struct name_address_pair GLX_functions[] = {
2735 /*** GLX_VERSION_1_0 ***/
2736 GLX_FUNCTION( glXChooseVisual ),
2737 GLX_FUNCTION( glXCopyContext ),
2738 GLX_FUNCTION( glXCreateContext ),
2739 GLX_FUNCTION( glXCreateGLXPixmap ),
2740 GLX_FUNCTION( glXDestroyContext ),
2741 GLX_FUNCTION( glXDestroyGLXPixmap ),
2742 GLX_FUNCTION( glXGetConfig ),
2743 GLX_FUNCTION( glXGetCurrentContext ),
2744 GLX_FUNCTION( glXGetCurrentDrawable ),
2745 GLX_FUNCTION( glXIsDirect ),
2746 GLX_FUNCTION( glXMakeCurrent ),
2747 GLX_FUNCTION( glXQueryExtension ),
2748 GLX_FUNCTION( glXQueryVersion ),
2749 GLX_FUNCTION( glXSwapBuffers ),
2750 GLX_FUNCTION( glXUseXFont ),
2751 GLX_FUNCTION( glXWaitGL ),
2752 GLX_FUNCTION( glXWaitX ),
2753
2754 /*** GLX_VERSION_1_1 ***/
2755 GLX_FUNCTION( glXGetClientString ),
2756 GLX_FUNCTION( glXQueryExtensionsString ),
2757 GLX_FUNCTION( glXQueryServerString ),
2758
2759 /*** GLX_VERSION_1_2 ***/
2760 GLX_FUNCTION( glXGetCurrentDisplay ),
2761
2762 /*** GLX_VERSION_1_3 ***/
2763 GLX_FUNCTION( glXChooseFBConfig ),
2764 GLX_FUNCTION( glXCreateNewContext ),
2765 GLX_FUNCTION( glXCreatePbuffer ),
2766 GLX_FUNCTION( glXCreatePixmap ),
2767 GLX_FUNCTION( glXCreateWindow ),
2768 GLX_FUNCTION( glXDestroyPbuffer ),
2769 GLX_FUNCTION( glXDestroyPixmap ),
2770 GLX_FUNCTION( glXDestroyWindow ),
2771 GLX_FUNCTION( glXGetCurrentReadDrawable ),
2772 GLX_FUNCTION( glXGetFBConfigAttrib ),
2773 GLX_FUNCTION( glXGetFBConfigs ),
2774 GLX_FUNCTION( glXGetSelectedEvent ),
2775 GLX_FUNCTION( glXGetVisualFromFBConfig ),
2776 GLX_FUNCTION( glXMakeContextCurrent ),
2777 GLX_FUNCTION( glXQueryContext ),
2778 GLX_FUNCTION( glXQueryDrawable ),
2779 GLX_FUNCTION( glXSelectEvent ),
2780
2781 /*** GLX_SGI_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002782 GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002783
2784 /*** GLX_SGI_video_sync ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002785 GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ),
2786 GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002787
2788 /*** GLX_SGI_make_current_read ***/
2789 GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ),
2790 GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ),
2791
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002792 /*** GLX_EXT_import_context ***/
2793 GLX_FUNCTION( glXFreeContextEXT ),
2794 GLX_FUNCTION( glXGetContextIDEXT ),
2795 GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ),
2796 GLX_FUNCTION( glXImportContextEXT ),
2797 GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ),
2798
2799 /*** GLX_SGIX_fbconfig ***/
2800 GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ),
2801 GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ),
2802 GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ),
2803 GLX_FUNCTION( glXCreateContextWithConfigSGIX ),
2804 GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ),
2805 GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ),
2806
2807 /*** GLX_SGIX_pbuffer ***/
2808 GLX_FUNCTION( glXCreateGLXPbufferSGIX ),
2809 GLX_FUNCTION( glXDestroyGLXPbufferSGIX ),
2810 GLX_FUNCTION( glXQueryGLXPbufferSGIX ),
2811 GLX_FUNCTION( glXSelectEventSGIX ),
2812 GLX_FUNCTION( glXGetSelectedEventSGIX ),
2813
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002814 /*** GLX_SGIX_swap_group ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002815 GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002816
2817 /*** GLX_SGIX_swap_barrier ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002818 GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ),
2819 GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002820
2821 /*** GLX_MESA_allocate_memory ***/
2822 GLX_FUNCTION( glXAllocateMemoryMESA ),
2823 GLX_FUNCTION( glXFreeMemoryMESA ),
2824 GLX_FUNCTION( glXGetMemoryOffsetMESA ),
2825
2826 /*** GLX_MESA_copy_sub_buffer ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002827 GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002828
2829 /*** GLX_MESA_pixmap_colormap ***/
2830 GLX_FUNCTION( glXCreateGLXPixmapMESA ),
2831
2832 /*** GLX_MESA_release_buffers ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002833 GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002834
2835 /*** GLX_MESA_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002836 GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ),
2837 GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002838
2839 /*** GLX_MESA_swap_frame_usage ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002840 GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ),
2841 GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ),
2842 GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ),
2843 GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002844
2845 /*** GLX_ARB_get_proc_address ***/
2846 GLX_FUNCTION( glXGetProcAddressARB ),
2847
2848 /*** GLX 1.4 ***/
2849 GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ),
2850
2851 /*** GLX_OML_sync_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002852 GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ),
2853 GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ),
2854 GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ),
2855 GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ),
2856 GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002857
Brian Paul42725d62006-02-07 00:39:56 +00002858 /*** GLX_EXT_texture_from_pixmap ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002859 GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ),
2860 GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ),
Brian Paul42725d62006-02-07 00:39:56 +00002861
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002862#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002863 /*** DRI configuration ***/
2864 GLX_FUNCTION( glXGetScreenDriver ),
2865 GLX_FUNCTION( glXGetDriverConfig ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002866#endif
2867
2868 { NULL, NULL } /* end of list */
2869};
2870
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002871
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002872static const GLvoid *
2873get_glx_proc_address(const char *funcName)
2874{
2875 GLuint i;
2876
2877 /* try static functions */
2878 for (i = 0; GLX_functions[i].Name; i++) {
2879 if (strcmp(GLX_functions[i].Name, funcName) == 0)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002880 return GLX_functions[i].Address;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002881 }
2882
2883 return NULL;
2884}
2885
2886
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002887/**
2888 * Get the address of a named GL function. This is the pre-GLX 1.4 name for
2889 * \c glXGetProcAddress.
2890 *
2891 * \param procName Name of a GL or GLX function.
2892 * \returns A pointer to the named function
2893 *
2894 * \sa glXGetProcAddress
2895 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002896PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002897{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002898 typedef void (*gl_function)( void );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002899 gl_function f;
2900
2901
2902 /* Search the table of GLX and internal functions first. If that
2903 * fails and the supplied name could be a valid core GL name, try
2904 * searching the core GL function table. This check is done to prevent
2905 * DRI based drivers from searching the core GL function table for
2906 * internal API functions.
2907 */
2908
2909 f = (gl_function) get_glx_proc_address((const char *) procName);
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002910 if ( (f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2911 && (procName[2] != 'X') ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002912 f = (gl_function) _glapi_get_proc_address((const char *) procName);
2913 }
2914
2915 return f;
2916}
2917
2918/**
2919 * Get the address of a named GL function. This is the GLX 1.4 name for
2920 * \c glXGetProcAddressARB.
2921 *
2922 * \param procName Name of a GL or GLX function.
2923 * \returns A pointer to the named function
2924 *
2925 * \sa glXGetProcAddressARB
2926 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002927PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002928#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002929 __attribute__ ((alias ("glXGetProcAddressARB")));
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002930#else
2931{
2932 return glXGetProcAddressARB(procName);
2933}
2934#endif /* __GNUC__ */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002935
2936
2937#ifdef GLX_DIRECT_RENDERING
2938/**
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002939 * Get the unadjusted system time (UST). Currently, the UST is measured in
2940 * microseconds since Epoc. The actual resolution of the UST may vary from
2941 * system to system, and the units may vary from release to release.
2942 * Drivers should not call this function directly. They should instead use
2943 * \c glXGetProcAddress to obtain a pointer to the function.
2944 *
2945 * \param ust Location to store the 64-bit UST
2946 * \returns Zero on success or a negative errno value on failure.
2947 *
2948 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2949 *
2950 * \since Internal API version 20030317.
2951 */
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002952_X_HIDDEN int __glXGetUST( int64_t * ust )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002953{
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002954 struct timeval tv;
2955
2956 if ( ust == NULL ) {
2957 return -EFAULT;
2958 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002959
Kristian Høgsberg77c7f902008-10-14 23:07:42 -04002960 if ( gettimeofday( & tv, NULL ) == 0 ) {
2961 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
2962 return 0;
2963 } else {
2964 return -errno;
2965 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002966}
2967#endif /* GLX_DIRECT_RENDERING */