1 /* $Id: glxapi.c,v 1.17 2000/06/08 22:50:28 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * This is the GLX API dispatcher. Calls to the glX* functions are
30 * either routed to real (SGI / Utah) GLX encoders or to Mesa's
42 * XXX - this really shouldn't be here.
43 * Instead, add -DUSE_MESA_GLX to the compiler flags when needed.
45 #define USE_MESA_GLX 1
48 /* Rather than include possibly non-existant headers... */
50 extern struct _glxapi_table
*_sgi_GetGLXDispatchtable(void);
53 extern struct _glxapi_table
*_utah_GetGLXDispatchTable(void);
56 extern struct _glxapi_table
*_mesa_GetGLXDispatchTable(void);
61 struct display_dispatch
{
63 struct _glxapi_table
*Table
;
64 struct display_dispatch
*Next
;
67 static struct display_dispatch
*DispatchList
= NULL
;
70 static struct _glxapi_table
*
71 get_dispatch(Display
*dpy
)
73 static Display
*prevDisplay
= NULL
;
74 static struct _glxapi_table
*prevTable
= NULL
;
79 /* try cached display */
80 if (dpy
== prevDisplay
) {
84 /* search list of display/dispatch pairs for this display */
86 const struct display_dispatch
*d
= DispatchList
;
91 return d
->Table
; /* done! */
97 /* A new display, determine if we should use real GLX (SGI / Utah)
98 * or Mesa's pseudo-GLX.
101 struct _glxapi_table
*t
= NULL
;
103 #if defined(USE_SGI_GLX) || defined(USE_UTAH_GLX)
104 if (!getenv("MESA_FORCE_SOFTX")) {
106 if (XQueryExtension( dpy
, "GLX", &ignore
, &ignore
, &ignore
)) {
107 /* the X server has the GLX extension */
108 #if defined(USE_SGI_GLX)
109 t
= _sgi_GetGLXDispatchtable();
110 #elif defined(USE_UTAH_GLX)
111 t
= _utah_GetGLXDispatchTable();
117 #if defined(USE_MESA_GLX)
119 t
= _mesa_GetGLXDispatchTable();
120 assert(t
); /* this has to work */
125 struct display_dispatch
*d
;
126 d
= (struct display_dispatch
*) malloc(sizeof(struct display_dispatch
));
130 /* insert at head of list */
131 d
->Next
= DispatchList
;
141 /* If we get here that means we can't use real GLX on this display
142 * and the Mesa pseudo-GLX software renderer wasn't compiled in.
143 * Or, we ran out of memory!
150 /* Set by glXMakeCurrent() and glXMakeContextCurrent() only */
151 static Display
*CurrentDisplay
= NULL
;
152 static GLXContext CurrentContext
= 0;
153 static GLXDrawable CurrentDrawable
= 0;
154 static GLXDrawable CurrentReadDrawable
= 0;
159 * GLX API entrypoints
163 XVisualInfo
*glXChooseVisual(Display
*dpy
, int screen
, int *list
)
165 struct _glxapi_table
*t
= get_dispatch(dpy
);
168 return (t
->ChooseVisual
)(dpy
, screen
, list
);
172 void glXCopyContext(Display
*dpy
, GLXContext src
, GLXContext dst
, unsigned long mask
)
174 struct _glxapi_table
*t
= get_dispatch(dpy
);
177 (t
->CopyContext
)(dpy
, src
, dst
, mask
);
181 GLXContext
glXCreateContext(Display
*dpy
, XVisualInfo
*visinfo
, GLXContext shareList
, Bool direct
)
183 struct _glxapi_table
*t
= get_dispatch(dpy
);
186 return (t
->CreateContext
)(dpy
, visinfo
, shareList
, direct
);
190 GLXPixmap
glXCreateGLXPixmap(Display
*dpy
, XVisualInfo
*visinfo
, Pixmap pixmap
)
192 struct _glxapi_table
*t
= get_dispatch(dpy
);
195 return (t
->CreateGLXPixmap
)(dpy
, visinfo
, pixmap
);
199 void glXDestroyContext(Display
*dpy
, GLXContext ctx
)
201 struct _glxapi_table
*t
= get_dispatch(dpy
);
204 (t
->DestroyContext
)(dpy
, ctx
);
208 void glXDestroyGLXPixmap(Display
*dpy
, GLXPixmap pixmap
)
210 struct _glxapi_table
*t
= get_dispatch(dpy
);
213 (t
->DestroyGLXPixmap
)(dpy
, pixmap
);
217 int glXGetConfig(Display
*dpy
, XVisualInfo
*visinfo
, int attrib
, int *value
)
219 struct _glxapi_table
*t
= get_dispatch(dpy
);
221 return GLX_NO_EXTENSION
;
222 return (t
->GetConfig
)(dpy
, visinfo
, attrib
, value
);
226 GLXContext
glXGetCurrentContext(void)
228 return CurrentContext
;
232 GLXDrawable
glXGetCurrentDrawable(void)
234 return CurrentDrawable
;
238 Bool
glXIsDirect(Display
*dpy
, GLXContext ctx
)
240 struct _glxapi_table
*t
= get_dispatch(dpy
);
243 return (t
->IsDirect
)(dpy
, ctx
);
247 Bool
glXMakeCurrent(Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
250 struct _glxapi_table
*t
= get_dispatch(dpy
);
253 b
= (*t
->MakeCurrent
)(dpy
, drawable
, ctx
);
255 CurrentDisplay
= dpy
;
256 CurrentContext
= ctx
;
257 CurrentDrawable
= drawable
;
258 CurrentReadDrawable
= drawable
;
264 Bool
glXQueryExtension(Display
*dpy
, int *errorb
, int *event
)
266 struct _glxapi_table
*t
= get_dispatch(dpy
);
269 return (t
->QueryExtension
)(dpy
, errorb
, event
);
273 Bool
glXQueryVersion(Display
*dpy
, int *maj
, int *min
)
275 struct _glxapi_table
*t
= get_dispatch(dpy
);
278 return (t
->QueryVersion
)(dpy
, maj
, min
);
282 void glXSwapBuffers(Display
*dpy
, GLXDrawable drawable
)
284 struct _glxapi_table
*t
= get_dispatch(dpy
);
287 (t
->SwapBuffers
)(dpy
, drawable
);
291 void glXUseXFont(Font font
, int first
, int count
, int listBase
)
293 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
296 (t
->UseXFont
)(font
, first
, count
, listBase
);
302 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
311 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
319 #ifdef GLX_VERSION_1_1
321 const char *glXGetClientString(Display
*dpy
, int name
)
323 struct _glxapi_table
*t
= get_dispatch(dpy
);
326 return (t
->GetClientString
)(dpy
, name
);
330 const char *glXQueryExtensionsString(Display
*dpy
, int screen
)
332 struct _glxapi_table
*t
= get_dispatch(dpy
);
335 return (t
->QueryExtensionsString
)(dpy
, screen
);
339 const char *glXQueryServerString(Display
*dpy
, int screen
, int name
)
341 struct _glxapi_table
*t
= get_dispatch(dpy
);
344 return (t
->QueryServerString
)(dpy
, screen
, name
);
351 #ifdef GLX_VERSION_1_2
352 Display
*glXGetCurrentDisplay(void)
354 return CurrentDisplay
;
360 #ifdef GLX_VERSION_1_3
362 GLXFBConfig
*glXChooseFBConfig(Display
*dpy
, int screen
, const int *attribList
, int *nitems
)
364 struct _glxapi_table
*t
= get_dispatch(dpy
);
367 return (t
->ChooseFBConfig
)(dpy
, screen
, attribList
, nitems
);
371 GLXContext
glXCreateNewContext(Display
*dpy
, GLXFBConfig config
, int renderType
, GLXContext shareList
, Bool direct
)
373 struct _glxapi_table
*t
= get_dispatch(dpy
);
376 return (t
->CreateNewContext
)(dpy
, config
, renderType
, shareList
, direct
);
380 GLXPbuffer
glXCreatePbuffer(Display
*dpy
, GLXFBConfig config
, const int *attribList
)
382 struct _glxapi_table
*t
= get_dispatch(dpy
);
385 return (t
->CreatePbuffer
)(dpy
, config
, attribList
);
389 GLXPixmap
glXCreatePixmap(Display
*dpy
, GLXFBConfig config
, Pixmap pixmap
, const int *attribList
)
391 struct _glxapi_table
*t
= get_dispatch(dpy
);
394 return (t
->CreatePixmap
)(dpy
, config
, pixmap
, attribList
);
398 GLXWindow
glXCreateWindow(Display
*dpy
, GLXFBConfig config
, Window win
, const int *attribList
)
400 struct _glxapi_table
*t
= get_dispatch(dpy
);
403 return (t
->CreateWindow
)(dpy
, config
, win
, attribList
);
407 void glXDestroyPbuffer(Display
*dpy
, GLXPbuffer pbuf
)
409 struct _glxapi_table
*t
= get_dispatch(dpy
);
412 (t
->DestroyPbuffer
)(dpy
, pbuf
);
416 void glXDestroyPixmap(Display
*dpy
, GLXPixmap pixmap
)
418 struct _glxapi_table
*t
= get_dispatch(dpy
);
421 (t
->DestroyPixmap
)(dpy
, pixmap
);
425 void glXDestroyWindow(Display
*dpy
, GLXWindow window
)
427 struct _glxapi_table
*t
= get_dispatch(dpy
);
430 (t
->DestroyWindow
)(dpy
, window
);
434 GLXDrawable
glXGetCurrentReadDrawable(void)
436 return CurrentReadDrawable
;
440 int glXGetFBConfigAttrib(Display
*dpy
, GLXFBConfig config
, int attribute
, int *value
)
442 struct _glxapi_table
*t
= get_dispatch(dpy
);
444 return GLX_NO_EXTENSION
;
445 return (t
->GetFBConfigAttrib
)(dpy
, config
, attribute
, value
);
449 GLXFBConfig
*glXGetFBConfigs(Display
*dpy
, int screen
, int *nelements
)
451 struct _glxapi_table
*t
= get_dispatch(dpy
);
454 return (t
->GetFBConfigs
)(dpy
, screen
, nelements
);
457 void glXGetSelectedEvent(Display
*dpy
, GLXDrawable drawable
, unsigned long *mask
)
459 struct _glxapi_table
*t
= get_dispatch(dpy
);
462 (t
->GetSelectedEvent
)(dpy
, drawable
, mask
);
466 XVisualInfo
*glXGetVisualFromFBConfig(Display
*dpy
, GLXFBConfig config
)
468 struct _glxapi_table
*t
= get_dispatch(dpy
);
471 return (t
->GetVisualFromFBConfig
)(dpy
, config
);
475 Bool
glXMakeContextCurrent(Display
*dpy
, GLXDrawable draw
, GLXDrawable read
, GLXContext ctx
)
477 struct _glxapi_table
*t
= get_dispatch(dpy
);
481 b
= (t
->MakeContextCurrent
)(dpy
, draw
, read
, ctx
);
483 CurrentDisplay
= dpy
;
484 CurrentContext
= ctx
;
485 CurrentDrawable
= draw
;
486 CurrentReadDrawable
= read
;
492 int glXQueryContext(Display
*dpy
, GLXContext ctx
, int attribute
, int *value
)
494 struct _glxapi_table
*t
= get_dispatch(dpy
);
497 return 0; /* XXX correct? */
498 return (t
->QueryContext
)(dpy
, ctx
, attribute
, value
);
502 void glXQueryDrawable(Display
*dpy
, GLXDrawable draw
, int attribute
, unsigned int *value
)
504 struct _glxapi_table
*t
= get_dispatch(dpy
);
507 (t
->QueryDrawable
)(dpy
, draw
, attribute
, value
);
511 void glXSelectEvent(Display
*dpy
, GLXDrawable drawable
, unsigned long mask
)
513 struct _glxapi_table
*t
= get_dispatch(dpy
);
516 (t
->SelectEvent
)(dpy
, drawable
, mask
);
519 #endif /* GLX_VERSION_1_3 */
522 #ifdef GLX_EXT_import_context
524 void glXFreeContextEXT(Display
*dpy
, GLXContext context
)
526 struct _glxapi_table
*t
= get_dispatch(dpy
);
529 (t
->FreeContextEXT
)(dpy
, context
);
533 GLXContextID
glXGetContextIDEXT(const GLXContext context
)
535 /* XXX is this function right? */
536 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
539 return (t
->GetContextIDEXT
)(context
);
543 Display
*glXGetCurrentDisplayEXT(void)
545 return CurrentDisplay
;
549 GLXContext
glXImportContextEXT(Display
*dpy
, GLXContextID contextID
)
551 struct _glxapi_table
*t
= get_dispatch(dpy
);
554 return (t
->ImportContextEXT
)(dpy
, contextID
);
557 int glXQueryContextInfoEXT(Display
*dpy
, GLXContext context
, int attribute
,int *value
)
559 struct _glxapi_table
*t
= get_dispatch(dpy
);
561 return 0; /* XXX ok? */
562 return (t
->QueryContextInfoEXT
)(dpy
, context
, attribute
, value
);
568 #ifdef GLX_SGI_video_sync
570 int glXGetVideoSyncSGI(unsigned int *count
)
572 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
575 return (t
->GetVideoSyncSGI
)(count
);
579 int glXWaitVideoSyncSGI(int divisor
, int remainder
, unsigned int *count
)
581 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
584 return (t
->WaitVideoSyncSGI
)(divisor
, remainder
, count
);
590 #ifdef GLX_MESA_copy_sub_buffer
592 void glXCopySubBufferMESA(Display
*dpy
, GLXDrawable drawable
, int x
, int y
, int width
, int height
)
594 struct _glxapi_table
*t
= get_dispatch(dpy
);
597 (t
->CopySubBufferMESA
)(dpy
, drawable
, x
, y
, width
, height
);
603 #ifdef GLX_MESA_release_buffers
605 Bool
glXReleaseBuffersMESA(Display
*dpy
, Window w
)
607 struct _glxapi_table
*t
= get_dispatch(dpy
);
610 return (t
->ReleaseBuffersMESA
)(dpy
, w
);
616 #ifdef GLX_MESA_pixmap_colormap
618 GLXPixmap
glXCreateGLXPixmapMESA(Display
*dpy
, XVisualInfo
*visinfo
, Pixmap pixmap
, Colormap cmap
)
620 struct _glxapi_table
*t
= get_dispatch(dpy
);
623 return (t
->CreateGLXPixmapMESA
)(dpy
, visinfo
, pixmap
, cmap
);
629 #ifdef GLX_MESA_set_3dfx_mode
631 GLboolean
glXSet3DfxModeMESA(GLint mode
)
633 struct _glxapi_table
*t
= get_dispatch(CurrentDisplay
);
636 return (t
->Set3DfxModeMESA
)(mode
);
643 /**********************************************************************/
644 /* GLX API management functions */
645 /**********************************************************************/
649 _glxapi_get_version(void)
656 * Return array of extension strings.
659 _glxapi_get_extensions(void)
661 static const char *extensions
[] = {
662 #ifdef GLX_EXT_import_context
663 "GLX_EXT_import_context",
665 #ifdef GLX_SGI_video_sync
666 "GLX_SGI_video_sync",
668 #ifdef GLX_MESA_copy_sub_buffer
669 "GLX_MESA_copy_sub_buffer",
671 #ifdef GLX_MESA_release_buffers
672 "GLX_MESA_release_buffers",
674 #ifdef GLX_MESA_pixmap_colormap
675 "GLX_MESA_pixmap_colormap",
677 #ifdef GLX_MESA_set_3dfx_mode
678 "GLX_MESA_set_3dfx_mode",
687 * Return size of the GLX dispatch table, in entries, not bytes.
690 _glxapi_get_dispatch_table_size(void)
692 return sizeof(struct _glxapi_table
) / sizeof(void *);
697 generic_no_op_func(void)
704 * Initialize all functions in given dispatch table to be no-ops
707 _glxapi_set_no_op_table(struct _glxapi_table
*t
)
709 GLuint n
= _glxapi_get_dispatch_table_size();
711 void **dispatch
= (void **) t
;
712 for (i
= 0; i
< n
; i
++) {
713 dispatch
[i
] = (void *) generic_no_op_func
;
719 struct name_address_pair
{
724 static struct name_address_pair GLX_functions
[] = {
725 { "glXChooseVisual", (GLvoid
*) glXChooseVisual
},
726 { "glXCopyContext", (GLvoid
*) glXCopyContext
},
727 { "glXCreateContext", (GLvoid
*) glXCreateContext
},
728 { "glXCreateGLXPixmap", (GLvoid
*) glXCreateGLXPixmap
},
729 { "glXDestroyContext", (GLvoid
*) glXDestroyContext
},
730 { "glXDestroyGLXPixmap", (GLvoid
*) glXDestroyGLXPixmap
},
731 { "glXGetConfig", (GLvoid
*) glXGetConfig
},
732 { "glXGetCurrentContext", (GLvoid
*) glXGetCurrentContext
},
733 { "glXGetCurrentDrawable", (GLvoid
*) glXGetCurrentDrawable
},
734 { "glXIsDirect", (GLvoid
*) glXIsDirect
},
735 { "glXMakeCurrent", (GLvoid
*) glXMakeCurrent
},
736 { "glXQueryExtension", (GLvoid
*) glXQueryExtension
},
737 { "glXQueryVersion", (GLvoid
*) glXQueryVersion
},
738 { "glXSwapBuffers", (GLvoid
*) glXSwapBuffers
},
739 { "glXUseXFont", (GLvoid
*) glXUseXFont
},
740 { "glXWaitGL", (GLvoid
*) glXWaitGL
},
741 { "glXWaitX", (GLvoid
*) glXWaitX
},
743 #ifdef GLX_VERSION_1_1
744 { "glXGetClientString", (GLvoid
*) glXGetClientString
},
745 { "glXQueryExtensionsString", (GLvoid
*) glXQueryExtensionsString
},
746 { "glXQueryServerString", (GLvoid
*) glXQueryServerString
},
749 #ifdef GLX_VERSION_1_2
750 { "glXGetCurrentDisplay", (GLvoid
*) glXGetCurrentDisplay
},
753 #ifdef GLX_VERSION_1_3
754 { "glXChooseFBConfig", (GLvoid
*) glXChooseFBConfig
},
755 { "glXCreateNewContext", (GLvoid
*) glXCreateNewContext
},
756 { "glXCreatePbuffer", (GLvoid
*) glXCreatePbuffer
},
757 { "glXCreatePixmap", (GLvoid
*) glXCreatePixmap
},
758 { "glXCreateWindow", (GLvoid
*) glXCreateWindow
},
759 { "glXDestroyPbuffer", (GLvoid
*) glXDestroyPbuffer
},
760 { "glXDestroyPixmap", (GLvoid
*) glXDestroyPixmap
},
761 { "glXDestroyWindow", (GLvoid
*) glXDestroyWindow
},
762 { "glXGetCurrentReadDrawable", (GLvoid
*) glXGetCurrentReadDrawable
},
763 { "glXGetFBConfigAttrib", (GLvoid
*) glXGetFBConfigAttrib
},
764 { "glXGetSelectedEvent", (GLvoid
*) glXGetSelectedEvent
},
765 { "glXGetVisualFromFBConfig", (GLvoid
*) glXGetVisualFromFBConfig
},
766 { "glXMakeContextCurrent", (GLvoid
*) glXMakeContextCurrent
},
767 { "glXQueryContext", (GLvoid
*) glXQueryContext
},
768 { "glXQueryDrawable", (GLvoid
*) glXQueryDrawable
},
769 { "glXSelectEvent", (GLvoid
*) glXSelectEvent
},
772 #ifdef GLX_SGI_video_sync
773 { "glXGetVideoSyncSGI", (GLvoid
*) glXGetVideoSyncSGI
},
774 { "glXWaitVideoSyncSGI", (GLvoid
*) glXWaitVideoSyncSGI
},
777 #ifdef GLX_MESA_copy_sub_buffer
778 { "glXCopySubBufferMESA", (GLvoid
*) glXCopySubBufferMESA
},
781 #ifdef GLX_MESA_release_buffers
782 { "glXReleaseBuffersMESA", (GLvoid
*) glXReleaseBuffersMESA
},
785 #ifdef GLX_MESA_pixmap_colormap
786 { "glXCreateGLXPixmapMESA", (GLvoid
*) glXCreateGLXPixmapMESA
},
789 #ifdef GLX_MESA_set_3dfx_mode
790 { "glXSet3DfxModeMESA", (GLvoid
*) glXSet3DfxModeMESA
},
793 { "glXGetProcAddressARB", (GLvoid
*) glXGetProcAddressARB
},
795 { NULL
, NULL
} /* end of list */
801 * Return address of named glX function, or NULL if not found.
804 _glxapi_get_proc_address(const char *funcName
)
807 for (i
= 0; GLX_functions
[i
].Name
; i
++) {
808 if (strcmp(GLX_functions
[i
].Name
, funcName
) == 0)
809 return GLX_functions
[i
].Address
;
817 * This function does not get dispatched through the dispatch table
818 * since it's really a "meta" function.
820 void (*glXGetProcAddressARB(const GLubyte
*procName
))()
822 typedef void (*gl_function
)();
825 f
= (gl_function
) _glxapi_get_proc_address((const char *) procName
);
830 f
= (gl_function
) _glapi_get_proc_address((const char *) procName
);