blob: 15c9d19c97d25c171d370a22082c7831d2903673 [file] [log] [blame]
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001/* $XFree86: xc/lib/GL/glx/glxcmds.c,v 1.30 2004/01/30 20:33:06 alanh Exp $ */
2/*
3** License Applicability. Except to the extent portions of this file are
4** made subject to an alternative license as permitted in the SGI Free
5** Software License B, Version 1.1 (the "License"), the contents of this
6** file are subject only to the provisions of the License. You may not use
7** this file except in compliance with the License. You may obtain a copy
8** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
9** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10**
11** http://oss.sgi.com/projects/FreeB
12**
13** Note that, as provided in the License, the Software is distributed on an
14** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
15** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
16** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
17** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18**
19** Original Code. The Original Code is: OpenGL Sample Implementation,
20** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
21** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
22** Copyright in any portions created by third parties is as indicated
23** elsewhere herein. All Rights Reserved.
24**
25** Additional Notice Provisions: The application programming interfaces
26** established by SGI in conjunction with the Original Code are The
27** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
28** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
29** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
30** Window System(R) (Version 1.3), released October 19, 1998. This software
31** was created using the OpenGL(R) version 1.2.1 Sample Implementation
32** published by SGI, but has not been independently verified as being
33** compliant with the OpenGL(R) version 1.2.1 Specification.
34**
35*/
36
37/**
38 * \file glxcmds.c
39 * Client-side GLX interface.
40 */
41
42#include <inttypes.h>
43#include "glxclient.h"
Brian Paul82dfd4b2005-08-11 14:18:53 +000044#include <X11/extensions/extutil.h>
45#include <X11/extensions/Xext.h>
Adam Jacksoncb3610e2004-10-25 21:09:16 +000046#include <assert.h>
47#include <string.h>
48#include "glapi.h"
49#ifdef GLX_DIRECT_RENDERING
50#include "indirect_init.h"
Brian Paul82dfd4b2005-08-11 14:18:53 +000051#include <X11/extensions/xf86vmode.h>
Ian Romanick5f1ba3e2005-07-26 02:44:01 +000052#include "xf86dri.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000053#endif
54#include "glxextensions.h"
55#include "glcontextmodes.h"
Adam Jackson489ccef2004-12-15 17:18:06 +000056#include "glheader.h"
Adam Jacksoncb3610e2004-10-25 21:09:16 +000057#include <sys/time.h>
58
Adam Jacksoncb3610e2004-10-25 21:09:16 +000059static const char __glXGLXClientVendorName[] = "SGI";
60static const char __glXGLXClientVersion[] = "1.4";
61
62
Adam Jacksoncb3610e2004-10-25 21:09:16 +000063/****************************************************************************/
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050064
65#ifdef GLX_DIRECT_RENDERING
66
67static Bool windowExistsFlag;
68static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
69{
70 if (xerr->error_code == BadWindow) {
71 windowExistsFlag = GL_FALSE;
72 }
73 return 0;
74}
75
76/**
77 * Find drawables in the local hash that have been destroyed on the
78 * server.
79 *
80 * \param dpy Display to destroy drawables for
81 * \param screen Screen number to destroy drawables for
82 */
Kristian Høgsberg9590ba92007-05-11 13:24:34 -040083static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050084{
Kristian Høgsbergfa720132007-05-11 13:54:44 -040085 XID draw;
Kristian Høgsberg4ff95e72007-05-10 17:14:38 -040086 __GLXdrawable *pdraw;
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050087 XWindowAttributes xwa;
88 int (*oldXErrorHandler)(Display *, XErrorEvent *);
89
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050090 /* Set no-op error handler so Xlib doesn't bail out if the windows
91 * has alreay been destroyed on the server. */
92 XSync(dpy, GL_FALSE);
93 oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler);
94
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -050095 if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) {
96 do {
97 windowExistsFlag = GL_TRUE;
98 XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
99 if (!windowExistsFlag) {
100 /* Destroy the local drawable data, if the drawable no
101 longer exists in the Xserver */
Kristian Høgsberg5987a032007-05-11 16:43:20 -0400102 (*pdraw->driDrawable.destroyDrawable)(&pdraw->driDrawable);
Kristian Høgsberg4ff95e72007-05-10 17:14:38 -0400103 XF86DRIDestroyDrawable(dpy, sc->scr, draw);
WuNian16099c12007-11-27 18:22:42 -0700104 __glxHashDelete(sc->drawHash, draw);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500105 Xfree(pdraw);
106 }
107 } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1);
108 }
109
Chris Rankin1421bff2007-10-29 14:37:32 -0400110 XSync(dpy, GL_FALSE);
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500111 XSetErrorHandler(oldXErrorHandler);
112}
113
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000114/**
115 * Get the __DRIdrawable for the drawable associated with a GLXContext
116 *
117 * \param dpy The display associated with \c drawable.
118 * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved.
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500119 * \param scrn_num If non-NULL, the drawables screen is stored there
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000120 * \returns A pointer to the context's __DRIdrawable on success, or NULL if
121 * the drawable is not associated with a direct-rendering context.
122 */
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000123static __DRIdrawable *
124GetDRIDrawable( Display *dpy, GLXDrawable drawable, int * const scrn_num )
125{
126 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
Kristian Høgsbergaceccda2007-05-10 15:52:22 -0400127 __GLXdrawable * const pdraw;
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500128 const unsigned screen_count = ScreenCount(dpy);
129 unsigned i;
130 __GLXscreenConfigs *sc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000131
Kristian Høgsberg425f9ed2008-03-08 19:02:10 -0500132 if (priv == NULL || priv->driDisplay == NULL)
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500133 return NULL;
134
135 for (i = 0; i < screen_count; i++) {
136 sc = &priv->screenConfigs[i];
137 if (__glxHashLookup(sc->drawHash, drawable, (void *) &pdraw) == 0) {
138 if (scrn_num != NULL)
139 *scrn_num = i;
Kristian Høgsbergaceccda2007-05-10 15:52:22 -0400140 return &pdraw->driDrawable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000141 }
142 }
143
144 return NULL;
145}
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -0500146
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000147#endif
148
149
150/**
151 * Get the GLX per-screen data structure associated with a GLX context.
152 *
153 * \param dpy Display for which the GLX per-screen information is to be
154 * retrieved.
155 * \param scrn Screen on \c dpy for which the GLX per-screen information is
156 * to be retrieved.
157 * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn
158 * specify a valid GLX screen, or NULL otherwise.
159 *
160 * \todo Should this function validate that \c scrn is within the screen
161 * number range for \c dpy?
162 */
163
164static __GLXscreenConfigs *
165GetGLXScreenConfigs(Display *dpy, int scrn)
166{
167 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
168
169 return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;
170}
171
172
173static int
174GetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv,
175 __GLXscreenConfigs ** ppsc )
176{
177 /* Initialize the extension, if needed . This has the added value
178 * of initializing/allocating the display private
179 */
180
181 if ( dpy == NULL ) {
182 return GLX_NO_EXTENSION;
183 }
184
185 *ppriv = __glXInitialize(dpy);
186 if ( *ppriv == NULL ) {
187 return GLX_NO_EXTENSION;
188 }
189
190 /* Check screen number to see if its valid */
191 if ((scrn < 0) || (scrn >= ScreenCount(dpy))) {
192 return GLX_BAD_SCREEN;
193 }
194
195 /* Check to see if the GL is supported on this screen */
196 *ppsc = &((*ppriv)->screenConfigs[scrn]);
197 if ( (*ppsc)->configs == NULL ) {
198 /* No support for GL on this screen regardless of visual */
199 return GLX_BAD_VISUAL;
200 }
201
202 return Success;
203}
204
205
206/**
207 * Determine if a \c GLXFBConfig supplied by the application is valid.
208 *
209 * \param dpy Application supplied \c Display pointer.
210 * \param config Application supplied \c GLXFBConfig.
211 *
212 * \returns If the \c GLXFBConfig is valid, the a pointer to the matching
213 * \c __GLcontextModes structure is returned. Otherwise, \c NULL
214 * is returned.
215 */
216static __GLcontextModes *
217ValidateGLXFBConfig( Display * dpy, GLXFBConfig config )
218{
219 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
220 const unsigned num_screens = ScreenCount(dpy);
221 unsigned i;
222 const __GLcontextModes * modes;
223
224
225 if ( priv != NULL ) {
226 for ( i = 0 ; i < num_screens ; i++ ) {
227 for ( modes = priv->screenConfigs[i].configs
228 ; modes != NULL
229 ; modes = modes->next ) {
230 if ( modes == (__GLcontextModes *) config ) {
231 return (__GLcontextModes *) config;
232 }
233 }
234 }
235 }
236
237 return NULL;
238}
239
240
241/**
242 * \todo It should be possible to move the allocate of \c client_state_private
243 * later in the function for direct-rendering contexts. Direct-rendering
244 * contexts don't need to track client state, so they don't need that memory
245 * at all.
246 *
247 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
248 * function called \c __glXAllocateClientState that allocates the memory and
249 * does all the initialization (including the pixel pack / unpack).
250 */
251static
252GLXContext AllocateGLXContext( Display *dpy )
253{
254 GLXContext gc;
255 int bufSize;
256 CARD8 opcode;
257 __GLXattribute *state;
258
259 if (!dpy)
260 return NULL;
261
262 opcode = __glXSetupForCommand(dpy);
263 if (!opcode) {
264 return NULL;
265 }
266
267 /* Allocate our context record */
268 gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec));
269 if (!gc) {
270 /* Out of memory */
271 return NULL;
272 }
273 memset(gc, 0, sizeof(struct __GLXcontextRec));
274
275 state = Xmalloc(sizeof(struct __GLXattributeRec));
276 if (state == NULL) {
277 /* Out of memory */
278 Xfree(gc);
279 return NULL;
280 }
281 gc->client_state_private = state;
282 memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec));
283 state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
284
285 /*
286 ** Create a temporary buffer to hold GLX rendering commands. The size
287 ** of the buffer is selected so that the maximum number of GLX rendering
288 ** commands can fit in a single X packet and still have room in the X
289 ** packet for the GLXRenderReq header.
290 */
291
292 bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq;
293 gc->buf = (GLubyte *) Xmalloc(bufSize);
294 if (!gc->buf) {
295 Xfree(gc->client_state_private);
296 Xfree(gc);
297 return NULL;
298 }
299 gc->bufSize = bufSize;
300
301 /* Fill in the new context */
302 gc->renderMode = GL_RENDER;
303
304 state->storePack.alignment = 4;
305 state->storeUnpack.alignment = 4;
306
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000307 gc->attributes.stackPointer = &gc->attributes.stack[0];
308
309 /*
310 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
311 ** Other code uses the fastImageUnpack bit, but it is never set
312 ** to GL_TRUE.
313 */
314 gc->fastImageUnpack = GL_FALSE;
315 gc->fillImage = __glFillImage;
316 gc->isDirect = GL_FALSE;
317 gc->pc = gc->buf;
318 gc->bufEnd = gc->buf + bufSize;
319 if (__glXDebug) {
320 /*
321 ** Set limit register so that there will be one command per packet
322 */
323 gc->limit = gc->buf;
324 } else {
325 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
326 }
327 gc->createDpy = dpy;
328 gc->majorOpcode = opcode;
329
330 /*
331 ** Constrain the maximum drawing command size allowed to be
332 ** transfered using the X_GLXRender protocol request. First
333 ** constrain by a software limit, then constrain by the protocl
334 ** limit.
335 */
336 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
337 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
338 }
339 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
340 bufSize = __GLX_MAX_RENDER_CMD_SIZE;
341 }
342 gc->maxSmallRenderCommandSize = bufSize;
343 return gc;
344}
345
346
347/**
348 * Create a new context. Exactly one of \c vis and \c fbconfig should be
349 * non-NULL.
350 *
351 * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or
352 * SGIX_fbconfig protocol be used?
353 * \param renderType For FBConfigs, what is the rendering type?
354 */
355
356static GLXContext
357CreateContext(Display *dpy, XVisualInfo *vis,
358 const __GLcontextModes * const fbconfig,
359 GLXContext shareList,
360 Bool allowDirect, GLXContextID contextID,
361 Bool use_glx_1_3, int renderType)
362{
363 GLXContext gc;
364
365 if ( dpy == NULL )
366 return NULL;
367
368 gc = AllocateGLXContext(dpy);
369 if (!gc)
370 return NULL;
371
372 if (None == contextID) {
373 if ( (vis == NULL) && (fbconfig == NULL) )
374 return NULL;
375
376#ifdef GLX_DIRECT_RENDERING
377 if (allowDirect) {
378 int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen;
379 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
380 const __GLcontextModes * mode;
Kristian Høgsberg8e66c3d2007-11-05 17:02:03 -0500381
382 if (fbconfig == NULL) {
383 mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
384 if (mode == NULL) {
385 xError error;
386
387 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 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000396 }
397 else {
398 mode = fbconfig;
399 }
400
Kristian Høgsberg92d2a782008-03-08 20:34:24 -0500401 psc->driScreen->createContext(psc, mode, gc, shareList, renderType);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000402 }
403#endif
404
405 LockDisplay(dpy);
406 if ( fbconfig == NULL ) {
407 xGLXCreateContextReq *req;
408
409 /* Send the glXCreateContext request */
410 GetReq(GLXCreateContext,req);
411 req->reqType = gc->majorOpcode;
412 req->glxCode = X_GLXCreateContext;
413 req->context = gc->xid = XAllocID(dpy);
414 req->visual = vis->visualid;
415 req->screen = vis->screen;
416 req->shareList = shareList ? shareList->xid : None;
417 req->isDirect = gc->isDirect;
418 }
419 else if ( use_glx_1_3 ) {
420 xGLXCreateNewContextReq *req;
421
422 /* Send the glXCreateNewContext request */
423 GetReq(GLXCreateNewContext,req);
424 req->reqType = gc->majorOpcode;
425 req->glxCode = X_GLXCreateNewContext;
426 req->context = gc->xid = XAllocID(dpy);
427 req->fbconfig = fbconfig->fbconfigID;
428 req->screen = fbconfig->screen;
429 req->renderType = renderType;
430 req->shareList = shareList ? shareList->xid : None;
431 req->isDirect = gc->isDirect;
432 }
433 else {
434 xGLXVendorPrivateWithReplyReq *vpreq;
435 xGLXCreateContextWithConfigSGIXReq *req;
436
437 /* Send the glXCreateNewContext request */
438 GetReqExtra(GLXVendorPrivateWithReply,
439 sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
440 req = (xGLXCreateContextWithConfigSGIXReq *)vpreq;
441 req->reqType = gc->majorOpcode;
442 req->glxCode = X_GLXVendorPrivateWithReply;
443 req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX;
444 req->context = gc->xid = XAllocID(dpy);
445 req->fbconfig = fbconfig->fbconfigID;
446 req->screen = fbconfig->screen;
447 req->renderType = renderType;
448 req->shareList = shareList ? shareList->xid : None;
449 req->isDirect = gc->isDirect;
450 }
451
452 UnlockDisplay(dpy);
453 SyncHandle();
454 gc->imported = GL_FALSE;
455 }
456 else {
457 gc->xid = contextID;
458 gc->imported = GL_TRUE;
459 }
460
461 return gc;
462}
463
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000464PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,
465 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000466{
467 return CreateContext(dpy, vis, NULL, shareList, allowDirect, None,
468 False, 0);
469}
470
471void __glXFreeContext(__GLXcontext *gc)
472{
473 if (gc->vendor) XFree((char *) gc->vendor);
474 if (gc->renderer) XFree((char *) gc->renderer);
475 if (gc->version) XFree((char *) gc->version);
476 if (gc->extensions) XFree((char *) gc->extensions);
477 __glFreeAttributeState(gc);
478 XFree((char *) gc->buf);
479 Xfree((char *) gc->client_state_private);
480 XFree((char *) gc);
481
482}
483
484/*
485** Destroy the named context
486*/
487static void
488DestroyContext(Display *dpy, GLXContext gc)
489{
490 xGLXDestroyContextReq *req;
491 GLXContextID xid;
492 CARD8 opcode;
493 GLboolean imported;
494
495 opcode = __glXSetupForCommand(dpy);
496 if (!opcode || !gc) {
497 return;
498 }
499
500 __glXLock();
501 xid = gc->xid;
502 imported = gc->imported;
503 gc->xid = None;
504
505#ifdef GLX_DIRECT_RENDERING
506 /* Destroy the direct rendering context */
507 if (gc->isDirect) {
508 if (gc->driContext.private) {
Kristian Høgsberg5987a032007-05-11 16:43:20 -0400509 (*gc->driContext.destroyContext)(&gc->driContext);
Kristian Høgsberg8ed5c7c2007-05-10 18:38:49 -0400510 XF86DRIDestroyContext(dpy, gc->psc->scr, gc->hwContextID);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000511 gc->driContext.private = NULL;
512 }
Kristian Høgsberg9590ba92007-05-11 13:24:34 -0400513 GarbageCollectDRIDrawables(dpy, gc->psc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000514 }
515#endif
516
517 if (gc->currentDpy) {
518 /* Have to free later cuz it's in use now */
519 __glXUnlock();
520 } else {
521 /* Destroy the handle if not current to anybody */
522 __glXUnlock();
523 __glXFreeContext(gc);
524 }
525
526 if (!imported) {
527 /*
528 ** This dpy also created the server side part of the context.
529 ** Send the glXDestroyContext request.
530 */
531 LockDisplay(dpy);
532 GetReq(GLXDestroyContext,req);
533 req->reqType = opcode;
534 req->glxCode = X_GLXDestroyContext;
535 req->context = xid;
536 UnlockDisplay(dpy);
537 SyncHandle();
538 }
539}
Adam Jackson489ccef2004-12-15 17:18:06 +0000540
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000541PUBLIC void glXDestroyContext(Display *dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000542{
543 DestroyContext(dpy, gc);
544}
545
546/*
547** Return the major and minor version #s for the GLX extension
548*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000549PUBLIC Bool glXQueryVersion(Display *dpy, int *major, int *minor)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000550{
551 __GLXdisplayPrivate *priv;
552
553 /* Init the extension. This fetches the major and minor version. */
554 priv = __glXInitialize(dpy);
555 if (!priv) return GL_FALSE;
556
557 if (major) *major = priv->majorVersion;
558 if (minor) *minor = priv->minorVersion;
559 return GL_TRUE;
560}
561
562/*
563** Query the existance of the GLX extension
564*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000565PUBLIC Bool glXQueryExtension(Display *dpy, int *errorBase, int *eventBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000566{
567 int major_op, erb, evb;
568 Bool rv;
569
570 rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb);
571 if (rv) {
572 if (errorBase) *errorBase = erb;
573 if (eventBase) *eventBase = evb;
574 }
575 return rv;
576}
577
578/*
579** Put a barrier in the token stream that forces the GL to finish its
580** work before X can proceed.
581*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000582PUBLIC void glXWaitGL(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000583{
584 xGLXWaitGLReq *req;
585 GLXContext gc = __glXGetCurrentContext();
586 Display *dpy = gc->currentDpy;
587
588 if (!dpy) return;
589
590 /* Flush any pending commands out */
591 __glXFlushRenderBuffer(gc, gc->pc);
592
593#ifdef GLX_DIRECT_RENDERING
594 if (gc->isDirect) {
595/* This bit of ugliness unwraps the glFinish function */
596#ifdef glFinish
597#undef glFinish
598#endif
599 glFinish();
600 return;
601 }
602#endif
603
604 /* Send the glXWaitGL request */
605 LockDisplay(dpy);
606 GetReq(GLXWaitGL,req);
607 req->reqType = gc->majorOpcode;
608 req->glxCode = X_GLXWaitGL;
609 req->contextTag = gc->currentContextTag;
610 UnlockDisplay(dpy);
611 SyncHandle();
612}
613
614/*
615** Put a barrier in the token stream that forces X to finish its
616** work before GL can proceed.
617*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000618PUBLIC void glXWaitX(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000619{
620 xGLXWaitXReq *req;
621 GLXContext gc = __glXGetCurrentContext();
622 Display *dpy = gc->currentDpy;
623
624 if (!dpy) return;
625
626 /* Flush any pending commands out */
627 __glXFlushRenderBuffer(gc, gc->pc);
628
629#ifdef GLX_DIRECT_RENDERING
630 if (gc->isDirect) {
631 XSync(dpy, False);
632 return;
633 }
634#endif
635
636 /*
637 ** Send the glXWaitX request.
638 */
639 LockDisplay(dpy);
640 GetReq(GLXWaitX,req);
641 req->reqType = gc->majorOpcode;
642 req->glxCode = X_GLXWaitX;
643 req->contextTag = gc->currentContextTag;
644 UnlockDisplay(dpy);
645 SyncHandle();
646}
647
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000648PUBLIC void glXUseXFont(Font font, int first, int count, int listBase)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000649{
650 xGLXUseXFontReq *req;
651 GLXContext gc = __glXGetCurrentContext();
652 Display *dpy = gc->currentDpy;
653
654 if (!dpy) return;
655
656 /* Flush any pending commands out */
657 (void) __glXFlushRenderBuffer(gc, gc->pc);
658
659#ifdef GLX_DIRECT_RENDERING
660 if (gc->isDirect) {
661 DRI_glXUseXFont(font, first, count, listBase);
662 return;
663 }
664#endif
665
666 /* Send the glXUseFont request */
667 LockDisplay(dpy);
668 GetReq(GLXUseXFont,req);
669 req->reqType = gc->majorOpcode;
670 req->glxCode = X_GLXUseXFont;
671 req->contextTag = gc->currentContextTag;
672 req->font = font;
673 req->first = first;
674 req->count = count;
675 req->listBase = listBase;
676 UnlockDisplay(dpy);
677 SyncHandle();
678}
679
680/************************************************************************/
681
682/*
683** Copy the source context to the destination context using the
684** attribute "mask".
685*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000686PUBLIC void glXCopyContext(Display *dpy, GLXContext source,
687 GLXContext dest, unsigned long mask)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000688{
689 xGLXCopyContextReq *req;
690 GLXContext gc = __glXGetCurrentContext();
691 GLXContextTag tag;
692 CARD8 opcode;
693
694 opcode = __glXSetupForCommand(dpy);
695 if (!opcode) {
696 return;
697 }
698
699#ifdef GLX_DIRECT_RENDERING
700 if (gc->isDirect) {
701 /* NOT_DONE: This does not work yet */
702 }
703#endif
704
705 /*
706 ** If the source is the current context, send its tag so that the context
707 ** can be flushed before the copy.
708 */
709 if (source == gc && dpy == gc->currentDpy) {
710 tag = gc->currentContextTag;
711 } else {
712 tag = 0;
713 }
714
715 /* Send the glXCopyContext request */
716 LockDisplay(dpy);
717 GetReq(GLXCopyContext,req);
718 req->reqType = opcode;
719 req->glxCode = X_GLXCopyContext;
720 req->source = source ? source->xid : None;
721 req->dest = dest ? dest->xid : None;
722 req->mask = mask;
723 req->contextTag = tag;
724 UnlockDisplay(dpy);
725 SyncHandle();
726}
727
728
729/**
730 * Determine if a context uses direct rendering.
731 *
732 * \param dpy Display where the context was created.
733 * \param contextID ID of the context to be tested.
734 *
735 * \returns \c GL_TRUE if the context is direct rendering or not.
736 */
737static Bool __glXIsDirect(Display *dpy, GLXContextID contextID)
738{
739 xGLXIsDirectReq *req;
740 xGLXIsDirectReply reply;
741 CARD8 opcode;
742
743 opcode = __glXSetupForCommand(dpy);
744 if (!opcode) {
745 return GL_FALSE;
746 }
747
748 /* Send the glXIsDirect request */
749 LockDisplay(dpy);
750 GetReq(GLXIsDirect,req);
751 req->reqType = opcode;
752 req->glxCode = X_GLXIsDirect;
753 req->context = contextID;
754 _XReply(dpy, (xReply*) &reply, 0, False);
755 UnlockDisplay(dpy);
756 SyncHandle();
757
758 return reply.isDirect;
759}
760
Ian Romanickc39bf5e2005-07-24 06:29:14 +0000761/**
762 * \todo
763 * Shouldn't this function \b always return \c GL_FALSE when
764 * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with
765 * the GLX protocol here at all?
766 */
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000767PUBLIC Bool glXIsDirect(Display *dpy, GLXContext gc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000768{
769 if (!gc) {
770 return GL_FALSE;
771#ifdef GLX_DIRECT_RENDERING
772 } else if (gc->isDirect) {
773 return GL_TRUE;
774#endif
775 }
776 return __glXIsDirect(dpy, gc->xid);
777}
778
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000779PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis,
780 Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000781{
782 xGLXCreateGLXPixmapReq *req;
783 GLXPixmap xid;
784 CARD8 opcode;
785
786 opcode = __glXSetupForCommand(dpy);
787 if (!opcode) {
788 return None;
789 }
790
791 /* Send the glXCreateGLXPixmap request */
792 LockDisplay(dpy);
793 GetReq(GLXCreateGLXPixmap,req);
794 req->reqType = opcode;
795 req->glxCode = X_GLXCreateGLXPixmap;
796 req->screen = vis->screen;
797 req->visual = vis->visualid;
798 req->pixmap = pixmap;
799 req->glxpixmap = xid = XAllocID(dpy);
800 UnlockDisplay(dpy);
801 SyncHandle();
802 return xid;
803}
804
805/*
806** Destroy the named pixmap
807*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000808PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap glxpixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000809{
810 xGLXDestroyGLXPixmapReq *req;
811 CARD8 opcode;
812
813 opcode = __glXSetupForCommand(dpy);
814 if (!opcode) {
815 return;
816 }
817
818 /* Send the glXDestroyGLXPixmap request */
819 LockDisplay(dpy);
820 GetReq(GLXDestroyGLXPixmap,req);
821 req->reqType = opcode;
822 req->glxCode = X_GLXDestroyGLXPixmap;
823 req->glxpixmap = glxpixmap;
824 UnlockDisplay(dpy);
825 SyncHandle();
826}
827
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000828PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000829{
830 xGLXSwapBuffersReq *req;
831 GLXContext gc;
832 GLXContextTag tag;
833 CARD8 opcode;
834#ifdef GLX_DIRECT_RENDERING
835 __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, NULL );
836
837 if ( pdraw != NULL ) {
Kristian Høgsberg5987a032007-05-11 16:43:20 -0400838 (*pdraw->swapBuffers)(pdraw);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000839 return;
840 }
841#endif
842
843 opcode = __glXSetupForCommand(dpy);
844 if (!opcode) {
845 return;
846 }
847
848 /*
849 ** The calling thread may or may not have a current context. If it
850 ** does, send the context tag so the server can do a flush.
851 */
852 gc = __glXGetCurrentContext();
853 if ((gc != NULL) && (dpy == gc->currentDpy) &&
854 ((drawable == gc->currentDrawable) || (drawable == gc->currentReadable)) ) {
855 tag = gc->currentContextTag;
856 } else {
857 tag = 0;
858 }
859
860 /* Send the glXSwapBuffers request */
861 LockDisplay(dpy);
862 GetReq(GLXSwapBuffers,req);
863 req->reqType = opcode;
864 req->glxCode = X_GLXSwapBuffers;
865 req->drawable = drawable;
866 req->contextTag = tag;
867 UnlockDisplay(dpy);
868 SyncHandle();
869 XFlush(dpy);
870}
871
872
873/*
874** Return configuration information for the given display, screen and
875** visual combination.
876*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +0000877PUBLIC int glXGetConfig(Display *dpy, XVisualInfo *vis, int attribute,
878 int *value_return)
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000879{
880 __GLXdisplayPrivate *priv;
881 __GLXscreenConfigs *psc;
Kristian Høgsberg6c533ea2007-10-16 16:07:47 -0400882 __GLcontextModes *modes;
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000883 int status;
884
885 status = GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc );
886 if ( status == Success ) {
Kristian Høgsberg6c533ea2007-10-16 16:07:47 -0400887 modes = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
Adam Jacksoncb3610e2004-10-25 21:09:16 +0000888
889 /* Lookup attribute after first finding a match on the visual */
890 if ( modes != NULL ) {
891 return _gl_get_context_mode_data( modes, attribute, value_return );
892 }
893
894 status = GLX_BAD_VISUAL;
895 }
896
897 /*
898 ** If we can't find the config for this visual, this visual is not
899 ** supported by the OpenGL implementation on the server.
900 */
901 if ( (status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL) ) {
902 *value_return = GL_FALSE;
903 status = Success;
904 }
905
906 return status;
907}
908
909/************************************************************************/
910
911static void
912init_fbconfig_for_chooser( __GLcontextModes * config,
913 GLboolean fbconfig_style_tags )
914{
915 memset( config, 0, sizeof( __GLcontextModes ) );
916 config->visualID = (XID) GLX_DONT_CARE;
917 config->visualType = GLX_DONT_CARE;
918
919 /* glXChooseFBConfig specifies different defaults for these two than
920 * glXChooseVisual.
921 */
922 if ( fbconfig_style_tags ) {
923 config->rgbMode = GL_TRUE;
924 config->doubleBufferMode = GLX_DONT_CARE;
925 }
926
927 config->visualRating = GLX_DONT_CARE;
928 config->transparentPixel = GLX_NONE;
929 config->transparentRed = GLX_DONT_CARE;
930 config->transparentGreen = GLX_DONT_CARE;
931 config->transparentBlue = GLX_DONT_CARE;
932 config->transparentAlpha = GLX_DONT_CARE;
933 config->transparentIndex = GLX_DONT_CARE;
934
935 config->drawableType = GLX_WINDOW_BIT;
936 config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
937 config->xRenderable = GLX_DONT_CARE;
938 config->fbconfigID = (GLXFBConfigID)(GLX_DONT_CARE);
939
940 config->swapMethod = GLX_DONT_CARE;
941}
942
943#define MATCH_DONT_CARE( param ) \
944 do { \
945 if ( (a-> param != GLX_DONT_CARE) \
946 && (a-> param != b-> param) ) { \
947 return False; \
948 } \
949 } while ( 0 )
950
951#define MATCH_MINIMUM( param ) \
952 do { \
953 if ( (a-> param != GLX_DONT_CARE) \
954 && (a-> param > b-> param) ) { \
955 return False; \
956 } \
957 } while ( 0 )
958
959#define MATCH_EXACT( param ) \
960 do { \
961 if ( a-> param != b-> param) { \
962 return False; \
963 } \
964 } while ( 0 )
965
966/**
967 * Determine if two GLXFBConfigs are compatible.
968 *
969 * \param a Application specified config to test.
970 * \param b Server specified config to test against \c a.
971 */
972static Bool
973fbconfigs_compatible( const __GLcontextModes * const a,
974 const __GLcontextModes * const b )
975{
976 MATCH_DONT_CARE( doubleBufferMode );
977 MATCH_DONT_CARE( visualType );
978 MATCH_DONT_CARE( visualRating );
979 MATCH_DONT_CARE( xRenderable );
980 MATCH_DONT_CARE( fbconfigID );
981 MATCH_DONT_CARE( swapMethod );
982
983 MATCH_MINIMUM( rgbBits );
984 MATCH_MINIMUM( numAuxBuffers );
985 MATCH_MINIMUM( redBits );
986 MATCH_MINIMUM( greenBits );
987 MATCH_MINIMUM( blueBits );
988 MATCH_MINIMUM( alphaBits );
989 MATCH_MINIMUM( depthBits );
990 MATCH_MINIMUM( stencilBits );
991 MATCH_MINIMUM( accumRedBits );
992 MATCH_MINIMUM( accumGreenBits );
993 MATCH_MINIMUM( accumBlueBits );
994 MATCH_MINIMUM( accumAlphaBits );
995 MATCH_MINIMUM( sampleBuffers );
996 MATCH_MINIMUM( maxPbufferWidth );
997 MATCH_MINIMUM( maxPbufferHeight );
998 MATCH_MINIMUM( maxPbufferPixels );
999 MATCH_MINIMUM( samples );
1000
1001 MATCH_DONT_CARE( stereoMode );
1002 MATCH_EXACT( level );
1003
1004 if ( ((a->drawableType & b->drawableType) == 0)
1005 || ((a->renderType & b->renderType) == 0) ) {
1006 return False;
1007 }
1008
1009
1010 /* There is a bug in a few of the XFree86 DDX drivers. They contain
1011 * visuals with a "transparent type" of 0 when they really mean GLX_NONE.
1012 * Technically speaking, it is a bug in the DDX driver, but there is
1013 * enough of an installed base to work around the problem here. In any
1014 * case, 0 is not a valid value of the transparent type, so we'll treat 0
1015 * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and
1016 * 0 from the server to be a match to maintain backward compatibility with
1017 * the (broken) drivers.
1018 */
1019
1020 if ( a->transparentPixel != GLX_DONT_CARE
1021 && a->transparentPixel != 0 ) {
1022 if ( a->transparentPixel == GLX_NONE ) {
1023 if ( b->transparentPixel != GLX_NONE && b->transparentPixel != 0 )
1024 return False;
1025 } else {
1026 MATCH_EXACT( transparentPixel );
1027 }
1028
1029 switch ( a->transparentPixel ) {
1030 case GLX_TRANSPARENT_RGB:
1031 MATCH_DONT_CARE( transparentRed );
1032 MATCH_DONT_CARE( transparentGreen );
1033 MATCH_DONT_CARE( transparentBlue );
1034 MATCH_DONT_CARE( transparentAlpha );
1035 break;
1036
1037 case GLX_TRANSPARENT_INDEX:
1038 MATCH_DONT_CARE( transparentIndex );
1039 break;
1040
1041 default:
1042 break;
1043 }
1044 }
1045
1046 return True;
1047}
1048
1049
1050/* There's some trickly language in the GLX spec about how this is supposed
1051 * to work. Basically, if a given component size is either not specified
1052 * or the requested size is zero, it is supposed to act like PERFER_SMALLER.
1053 * Well, that's really hard to do with the code as-is. This behavior is
1054 * closer to correct, but still not technically right.
1055 */
1056#define PREFER_LARGER_OR_ZERO(comp) \
1057 do { \
1058 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1059 if ( ((*a)-> comp) == 0 ) { \
1060 return -1; \
1061 } \
1062 else if ( ((*b)-> comp) == 0 ) { \
1063 return 1; \
1064 } \
1065 else { \
1066 return ((*b)-> comp) - ((*a)-> comp) ; \
1067 } \
1068 } \
1069 } while( 0 )
1070
1071#define PREFER_LARGER(comp) \
1072 do { \
1073 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1074 return ((*b)-> comp) - ((*a)-> comp) ; \
1075 } \
1076 } while( 0 )
1077
1078#define PREFER_SMALLER(comp) \
1079 do { \
1080 if ( ((*a)-> comp) != ((*b)-> comp) ) { \
1081 return ((*a)-> comp) - ((*b)-> comp) ; \
1082 } \
1083 } while( 0 )
1084
1085/**
1086 * Compare two GLXFBConfigs. This function is intended to be used as the
1087 * compare function passed in to qsort.
1088 *
1089 * \returns If \c a is a "better" config, according to the specification of
1090 * SGIX_fbconfig, a number less than zero is returned. If \c b is
1091 * better, then a number greater than zero is return. If both are
1092 * equal, zero is returned.
1093 * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1094 */
1095static int
1096fbconfig_compare( const __GLcontextModes * const * const a,
1097 const __GLcontextModes * const * const b )
1098{
1099 /* The order of these comparisons must NOT change. It is defined by
1100 * the GLX 1.3 spec and ARB_multisample.
1101 */
1102
1103 PREFER_SMALLER( visualSelectGroup );
1104
1105 /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and
1106 * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the
1107 * numerical sort order of the enums (0x8000, 0x8001, and 0x800D).
1108 */
1109 PREFER_SMALLER( visualRating );
1110
1111 /* This isn't quite right. It is supposed to compare the sum of the
1112 * components the user specifically set minimums for.
1113 */
1114 PREFER_LARGER_OR_ZERO( redBits );
1115 PREFER_LARGER_OR_ZERO( greenBits );
1116 PREFER_LARGER_OR_ZERO( blueBits );
1117 PREFER_LARGER_OR_ZERO( alphaBits );
1118
1119 PREFER_SMALLER( rgbBits );
1120
1121 if ( ((*a)->doubleBufferMode != (*b)->doubleBufferMode) ) {
1122 /* Prefer single-buffer.
1123 */
1124 return ( !(*a)->doubleBufferMode ) ? -1 : 1;
1125 }
1126
1127 PREFER_SMALLER( numAuxBuffers );
1128
1129 PREFER_LARGER_OR_ZERO( depthBits );
1130 PREFER_SMALLER( stencilBits );
1131
1132 /* This isn't quite right. It is supposed to compare the sum of the
1133 * components the user specifically set minimums for.
1134 */
1135 PREFER_LARGER_OR_ZERO( accumRedBits );
1136 PREFER_LARGER_OR_ZERO( accumGreenBits );
1137 PREFER_LARGER_OR_ZERO( accumBlueBits );
1138 PREFER_LARGER_OR_ZERO( accumAlphaBits );
1139
1140 PREFER_SMALLER( visualType );
1141
1142 /* None of the multisample specs say where this comparison should happen,
1143 * so I put it near the end.
1144 */
1145 PREFER_SMALLER( sampleBuffers );
1146 PREFER_SMALLER( samples );
1147
1148 /* None of the pbuffer or fbconfig specs say that this comparison needs
1149 * to happen at all, but it seems like it should.
1150 */
1151 PREFER_LARGER( maxPbufferWidth );
1152 PREFER_LARGER( maxPbufferHeight );
1153 PREFER_LARGER( maxPbufferPixels );
1154
1155 return 0;
1156}
1157
1158
1159/**
1160 * Selects and sorts a subset of the supplied configs based on the attributes.
1161 * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig,
1162 * and \c glXChooseFBConfigSGIX.
1163 *
1164 * \param configs Array of pointers to possible configs. The elements of
1165 * this array that do not meet the criteria will be set to
1166 * NULL. The remaining elements will be sorted according to
1167 * the various visual / FBConfig selection rules.
1168 * \param num_configs Number of elements in the \c configs array.
1169 * \param attribList Attributes used select from \c configs. This array is
1170 * terminated by a \c None tag. The array can either take
1171 * the form expected by \c glXChooseVisual (where boolean
1172 * tags do not have a value) or by \c glXChooseFBConfig
1173 * (where every tag has a value).
1174 * \param fbconfig_style_tags Selects whether \c attribList is in
1175 * \c glXChooseVisual style or
1176 * \c glXChooseFBConfig style.
1177 * \returns The number of valid elements left in \c configs.
1178 *
1179 * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX
1180 */
1181static int
1182choose_visual( __GLcontextModes ** configs, int num_configs,
1183 const int *attribList, GLboolean fbconfig_style_tags )
1184{
1185 __GLcontextModes test_config;
1186 int base;
1187 int i;
1188
1189 /* This is a fairly direct implementation of the selection method
1190 * described by GLX_SGIX_fbconfig. Start by culling out all the
1191 * configs that are not compatible with the selected parameter
1192 * list.
1193 */
1194
1195 init_fbconfig_for_chooser( & test_config, fbconfig_style_tags );
1196 __glXInitializeVisualConfigFromTags( & test_config, 512,
1197 (const INT32 *) attribList,
1198 GL_TRUE, fbconfig_style_tags );
1199
1200 base = 0;
1201 for ( i = 0 ; i < num_configs ; i++ ) {
1202 if ( fbconfigs_compatible( & test_config, configs[i] ) ) {
1203 configs[ base ] = configs[ i ];
1204 base++;
1205 }
1206 }
1207
1208 if ( base == 0 ) {
1209 return 0;
1210 }
1211
1212 if ( base < num_configs ) {
1213 (void) memset( & configs[ base ], 0,
1214 sizeof( void * ) * (num_configs - base) );
1215 }
1216
1217 /* After the incompatible configs are removed, the resulting
1218 * list is sorted according to the rules set out in the various
1219 * specifications.
1220 */
1221
1222 qsort( configs, base, sizeof( __GLcontextModes * ),
1223 (int (*)(const void*, const void*)) fbconfig_compare );
1224 return base;
1225}
1226
1227
1228
1229
1230/*
1231** Return the visual that best matches the template. Return None if no
1232** visual matches the template.
1233*/
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001234PUBLIC XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001235{
1236 XVisualInfo *visualList = NULL;
1237 __GLXdisplayPrivate *priv;
1238 __GLXscreenConfigs *psc;
1239 __GLcontextModes test_config;
1240 __GLcontextModes *modes;
1241 const __GLcontextModes *best_config = NULL;
1242
1243 /*
1244 ** Get a list of all visuals, return if list is empty
1245 */
1246 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1247 return None;
1248 }
1249
1250
1251 /*
1252 ** Build a template from the defaults and the attribute list
1253 ** Free visual list and return if an unexpected token is encountered
1254 */
1255 init_fbconfig_for_chooser( & test_config, GL_FALSE );
1256 __glXInitializeVisualConfigFromTags( & test_config, 512,
1257 (const INT32 *) attribList,
1258 GL_TRUE, GL_FALSE );
1259
1260 /*
1261 ** Eliminate visuals that don't meet minimum requirements
1262 ** Compute a score for those that do
1263 ** Remember which visual, if any, got the highest score
1264 */
Kristian Høgsberg6c533ea2007-10-16 16:07:47 -04001265 for ( modes = psc->visuals ; modes != NULL ; modes = modes->next ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001266 if ( fbconfigs_compatible( & test_config, modes )
1267 && ((best_config == NULL)
1268 || (fbconfig_compare( (const __GLcontextModes * const * const)&modes, &best_config ) < 0)) ) {
1269 best_config = modes;
1270 }
1271 }
1272
1273 /*
1274 ** If no visual is acceptable, return None
1275 ** Otherwise, create an XVisualInfo list with just the selected X visual
1276 ** and return this.
1277 */
1278 if (best_config != NULL) {
1279 XVisualInfo visualTemplate;
1280 int i;
1281
1282 visualTemplate.screen = screen;
1283 visualTemplate.visualid = best_config->visualID;
1284 visualList = XGetVisualInfo( dpy, VisualScreenMask|VisualIDMask,
1285 &visualTemplate, &i );
1286 }
1287
1288 return visualList;
1289}
1290
1291
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001292PUBLIC const char *glXQueryExtensionsString( Display *dpy, int screen )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001293{
1294 __GLXscreenConfigs *psc;
1295 __GLXdisplayPrivate *priv;
1296
1297 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1298 return NULL;
1299 }
1300
1301 if (!psc->effectiveGLXexts) {
1302 if (!psc->serverGLXexts) {
1303 psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode,
1304 X_GLXQueryServerString,
1305 screen, GLX_EXTENSIONS);
1306 }
1307
1308 __glXCalculateUsableExtensions(psc,
1309#ifdef GLX_DIRECT_RENDERING
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001310 (psc->driScreen != NULL),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001311#else
1312 GL_FALSE,
1313#endif
1314 priv->minorVersion);
1315 }
1316
1317 return psc->effectiveGLXexts;
1318}
1319
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001320PUBLIC const char *glXGetClientString( Display *dpy, int name )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001321{
1322 switch(name) {
1323 case GLX_VENDOR:
1324 return (__glXGLXClientVendorName);
1325 case GLX_VERSION:
1326 return (__glXGLXClientVersion);
1327 case GLX_EXTENSIONS:
1328 return (__glXGetClientExtensions());
1329 default:
1330 return NULL;
1331 }
1332}
1333
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001334PUBLIC const char *glXQueryServerString( Display *dpy, int screen, int name )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001335{
1336 __GLXscreenConfigs *psc;
1337 __GLXdisplayPrivate *priv;
1338 const char ** str;
1339
1340
1341 if ( GetGLXPrivScreenConfig( dpy, screen, & priv, & psc ) != Success ) {
1342 return NULL;
1343 }
1344
1345 switch(name) {
1346 case GLX_VENDOR:
1347 str = & priv->serverGLXvendor;
1348 break;
1349 case GLX_VERSION:
1350 str = & priv->serverGLXversion;
1351 break;
1352 case GLX_EXTENSIONS:
1353 str = & psc->serverGLXexts;
1354 break;
1355 default:
1356 return NULL;
1357 }
1358
1359 if ( *str == NULL ) {
1360 *str = __glXGetStringFromServer(dpy, priv->majorOpcode,
1361 X_GLXQueryServerString, screen, name);
1362 }
1363
1364 return *str;
1365}
1366
1367void __glXClientInfo ( Display *dpy, int opcode )
1368{
1369 xGLXClientInfoReq *req;
1370 int size;
1371 char * ext_str = __glXGetClientGLExtensionString();
1372
1373 /* Send the glXClientInfo request */
1374 LockDisplay(dpy);
1375 GetReq(GLXClientInfo,req);
1376 req->reqType = opcode;
1377 req->glxCode = X_GLXClientInfo;
1378 req->major = GLX_MAJOR_VERSION;
1379 req->minor = GLX_MINOR_VERSION;
1380
1381 size = strlen( ext_str ) + 1;
1382 req->length += (size + 3) >> 2;
1383 req->numbytes = size;
1384 Data(dpy, ext_str, size);
1385
1386 UnlockDisplay(dpy);
1387 SyncHandle();
1388
1389 Xfree( ext_str );
1390}
1391
1392
1393/*
1394** EXT_import_context
1395*/
1396
Adam Jackson489ccef2004-12-15 17:18:06 +00001397PUBLIC Display *glXGetCurrentDisplay(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001398{
1399 GLXContext gc = __glXGetCurrentContext();
1400 if (NULL == gc) return NULL;
1401 return gc->currentDpy;
1402}
1403
Adam Jackson489ccef2004-12-15 17:18:06 +00001404PUBLIC GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001405 glXGetCurrentDisplay)
1406
1407/**
1408 * Used internally by libGL to send \c xGLXQueryContextinfoExtReq requests
1409 * to the X-server.
1410 *
1411 * \param dpy Display where \c ctx was created.
1412 * \param ctx Context to query.
1413 * \returns \c Success on success. \c GLX_BAD_CONTEXT if \c ctx is invalid,
1414 * or zero if the request failed due to internal problems (i.e.,
1415 * unable to allocate temporary memory, etc.)
1416 *
1417 * \note
1418 * This function dynamically determines whether to use the EXT_import_context
1419 * version of the protocol or the GLX 1.3 version of the protocol.
1420 */
1421static int __glXQueryContextInfo(Display *dpy, GLXContext ctx)
1422{
1423 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1424 xGLXQueryContextReply reply;
1425 CARD8 opcode;
1426 GLuint numValues;
1427 int retval;
1428
1429 if (ctx == NULL) {
1430 return GLX_BAD_CONTEXT;
1431 }
1432 opcode = __glXSetupForCommand(dpy);
1433 if (!opcode) {
1434 return 0;
1435 }
1436
1437 /* Send the glXQueryContextInfoEXT request */
1438 LockDisplay(dpy);
1439
1440 if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
1441 xGLXQueryContextReq *req;
1442
1443 GetReq(GLXQueryContext, req);
1444
1445 req->reqType = opcode;
1446 req->glxCode = X_GLXQueryContext;
1447 req->context = (unsigned int)(ctx->xid);
1448 }
1449 else {
1450 xGLXVendorPrivateReq *vpreq;
1451 xGLXQueryContextInfoEXTReq *req;
1452
1453 GetReqExtra( GLXVendorPrivate,
1454 sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq,
1455 vpreq );
1456 req = (xGLXQueryContextInfoEXTReq *)vpreq;
1457 req->reqType = opcode;
1458 req->glxCode = X_GLXVendorPrivateWithReply;
1459 req->vendorCode = X_GLXvop_QueryContextInfoEXT;
1460 req->context = (unsigned int)(ctx->xid);
1461 }
1462
1463 _XReply(dpy, (xReply*) &reply, 0, False);
1464
1465 numValues = reply.n;
1466 if (numValues == 0)
1467 retval = Success;
1468 else if (numValues > __GLX_MAX_CONTEXT_PROPS)
1469 retval = 0;
1470 else
1471 {
1472 int *propList, *pProp;
1473 int nPropListBytes;
1474 int i;
1475
1476 nPropListBytes = numValues << 3;
1477 propList = (int *) Xmalloc(nPropListBytes);
1478 if (NULL == propList) {
1479 retval = 0;
1480 } else {
1481 _XRead(dpy, (char *)propList, nPropListBytes);
1482 pProp = propList;
1483 for (i=0; i < numValues; i++) {
1484 switch (*pProp++) {
1485 case GLX_SHARE_CONTEXT_EXT:
1486 ctx->share_xid = *pProp++;
1487 break;
1488 case GLX_VISUAL_ID_EXT:
Kristian Høgsberg001de0a2007-11-06 13:32:04 -05001489 ctx->mode =
1490 _gl_context_modes_find_visual(ctx->psc->visuals, *pProp++);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001491 break;
1492 case GLX_SCREEN:
1493 ctx->screen = *pProp++;
1494 break;
1495 case GLX_FBCONFIG_ID:
Kristian Høgsberg001de0a2007-11-06 13:32:04 -05001496 ctx->mode =
1497 _gl_context_modes_find_fbconfig(ctx->psc->configs, *pProp++);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001498 break;
1499 case GLX_RENDER_TYPE:
1500 ctx->renderType = *pProp++;
1501 break;
1502 default:
1503 pProp++;
1504 continue;
1505 }
1506 }
1507 Xfree((char *)propList);
1508 retval = Success;
1509 }
1510 }
1511 UnlockDisplay(dpy);
1512 SyncHandle();
1513 return retval;
1514}
1515
Adam Jackson489ccef2004-12-15 17:18:06 +00001516PUBLIC int
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001517glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001518{
1519 int retVal;
1520
1521 /* get the information from the server if we don't have it already */
Kristian Høgsberg001de0a2007-11-06 13:32:04 -05001522 if (!ctx->isDirect && (ctx->mode == NULL)) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001523 retVal = __glXQueryContextInfo(dpy, ctx);
1524 if (Success != retVal) return retVal;
1525 }
1526 switch (attribute) {
1527 case GLX_SHARE_CONTEXT_EXT:
1528 *value = (int)(ctx->share_xid);
1529 break;
1530 case GLX_VISUAL_ID_EXT:
Kristian Høgsberg001de0a2007-11-06 13:32:04 -05001531 *value = ctx->mode ? ctx->mode->visualID : None;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001532 break;
1533 case GLX_SCREEN:
1534 *value = (int)(ctx->screen);
1535 break;
1536 case GLX_FBCONFIG_ID:
Kristian Høgsberg001de0a2007-11-06 13:32:04 -05001537 *value = ctx->mode ? ctx->mode->fbconfigID : None;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001538 break;
1539 case GLX_RENDER_TYPE:
1540 *value = (int)(ctx->renderType);
1541 break;
1542 default:
1543 return GLX_BAD_ATTRIBUTE;
1544 }
1545 return Success;
1546}
1547
Adam Jackson489ccef2004-12-15 17:18:06 +00001548PUBLIC GLX_ALIAS( int, glXQueryContextInfoEXT,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001549 (Display *dpy, GLXContext ctx, int attribute, int *value),
1550 (dpy, ctx, attribute, value),
1551 glXQueryContext )
1552
Adam Jackson489ccef2004-12-15 17:18:06 +00001553PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001554{
1555 return ctx->xid;
1556}
1557
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001558PUBLIC GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001559{
1560 GLXContext ctx;
1561
1562 if (contextID == None) {
1563 return NULL;
1564 }
1565 if (__glXIsDirect(dpy, contextID)) {
1566 return NULL;
1567 }
1568
1569 ctx = CreateContext(dpy, NULL, NULL, NULL, False, contextID, False, 0);
1570 if (NULL != ctx) {
1571 if (Success != __glXQueryContextInfo(dpy, ctx)) {
1572 return NULL;
1573 }
1574 }
1575 return ctx;
1576}
1577
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001578PUBLIC void glXFreeContextEXT(Display *dpy, GLXContext ctx)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001579{
1580 DestroyContext(dpy, ctx);
1581}
1582
1583
1584
1585/*
1586 * GLX 1.3 functions - these are just stubs for now!
1587 */
1588
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001589PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
1590 const int *attribList, int *nitems)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001591{
1592 __GLcontextModes ** config_list;
1593 int list_size;
1594
1595
1596 config_list = (__GLcontextModes **)
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001597 glXGetFBConfigs( dpy, screen, & list_size );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001598
Ian Romanickc51ed8c2005-04-07 00:05:55 +00001599 if ( (config_list != NULL) && (list_size > 0) && (attribList != NULL) ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001600 list_size = choose_visual( config_list, list_size, attribList,
1601 GL_TRUE );
1602 if ( list_size == 0 ) {
1603 XFree( config_list );
1604 config_list = NULL;
1605 }
1606 }
1607
1608 *nitems = list_size;
1609 return (GLXFBConfig *) config_list;
1610}
1611
1612
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001613PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config,
1614 int renderType, GLXContext shareList,
1615 Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001616{
1617 return CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
1618 allowDirect, None, True, renderType );
1619}
1620
1621
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001622PUBLIC GLXDrawable glXGetCurrentReadDrawable(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001623{
1624 GLXContext gc = __glXGetCurrentContext();
1625 return gc->currentReadable;
1626}
1627
1628
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001629PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001630{
1631 __GLXdisplayPrivate *priv = __glXInitialize(dpy);
1632 __GLcontextModes ** config = NULL;
1633 int i;
1634
Kristian Høgsberg6c533ea2007-10-16 16:07:47 -04001635 *nelements = 0;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001636 if ( (priv->screenConfigs != NULL)
1637 && (screen >= 0) && (screen <= ScreenCount(dpy))
1638 && (priv->screenConfigs[screen].configs != NULL)
1639 && (priv->screenConfigs[screen].configs->fbconfigID != GLX_DONT_CARE) ) {
1640 unsigned num_configs = 0;
1641 __GLcontextModes * modes;
1642
1643
1644 for ( modes = priv->screenConfigs[screen].configs
1645 ; modes != NULL
1646 ; modes = modes->next ) {
1647 if ( modes->fbconfigID != GLX_DONT_CARE ) {
1648 num_configs++;
1649 }
1650 }
1651
1652 config = (__GLcontextModes **) Xmalloc( sizeof(__GLcontextModes *)
1653 * num_configs );
1654 if ( config != NULL ) {
1655 *nelements = num_configs;
1656 i = 0;
1657 for ( modes = priv->screenConfigs[screen].configs
1658 ; modes != NULL
1659 ; modes = modes->next ) {
Kristian Høgsberga87e9a32007-08-30 13:05:59 -04001660 if ( modes->fbconfigID != GLX_DONT_CARE ) {
1661 config[i] = modes;
1662 i++;
1663 }
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001664 }
1665 }
1666 }
1667 return (GLXFBConfig *) config;
1668}
1669
1670
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001671PUBLIC int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
1672 int attribute, int *value)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001673{
1674 __GLcontextModes * const modes = ValidateGLXFBConfig( dpy, config );
1675
1676 return (modes != NULL)
1677 ? _gl_get_context_mode_data( modes, attribute, value )
1678 : GLXBadFBConfig;
1679}
1680
1681
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001682PUBLIC XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001683{
1684 XVisualInfo visualTemplate;
1685 __GLcontextModes * fbconfig = (__GLcontextModes *) config;
1686 int count;
1687
1688 /*
1689 ** Get a list of all visuals, return if list is empty
1690 */
1691 visualTemplate.visualid = fbconfig->visualID;
1692 return XGetVisualInfo(dpy,VisualIDMask,&visualTemplate,&count);
1693}
1694
1695
1696/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001697** GLX_SGI_swap_control
1698*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001699static int __glXSwapIntervalSGI(int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001700{
1701 xGLXVendorPrivateReq *req;
1702 GLXContext gc = __glXGetCurrentContext();
1703 Display * dpy;
1704 CARD32 * interval_ptr;
1705 CARD8 opcode;
1706
1707 if ( gc == NULL ) {
1708 return GLX_BAD_CONTEXT;
1709 }
1710
1711 if ( interval <= 0 ) {
1712 return GLX_BAD_VALUE;
1713 }
1714
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001715#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001716 if ( gc->isDirect ) {
1717 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1718 gc->screen );
1719 __DRIdrawable * const pdraw = GetDRIDrawable( gc->currentDpy,
1720 gc->currentDrawable,
1721 NULL );
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001722 if (psc->swapControl != NULL && pdraw != NULL) {
1723 psc->swapControl->setSwapInterval(pdraw, interval);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001724 return 0;
1725 }
1726 else {
1727 return GLX_BAD_CONTEXT;
1728 }
1729 }
1730#endif
1731 dpy = gc->currentDpy;
1732 opcode = __glXSetupForCommand(dpy);
1733 if (!opcode) {
1734 return 0;
1735 }
1736
1737 /* Send the glXSwapIntervalSGI request */
1738 LockDisplay(dpy);
1739 GetReqExtra(GLXVendorPrivate,sizeof(CARD32),req);
1740 req->reqType = opcode;
1741 req->glxCode = X_GLXVendorPrivate;
1742 req->vendorCode = X_GLXvop_SwapIntervalSGI;
1743 req->contextTag = gc->currentContextTag;
1744
Ian Romanicka70d5642006-08-30 23:15:02 +00001745 interval_ptr = (CARD32 *) (req + 1);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001746 *interval_ptr = interval;
1747
1748 UnlockDisplay(dpy);
1749 SyncHandle();
1750 XFlush(dpy);
1751
1752 return 0;
1753}
1754
1755
1756/*
1757** GLX_MESA_swap_control
1758*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001759static int __glXSwapIntervalMESA(unsigned int interval)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001760{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001761#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001762 GLXContext gc = __glXGetCurrentContext();
1763
1764 if ( interval < 0 ) {
1765 return GLX_BAD_VALUE;
1766 }
1767
1768 if ( (gc != NULL) && gc->isDirect ) {
1769 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1770 gc->screen );
1771
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001772 if ( (psc != NULL) && (psc->driScreen != NULL) ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001773 __DRIdrawable * const pdraw =
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -05001774 GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001775 if (psc->swapControl != NULL && pdraw != NULL) {
1776 psc->swapControl->setSwapInterval(pdraw, interval);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001777 return 0;
1778 }
1779 }
1780 }
1781#else
1782 (void) interval;
1783#endif
1784
1785 return GLX_BAD_CONTEXT;
1786}
1787
Brian Paul841a8232006-03-09 16:25:46 +00001788
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001789static int __glXGetSwapIntervalMESA(void)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001790{
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001791#ifdef __DRI_SWAP_CONTROL
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001792 GLXContext gc = __glXGetCurrentContext();
1793
1794 if ( (gc != NULL) && gc->isDirect ) {
1795 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1796 gc->screen );
1797
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001798 if ( (psc != NULL) && (psc->driScreen != NULL) ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001799 __DRIdrawable * const pdraw =
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -05001800 GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
Kristian Høgsbergefaf90b2007-05-15 16:09:44 -04001801 if (psc->swapControl != NULL && pdraw != NULL) {
1802 return psc->swapControl->getSwapInterval(pdraw);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001803 }
1804 }
1805 }
1806#endif
1807
1808 return 0;
1809}
1810
1811
1812/*
1813** GLX_MESA_swap_frame_usage
1814*/
1815
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001816static GLint __glXBeginFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001817{
1818 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001819#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001820 int screen;
1821 __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen);
1822 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
1823
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001824 if (pdraw != NULL && psc->frameTracking != NULL)
1825 status = psc->frameTracking->frameTracking(pdraw, GL_TRUE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001826#else
1827 (void) dpy;
1828 (void) drawable;
1829#endif
1830 return status;
1831}
1832
1833
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001834static GLint __glXEndFrameTrackingMESA(Display *dpy, GLXDrawable drawable)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001835{
1836 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001837#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001838 int screen;
1839 __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen);
1840 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
1841
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001842 if (pdraw != NULL && psc->frameTracking != NULL)
1843 status = psc->frameTracking->frameTracking(pdraw, GL_FALSE);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001844#else
1845 (void) dpy;
1846 (void) drawable;
1847#endif
1848 return status;
1849}
1850
1851
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001852static GLint __glXGetFrameUsageMESA(Display *dpy, GLXDrawable drawable,
1853 GLfloat *usage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001854{
1855 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001856#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001857 int screen;
1858 __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen);
1859 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
1860
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001861 if (pdraw != NULL && psc->frameTracking != NULL) {
1862 int64_t sbc, missedFrames;
1863 float lastMissedUsage;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001864
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001865 status = psc->frameTracking->queryFrameTracking(pdraw, &sbc,
1866 &missedFrames,
1867 &lastMissedUsage,
1868 usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001869 }
1870#else
1871 (void) dpy;
1872 (void) drawable;
1873 (void) usage;
1874#endif
1875 return status;
1876}
1877
1878
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001879static GLint __glXQueryFrameTrackingMESA(Display *dpy, GLXDrawable drawable,
1880 int64_t *sbc, int64_t *missedFrames,
1881 GLfloat *lastMissedUsage)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001882{
1883 int status = GLX_BAD_CONTEXT;
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001884#ifdef __DRI_FRAME_TRACKING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001885 int screen;
1886 __DRIdrawable * const pdraw = GetDRIDrawable(dpy, drawable, & screen);
1887 __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
1888
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001889 if (pdraw != NULL && psc->frameTracking != NULL) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001890 float usage;
1891
Kristian Høgsberga7a0a2b2007-05-16 15:50:40 -04001892 status = psc->frameTracking->queryFrameTracking(pdraw, sbc, missedFrames,
1893 lastMissedUsage, &usage);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001894 }
1895#else
1896 (void) dpy;
1897 (void) drawable;
1898 (void) sbc;
1899 (void) missedFrames;
1900 (void) lastMissedUsage;
1901#endif
1902 return status;
1903}
1904
1905
1906/*
1907** GLX_SGI_video_sync
1908*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001909static int __glXGetVideoSyncSGI(unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001910{
1911 /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry,
1912 * FIXME: there should be a GLX encoding for this call. I can find no
1913 * FIXME: documentation for the GLX encoding.
1914 */
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04001915#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001916 GLXContext gc = __glXGetCurrentContext();
1917
1918
1919 if ( (gc != NULL) && gc->isDirect ) {
1920 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1921 gc->screen );
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001922 if ( psc->msc && psc->driScreen ) {
Jesse Barnes38fdb472007-10-29 11:56:31 -07001923 __DRIdrawable * const pdraw =
1924 GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
1925 int64_t temp;
1926 int ret;
1927
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001928 ret = (*psc->msc->getDrawableMSC)(&psc->__driScreen, pdraw, &temp);
Jesse Barnes38fdb472007-10-29 11:56:31 -07001929 *count = (unsigned) temp;
Kristian Høgsberg6e8d21d2008-02-25 16:14:37 -05001930
Jesse Barnes38fdb472007-10-29 11:56:31 -07001931 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001932 }
1933 }
1934#else
1935 (void) count;
1936#endif
1937 return GLX_BAD_CONTEXT;
1938}
1939
Ian Romanickfc5b57b2006-08-29 15:38:19 +00001940static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001941{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04001942#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001943 GLXContext gc = __glXGetCurrentContext();
1944
1945 if ( divisor <= 0 || remainder < 0 )
1946 return GLX_BAD_VALUE;
1947
1948 if ( (gc != NULL) && gc->isDirect ) {
1949 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
1950 gc->screen );
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05001951 if (psc->msc != NULL && psc->driScreen ) {
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001952 __DRIdrawable * const pdraw =
Kristian Høgsberg4a22ae82007-01-07 08:12:01 -05001953 GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
Jesse Barnes38fdb472007-10-29 11:56:31 -07001954 int ret;
1955 int64_t msc;
1956 int64_t sbc;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001957
Jesse Barnes38fdb472007-10-29 11:56:31 -07001958 ret = (*psc->msc->waitForMSC)(pdraw, 0, divisor, remainder, &msc,
1959 &sbc);
1960 *count = (unsigned) msc;
1961 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001962 }
1963 }
1964#else
1965 (void) count;
1966#endif
1967 return GLX_BAD_CONTEXT;
1968}
1969
1970
1971/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001972** GLX_SGIX_fbconfig
1973** Many of these functions are aliased to GLX 1.3 entry points in the
1974** GLX_functions table.
1975*/
1976
Adam Jackson489ccef2004-12-15 17:18:06 +00001977PUBLIC GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001978 (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value),
1979 (dpy, config, attribute, value),
1980 glXGetFBConfigAttrib)
1981
Adam Jackson489ccef2004-12-15 17:18:06 +00001982PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001983 (Display *dpy, int screen, int *attrib_list, int *nelements),
1984 (dpy, screen, attrib_list, nelements),
1985 glXChooseFBConfig)
1986
Adam Jackson489ccef2004-12-15 17:18:06 +00001987PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001988 (Display * dpy, GLXFBConfigSGIX config),
1989 (dpy, config),
1990 glXGetVisualFromFBConfig)
1991
Ian Romanickab7c6ff2005-07-26 22:53:38 +00001992PUBLIC GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy,
Adam Jackson489ccef2004-12-15 17:18:06 +00001993 GLXFBConfigSGIX config, Pixmap pixmap)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00001994{
1995 xGLXVendorPrivateWithReplyReq *vpreq;
1996 xGLXCreateGLXPixmapWithConfigSGIXReq *req;
1997 GLXPixmap xid = None;
1998 CARD8 opcode;
1999 const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
2000 __GLXscreenConfigs * psc;
2001
2002
2003 if ( (dpy == NULL) || (config == NULL) ) {
2004 return None;
2005 }
2006
2007 psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
2008 if ( (psc != NULL)
2009 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
2010 opcode = __glXSetupForCommand(dpy);
2011 if (!opcode) {
2012 return None;
2013 }
2014
2015 /* Send the glXCreateGLXPixmapWithConfigSGIX request */
2016 LockDisplay(dpy);
2017 GetReqExtra(GLXVendorPrivateWithReply,
2018 sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
2019 req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq;
2020 req->reqType = opcode;
2021 req->glxCode = X_GLXVendorPrivateWithReply;
2022 req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX;
2023 req->screen = fbconfig->screen;
2024 req->fbconfig = fbconfig->fbconfigID;
2025 req->pixmap = pixmap;
2026 req->glxpixmap = xid = XAllocID(dpy);
2027 UnlockDisplay(dpy);
2028 SyncHandle();
2029 }
2030
2031 return xid;
2032}
2033
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002034PUBLIC GLXContext glXCreateContextWithConfigSGIX(Display *dpy,
Adam Jackson489ccef2004-12-15 17:18:06 +00002035 GLXFBConfigSGIX config, int renderType,
2036 GLXContext shareList, Bool allowDirect)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002037{
2038 GLXContext gc = NULL;
2039 const __GLcontextModes * const fbconfig = (__GLcontextModes *) config;
2040 __GLXscreenConfigs * psc;
2041
2042
2043 if ( (dpy == NULL) || (config == NULL) ) {
2044 return None;
2045 }
2046
2047 psc = GetGLXScreenConfigs( dpy, fbconfig->screen );
2048 if ( (psc != NULL)
2049 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
2050 gc = CreateContext( dpy, NULL, (__GLcontextModes *) config, shareList,
2051 allowDirect, None, False, renderType );
2052 }
2053
2054 return gc;
2055}
2056
2057
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002058PUBLIC GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy,
2059 XVisualInfo *vis)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002060{
2061 __GLXdisplayPrivate *priv;
2062 __GLXscreenConfigs *psc;
2063
2064 if ( (GetGLXPrivScreenConfig( dpy, vis->screen, & priv, & psc ) != Success)
2065 && __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit )
2066 && (psc->configs->fbconfigID != GLX_DONT_CARE) ) {
2067 return (GLXFBConfigSGIX) _gl_context_modes_find_visual( psc->configs,
2068 vis->visualid );
2069 }
2070
2071 return NULL;
2072}
2073
2074
2075/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002076** GLX_SGIX_swap_group
2077*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002078static void __glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable,
2079 GLXDrawable member)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002080{
2081 (void) dpy;
2082 (void) drawable;
2083 (void) member;
2084}
2085
2086
2087/*
2088** GLX_SGIX_swap_barrier
2089*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002090static void __glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable,
2091 int barrier)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002092{
2093 (void) dpy;
2094 (void) drawable;
2095 (void) barrier;
2096}
2097
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002098static Bool __glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002099{
2100 (void) dpy;
2101 (void) screen;
2102 (void) max;
2103 return False;
2104}
2105
2106
2107/*
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002108** GLX_OML_sync_control
2109*/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002110static Bool __glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
2111 int64_t *ust, int64_t *msc, int64_t *sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002112{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002113#if defined(__DRI_SWAP_BUFFER_COUNTER) && defined(__DRI_MEDIA_STREAM_COUNTER)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002114 __GLXdisplayPrivate * const priv = __glXInitialize(dpy);
2115
2116 if ( priv != NULL ) {
2117 int i;
2118 __DRIdrawable * const pdraw = GetDRIDrawable( dpy, drawable, & i );
2119 __GLXscreenConfigs * const psc = &priv->screenConfigs[i];
2120
2121 assert( (pdraw == NULL) || (i != -1) );
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002122 return ( (pdraw && psc->sbc && psc->msc)
2123 && ((*psc->msc->getMSC)(&psc->driScreen, msc) == 0)
2124 && ((*psc->sbc->getSBC)(pdraw, sbc) == 0)
2125 && (__glXGetUST(ust) == 0) );
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002126 }
2127#else
2128 (void) dpy;
2129 (void) drawable;
2130 (void) ust;
2131 (void) msc;
2132 (void) sbc;
2133#endif
2134 return False;
2135}
2136
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002137#ifdef GLX_DIRECT_RENDERING
2138GLboolean
2139__driGetMscRateOML(__DRIdrawable *draw, int32_t *numerator, int32_t *denominator)
2140{
2141#ifdef XF86VIDMODE
2142 __GLXscreenConfigs *psc;
2143 XF86VidModeModeLine mode_line;
2144 int dot_clock;
2145 int i;
2146 __GLXdrawable *glxDraw;
2147
2148 glxDraw = containerOf(draw, __GLXdrawable, driDrawable);
2149 psc = glxDraw->psc;
2150 if (XF86VidModeQueryVersion(psc->dpy, &i, &i) &&
2151 XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line) ) {
2152 unsigned n = dot_clock * 1000;
2153 unsigned d = mode_line.vtotal * mode_line.htotal;
2154
2155# define V_INTERLACE 0x010
2156# define V_DBLSCAN 0x020
2157
2158 if (mode_line.flags & V_INTERLACE)
2159 n *= 2;
2160 else if (mode_line.flags & V_DBLSCAN)
2161 d *= 2;
2162
2163 /* The OML_sync_control spec requires that if the refresh rate is a
2164 * whole number, that the returned numerator be equal to the refresh
2165 * rate and the denominator be 1.
2166 */
2167
2168 if (n % d == 0) {
2169 n /= d;
2170 d = 1;
2171 }
2172 else {
2173 static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 };
2174
2175 /* This is a poor man's way to reduce a fraction. It's far from
2176 * perfect, but it will work well enough for this situation.
2177 */
2178
2179 for (i = 0; f[i] != 0; i++) {
2180 while (n % f[i] == 0 && d % f[i] == 0) {
2181 d /= f[i];
2182 n /= f[i];
2183 }
2184 }
2185 }
2186
2187 *numerator = n;
2188 *denominator = d;
2189
2190 return True;
2191 }
2192 else
2193 return False;
2194#else
2195 return False;
2196#endif
2197}
2198#endif
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002199
2200/**
2201 * Determine the refresh rate of the specified drawable and display.
2202 *
2203 * \param dpy Display whose refresh rate is to be determined.
2204 * \param drawable Drawable whose refresh rate is to be determined.
2205 * \param numerator Numerator of the refresh rate.
2206 * \param demoninator Denominator of the refresh rate.
2207 * \return If the refresh rate for the specified display and drawable could
2208 * be calculated, True is returned. Otherwise False is returned.
2209 *
2210 * \note This function is implemented entirely client-side. A lot of other
2211 * functionality is required to export GLX_OML_sync_control, so on
2212 * XFree86 this function can be called for direct-rendering contexts
2213 * when GLX_OML_sync_control appears in the client extension string.
2214 */
2215
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002216GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
Kristian Høgsbergaceccda2007-05-10 15:52:22 -04002217 int32_t * numerator, int32_t * denominator)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002218{
2219#if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE )
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002220 __DRIdrawable *driDraw = GetDRIDrawable(dpy, drawable, NULL);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002221
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002222 if (driDraw == NULL)
2223 return False;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002224
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002225 return __driGetMscRateOML(driDraw, numerator, denominator);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002226#else
Kristian Høgsberg286ce272007-11-06 14:34:15 -05002227 (void) dpy;
2228 (void) drawable;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002229 (void) numerator;
2230 (void) denominator;
2231#endif
2232 return False;
2233}
2234
2235
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002236static int64_t __glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
2237 int64_t target_msc, int64_t divisor,
2238 int64_t remainder)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002239{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002240#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002241 int screen;
2242 __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen );
2243 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2244
2245 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2246 * error", but it also says "It [glXSwapBuffersMscOML] will return a value
2247 * of -1 if the function failed because of errors detected in the input
2248 * parameters"
2249 */
2250 if ( divisor < 0 || remainder < 0 || target_msc < 0 )
2251 return -1;
2252 if ( divisor > 0 && remainder >= divisor )
2253 return -1;
2254
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002255 if (pdraw != NULL && psc->counters != NULL)
2256 return (*psc->sbc->swapBuffersMSC)(pdraw, target_msc,
2257 divisor, remainder);
2258
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002259#else
2260 (void) dpy;
2261 (void) drawable;
2262 (void) target_msc;
2263 (void) divisor;
2264 (void) remainder;
2265#endif
2266 return 0;
2267}
2268
2269
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002270static Bool __glXWaitForMscOML(Display * dpy, GLXDrawable drawable,
2271 int64_t target_msc, int64_t divisor,
2272 int64_t remainder, int64_t *ust,
2273 int64_t *msc, int64_t *sbc)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002274{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002275#ifdef __DRI_MEDIA_STREAM_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002276 int screen;
2277 __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen );
2278 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2279 int ret;
2280
2281 /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
2282 * error", but the return type in the spec is Bool.
2283 */
2284 if ( divisor < 0 || remainder < 0 || target_msc < 0 )
2285 return False;
2286 if ( divisor > 0 && remainder >= divisor )
2287 return False;
2288
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002289 if (pdraw != NULL && psc->msc != NULL) {
2290 ret = (*psc->msc->waitForMSC)(pdraw, target_msc,
2291 divisor, remainder, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002292
2293 /* __glXGetUST returns zero on success and non-zero on failure.
2294 * This function returns True on success and False on failure.
2295 */
2296 return ( (ret == 0) && (__glXGetUST( ust ) == 0) );
2297 }
2298#else
2299 (void) dpy;
2300 (void) drawable;
2301 (void) target_msc;
2302 (void) divisor;
2303 (void) remainder;
2304 (void) ust;
2305 (void) msc;
2306 (void) sbc;
2307#endif
2308 return False;
2309}
2310
2311
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002312static Bool __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable,
2313 int64_t target_sbc, int64_t *ust,
2314 int64_t *msc, int64_t *sbc )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002315{
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002316#ifdef __DRI_SWAP_BUFFER_COUNTER
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002317 int screen;
2318 __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen );
2319 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
2320 int ret;
2321
2322 /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE
2323 * error", but the return type in the spec is Bool.
2324 */
2325 if ( target_sbc < 0 )
2326 return False;
2327
Kristian Høgsberg106a6f22007-05-16 18:13:41 -04002328 if (pdraw != NULL && psc->sbc != NULL) {
2329 ret = (*psc->sbc->waitForSBC)(pdraw, target_sbc, msc, sbc);
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002330
2331 /* __glXGetUST returns zero on success and non-zero on failure.
2332 * This function returns True on success and False on failure.
2333 */
2334 return( (ret == 0) && (__glXGetUST( ust ) == 0) );
2335 }
2336#else
2337 (void) dpy;
2338 (void) drawable;
2339 (void) target_sbc;
2340 (void) ust;
2341 (void) msc;
2342 (void) sbc;
2343#endif
2344 return False;
2345}
2346
2347
2348/**
2349 * GLX_MESA_allocate_memory
2350 */
2351/*@{*/
2352
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002353PUBLIC void *glXAllocateMemoryMESA(Display *dpy, int scrn,
2354 size_t size, float readFreq,
2355 float writeFreq, float priority)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002356{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002357#ifdef __DRI_ALLOCATE
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002358 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
2359
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002360 if (psc && psc->allocate)
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05002361 return (*psc->allocate->allocateMemory)( &psc->__driScreen, size,
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002362 readFreq, writeFreq,
2363 priority );
2364
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002365#else
2366 (void) dpy;
2367 (void) scrn;
2368 (void) size;
2369 (void) readFreq;
2370 (void) writeFreq;
2371 (void) priority;
2372#endif /* GLX_DIRECT_RENDERING */
2373
2374 return NULL;
2375}
2376
2377
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002378PUBLIC void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002379{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002380#ifdef __DRI_ALLOCATE
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002381 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
2382
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002383 if (psc && psc->allocate)
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05002384 (*psc->allocate->freeMemory)( &psc->__driScreen, pointer );
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002385
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002386#else
2387 (void) dpy;
2388 (void) scrn;
2389 (void) pointer;
2390#endif /* GLX_DIRECT_RENDERING */
2391}
2392
2393
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002394PUBLIC GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
2395 const void *pointer )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002396{
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002397#ifdef __DRI_ALLOCATE
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002398 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, scrn );
2399
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002400 if (psc && psc->allocate)
Kristian Høgsberg92d2a782008-03-08 20:34:24 -05002401 return (*psc->allocate->memoryOffset)( &psc->__driScreen, pointer );
Kristian Høgsberg78a6aa52007-05-16 14:10:29 -04002402
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002403#else
2404 (void) dpy;
2405 (void) scrn;
2406 (void) pointer;
2407#endif /* GLX_DIRECT_RENDERING */
2408
2409 return ~0L;
2410}
2411/*@}*/
2412
2413
2414/**
2415 * Mesa extension stubs. These will help reduce portability problems.
2416 */
2417/*@{*/
2418
2419/**
2420 * Release all buffers associated with the specified GLX drawable.
2421 *
2422 * \todo
2423 * This function was intended for stand-alone Mesa. The issue there is that
2424 * the library doesn't get any notification when a window is closed. In
2425 * DRI there is a similar but slightly different issue. When GLX 1.3 is
2426 * supported, there are 3 different functions to destroy a drawable. It
2427 * should be possible to create GLX protocol (or have it determine which
2428 * protocol to use based on the type of the drawable) to have one function
2429 * do the work of 3. For the direct-rendering case, this function could
2430 * just call the driver's \c __DRIdrawableRec::destroyDrawable function.
2431 * This would reduce the frequency with which \c __driGarbageCollectDrawables
2432 * would need to be used. This really should be done as part of the new DRI
2433 * interface work.
2434 *
2435 * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt
2436 * __driGarbageCollectDrawables
2437 * glXDestroyGLXPixmap
2438 * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow
2439 * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX
2440 */
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002441static Bool __glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002442{
2443 (void) dpy;
2444 (void) d;
2445 return False;
2446}
2447
2448
Ian Romanickab7c6ff2005-07-26 22:53:38 +00002449PUBLIC GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visual,
2450 Pixmap pixmap, Colormap cmap )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002451{
2452 (void) dpy;
2453 (void) visual;
2454 (void) pixmap;
2455 (void) cmap;
2456 return 0;
2457}
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002458/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002459
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002460
2461/**
2462 * GLX_MESA_copy_sub_buffer
2463 */
Brian Paulf2ad1b62006-03-31 15:48:04 +00002464#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002465static void __glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
2466 int x, int y, int width, int height)
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002467{
Brian Paulf2ad1b62006-03-31 15:48:04 +00002468 xGLXVendorPrivateReq *req;
2469 GLXContext gc;
2470 GLXContextTag tag;
2471 CARD32 *drawable_ptr;
2472 INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr;
2473 CARD8 opcode;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002474
Kristian Høgsbergac3e8382007-05-15 15:17:30 -04002475#ifdef __DRI_COPY_SUB_BUFFER
Brian Paulf2ad1b62006-03-31 15:48:04 +00002476 int screen;
2477 __DRIdrawable *pdraw = GetDRIDrawable( dpy, drawable, & screen );
2478 if ( pdraw != NULL ) {
2479 __GLXscreenConfigs * const psc = GetGLXScreenConfigs( dpy, screen );
Kristian Høgsbergac3e8382007-05-15 15:17:30 -04002480 if (psc->copySubBuffer != NULL) {
2481 (*psc->copySubBuffer->copySubBuffer)(pdraw, x, y, width, height);
Brian Paulf2ad1b62006-03-31 15:48:04 +00002482 }
2483
2484 return;
2485 }
2486#endif
2487
2488 opcode = __glXSetupForCommand(dpy);
2489 if (!opcode)
2490 return;
2491
2492 /*
2493 ** The calling thread may or may not have a current context. If it
2494 ** does, send the context tag so the server can do a flush.
2495 */
2496 gc = __glXGetCurrentContext();
2497 if ((gc != NULL) && (dpy == gc->currentDpy) &&
2498 ((drawable == gc->currentDrawable) ||
2499 (drawable == gc->currentReadable)) ) {
2500 tag = gc->currentContextTag;
2501 } else {
2502 tag = 0;
2503 }
2504
2505 LockDisplay(dpy);
2506 GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4,req);
2507 req->reqType = opcode;
2508 req->glxCode = X_GLXVendorPrivate;
2509 req->vendorCode = X_GLXvop_CopySubBufferMESA;
2510 req->contextTag = tag;
2511
2512 drawable_ptr = (CARD32 *) (req + 1);
2513 x_ptr = (INT32 *) (drawable_ptr + 1);
2514 y_ptr = (INT32 *) (drawable_ptr + 2);
2515 w_ptr = (INT32 *) (drawable_ptr + 3);
2516 h_ptr = (INT32 *) (drawable_ptr + 4);
2517
2518 *drawable_ptr = drawable;
2519 *x_ptr = x;
2520 *y_ptr = y;
2521 *w_ptr = width;
2522 *h_ptr = height;
2523
2524 UnlockDisplay(dpy);
2525 SyncHandle();
2526}
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002527
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002528
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002529/**
2530 * GLX_EXT_texture_from_pixmap
2531 */
2532/*@{*/
2533static void __glXBindTexImageEXT(Display *dpy,
2534 GLXDrawable drawable,
2535 int buffer,
2536 const int *attrib_list)
Brian Paul42725d62006-02-07 00:39:56 +00002537{
2538 xGLXVendorPrivateReq *req;
2539 GLXContext gc = __glXGetCurrentContext();
2540 CARD32 *drawable_ptr;
2541 INT32 *buffer_ptr;
David Revemanc6f8ae12006-04-11 12:12:13 +00002542 CARD32 *num_attrib_ptr;
2543 CARD32 *attrib_ptr;
Brian Paul42725d62006-02-07 00:39:56 +00002544 CARD8 opcode;
David Revemanc6f8ae12006-04-11 12:12:13 +00002545 unsigned int i;
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002546
Brian Paul42725d62006-02-07 00:39:56 +00002547 if (gc == NULL)
Adam Jackson01576242006-05-01 22:25:18 +00002548 return;
Brian Paul42725d62006-02-07 00:39:56 +00002549
David Revemanc6f8ae12006-04-11 12:12:13 +00002550 i = 0;
2551 if (attrib_list) {
2552 while (attrib_list[i * 2] != None)
2553 i++;
2554 }
2555
Brian Paul42725d62006-02-07 00:39:56 +00002556#ifdef GLX_DIRECT_RENDERING
2557 if (gc->isDirect)
Adam Jackson01576242006-05-01 22:25:18 +00002558 return;
Brian Paul42725d62006-02-07 00:39:56 +00002559#endif
2560
2561 opcode = __glXSetupForCommand(dpy);
2562 if (!opcode)
Adam Jackson01576242006-05-01 22:25:18 +00002563 return;
Brian Paul42725d62006-02-07 00:39:56 +00002564
2565 LockDisplay(dpy);
David Revemanc6f8ae12006-04-11 12:12:13 +00002566 GetReqExtra(GLXVendorPrivate, 12 + 8 * i,req);
Brian Paul42725d62006-02-07 00:39:56 +00002567 req->reqType = opcode;
2568 req->glxCode = X_GLXVendorPrivate;
2569 req->vendorCode = X_GLXvop_BindTexImageEXT;
2570 req->contextTag = gc->currentContextTag;
2571
2572 drawable_ptr = (CARD32 *) (req + 1);
2573 buffer_ptr = (INT32 *) (drawable_ptr + 1);
David Revemanc6f8ae12006-04-11 12:12:13 +00002574 num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2575 attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
Brian Paul42725d62006-02-07 00:39:56 +00002576
2577 *drawable_ptr = drawable;
2578 *buffer_ptr = buffer;
David Revemanc6f8ae12006-04-11 12:12:13 +00002579 *num_attrib_ptr = (CARD32) i;
2580
2581 i = 0;
2582 if (attrib_list) {
2583 while (attrib_list[i * 2] != None)
2584 {
2585 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2586 *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2587 i++;
2588 }
2589 }
Brian Paul42725d62006-02-07 00:39:56 +00002590
2591 UnlockDisplay(dpy);
2592 SyncHandle();
Brian Paul42725d62006-02-07 00:39:56 +00002593}
2594
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002595static void __glXReleaseTexImageEXT(Display *dpy,
2596 GLXDrawable drawable,
2597 int buffer)
Brian Paul42725d62006-02-07 00:39:56 +00002598{
2599 xGLXVendorPrivateReq *req;
2600 GLXContext gc = __glXGetCurrentContext();
2601 CARD32 *drawable_ptr;
2602 INT32 *buffer_ptr;
2603 CARD8 opcode;
2604
2605 if (gc == NULL)
Adam Jackson01576242006-05-01 22:25:18 +00002606 return;
Brian Paul42725d62006-02-07 00:39:56 +00002607
2608#ifdef GLX_DIRECT_RENDERING
2609 if (gc->isDirect)
Adam Jackson01576242006-05-01 22:25:18 +00002610 return;
Brian Paul42725d62006-02-07 00:39:56 +00002611#endif
2612
2613 opcode = __glXSetupForCommand(dpy);
2614 if (!opcode)
Adam Jackson01576242006-05-01 22:25:18 +00002615 return;
Brian Paul42725d62006-02-07 00:39:56 +00002616
2617 LockDisplay(dpy);
2618 GetReqExtra(GLXVendorPrivate, sizeof(CARD32)+sizeof(INT32),req);
2619 req->reqType = opcode;
2620 req->glxCode = X_GLXVendorPrivate;
2621 req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
2622 req->contextTag = gc->currentContextTag;
2623
2624 drawable_ptr = (CARD32 *) (req + 1);
2625 buffer_ptr = (INT32 *) (drawable_ptr + 1);
2626
2627 *drawable_ptr = drawable;
2628 *buffer_ptr = buffer;
2629
2630 UnlockDisplay(dpy);
2631 SyncHandle();
Brian Paul42725d62006-02-07 00:39:56 +00002632}
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002633/*@}*/
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002634
2635/**
2636 * \c strdup is actually not a standard ANSI C or POSIX routine.
2637 * Irix will not define it if ANSI mode is in effect.
2638 *
2639 * \sa strdup
2640 */
2641char *
2642__glXstrdup(const char *str)
2643{
2644 char *copy;
2645 copy = (char *) Xmalloc(strlen(str) + 1);
2646 if (!copy)
2647 return NULL;
2648 strcpy(copy, str);
2649 return copy;
2650}
2651
2652/*
2653** glXGetProcAddress support
2654*/
2655
2656struct name_address_pair {
2657 const char *Name;
2658 GLvoid *Address;
2659};
2660
2661#define GLX_FUNCTION(f) { # f, (GLvoid *) f }
2662#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f }
2663
2664static const struct name_address_pair GLX_functions[] = {
2665 /*** GLX_VERSION_1_0 ***/
2666 GLX_FUNCTION( glXChooseVisual ),
2667 GLX_FUNCTION( glXCopyContext ),
2668 GLX_FUNCTION( glXCreateContext ),
2669 GLX_FUNCTION( glXCreateGLXPixmap ),
2670 GLX_FUNCTION( glXDestroyContext ),
2671 GLX_FUNCTION( glXDestroyGLXPixmap ),
2672 GLX_FUNCTION( glXGetConfig ),
2673 GLX_FUNCTION( glXGetCurrentContext ),
2674 GLX_FUNCTION( glXGetCurrentDrawable ),
2675 GLX_FUNCTION( glXIsDirect ),
2676 GLX_FUNCTION( glXMakeCurrent ),
2677 GLX_FUNCTION( glXQueryExtension ),
2678 GLX_FUNCTION( glXQueryVersion ),
2679 GLX_FUNCTION( glXSwapBuffers ),
2680 GLX_FUNCTION( glXUseXFont ),
2681 GLX_FUNCTION( glXWaitGL ),
2682 GLX_FUNCTION( glXWaitX ),
2683
2684 /*** GLX_VERSION_1_1 ***/
2685 GLX_FUNCTION( glXGetClientString ),
2686 GLX_FUNCTION( glXQueryExtensionsString ),
2687 GLX_FUNCTION( glXQueryServerString ),
2688
2689 /*** GLX_VERSION_1_2 ***/
2690 GLX_FUNCTION( glXGetCurrentDisplay ),
2691
2692 /*** GLX_VERSION_1_3 ***/
2693 GLX_FUNCTION( glXChooseFBConfig ),
2694 GLX_FUNCTION( glXCreateNewContext ),
2695 GLX_FUNCTION( glXCreatePbuffer ),
2696 GLX_FUNCTION( glXCreatePixmap ),
2697 GLX_FUNCTION( glXCreateWindow ),
2698 GLX_FUNCTION( glXDestroyPbuffer ),
2699 GLX_FUNCTION( glXDestroyPixmap ),
2700 GLX_FUNCTION( glXDestroyWindow ),
2701 GLX_FUNCTION( glXGetCurrentReadDrawable ),
2702 GLX_FUNCTION( glXGetFBConfigAttrib ),
2703 GLX_FUNCTION( glXGetFBConfigs ),
2704 GLX_FUNCTION( glXGetSelectedEvent ),
2705 GLX_FUNCTION( glXGetVisualFromFBConfig ),
2706 GLX_FUNCTION( glXMakeContextCurrent ),
2707 GLX_FUNCTION( glXQueryContext ),
2708 GLX_FUNCTION( glXQueryDrawable ),
2709 GLX_FUNCTION( glXSelectEvent ),
2710
2711 /*** GLX_SGI_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002712 GLX_FUNCTION2( glXSwapIntervalSGI, __glXSwapIntervalSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002713
2714 /*** GLX_SGI_video_sync ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002715 GLX_FUNCTION2( glXGetVideoSyncSGI, __glXGetVideoSyncSGI ),
2716 GLX_FUNCTION2( glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002717
2718 /*** GLX_SGI_make_current_read ***/
2719 GLX_FUNCTION2( glXMakeCurrentReadSGI, glXMakeContextCurrent ),
2720 GLX_FUNCTION2( glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable ),
2721
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002722 /*** GLX_EXT_import_context ***/
2723 GLX_FUNCTION( glXFreeContextEXT ),
2724 GLX_FUNCTION( glXGetContextIDEXT ),
2725 GLX_FUNCTION2( glXGetCurrentDisplayEXT, glXGetCurrentDisplay ),
2726 GLX_FUNCTION( glXImportContextEXT ),
2727 GLX_FUNCTION2( glXQueryContextInfoEXT, glXQueryContext ),
2728
2729 /*** GLX_SGIX_fbconfig ***/
2730 GLX_FUNCTION2( glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib ),
2731 GLX_FUNCTION2( glXChooseFBConfigSGIX, glXChooseFBConfig ),
2732 GLX_FUNCTION( glXCreateGLXPixmapWithConfigSGIX ),
2733 GLX_FUNCTION( glXCreateContextWithConfigSGIX ),
2734 GLX_FUNCTION2( glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig ),
2735 GLX_FUNCTION( glXGetFBConfigFromVisualSGIX ),
2736
2737 /*** GLX_SGIX_pbuffer ***/
2738 GLX_FUNCTION( glXCreateGLXPbufferSGIX ),
2739 GLX_FUNCTION( glXDestroyGLXPbufferSGIX ),
2740 GLX_FUNCTION( glXQueryGLXPbufferSGIX ),
2741 GLX_FUNCTION( glXSelectEventSGIX ),
2742 GLX_FUNCTION( glXGetSelectedEventSGIX ),
2743
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002744 /*** GLX_SGIX_swap_group ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002745 GLX_FUNCTION2( glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002746
2747 /*** GLX_SGIX_swap_barrier ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002748 GLX_FUNCTION2( glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX ),
2749 GLX_FUNCTION2( glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002750
2751 /*** GLX_MESA_allocate_memory ***/
2752 GLX_FUNCTION( glXAllocateMemoryMESA ),
2753 GLX_FUNCTION( glXFreeMemoryMESA ),
2754 GLX_FUNCTION( glXGetMemoryOffsetMESA ),
2755
2756 /*** GLX_MESA_copy_sub_buffer ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002757 GLX_FUNCTION2( glXCopySubBufferMESA, __glXCopySubBufferMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002758
2759 /*** GLX_MESA_pixmap_colormap ***/
2760 GLX_FUNCTION( glXCreateGLXPixmapMESA ),
2761
2762 /*** GLX_MESA_release_buffers ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002763 GLX_FUNCTION2( glXReleaseBuffersMESA, __glXReleaseBuffersMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002764
2765 /*** GLX_MESA_swap_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002766 GLX_FUNCTION2( glXSwapIntervalMESA, __glXSwapIntervalMESA ),
2767 GLX_FUNCTION2( glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002768
2769 /*** GLX_MESA_swap_frame_usage ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002770 GLX_FUNCTION2( glXBeginFrameTrackingMESA, __glXBeginFrameTrackingMESA ),
2771 GLX_FUNCTION2( glXEndFrameTrackingMESA, __glXEndFrameTrackingMESA ),
2772 GLX_FUNCTION2( glXGetFrameUsageMESA, __glXGetFrameUsageMESA ),
2773 GLX_FUNCTION2( glXQueryFrameTrackingMESA, __glXQueryFrameTrackingMESA ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002774
2775 /*** GLX_ARB_get_proc_address ***/
2776 GLX_FUNCTION( glXGetProcAddressARB ),
2777
2778 /*** GLX 1.4 ***/
2779 GLX_FUNCTION2( glXGetProcAddress, glXGetProcAddressARB ),
2780
2781 /*** GLX_OML_sync_control ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002782 GLX_FUNCTION2( glXWaitForSbcOML, __glXWaitForSbcOML ),
2783 GLX_FUNCTION2( glXWaitForMscOML, __glXWaitForMscOML ),
2784 GLX_FUNCTION2( glXSwapBuffersMscOML, __glXSwapBuffersMscOML ),
2785 GLX_FUNCTION2( glXGetMscRateOML, __glXGetMscRateOML ),
2786 GLX_FUNCTION2( glXGetSyncValuesOML, __glXGetSyncValuesOML ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002787
Brian Paul42725d62006-02-07 00:39:56 +00002788 /*** GLX_EXT_texture_from_pixmap ***/
Ian Romanickfc5b57b2006-08-29 15:38:19 +00002789 GLX_FUNCTION2( glXBindTexImageEXT, __glXBindTexImageEXT ),
2790 GLX_FUNCTION2( glXReleaseTexImageEXT, __glXReleaseTexImageEXT ),
Brian Paul42725d62006-02-07 00:39:56 +00002791
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002792#ifdef GLX_DIRECT_RENDERING
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002793 /*** DRI configuration ***/
2794 GLX_FUNCTION( glXGetScreenDriver ),
2795 GLX_FUNCTION( glXGetDriverConfig ),
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002796#endif
2797
2798 { NULL, NULL } /* end of list */
2799};
2800
2801
2802static const GLvoid *
2803get_glx_proc_address(const char *funcName)
2804{
2805 GLuint i;
2806
2807 /* try static functions */
2808 for (i = 0; GLX_functions[i].Name; i++) {
2809 if (strcmp(GLX_functions[i].Name, funcName) == 0)
2810 return GLX_functions[i].Address;
2811 }
2812
2813 return NULL;
2814}
2815
2816
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002817/**
2818 * Get the address of a named GL function. This is the pre-GLX 1.4 name for
2819 * \c glXGetProcAddress.
2820 *
2821 * \param procName Name of a GL or GLX function.
2822 * \returns A pointer to the named function
2823 *
2824 * \sa glXGetProcAddress
2825 */
Adam Jackson489ccef2004-12-15 17:18:06 +00002826PUBLIC void (*glXGetProcAddressARB(const GLubyte *procName))( void )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002827{
2828 typedef void (*gl_function)( void );
2829 gl_function f;
2830
2831
2832 /* Search the table of GLX and internal functions first. If that
2833 * fails and the supplied name could be a valid core GL name, try
2834 * searching the core GL function table. This check is done to prevent
2835 * DRI based drivers from searching the core GL function table for
2836 * internal API functions.
2837 */
2838
2839 f = (gl_function) get_glx_proc_address((const char *) procName);
2840 if ( (f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
2841 && (procName[2] != 'X') ) {
2842 f = (gl_function) _glapi_get_proc_address((const char *) procName);
2843 }
2844
2845 return f;
2846}
2847
2848/**
2849 * Get the address of a named GL function. This is the GLX 1.4 name for
2850 * \c glXGetProcAddressARB.
2851 *
2852 * \param procName Name of a GL or GLX function.
2853 * \returns A pointer to the named function
2854 *
2855 * \sa glXGetProcAddressARB
2856 */
Adam Jackson489ccef2004-12-15 17:18:06 +00002857PUBLIC void (*glXGetProcAddress(const GLubyte *procName))( void )
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002858#if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
2859 __attribute__ ((alias ("glXGetProcAddressARB")));
2860#else
2861{
2862 return glXGetProcAddressARB(procName);
2863}
2864#endif /* __GNUC__ */
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002865
2866
2867#ifdef GLX_DIRECT_RENDERING
2868/**
Adam Jacksoncb3610e2004-10-25 21:09:16 +00002869 * Get the unadjusted system time (UST). Currently, the UST is measured in
2870 * microseconds since Epoc. The actual resolution of the UST may vary from
2871 * system to system, and the units may vary from release to release.
2872 * Drivers should not call this function directly. They should instead use
2873 * \c glXGetProcAddress to obtain a pointer to the function.
2874 *
2875 * \param ust Location to store the 64-bit UST
2876 * \returns Zero on success or a negative errno value on failure.
2877 *
2878 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
2879 *
2880 * \since Internal API version 20030317.
2881 */
2882int __glXGetUST( int64_t * ust )
2883{
2884 struct timeval tv;
2885
2886 if ( ust == NULL ) {
2887 return -EFAULT;
2888 }
2889
2890 if ( gettimeofday( & tv, NULL ) == 0 ) {
2891 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
2892 return 0;
2893 } else {
2894 return -errno;
2895 }
2896}
2897#endif /* GLX_DIRECT_RENDERING */