diff --git a/configure.ac b/configure.ac index 27da19158800a112f8d6a92cce941aad52dfae48..9faf56f5ef60d4b0e842a4f78f338ee50af348f6 100644 --- a/configure.ac +++ b/configure.ac @@ -239,6 +239,7 @@ AC_CONFIG_FILES([Makefile src/GLdispatch/Makefile src/GLdispatch/vnd-glapi/Makefile src/util/Makefile + src/vendor/Makefile tests/Makefile tests/GLX_dummy/Makefile]) AC_OUTPUT diff --git a/src/GLX/Makefile.am b/src/GLX/Makefile.am index fa1f6241b4f31b02a667925266481d5bf73275a8..0f9fca1223e7476e992de5442a1481a320287916 100644 --- a/src/GLX/Makefile.am +++ b/src/GLX/Makefile.am @@ -34,17 +34,21 @@ noinst_HEADERS = \ libglxthread.h \ libglxproto.h +EXTRA_DIST = libglx_function_list.py + lib_LTLIBRARIES = libGLX.la UTIL_DIR = ../util UTHASH_DIR = ../util/uthash/src GL_DISPATCH_DIR = ../GLdispatch +VENDOR_DIR = ../vendor # Warning settings # Include paths libGLX_la_CFLAGS = -I$(srcdir)/$(UTHASH_DIR) libGLX_la_CFLAGS += -I$(srcdir)/$(UTIL_DIR) libGLX_la_CFLAGS += -I$(srcdir)/$(GL_DISPATCH_DIR) +libGLX_la_CFLAGS += -I$(srcdir)/$(VENDOR_DIR) libGLX_la_CFLAGS += -I$(top_srcdir)/include libGLX_la_CFLAGS += $(GLPROTO_CFLAGS) @@ -62,6 +66,7 @@ libGLX_la_LIBADD += $(UTIL_DIR)/libglvnd_genentry.la libGLX_la_LIBADD += $(UTIL_DIR)/libutils_misc.la libGLX_la_LIBADD += $(UTIL_DIR)/libapp_error_check.la libGLX_la_LIBADD += $(UTIL_DIR)/libwinsys_dispatch.la +libGLX_la_LIBADD += $(VENDOR_DIR)/libglxdispatchstubs.la libGLX_la_LDFLAGS = -shared -Wl,-Bsymbolic -version-info 0 $(LINKER_FLAG_NO_UNDEFINED) diff --git a/src/GLX/libglx.c b/src/GLX/libglx.c index d6281fac51aff4a7d71f6ccd0dfb115df9f95567..6ff7fabfb121a215de9840efd1e51d71af689439 100644 --- a/src/GLX/libglx.c +++ b/src/GLX/libglx.c @@ -47,6 +47,8 @@ #include "glvnd_list.h" #include "app_error_check.h" +#include "glxdispatchstubs.h" + #include "lkdhash.h" /* current version numbers */ @@ -132,45 +134,6 @@ static void FreeContextInfo(__GLXcontextInfo *ctx); */ static void CheckContextDeleted(__GLXcontextInfo *ctx); -static void __glXSendError(Display *dpy, unsigned char errorCode, - XID resourceID, unsigned char minorCode, Bool coreX11error); - -/*! - * A common helper for GLX functions that dispatch based on a drawable. - * - * This function will call __glXThreadInitialize and then look up the vendor - * for a drawable. - * - * If it can't find a vendor for the drawable, then it will call __glXSendError - * to generate an error. - * - * Note that if the server doesn't support the x11glvnd extension, then this - * will return the same vendor library whether or not the drawable is valid. - * In that case, we'll just rely on the vendor library to report the error if - * the drawable is not valid. - * - * \param dpy The display connection. - * \param draw The drawable XID. - * \param minorCode The minor opcode of the function being called. - * \param errorCode The error code to report if the drawable is invalid. - * \param coreX11error True if the error is a core X11 error code, or False if - * it's a GLX error code. - */ -static __GLXvendorInfo *CommonDispatchDrawable(Display *dpy, GLXDrawable draw, - unsigned char minorCode, unsigned char errorCode, Bool coreX11error) -{ - __GLXvendorInfo *vendor = NULL; - - if (draw != None) { - __glXThreadInitialize(); - vendor = __glXVendorFromDrawable(dpy, draw); - } - if (vendor == NULL) { - __glXSendError(dpy, errorCode, draw, minorCode, coreX11error); - } - return vendor; -} - static __GLXvendorInfo *CommonDispatchContext(Display *dpy, GLXContext context, unsigned char minorCode) { @@ -186,83 +149,6 @@ static __GLXvendorInfo *CommonDispatchContext(Display *dpy, GLXContext context, return vendor; } -static __GLXvendorInfo *CommonDispatchFBConfig(Display *dpy, GLXFBConfig config, - unsigned char minorCode) -{ - __GLXvendorInfo *vendor = NULL; - - if (config != NULL) { - __glXThreadInitialize(); - vendor = __glXVendorFromFBConfig(dpy, config); - } - if (vendor == NULL) { - __glXSendError(dpy, GLXBadFBConfig, 0, minorCode, False); - } - return vendor; -} - -PUBLIC XVisualInfo* glXChooseVisual(Display *dpy, int screen, int *attrib_list) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, screen); - if (vendor != NULL) { - return vendor->staticDispatch.chooseVisual(dpy, screen, attrib_list); - } else { - return NULL; - } -} - - -PUBLIC void glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, - unsigned long mask) -{ - /* - * GLX requires that src and dst are on the same X screen, but the - * application may have passed invalid input. Pick the screen - * from one of the contexts, and then let that vendor's - * implementation validate that both contexts are on the same - * screen. - */ - __GLXvendorInfo *vendor = CommonDispatchContext(dpy, src, X_GLXCopyContext); - if (vendor != NULL) { - vendor->staticDispatch.copyContext(dpy, src, dst, mask); - } -} - - -PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, - GLXContext share_list, Bool direct) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, vis->screen); - if (vendor != NULL) { - GLXContext context = vendor->staticDispatch.createContext(dpy, vis, share_list, direct); - if (__glXAddVendorContextMapping(dpy, context, vendor) != 0) { - vendor->staticDispatch.destroyContext(dpy, context); - context = NULL; - } - return context; - } else { - return NULL; - } -} - - -PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, - int render_type, GLXContext share_list, - Bool direct) -{ - GLXContext context = NULL; - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreateNewContext); - if (vendor != NULL) { - context = vendor->staticDispatch.createNewContext(dpy, config, render_type, - share_list, direct); - if (__glXAddVendorContextMapping(dpy, context, vendor) != 0) { - vendor->staticDispatch.destroyContext(dpy, context); - context = NULL; - } - } - return context; -} - PUBLIC void glXDestroyContext(Display *dpy, GLXContext context) { __GLXvendorInfo *vendor; @@ -381,7 +267,7 @@ static int __glXGetScreenForContextID(Display *dpy, __GLXdisplayInfo *dpyInfo, return screen; } -static GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID) +GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID) { __GLXdisplayInfo *dpyInfo; int screen; @@ -433,7 +319,7 @@ static GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID) } } -static void glXFreeContextEXT(Display *dpy, GLXContext context) +void glXFreeContextEXT(Display *dpy, GLXContext context) { __GLXvendorInfo *vendor = NULL; @@ -446,52 +332,6 @@ static void glXFreeContextEXT(Display *dpy, GLXContext context) } } - -PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis, Pixmap pixmap) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, vis->screen); - if (vendor != NULL) { - GLXPixmap pmap = vendor->staticDispatch.createGLXPixmap(dpy, vis, pixmap); - if (__glXAddVendorDrawableMapping(dpy, pmap, vendor) != 0) { - vendor->staticDispatch.destroyGLXPixmap(dpy, pmap); - pmap = None; - } - return pmap; - } else { - return None; - } -} - - -PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pix) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, pix, - X_GLXDestroyGLXPixmap, GLXBadPixmap, False); - if (vendor != NULL) { - __glXRemoveVendorDrawableMapping(dpy, pix); - vendor->staticDispatch.destroyGLXPixmap(dpy, pix); - } -} - - -PUBLIC int glXGetConfig(Display *dpy, XVisualInfo *vis, int attrib, int *value) -{ - __GLXvendorInfo *vendor; - - __glXThreadInitialize(); - - if (!dpy || !vis || !value) { - return GLX_BAD_VALUE; - } - - vendor = __glXLookupVendorByScreen(dpy, vis->screen); - if (vendor != NULL) { - return vendor->staticDispatch.getConfig(dpy, vis, attrib, value); - } else { - return GLX_BAD_VALUE; - } -} - PUBLIC GLXContext glXGetCurrentContext(void) { __glXThreadInitialize(); @@ -558,16 +398,6 @@ __GLXvendorInfo *__glXGetCurrentDynDispatch(void) } } -PUBLIC Bool glXIsDirect(Display *dpy, GLXContext context) -{ - __GLXvendorInfo *vendor = CommonDispatchContext(dpy, context, X_GLXIsDirect); - if (vendor != NULL) { - return vendor->staticDispatch.isDirect(dpy, context); - } else { - return False; - } -} - void __glXDisplayClosed(__GLXdisplayInfo *dpyInfo) { __GLXThreadState *threadState; @@ -727,7 +557,7 @@ static void CheckContextDeleted(__GLXcontextInfo *ctx) } } -static void __glXSendError(Display *dpy, unsigned char errorCode, +void __glXSendError(Display *dpy, unsigned char errorCode, XID resourceID, unsigned char minorCode, Bool coreX11error) { __GLXdisplayInfo *dpyInfo = NULL; @@ -1144,43 +974,6 @@ PUBLIC Bool glXQueryVersion(Display *dpy, int *major, int *minor) return True; } - -PUBLIC void glXSwapBuffers(Display *dpy, GLXDrawable drawable) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, drawable, - X_GLXSwapBuffers, GLXBadDrawable, False); - if (vendor != NULL) { - vendor->staticDispatch.swapBuffers(dpy, drawable); - } -} - - -PUBLIC void glXUseXFont(Font font, int first, int count, int list_base) -{ - __GLXvendorInfo *vendor = __glXGetCurrentDynDispatch(); - if (vendor != NULL) { - vendor->staticDispatch.useXFont(font, first, count, list_base); - } -} - - -PUBLIC void glXWaitGL(void) -{ - __GLXvendorInfo *vendor = __glXGetCurrentDynDispatch(); - if (vendor != NULL) { - vendor->staticDispatch.waitGL(); - } -} - - -PUBLIC void glXWaitX(void) -{ - __GLXvendorInfo *vendor = __glXGetCurrentDynDispatch(); - if (vendor != NULL) { - vendor->staticDispatch.waitX(); - } -} - /** * Queries a client string for each screen in a display. * @@ -1434,281 +1227,6 @@ done: return dpyInfo->clientStrings[index]; } -PUBLIC const char *glXQueryServerString(Display *dpy, int screen, int name) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, screen); - if (vendor != NULL) { - return vendor->staticDispatch.queryServerString(dpy, screen, name); - } else { - return NULL; - } -} - - -PUBLIC const char *glXQueryExtensionsString(Display *dpy, int screen) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, screen); - if (vendor != NULL) { - return vendor->staticDispatch.queryExtensionsString(dpy, screen); - } else { - return NULL; - } -} - -PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, - const int *attrib_list, int *nelements) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, screen); - if (vendor != NULL) { - GLXFBConfig *fbconfigs = - vendor->staticDispatch.chooseFBConfig(dpy, screen, attrib_list, nelements); - - if (fbconfigs != NULL) { - int i; - Bool success = True; - for (i = 0; i < *nelements; i++) { - if (__glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor) != 0) { - success = False; - break; - } - } - if (!success) { - XFree(fbconfigs); - fbconfigs = NULL; - *nelements = 0; - } - } - return fbconfigs; - } else { - return NULL; - } -} - - -PUBLIC GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, - const int *attrib_list) -{ - GLXPbuffer pbuffer = None; - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreatePbuffer); - if (vendor != NULL) { - pbuffer = vendor->staticDispatch.createPbuffer(dpy, config, attrib_list); - if (__glXAddVendorDrawableMapping(dpy, pbuffer, vendor) != 0) { - vendor->staticDispatch.destroyPbuffer(dpy, pbuffer); - pbuffer = None; - } - } - return pbuffer; -} - - -PUBLIC GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config, - Pixmap pixmap, const int *attrib_list) -{ - GLXPixmap glxPixmap = None; - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreatePixmap); - if (vendor != NULL) { - glxPixmap = vendor->staticDispatch.createPixmap(dpy, config, pixmap, attrib_list); - if (__glXAddVendorDrawableMapping(dpy, glxPixmap, vendor) != 0) { - vendor->staticDispatch.destroyGLXPixmap(dpy, glxPixmap); - glxPixmap = None; - } - } - return glxPixmap; -} - - -PUBLIC GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, - Window win, const int *attrib_list) -{ - GLXWindow glxWindow = None; - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreateWindow); - if (vendor != NULL) { - glxWindow = vendor->staticDispatch.createWindow(dpy, config, win, attrib_list); - if (__glXAddVendorDrawableMapping(dpy, glxWindow, vendor) != 0) { - vendor->staticDispatch.destroyWindow(dpy, glxWindow); - glxWindow = None; - } - } - return glxWindow; -} - - -PUBLIC void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, pbuf, - X_GLXDestroyPbuffer, GLXBadPbuffer, False); - if (vendor != NULL) { - __glXRemoveVendorDrawableMapping(dpy, pbuf); - vendor->staticDispatch.destroyPbuffer(dpy, pbuf); - } -} - - -PUBLIC void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, pixmap, - X_GLXDestroyPixmap, GLXBadPixmap, False); - if (vendor != NULL) { - __glXRemoveVendorDrawableMapping(dpy, pixmap); - vendor->staticDispatch.destroyPixmap(dpy, pixmap); - } -} - - -PUBLIC void glXDestroyWindow(Display *dpy, GLXWindow win) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, win, - X_GLXDestroyWindow, GLXBadWindow, False); - if (vendor != NULL) { - __glXRemoveVendorDrawableMapping(dpy, win); - vendor->staticDispatch.destroyWindow(dpy, win); - } -} - -PUBLIC int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, - int attribute, int *value) -{ - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXGetFBConfigs); - if (vendor != NULL) { - return vendor->staticDispatch.getFBConfigAttrib(dpy, config, attribute, value); - } else { - return GLX_BAD_VISUAL; - } -} - - -PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements) -{ - __GLXvendorInfo *vendor = __glXGetDynDispatch(dpy, screen); - if (vendor != NULL) { - GLXFBConfig *fbconfigs = vendor->staticDispatch.getFBConfigs(dpy, screen, nelements); - if (fbconfigs != NULL) { - int i; - Bool success = True; - for (i = 0; i < *nelements; i++) { - if (__glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor) != 0) { - success = False; - break; - } - } - if (!success) { - XFree(fbconfigs); - fbconfigs = NULL; - *nelements = 0; - } - } - return fbconfigs; - } else { - return NULL; - } -} - - -PUBLIC void glXGetSelectedEvent(Display *dpy, GLXDrawable draw, - unsigned long *event_mask) -{ - // glXGetSelectedEvent uses the glXGetDrawableAttributes protocol. - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, draw, - X_GLXGetDrawableAttributes, GLXBadDrawable, False); - if (vendor != NULL) { - vendor->staticDispatch.getSelectedEvent(dpy, draw, event_mask); - } -} - - -PUBLIC XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) -{ - __GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXGetFBConfigs); - if (vendor != NULL) { - return vendor->staticDispatch.getVisualFromFBConfig(dpy, config); - } else { - return NULL; - } -} - - -PUBLIC int glXQueryContext(Display *dpy, GLXContext context, int attribute, int *value) -{ - __GLXvendorInfo *vendor = CommonDispatchContext(dpy, context, X_GLXQueryContext); - if (vendor != NULL) { - return vendor->staticDispatch.queryContext(dpy, context, attribute, value); - } else { - return GLX_BAD_CONTEXT; - } -} - - -PUBLIC void glXQueryDrawable(Display *dpy, GLXDrawable draw, - int attribute, unsigned int *value) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, draw, - X_GLXGetDrawableAttributes, GLXBadDrawable, False); - if (vendor != NULL) { - vendor->staticDispatch.queryDrawable(dpy, draw, attribute, value); - } -} - - -PUBLIC void glXSelectEvent(Display *dpy, GLXDrawable draw, unsigned long event_mask) -{ - __GLXvendorInfo *vendor = CommonDispatchDrawable(dpy, draw, - X_GLXChangeDrawableAttributes, GLXBadDrawable, False); - if (vendor != NULL) { - vendor->staticDispatch.selectEvent(dpy, draw, event_mask); - } -} - -const __GLXlocalDispatchFunction LOCAL_GLX_DISPATCH_FUNCTIONS[] = -{ -#define LOCAL_FUNC_TABLE_ENTRY(func) \ - { #func, (__GLXextFuncPtr)(func) }, - LOCAL_FUNC_TABLE_ENTRY(glXChooseFBConfig) - LOCAL_FUNC_TABLE_ENTRY(glXChooseVisual) - LOCAL_FUNC_TABLE_ENTRY(glXCopyContext) - LOCAL_FUNC_TABLE_ENTRY(glXCreateContext) - LOCAL_FUNC_TABLE_ENTRY(glXCreateGLXPixmap) - LOCAL_FUNC_TABLE_ENTRY(glXCreateNewContext) - LOCAL_FUNC_TABLE_ENTRY(glXCreatePbuffer) - LOCAL_FUNC_TABLE_ENTRY(glXCreatePixmap) - LOCAL_FUNC_TABLE_ENTRY(glXCreateWindow) - LOCAL_FUNC_TABLE_ENTRY(glXDestroyContext) - LOCAL_FUNC_TABLE_ENTRY(glXDestroyGLXPixmap) - LOCAL_FUNC_TABLE_ENTRY(glXDestroyPbuffer) - LOCAL_FUNC_TABLE_ENTRY(glXDestroyPixmap) - LOCAL_FUNC_TABLE_ENTRY(glXDestroyWindow) - LOCAL_FUNC_TABLE_ENTRY(glXGetClientString) - LOCAL_FUNC_TABLE_ENTRY(glXGetConfig) - LOCAL_FUNC_TABLE_ENTRY(glXGetCurrentContext) - LOCAL_FUNC_TABLE_ENTRY(glXGetCurrentDisplay) - LOCAL_FUNC_TABLE_ENTRY(glXGetCurrentDrawable) - LOCAL_FUNC_TABLE_ENTRY(glXGetCurrentReadDrawable) - LOCAL_FUNC_TABLE_ENTRY(glXGetFBConfigAttrib) - LOCAL_FUNC_TABLE_ENTRY(glXGetFBConfigs) - LOCAL_FUNC_TABLE_ENTRY(glXGetProcAddress) - LOCAL_FUNC_TABLE_ENTRY(glXGetProcAddressARB) - LOCAL_FUNC_TABLE_ENTRY(glXGetSelectedEvent) - LOCAL_FUNC_TABLE_ENTRY(glXGetVisualFromFBConfig) - LOCAL_FUNC_TABLE_ENTRY(glXIsDirect) - LOCAL_FUNC_TABLE_ENTRY(glXMakeContextCurrent) - LOCAL_FUNC_TABLE_ENTRY(glXMakeCurrent) - LOCAL_FUNC_TABLE_ENTRY(glXQueryContext) - LOCAL_FUNC_TABLE_ENTRY(glXQueryDrawable) - LOCAL_FUNC_TABLE_ENTRY(glXQueryExtension) - LOCAL_FUNC_TABLE_ENTRY(glXQueryExtensionsString) - LOCAL_FUNC_TABLE_ENTRY(glXQueryServerString) - LOCAL_FUNC_TABLE_ENTRY(glXQueryVersion) - LOCAL_FUNC_TABLE_ENTRY(glXSelectEvent) - LOCAL_FUNC_TABLE_ENTRY(glXSwapBuffers) - LOCAL_FUNC_TABLE_ENTRY(glXUseXFont) - LOCAL_FUNC_TABLE_ENTRY(glXWaitGL) - LOCAL_FUNC_TABLE_ENTRY(glXWaitX) - - LOCAL_FUNC_TABLE_ENTRY(glXImportContextEXT) - LOCAL_FUNC_TABLE_ENTRY(glXFreeContextEXT) -#undef LOCAL_FUNC_TABLE_ENTRY - { NULL, NULL } -}; - typedef struct { GLubyte *procName; __GLXextFuncPtr addr; diff --git a/src/GLX/libglx_function_list.py b/src/GLX/libglx_function_list.py new file mode 100644 index 0000000000000000000000000000000000000000..d28ce591454f7ddf8f734667cdce80901b85b329 --- /dev/null +++ b/src/GLX/libglx_function_list.py @@ -0,0 +1,189 @@ +#!/usr/bin/python + +# Copyright (c) 2016, NVIDIA CORPORATION. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and/or associated documentation files (the +# "Materials"), to deal in the Materials without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Materials, and to +# permit persons to whom the Materials are furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# unaltered in all copies or substantial portions of the Materials. +# Any additions, deletions, or changes to the original source files +# must be clearly indicated in accompanying documentation. +# +# If only executable code is distributed, then the accompanying +# documentation must state that "this software is based in part on the +# work of the Khronos Group." +# +# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +""" +The GLX function list, used by gen_glx_dispatch.py. + +GLX Function values: +- "method" + How to select a vendor library. See "Method values" below. + +- "add_mapping" + Specifies that the return value should be added to one of libGLX's + mappings. See "add_mapping values" below. + +- "remove_mapping" + Specifies that the return value should be removed to one of libGLX's + mappings. + + Allowed values are "context", "drawable", and "config". + +- "remove_key" + The parameter that contains the value to remove from libGLX's mapping. + If unspecified, the default is the same as the "key" field. + +- "prefix" + If True, the function should be exported from the library. This is used for + generating dispatch stubs for libGLX itself -- vendor libraries generally + should not use it. + +- "static" + If this is True, then the function will be declared static. + +- "public" + If True, the function should be exported from the library. Vendor libraries + generally should not use this. + +- "display" + The name of the parameter that contains the Display pointer. + May be "" to specify the current display. + If not specified, it will look for a parameter with the correct type. + +- "extension" + The name of an extension macro to check for before defining the function. + +- "inheader" + If True, then this function should be declared in the generated header + file. + +method values: +- "custom" + The dispatch stub will be hand-written instead of generated. + +- "none" + No dispatch function exists at all, but the function should still have an + entry in the index array. This is for other functions that a stub may need + to call that are implemented in libGLX itself. + +- "current" + Use the current context. + +- "drawable", "context", "config" + Look up by a GLXDrawable, GLXContext, or GLXFBConfig parameter. + The parameter is given by the "key" field. If unspecified, it will use the + first parameter of the correct type that it finds. + +- "screen" + Get a screen number from a parameter. + The parameter name is given by the "key" field. If unspecifid, the default + parameter name is "screen". + +- "xvisinfo" + Use an XVisualInfo pointer from a parameter. + The parameter name is given by the "key" field. If unspecifid, it will look + for the first XVisualInfo parameter. + +add_mapping values: +- "context", "drawable", "config" + Adds the returned GLXContext, GLXDrawable, or GLXConfig. + +- "config_list" + Adds an array of GLXFBConfig values. In this case, you also need to specify + a pointer to the item count in the "nelements" field. +""" + + +def _glxFunc(name, method, opcode=None, error=None, prefix="", + display=None, key=None, extension=None, retval=None, static=False, + public=True, inheader=None, add_mapping=None, nelements=None, + remove_mapping=None, remove_key=None): + + if (inheader == None): + # The public functions are already declared in glx.h. + inheader = (not public) + values = { + "method" : method, + "opcode" : opcode, + "error" : error, + "key" : key, + "prefix" : prefix, + "display" : display, + "extension" : extension, + "retval" : retval, + "static" : static, + "public" : public, + "inheader" : inheader, + "add_mapping" : add_mapping, + "nelements" : nelements, + "remove_mapping" : remove_mapping, + "remove_key" : remove_key, + } + return (name, values) + +# This list contains all of the GLX functions that are implemented in libGLX +# itself. In addition to generating some of the dispatch functions, this list +# is also used to populate the GLX dispatch index list. + +GLX_FUNCTIONS = ( + _glxFunc("glXChooseFBConfig", "screen", "X_GLXGetFBConfigs", add_mapping="config_list", nelements=3), + _glxFunc("glXCreateContext", "xvisinfo", "X_GLXCreateContext", add_mapping="context"), + _glxFunc("glXCreateGLXPixmap", "xvisinfo", "X_GLXCreateGLXPixmap", add_mapping="drawable"), + _glxFunc("glXCreateNewContext", "config", "X_GLXCreateNewContext", add_mapping="context"), + _glxFunc("glXCreatePbuffer", "config", "X_GLXCreatePbuffer", add_mapping="drawable"), + _glxFunc("glXCreatePixmap", "config", "X_GLXCreatePixmap", add_mapping="drawable"), + _glxFunc("glXCreateWindow", "config", "X_GLXCreateWindow", add_mapping="drawable"), + _glxFunc("glXDestroyGLXPixmap", "drawable", "X_GLXDestroyGLXPixmap", error="GLXBadPixmap", remove_mapping="drawable"), + _glxFunc("glXDestroyPbuffer", "drawable", "X_GLXDestroyPbuffer", error="GLXBadPbuffer", remove_mapping="drawable"), + _glxFunc("glXDestroyPixmap", "drawable", "X_GLXDestroyPixmap", error="GLXBadPixmap", remove_mapping="drawable"), + _glxFunc("glXDestroyWindow", "drawable", "X_GLXDestroyWindow", error="GLXBadWindow", remove_mapping="drawable"), + _glxFunc("glXGetConfig", "xvisinfo", "X_GLXGetFBConfigs"), + _glxFunc("glXChooseVisual", "screen", "X_GLXGetVisualConfigs"), + _glxFunc("glXCopyContext", "context", "X_GLXCopyContext"), + _glxFunc("glXGetFBConfigAttrib", "config", "X_GLXGetFBConfigs"), + _glxFunc("glXGetFBConfigs", "screen", "X_GLXGetFBConfigs", add_mapping="config_list", nelements=2), + _glxFunc("glXGetSelectedEvent", "drawable", "X_GLXGetDrawableAttributes", error="GLXBadDrawable"), + _glxFunc("glXGetVisualFromFBConfig", "config", "X_GLXGetFBConfigs"), + _glxFunc("glXIsDirect", "context", "X_GLXIsDirect"), + _glxFunc("glXQueryExtensionsString", "screen", "X_GLXQueryServerString"), + _glxFunc("glXQueryServerString", "screen", "X_GLXQueryServerString"), + _glxFunc("glXQueryContext", "context", "X_GLXQueryContext"), + _glxFunc("glXQueryDrawable", "drawable", "X_GLXGetDrawableAttributes", error="GLXBadDrawable"), + _glxFunc("glXSelectEvent", "drawable", "X_GLXChangeDrawableAttributes", error="GLXBadDrawable"), + _glxFunc("glXSwapBuffers", "drawable", "X_GLXSwapBuffers", error="GLXBadDrawable"), + _glxFunc("glXUseXFont", "current", "X_GLXUseXFont"), + _glxFunc("glXWaitGL", "current", "X_GLXWaitGL"), + _glxFunc("glXWaitX", "current", "X_GLXWaitX"), + + _glxFunc("glXDestroyContext", "custom"), + _glxFunc("glXGetClientString", "custom"), + _glxFunc("glXGetCurrentContext", "custom"), + _glxFunc("glXGetCurrentDisplay", "custom"), + _glxFunc("glXGetCurrentDrawable", "custom"), + _glxFunc("glXGetCurrentReadDrawable", "custom"), + _glxFunc("glXGetProcAddress", "custom"), + _glxFunc("glXGetProcAddressARB", "custom"), + _glxFunc("glXMakeContextCurrent", "custom"), + _glxFunc("glXMakeCurrent", "custom"), + _glxFunc("glXQueryExtension", "custom"), + _glxFunc("glXQueryVersion", "custom"), + _glxFunc("glXImportContextEXT", "custom", public=False), + _glxFunc("glXFreeContextEXT", "custom", public=False), + +) + diff --git a/src/GLX/libglxmapping.c b/src/GLX/libglxmapping.c index 90957ac93ddba20ba17529e921f8dc1d672c7dc9..74337a4f0f0ac977c5fb00609f72a53a97a6511d 100644 --- a/src/GLX/libglxmapping.c +++ b/src/GLX/libglxmapping.c @@ -46,6 +46,7 @@ #include "glvnd_genentry.h" #include "trace.h" #include "winsys_dispatch.h" +#include "glxdispatchstubs.h" #include "lkdhash.h" @@ -226,6 +227,7 @@ __GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName) HASH_ITER(hh, _LH(__glXVendorNameHash), pEntry, tmp) { pEntry->vendor.glxvc->setDispatchIndex(procName, index); } + __glxSetDispatchIndex(procName, index); } else { addr = NULL; } @@ -994,13 +996,19 @@ void __glXMappingInit(void) int i; __glvndWinsysDispatchInit(); + __glxInitDispatchStubs(&glxExportsTable); // Add all of the GLX dispatch stubs that are defined in libGLX itself. - for (i=0; LOCAL_GLX_DISPATCH_FUNCTIONS[i].name != NULL; i++) { - // TODO: Is there any way to recover from a malloc failure here? - __glvndWinsysDispatchAllocIndex( - LOCAL_GLX_DISPATCH_FUNCTIONS[i].name, - LOCAL_GLX_DISPATCH_FUNCTIONS[i].addr); + for (i=0; i<__GLX_DISPATCH_FUNCTION_COUNT; i++) { + if (__GLX_DISPATCH_FUNCS[i] != NULL) { + int index = __glvndWinsysDispatchAllocIndex( + __GLX_DISPATCH_FUNC_NAMES[i], __GLX_DISPATCH_FUNCS[i]); + if (index < 0) { + fprintf(stderr, "Can't allocate memory for core GLX dispatch functions\n"); + abort(); + } + __glxSetDispatchIndex((const GLubyte *) __GLX_DISPATCH_FUNC_NAMES[i], index); + } } } diff --git a/src/GLX/libglxmapping.h b/src/GLX/libglxmapping.h index 0d18722fbb1a009c277804b0ad4d1e2310154f8c..25636a17a2b94678456ae17a18bb6fdc1293b63b 100644 --- a/src/GLX/libglxmapping.h +++ b/src/GLX/libglxmapping.h @@ -90,12 +90,6 @@ typedef struct __GLXlocalDispatchFunctionRec { __GLXextFuncPtr addr; } __GLXlocalDispatchFunction; -/*! - * A NULL-termianted list of GLX dispatch functions that are implemented in - * libGLX instead of in any vendor library. - */ -extern const __GLXlocalDispatchFunction LOCAL_GLX_DISPATCH_FUNCTIONS[]; - /*! * Accessor functions used to retrieve the "current" dispatch table for each of * the three types of dispatch tables (see libglxabi.h for an explanation of diff --git a/src/Makefile.am b/src/Makefile.am index b57606a3c5ee1d7415b452e5228d47ade0eb3787..603a8b799380140ffc2c985e3182801b37e57ab8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = util \ + vendor \ GLdispatch \ GLX \ OpenGL \ diff --git a/src/vendor/Makefile.am b/src/vendor/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..b3305ff7131264276bdb87c59d502a60d4db5232 --- /dev/null +++ b/src/vendor/Makefile.am @@ -0,0 +1,60 @@ +# Copyright (c) 2016, NVIDIA CORPORATION. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and/or associated documentation files (the +# "Materials"), to deal in the Materials without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Materials, and to +# permit persons to whom the Materials are furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# unaltered in all copies or substantial portions of the Materials. +# Any additions, deletions, or changes to the original source files +# must be clearly indicated in accompanying documentation. +# +# If only executable code is distributed, then the accompanying +# documentation must state that "this software is based in part on the +# work of the Khronos Group." +# +# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +noinst_HEADERS = glxdispatchstubs.h + +EXTRA_DIST = example_glx_function_list.py gen_glx_dispatch.py + +BUILT_SOURCES = g_glxdispatchstubs.h g_glxdispatchstubs.c + +CLEANFILES = $(BUILT_SOURCES) + +GEN_DISPATCH_SCRIPT = $(top_srcdir)/src/vendor/gen_glx_dispatch.py +DISPATCH_FUNC_LIST = $(top_srcdir)/src/GLX/libglx_function_list.py +DISPATCH_XML_FILES = $(top_srcdir)/src/generate/xml/glx.xml +GEN_DISPATCH_DEPS = \ + $(GEN_DISPATCH_SCRIPT) \ + $(DISPATCH_FUNC_LIST) \ + $(DISPATCH_XML_FILES) \ + $(top_srcdir)/src/generate/genCommon.py + +g_glxdispatchstubs.h : $(GEN_DISPATCH_DEPS) + $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/generate $(PYTHON2) \ + $(GEN_DISPATCH_SCRIPT) header $(DISPATCH_FUNC_LIST) \ + $(DISPATCH_XML_FILES) > $@ + +g_glxdispatchstubs.c : $(GEN_DISPATCH_DEPS) + $(AM_V_GEN) PYTHONPATH=$(top_srcdir)/src/generate $(PYTHON2) \ + $(GEN_DISPATCH_SCRIPT) source $(DISPATCH_FUNC_LIST) \ + $(DISPATCH_XML_FILES) > $@ + +noinst_LTLIBRARIES = libglxdispatchstubs.la +libglxdispatchstubs_la_CFLAGS = -I$(top_srcdir)/include +libglxdispatchstubs_la_SOURCES = \ + glxdispatchstubs.c \ + g_glxdispatchstubs.c + diff --git a/src/vendor/example_glx_function_list.py b/src/vendor/example_glx_function_list.py new file mode 100644 index 0000000000000000000000000000000000000000..9e0c73c3ca7add5536b363a28085b093582bdca8 --- /dev/null +++ b/src/vendor/example_glx_function_list.py @@ -0,0 +1,232 @@ +#!/usr/bin/python + +# Copyright (c) 2016, NVIDIA CORPORATION. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and/or associated documentation files (the +# "Materials"), to deal in the Materials without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Materials, and to +# permit persons to whom the Materials are furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# unaltered in all copies or substantial portions of the Materials. +# Any additions, deletions, or changes to the original source files +# must be clearly indicated in accompanying documentation. +# +# If only executable code is distributed, then the accompanying +# documentation must state that "this software is based in part on the +# work of the Khronos Group." +# +# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +""" +The GLX function list, used by gen_glx_dispatch.py. + +GLX Function values: +- "method" + How to select a vendor library. See "Method values" below. + +- "add_mapping" + Specifies that the return value should be added to one of libGLX's + mappings. See "add_mapping values" below. + +- "remove_mapping" + Specifies that the return value should be removed to one of libGLX's + mappings. + + Allowed values are "context", "drawable", and "config". + +- "remove_key" + The parameter that contains the value to remove from libGLX's mapping. + If unspecified, the default is the same as the "key" field. + +- "prefix" + If True, the function should be exported from the library. This is used for + generating dispatch stubs for libGLX itself -- vendor libraries generally + should not use it. + +- "static" + If this is True, then the function will be declared static. + +- "public" + If True, the function should be exported from the library. Vendor libraries + generally should not use this. + +- "display" + The name of the parameter that contains the Display pointer. + May be "" to specify the current display. + If not specified, it will look for a parameter with the correct type. + +- "extension" + The name of an extension macro to check for before defining the function. + +- "inheader" + If True, then this function should be declared in the generated header + file. + +method values: +- "custom" + The dispatch stub will be hand-written instead of generated. + +- "none" + No dispatch function exists at all, but the function should still have an + entry in the index array. This is for other functions that a stub may need + to call that are implemented in libGLX itself. + +- "current" + Use the current context. + +- "drawable", "context", "config" + Look up by a GLXDrawable, GLXContext, or GLXFBConfig parameter. + The parameter is given by the "key" field. If unspecified, it will use the + first parameter of the correct type that it finds. + +- "screen" + Get a screen number from a parameter. + The parameter name is given by the "key" field. If unspecifid, the default + parameter name is "screen". + +- "xvisinfo" + Use an XVisualInfo pointer from a parameter. + The parameter name is given by the "key" field. If unspecifid, it will look + for the first XVisualInfo parameter. + +add_mapping values: +- "context", "drawable", "config" + Adds the returned GLXContext, GLXDrawable, or GLXConfig. + +- "config_list" + Adds an array of GLXFBConfig values. In this case, you also need to specify + a pointer to the item count in the "nelements" field. +""" + +def _glxFunc(name, method, opcode=None, error=None, prefix="dispatch_", + display=None, key=None, extension=None, retval=None, static=None, + public=False, inheader=None, add_mapping=None, nelements=None, + remove_mapping=None, remove_key=None): + + if (static == None): + static = (method not in ("none", "custom")) + if (inheader == None): + inheader = (method != "none" and not static) + values = { + "method" : method, + "opcode" : opcode, + "error" : error, + "key" : key, + "prefix" : prefix, + "display" : display, + "extension" : extension, + "retval" : retval, + "static" : static, + "public" : public, + "inheader" : inheader, + "add_mapping" : add_mapping, + "nelements" : nelements, + "remove_mapping" : remove_mapping, + "remove_key" : remove_key, + } + return (name, values) + +GLX_FUNCTIONS = ( + # GLX core functions. These are all implemented in libGLX, but are listed + # here to keep track of the dispatch indexes for them. + _glxFunc("glXChooseFBConfig", "none"), + _glxFunc("glXCreateContext", "none"), + _glxFunc("glXCreateGLXPixmap", "none"), + _glxFunc("glXCreateNewContext", "none"), + _glxFunc("glXCreatePbuffer", "none"), + _glxFunc("glXCreatePixmap", "none"), + _glxFunc("glXCreateWindow", "none"), + _glxFunc("glXDestroyGLXPixmap", "none"), + _glxFunc("glXDestroyPbuffer", "none"), + _glxFunc("glXDestroyPixmap", "none"), + _glxFunc("glXDestroyWindow", "none"), + _glxFunc("glXGetConfig", "none"), + _glxFunc("glXChooseVisual", "none"), + _glxFunc("glXCopyContext", "none"), + _glxFunc("glXGetFBConfigAttrib", "none"), + _glxFunc("glXGetFBConfigs", "none"), + _glxFunc("glXGetSelectedEvent", "none"), + _glxFunc("glXGetVisualFromFBConfig", "none"), + _glxFunc("glXIsDirect", "none"), + _glxFunc("glXQueryExtensionsString", "none"), + _glxFunc("glXQueryServerString", "none"), + _glxFunc("glXQueryContext", "none"), + _glxFunc("glXQueryDrawable", "none"), + _glxFunc("glXSelectEvent", "none"), + _glxFunc("glXSwapBuffers", "none"), + _glxFunc("glXUseXFont", "none"), + _glxFunc("glXWaitGL", "none"), + _glxFunc("glXWaitX", "none"), + _glxFunc("glXDestroyContext", "none"), + _glxFunc("glXGetClientString", "none"), + _glxFunc("glXGetCurrentContext", "none"), + _glxFunc("glXGetCurrentDisplay", "none"), + _glxFunc("glXGetCurrentDrawable", "none"), + _glxFunc("glXGetCurrentReadDrawable", "none"), + _glxFunc("glXGetProcAddress", "none"), + _glxFunc("glXGetProcAddressARB", "none"), + _glxFunc("glXMakeContextCurrent", "none"), + _glxFunc("glXMakeCurrent", "none"), + _glxFunc("glXQueryExtension", "none"), + _glxFunc("glXQueryVersion", "none"), + + # GLX_ARB_create_context + _glxFunc("glXCreateContextAttribsARB", "config", "X_GLXCreateContextAtrribsARB", add_mapping="context"), + + # GLX_EXT_import_context + _glxFunc("glXImportContextEXT", "none"), # Implemented in libGLX + _glxFunc("glXFreeContextEXT", "none"), # Implemented in libGLX + _glxFunc("glXGetContextIDEXT", "context", None), + _glxFunc("glXGetCurrentDisplayEXT", "current"), + _glxFunc("glXQueryContextInfoEXT", "context", "X_GLXVendorPrivateWithReply"), + + # GLX_EXT_texture_from_pixmap + _glxFunc("glXBindTexImageEXT", "drawable", "X_GLXVendorPrivate", error="GLXBadPixmap"), + _glxFunc("glXReleaseTexImageEXT", "drawable", "X_GLXVendorPrivate", error="GLXBadPixmap"), + + # GLX_EXT_swap_control + _glxFunc("glXSwapIntervalEXT", "drawable", "X_GLXVendorPrivate", error="GLXBadDrawable"), + + # GLX_SGI_video_sync + _glxFunc("glXGetVideoSyncSGI", "current"), + _glxFunc("glXWaitVideoSyncSGI", "current"), + + # GLX_SGI_swap_control + _glxFunc("glXSwapIntervalSGI", "current"), + + # GLX_SGIX_swap_barrier + _glxFunc("glXBindSwapBarrierSGIX", "drawable"), + _glxFunc("glXQueryMaxSwapBarriersSGIX", "screen"), + + # GLX_SGIX_video_resize + _glxFunc("glXBindChannelToWindowSGIX", "screen"), + _glxFunc("glXChannelRectSGIX", "screen"), + _glxFunc("glXQueryChannelRectSGIX", "screen"), + _glxFunc("glXQueryChannelDeltasSGIX", "screen"), + _glxFunc("glXChannelRectSyncSGIX", "screen"), + + # GLX_SGIX_fbconfig + _glxFunc("glXCreateContextWithConfigSGIX", "config", "X_GLXVendorPrivateWithReply", add_mapping="context"), + _glxFunc("glXGetFBConfigAttribSGIX", "config", "X_GLXVendorPrivateWithReply"), + _glxFunc("glXChooseFBConfigSGIX", "screen", add_mapping="config_list", nelements=3), + _glxFunc("glXCreateGLXPixmapWithConfigSGIX", "config", "X_GLXVendorPrivateWithReply", add_mapping="drawable"), + _glxFunc("glXGetVisualFromFBConfigSGIX", "config", "X_GLXVendorPrivateWithReply"), + _glxFunc("glXGetFBConfigFromVisualSGIX", "xvisinfo"), + + # GLX_SGIX_pbuffer + _glxFunc("glXCreateGLXPbufferSGIX", "config", "X_GLXVendorPrivateWithReply", add_mapping="drawable"), + _glxFunc("glXDestroyGLXPbufferSGIX", "drawable", "X_GLXVendorPrivateWithReply", remove_mapping="drawable"), + _glxFunc("glXQueryGLXPbufferSGIX", "drawable", "X_GLXVendorPrivateWithReply"), + _glxFunc("glXSelectEventSGIX", "drawable", "X_GLXVendorPrivateWithReply"), + _glxFunc("glXGetSelectedEventSGIX", "drawable", "X_GLXVendorPrivateWithReply"), +) diff --git a/src/vendor/gen_glx_dispatch.py b/src/vendor/gen_glx_dispatch.py new file mode 100755 index 0000000000000000000000000000000000000000..e71628ed94b07dadf5fe326401844324dcfc2e60 --- /dev/null +++ b/src/vendor/gen_glx_dispatch.py @@ -0,0 +1,409 @@ +#!/usr/bin/python + +# Copyright (c) 2016, NVIDIA CORPORATION. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and/or associated documentation files (the +# "Materials"), to deal in the Materials without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Materials, and to +# permit persons to whom the Materials are furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# unaltered in all copies or substantial portions of the Materials. +# Any additions, deletions, or changes to the original source files +# must be clearly indicated in accompanying documentation. +# +# If only executable code is distributed, then the accompanying +# documentation must state that "this software is based in part on the +# work of the Khronos Group." +# +# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +""" +Generates dispatch functions for GLX. + +This script is provided to make it easier to generate the GLX dispatch stubs +for a vendor library. + +The script will read a list of functions from Khronos's glx.xml list, with +additional information provided in a separate Python module. + +See example_glx_function_list.py for an example of the function list. +""" + +import sys +import collections +import imp + +import os.path +import genCommon + +_GLX_DRAWABLE_TYPES = frozenset(("GLXDrawable", "GLXWindow", "GLXPixmap", + "GLXPbuffer", "GLXPbufferSGIX")) +_GLX_FBCONFIG_TYPES = frozenset(("GLXFBConfig", "GLXFBConfigSGIX")) + +def main(): + if (len(sys.argv) < 4): + print("Usage: %r source|header [xml_file...]" % (sys.argv[0],)) + sys.exit(2) + + target = sys.argv[1] + funcListFile = sys.argv[2] + xmlFiles = sys.argv[3:] + + # The function list is a Python module, but it's specified on the command + # line. + glxFunctionList = imp.load_source("glxFunctionList", funcListFile) + + xmlFunctions = genCommon.getFunctions(xmlFiles) + xmlByName = dict((f.name, f) for f in xmlFunctions) + functions = [] + for (name, glxFunc) in glxFunctionList.GLX_FUNCTIONS: + func = xmlByName[name] + glxFunc = fixupFunc(func, glxFunc) + functions.append((func, glxFunc)) + + # Sort the function list by name. + functions = sorted(functions, key=lambda f: f[0].name) + + if (target == "header"): + text = generateHeader(functions) + elif (target == "source"): + text = generateSource(functions) + else: + raise ValueError("Invalid target: %r" % (target,)) + sys.stdout.write(text) + +def fixupFunc(func, glxFunc): + """ + Does some basic error-checking on a function, and fills in default values + for any fields that haven't been set. + """ + + result = dict(glxFunc) + if (result.get("prefix") == None): + result["prefix"] = "" + + if (result.get("static") == None): + result["static"] = False + + if (result.get("public") == None): + result["public"] = False + + if (result.get("static") and result.get("public")): + raise ValueError("Function %s cannot be both static and public" % (func.name,)) + + # If the method is "custom" or "none", then we're not going to generate a + # stub for it, so the rest of the data doesn't matter. + if (result["method"] in ("custom", "none")): + return result + + if (func.hasReturn()): + if (result.get("retval") == None): + result["retval"] = getDefaultReturnValue(func.rt) + + if (result.get("extension") != None): + text = "defined(" + result["extension"] + ")" + result["extension"] = text + + if (result["method"] != "current"): + # This function is dispatched based on a paramter. Figure out which + # one. + if (result.get("key") != None): + # The parameter was specified, so just use it. + result["key"] = fixupParamName(func, result["key"]) + else: + # Look for a parameter of the correct type. + if (result["method"] == "drawable"): + result["key"] = findParamByType(func, _GLX_DRAWABLE_TYPES) + elif (result["method"] == "context"): + result["key"] = findParamByType(func, ("GLXContext", "const GLXContext")) + elif (result["method"] == "config"): + result["key"] = findParamByType(func, _GLX_FBCONFIG_TYPES) + elif (result["method"] == "screen"): + result["key"] = fixupParamName(func, "screen") + elif (result["method"] == "xvisinfo"): + result["key"] = findParamByType(func, ("XVisualInfo *", "const XVisualInfo *")) + else: + raise ValueError("Unknown lookup method %r for function %r" % (result["method"], func.name)) + if (result["key"] == None): + raise ValueError("Can't find lookup key for function %r" % (func.name,)) + + if (result["method"] == "xvisinfo"): + # If we're using an XVisualInfo pointer, then we just need the + # screen number from it. + result["key"] = "(" + result["key"] + ")->screen" + result["method"] = "screen" + + if (result["method"] == "drawable"): + # For reporting errors when we look up a vendor by drawable, we also + # have to specify the error code. + if (result.get("opcode") != None and result.get("error") == None): + raise ValueError("Missing error code for function %r" % (func.name,)) + + if (result.get("remove_mapping") != None): + if (result["remove_mapping"] not in ("context", "drawable", "config")): + raise ValueError("Invalid remove_mapping value %r for function %r" % + (result["remove_mapping"], func.name)) + if (result.get("remove_key") != None): + result["remove_key"] = fixupParamName(func, result["remove_key"]) + else: + assert(result["remove_mapping"] == result["method"]) + result["remove_key"] = result["key"] + + if (result.get("opcode") == None): + result["opcode"] = "-1" + result["error"] = "-1" + + if (result.get("display") != None): + result["display"] = fixupParamName(func, result["display"]) + else: + result["display"] = findParamByType(func, ("Display *",)) + if (result["display"] == None): + if (getNeedsDisplayPointer(func, result)): + raise ValueError("Can't find display pointer for function %r" % (func.name,)) + result["display"] = "NULL" + + return result + +def getDefaultReturnValue(typename): + """ + Picks a default return value. The dispatch stub will return this value if + it can't find an implementation function. + """ + if (typename.endswith("*")): + return "NULL" + if (typename == "GLXContext" or typename in _GLX_FBCONFIG_TYPES): + return "NULL" + if (typename in _GLX_DRAWABLE_TYPES): + return "None" + if (typename in ("XID", "GLXFBConfigID", "GLXContextID")): + return "None" + + return "0" + +def getNeedsDisplayPointer(func, glxFunc): + """ + Returns True if a function needs a Display pointer. + """ + if (glxFunc["method"] not in ("none", "custom", "context", "current")): + return True + if (glxFunc.get("add_mapping") != None): + return True + if (glxFunc.get("remove_mapping") != None): + return True + return False + +def findParamByType(func, typeNames): + """ + Looks for a parameter of a given data type. Returns the name of the + parameter, or None if no matching parameter was found. + """ + for arg in func.args: + if (arg.type in typeNames): + return arg.name + return None + +def fixupParamName(func, paramSpec): + """ + Takes a parameter that was specified in the function list and returns a + parameter name or a C expression. + """ + try: + # If the parameter is an integer, then treat it as a parameter index. + index = int(paramSpec) + return func.args[index] + except ValueError: + # Not an integer + pass + + # If the string is contained in parentheses, then assume it's a valid C + # expression. + if (paramSpec.startswith("(") and paramSpec.endswith(")")): + return paramSpec[1:-1] + + # Otherwise, assume the string is a parameter name. + for arg in func.args: + if (arg.name == paramSpec): + return arg.name + + raise ValueError("Invalid parameter name %r in function %r" % (paramSpec, func)) + +def generateHeader(functions): + text = r""" +#ifndef G_GLXDISPATCH_STUBS_H +#define G_GLXDISPATCH_STUBS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +""".lstrip("\n") + + text += "enum {\n" + for (func, glxFunc) in functions: + text += generateGuardBegin(func, glxFunc) + text += " __GLX_DISPATCH_" + func.name + ",\n" + text += generateGuardEnd(func, glxFunc) + text += " __GLX_DISPATCH_COUNT\n" + text += "};\n\n" + + for (func, glxFunc) in functions: + if (glxFunc["inheader"]): + text += generateGuardBegin(func, glxFunc) + text += "{f.rt} {ex[prefix]}{f.name}({f.decArgs});\n".format(f=func, ex=glxFunc) + text += generateGuardEnd(func, glxFunc) + + text += r""" +#ifdef __cplusplus +} +#endif +#endif // G_GLXDISPATCH_STUBS_H +""" + return text + +def generateSource(functions): + text = r''' +#include "glxdispatchstubs.h" +#include "g_glxdispatchstubs.h" + +#include +#include + +'''.lstrip("\n") + + for (func, glxFunc) in functions: + if (glxFunc["method"] not in ("none", "custom")): + text += generateGuardBegin(func, glxFunc) + text += generateDispatchFunc(func, glxFunc) + text += generateGuardEnd(func, glxFunc) + + text += "\n" + text += "const char * const __GLX_DISPATCH_FUNC_NAMES[__GLX_DISPATCH_COUNT + 1] = {\n" + for (func, glxFunc) in functions: + text += generateGuardBegin(func, glxFunc) + text += ' "' + func.name + '",\n' + text += generateGuardEnd(func, glxFunc) + text += " NULL,\n" + text += "};\n" + + text += "const __GLXextFuncPtr __GLX_DISPATCH_FUNCS[__GLX_DISPATCH_COUNT + 1] = {\n" + for (func, glxFunc) in functions: + text += generateGuardBegin(func, glxFunc) + if (glxFunc["method"] != "none"): + text += " (__GLXextFuncPtr) " + glxFunc["prefix"] + func.name + ",\n" + else: + text += " NULL, // " + func.name + "\n" + text += generateGuardEnd(func, glxFunc) + text += " NULL,\n" + text += "};\n" + + return text + +def generateGuardBegin(func, glxFunc): + ext = glxFunc.get("extension") + if (ext != None): + return "#if " + ext + "\n" + else: + return "" + +def generateGuardEnd(func, glxFunc): + if (glxFunc.get("extension") != None): + return "#endif\n" + else: + return "" + +def generateDispatchFunc(func, glxFunc): + text = "" + + if (glxFunc["static"]): + text += "static " + elif (glxFunc["public"]): + text += "PUBLIC " + + text += r"""{f.rt} {ex[prefix]}{f.name}({f.decArgs}) +{{ + typedef {f.rt} (* _pfn_{f.name})({f.decArgs}); +""" + + text += " __GLXvendorInfo *_vendor;\n" + text += " _pfn_{f.name} _ptr_{f.name};\n" + if (func.hasReturn()): + text += " {f.rt} _ret = {ex[retval]};\n" + text += "\n" + + # Look up the vendor library + text += " _vendor = " + if (glxFunc["method"] == "current"): + text += "__glXDispatchApiExports->getCurrentDynDispatch();\n" + elif (glxFunc["method"] == "screen"): + text += "__glXDispatchApiExports->getDynDispatch({ex[display]}, {ex[key]});\n" + elif (glxFunc["method"] == "drawable"): + text += "__glxDispatchVendorByDrawable({ex[display]}, {ex[key]}, {ex[opcode]}, {ex[error]});\n" + elif (glxFunc["method"] == "context"): + text += "__glxDispatchVendorByContext({ex[display]}, {ex[key]}, {ex[opcode]});\n" + elif (glxFunc["method"] == "config"): + text += "__glxDispatchVendorByConfig({ex[display]}, {ex[key]}, {ex[opcode]});\n" + else: + raise ValueError("Unknown dispatch method: %r" % (glxFunc["method"],)) + + # Look up and call the function. + text += r""" + if (_vendor != NULL) {{ + _ptr_{f.name} = (_pfn_{f.name}) + __glXDispatchApiExports->fetchDispatchEntry(_vendor, __glXDispatchFuncIndices[__GLX_DISPATCH_{f.name}]); + if (_ptr_{f.name} != NULL) {{ +""".lstrip("\n") + + text += " " + if (func.hasReturn()): + text += "_ret = " + text += "(*_ptr_{f.name})({f.callArgs});\n" + + # Handle any added or removed object mappings. + if (glxFunc.get("add_mapping") != None): + if (glxFunc["add_mapping"] == "context"): + text += " _ret = __glXDispatchAddContextMapping({ex[display]}, _ret, _vendor);\n" + elif (glxFunc["add_mapping"] == "drawable"): + text += " __glXDispatchAddDrawableMapping({ex[display]}, _ret, _vendor);\n" + elif (glxFunc["add_mapping"] == "config"): + text += " _ret = __glXDispatchAddFBConfigMapping({ex[display]}, _ret, _vendor);\n" + elif (glxFunc["add_mapping"] == "config_list"): + text += " _ret = __glXDispatchAddFBConfigListMapping({ex[display]}, _ret, nelements, _vendor);\n" + else: + raise ValueError("Unknown add_mapping method: %r" % (glxFunc["add_mapping"],)) + + if (glxFunc.get("remove_mapping") != None): + if (glxFunc["remove_mapping"] == "context"): + text += " __glXDispatchApiExports->removeVendorContextMapping({ex[display]}, {ex[remove_key]});\n" + elif (glxFunc["remove_mapping"] == "drawable"): + text += " __glXDispatchApiExports->removeVendorDrawableMapping({ex[display]}, {ex[remove_key]});\n" + elif (glxFunc["remove_mapping"] == "config"): + text += " __glXDispatchApiExports->removeVendorFBConfigMapping({ex[display]}, {ex[remove_key]});\n" + else: + raise ValueError("Unknown remove_mapping method: %r" % (glxFunc["add_mapping"],)) + + text += " }}\n" + text += " }}\n" + if (func.hasReturn()): + text += " return _ret;\n" + text += "}}\n\n" + + text = text.format(f=func, ex=glxFunc) + return text + +if (__name__ == "__main__"): + main() + diff --git a/src/vendor/glxdispatchstubs.c b/src/vendor/glxdispatchstubs.c new file mode 100644 index 0000000000000000000000000000000000000000..c5c1199f1d272640c32f830b225b42119077dae0 --- /dev/null +++ b/src/vendor/glxdispatchstubs.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * unaltered in all copies or substantial portions of the Materials. + * Any additions, deletions, or changes to the original source files + * must be clearly indicated in accompanying documentation. + * + * If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the + * work of the Khronos Group." + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +#include "glxdispatchstubs.h" + +#include +#include +#include + +#include "g_glxdispatchstubs.h" + +const __GLXapiExports *__glXDispatchApiExports = NULL; +int __glXDispatchFuncIndices[__GLX_DISPATCH_COUNT + 1]; +const int __GLX_DISPATCH_FUNCTION_COUNT = __GLX_DISPATCH_COUNT; + +static int FindProcIndex(const GLubyte *name) +{ + unsigned first = 0; + unsigned last = __GLX_DISPATCH_COUNT - 1; + + while (first <= last) { + unsigned middle = (first + last) / 2; + int comp = strcmp((const char *) name, + __GLX_DISPATCH_FUNC_NAMES[middle]); + + if (comp > 0) + first = middle + 1; + else if (comp < 0) + last = middle - 1; + else + return middle; + } + + /* Just point to the dummy entry at the end of the respective table */ + return __GLX_DISPATCH_COUNT; +} + +void __glxInitDispatchStubs(const __GLXapiExports *exportsTable) +{ + int i; + __glXDispatchApiExports = exportsTable; + for (i=0; i<__GLX_DISPATCH_COUNT; i++) { + __glXDispatchFuncIndices[i] = -1; + } +} + +void __glxSetDispatchIndex(const GLubyte *name, int dispatchIndex) +{ + int index = FindProcIndex(name); + __glXDispatchFuncIndices[index] = dispatchIndex; +} + +void *__glxDispatchFindDispatchFunction(const GLubyte *name) +{ + int index = FindProcIndex(name); + return __GLX_DISPATCH_FUNCS[index]; +} + +__GLXvendorInfo *__glxDispatchVendorByDrawable(Display *dpy, GLXDrawable draw, + int opcode, int error) +{ + __GLXvendorInfo *vendor = NULL; + + if (draw != None) { + vendor = __glXDispatchApiExports->vendorFromDrawable(dpy, draw); + } + if (vendor == NULL && dpy != NULL && opcode >= 0 && error >= 0) { + __glXSendError(dpy, error, draw, opcode, False); + } + return vendor; +} + +__GLXvendorInfo *__glxDispatchVendorByContext(Display *dpy, GLXContext context, + int opcode) +{ + __GLXvendorInfo *vendor = NULL; + + if (context != NULL) { + vendor = __glXDispatchApiExports->vendorFromContext(context); + } + if (vendor == NULL && dpy != NULL && opcode >= 0) { + __glXSendError(dpy, GLXBadContext, 0, opcode, False); + } + return vendor; +} + +__GLXvendorInfo *__glxDispatchVendorByConfig(Display *dpy, GLXFBConfig config, + int opcode) +{ + __GLXvendorInfo *vendor = NULL; + + if (config != NULL) { + vendor = __glXDispatchApiExports->vendorFromFBConfig(dpy, config); + } + if (vendor == NULL && dpy != NULL && opcode >= 0) { + __glXSendError(dpy, GLXBadFBConfig, 0, opcode, False); + } + return vendor; +} + + +GLXContext __glXDispatchAddContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor) +{ + if (context != NULL) { + if (__glXDispatchApiExports->addVendorContextMapping(dpy, context, vendor) != 0) { + // We couldn't add the new context to libGLX's mapping. Call into + // the vendor to destroy the context again before returning. + typedef void (* pfn_glXDestroyContext) (Display *dpy, GLXContext ctx); + pfn_glXDestroyContext ptr_glXDestroyContext = (pfn_glXDestroyContext) + __glXDispatchApiExports->fetchDispatchEntry(vendor, + __glXDispatchFuncIndices[__GLX_DISPATCH_glXDestroyContext]); + if (ptr_glXDestroyContext != NULL) { + ptr_glXDestroyContext(dpy, context); + } + context = NULL; + } + } + return context; +} + +void __glXDispatchAddDrawableMapping(Display *dpy, GLXDrawable draw, __GLXvendorInfo *vendor) +{ + if (draw != None) { + // We don't have to worry about failing to add a mapping in this case, + // because libGLX can look up the vendor for the drawable on its own. + __glXDispatchApiExports->addVendorDrawableMapping(dpy, draw, vendor); + } +} + +GLXFBConfig __glXDispatchAddFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor) +{ + if (config != NULL) { + if (__glXDispatchApiExports->addVendorFBConfigMapping(dpy, config, vendor) != 0) { + config = NULL; + } + } + return config; +} + +GLXFBConfig *__glXDispatchAddFBConfigListMapping(Display *dpy, GLXFBConfig *configs, int *nelements, __GLXvendorInfo *vendor) +{ + if (configs != NULL && nelements != NULL) { + int i; + Bool success = True; + for (i=0; i<*nelements; i++) { + if (__glXDispatchApiExports->addVendorFBConfigMapping(dpy, configs[i], vendor) != 0) { + success = False; + break; + } + } + if (!success) { + XFree(configs); + configs = NULL; + *nelements = 0; + } + } + return configs; +} + diff --git a/src/vendor/glxdispatchstubs.h b/src/vendor/glxdispatchstubs.h new file mode 100644 index 0000000000000000000000000000000000000000..8394fbf72a32980f0300cac0a6f587eab6e0a6ac --- /dev/null +++ b/src/vendor/glxdispatchstubs.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and/or associated documentation files (the + * "Materials"), to deal in the Materials without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Materials, and to + * permit persons to whom the Materials are furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * unaltered in all copies or substantial portions of the Materials. + * Any additions, deletions, or changes to the original source files + * must be clearly indicated in accompanying documentation. + * + * If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the + * work of the Khronos Group." + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + */ + +#ifndef GLXDISPATCHSTUBS_H +#define GLXDISPATCHSTUBS_H + +/*! + * \file + * + * Functions for GLX dispatch stubs. + * + * This file declares various helper functions used with the GLX dispatch stubs. + */ + +#include "glvnd/libglxabi.h" + +#include "compiler.h" // Only needed for the PUBLIC macro + +/*! + * An array containing the names of all known GLX functions. + */ +extern const char * const __GLX_DISPATCH_FUNC_NAMES[]; + +/*! + * An array containing the dispatch stubs for GLX functions. Note that some + * elements may be NULL if no dispatch function is defined. This is used for + * functions like glXDestroyContext, where we'll need an index so that we can + * look up the function from other dispatch stubs. + */ +extern const __GLXextFuncPtr __GLX_DISPATCH_FUNCS[]; + +/*! + * The dispatch index for each function. + */ +extern int __glXDispatchFuncIndices[]; + +/*! + * The number of GLX functions. This is the length of the + * \c __GLX_DISPATCH_FUNC_NAMES, \c __GLX_DISPATCH_FUNCS, and + * \c __glXDispatchFuncIndices arrays. + */ +extern const int __GLX_DISPATCH_FUNCTION_COUNT; + +/*! + * A pointer to the exports table from libGLX. + */ +extern const __GLXapiExports *__glXDispatchApiExports; + +/*! + * Initializes the dispatch functions. + * + * This will set the __GLXapiExports pointer for the stubs to use and will + * initialize the index array. + */ +void __glxInitDispatchStubs(const __GLXapiExports *exportsTable); + +/*! + * Sets the dispatch index for a function. + * + * This function can be used for the vendor's \c __GLXapiImports::setDispatchIndex + * callback. + */ +void __glxSetDispatchIndex(const GLubyte *name, int index); + +/*! + * Returns the dispatch function for the given name, or \c NULL if the function + * isn't supported. + * + * This function can be used for the vendor's \c __GLXapiImports::getDispatchAddress + * callback. + */ +void *__glxDispatchFindDispatchFunction(const GLubyte *name); + +/*! + * Reports an X error. This function must be defined by the vendor library. + */ +void __glXSendError(Display *dpy, unsigned char errorCode, + XID resourceID, unsigned char minorCode, Bool coreX11error); + +// Helper functions used by the generated stubs. + +/*! + * Looks up a vendor from a drawable. + * + * If \p opcode and \p error are non-negative, then they are used to report an + * X error if the lookup fails. + */ +__GLXvendorInfo *__glxDispatchVendorByDrawable(Display *dpy, GLXDrawable draw, + int opcode, int error); + +/*! + * Looks up a vendor from a context. + */ +__GLXvendorInfo *__glxDispatchVendorByContext(Display *dpy, GLXContext ctx, + int opcode); + +/*! + * Looks up a vendor from a GLXFBConfig. + */ +__GLXvendorInfo *__glxDispatchVendorByConfig(Display *dpy, GLXFBConfig config, + int opcode); + +/*! + * Adds a GLXContext to libGLX's mapping. + * + * If it fails to add the context to the map, then this function will try to + * destroy the context before returning. + * + * \param dpy The display pointer. + * \param context The context to add. + * \param vendor The vendor that owns the context. + * \return \p context on success, or \c NULL on failure. + */ +GLXContext __glXDispatchAddContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor); + +/*! + * Adds a drawable to libGLX's mapping. + * + * Note that unlike contexts and configs, failing to add a drawable is not a + * problem. libGLX can query the server later to find out which vendor owns the + * drawable. + * + * \param dpy The display pointer. + * \param draw The drawable to add. + * \param vendor The vendor that owns the drawable. + */ +void __glXDispatchAddDrawableMapping(Display *dpy, GLXDrawable draw, __GLXvendorInfo *vendor); + +/*! + * Adds a GLXFBConfig to libGLX's mapping. + * + * \param dpy The display pointer. + * \param config The config to add. + * \param vendor The vendor that owns the config. + * \return \p config on success, or \c NULL on failure. + */ +GLXFBConfig __glXDispatchAddFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor); + +/*! + * Adds an array of GLXFBConfigs to libGLX's mapping. + * + * If it fails to add any config, then it will free the \p configs array and + * set \p nelements to zero before returning. + * + * \param dpy The display pointer. + * \param configs The array of configs to add. + * \param nelements A pointer to the number of elements in \p configs. + * \param vendor The vendor that owns the configs. + * \return \p configs on success, or \c NULL on failure. + */ +GLXFBConfig *__glXDispatchAddFBConfigListMapping(Display *dpy, GLXFBConfig *configs, int *nelements, __GLXvendorInfo *vendor); + +#endif // GLXDISPATCHSTUBS_H