diff options
author | Kyle Brenneman <kbrenneman@nvidia.com> | 2016-03-28 17:40:51 -0600 |
---|---|---|
committer | Kyle Brenneman <kbrenneman@nvidia.com> | 2016-03-28 17:40:51 -0600 |
commit | 95a5bfcdfbc3c38e201e81d6497efe6c7b97f72b (patch) | |
tree | 84d622feb712ea43d432a2c8b0ca9cd65e8ae20d /include | |
parent | 5c8e63290620d78763503f9ba4de28530ae1961e (diff) | |
parent | 86585e3bb0781ad1ef925e6fd81888190c12b1a5 (diff) |
Merge pull request #74 from kbrenneman/libglx-abi-version-1.
Updates to libGLX vendor library interface.
Diffstat (limited to 'include')
-rw-r--r-- | include/glvnd/GLdispatchABI.h | 101 | ||||
-rw-r--r-- | include/glvnd/libglxabi.h | 195 |
2 files changed, 186 insertions, 110 deletions
diff --git a/include/glvnd/GLdispatchABI.h b/include/glvnd/GLdispatchABI.h index d16de2d..25d593a 100644 --- a/include/glvnd/GLdispatchABI.h +++ b/include/glvnd/GLdispatchABI.h @@ -44,18 +44,45 @@ extern "C" { * these client ABIs. */ -/* - * Thread-local implementation used by libglvnd. This is passed into - * the patch function callback via the type parameter. +/*! + * Thread-local implementation used by libglvnd. This is passed into the patch + * function callback via the type parameter. + * + * For most architectures, the vendor library can ignore this parameter, since + * it will always be the same value. It's used for systems like ARM, where the + * stubs might be use the ARM or Thumb instruction sets. + * + * The stub type does not make any distinction between TLS and TSD stubs. The + * entire purpose of entrypoint rewriting is to skip the dispatch table in + * libGLdispatch.so, so it doesn't matter how that dispatch table is stored. */ enum { - __GLDISPATCH_STUB_X86_TLS, - __GLDISPATCH_STUB_X86_64_TLS, - __GLDISPATCH_STUB_X86_TSD, - __GLDISPATCH_STUB_PURE_C, - __GLDISPATCH_STUB_X86_64_TSD, - __GLDISPATCH_STUB_ARMV7_THUMB_TSD, - __GLDISPATCH_STUB_NUM_TYPES + /*! + * Indicates that the stubs aren't defined in assembly. For example, if the + * dispatch stubs are written in C. Vendor libraries generally won't see + * this value. + */ + __GLDISPATCH_STUB_UNKNOWN, + + /*! + * Used for stubs on x86 systems. + */ + __GLDISPATCH_STUB_X86, + + /*! + * Used for stubs on x86-64 systems. + */ + __GLDISPATCH_STUB_X86_64, + + /*! + * Used for stubs on ARMv7, using the Thumb instruction set. + */ + __GLDISPATCH_STUB_ARMV7_THUMB, + + /*! + * Used for stubs on ARMv7, using the normal ARM instruction set. + */ + __GLDISPATCH_STUB_ARMV7_ARM }; /*! @@ -86,60 +113,6 @@ enum { typedef GLboolean (*DispatchPatchLookupStubOffset)(const char *funcName, void **writePtr, const void **execPtr); -typedef struct __GLdispatchPatchCallbacksRec { - /*! - * Checks to see if the vendor library supports patching the given stub - * type and size. - * - * \param type The type of entrypoints. This will be a one of the - * __GLDISPATCH_STUB_* values. - * \param stubSize The maximum size of the stub that the vendor library can - * write, in bytes. - * \param lookupStubOffset A callback into libglvnd to look up the address - * of each entrypoint. - */ - GLboolean (* checkPatchSupported)(int type, int stubSize); - - /*! - * Called by libglvnd to request that a vendor library patch its top-level - * entrypoints. - * - * The vendor library should use the \p lookupStubOffset callback to find - * the addresses of each entrypoint. - * - * This function may be called more than once to patch multiple sets of - * entrypoints. For example, depending on how they're built, libOpenGL.so - * or libGL.so may have their own entrypoints that are separate functions - * from the ones in libGLdispatch. - * - * Note that during this call is the only time that the entrypoints can be - * modified. After the call to \c initiatePatch returns, the vendor library - * should treat the entrypoints as read-only. - * - * \param type The type of entrypoints. This will be a one of the - * __GLDISPATCH_STUB_* values. - * \param stubSize The maximum size of the stub that the vendor library can - * write, in bytes. - * \param lookupStubOffset A callback into libglvnd to look up the address - * of each entrypoint. - * - * \return GL_TRUE if the vendor library supports patching with this type - * and size. - */ - GLboolean (*initiatePatch)(int type, - int stubSize, - DispatchPatchLookupStubOffset lookupStubOffset); - - /*! - * Called by libglvnd to notify the current vendor that it no longer owns - * the top-level entrypoints. - * - * Libglvnd will take care of the restoring the entrypoints back to their - * original state. The vendor library must not try to modify them. - */ - void (*releasePatch)(void); -} __GLdispatchPatchCallbacks; - #if defined(__cplusplus) } #endif diff --git a/include/glvnd/libglxabi.h b/include/glvnd/libglxabi.h index 3a59691..b664e76 100644 --- a/include/glvnd/libglxabi.h +++ b/include/glvnd/libglxabi.h @@ -90,8 +90,18 @@ extern "C" { /*! * Current version of the ABI. + * + * This version number contains a major number in the high-order 16 bits, and + * a minor version number in the low-order 16 bits. + * + * The major version number is incremented when an interface change will break + * backwards compatibility with existing vendor libraries. The minor version + * number is incremented when there's a change but existing vendor libraries + * will still work. */ -#define GLX_VENDOR_ABI_VERSION 0 +#define GLX_VENDOR_ABI_VERSION ((1 << 16) | 0) +#define GLX_VENDOR_ABI_GET_MAJOR_VERSION(version) ((version) & 0xFFFF) +#define GLX_VENDOR_ABI_GET_MINOR_VERSION(version) ((version) >> 16) /*! @@ -151,15 +161,19 @@ typedef struct __GLXapiExportsRec { /************************************************************************ * These routines are used by vendor dispatch functions to look up - * and add mappings between various objects and screens. + * and add mappings between various objects and vendors. ************************************************************************/ /*! - * Records the screen number and vendor for a context. The screen and - * vendor must be the ones returned for the XVisualInfo or GLXFBConfig that - * the context is created from. + * Records the vendor for a context. The vendor must be the one returned + * for the XVisualInfo or GLXFBConfig that the context is created from. + * + * \param dpy The display pointer. + * \param context The context handle. + * \param vendor The vendor that created the context. + * \return Zero on success, non-zero on error. */ - void (*addVendorContextMapping)(Display *dpy, GLXContext context, __GLXvendorInfo *vendor); + int (*addVendorContextMapping)(Display *dpy, GLXContext context, __GLXvendorInfo *vendor); /*! * Removes a mapping from context to vendor. The context must have been @@ -168,33 +182,27 @@ typedef struct __GLXapiExportsRec { void (*removeVendorContextMapping)(Display *dpy, GLXContext context); /*! - * Looks up the screen and vendor for a context. + * Looks up the vendor for a context. * - * If no mapping is found, then \p retScreen will be set to -1, and - * \p retVendor and \p retDisplay will be set to NULL. - * - * \p retScreen, \p retVendor, and \p retDisplay may be NULL if the screen, - * vendor, or display are not required. + * If no mapping is found, then this function will return \c NULL. No + * errors are raised, so the dispatch function must raise any appropriate X + * errors. * * Note that this function does not take a display connection, since * there are cases (e.g., glXGetContextIDEXT) that take a GLXContext but * not a display. * * \param context The context to look up. - * \param[out] retVendor Returns the vendor. - * \return Zero if a match was found, or non-zero if it was not. + * \return The vendor for the context, or NULL if no matching context was + * found. */ - int (*vendorFromContext)(GLXContext context, __GLXvendorInfo **retVendor); + __GLXvendorInfo * (*vendorFromContext)(GLXContext context); - void (*addVendorFBConfigMapping)(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor); + int (*addVendorFBConfigMapping)(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor); void (*removeVendorFBConfigMapping)(Display *dpy, GLXFBConfig config); - int (*vendorFromFBConfig)(Display *dpy, GLXFBConfig config, __GLXvendorInfo **retVendor); - - void (*addScreenVisualMapping)(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo *vendor); - void (*removeScreenVisualMapping)(Display *dpy, const XVisualInfo *visual); - int (*vendorFromVisual)(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor); + __GLXvendorInfo * (*vendorFromFBConfig)(Display *dpy, GLXFBConfig config); - void (*addVendorDrawableMapping)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor); + int (*addVendorDrawableMapping)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor); void (*removeVendorDrawableMapping)(Display *dpy, GLXDrawable drawable); /*! @@ -210,7 +218,7 @@ typedef struct __GLXapiExportsRec { * All of this should be opaque to a dispatch function, since the only * thing that matters is finding out which vendor to dispatch to. */ - int (*vendorFromDrawable)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo **retVendor); + __GLXvendorInfo * (*vendorFromDrawable)(Display *dpy, GLXDrawable drawable); } __GLXapiExports; @@ -231,7 +239,7 @@ typedef struct __GLXapiImportsRec { * \param screen The screen number. * \return True if the vendor library can support this screen. */ - Bool (* checkSupportsScreen) (Display *dpy, int screen); + Bool (* isScreenSupported) (Display *dpy, int screen); /*! * This retrieves the pointer to the real GLX or core GL function. @@ -289,39 +297,134 @@ typedef struct __GLXapiImportsRec { XID resid, unsigned char opcode, Bool coreX11error); - /*! - * (OPTIONAL) Callbacks by which the vendor library may re-write libglvnd's + /* + * The vendor library may use the isPatchSupported, initiatePatch, + * releasePatch, and patchThreadAttach callbacks to re-write libglvnd's * entrypoints at make current time, provided no other contexts are current - * and the TLS model supports this functionality. This is a performance + * and the TLS model supports this functionality. This is a performance * optimization that may not be available at runtime; the vendor library - * must not depend on this functionality for correctness. This should - * point to a statically-allocated structure, or NULL if unimplemented. + * must not depend on this functionality for correctness. + * + * To use this optimization, the vendor library must provide at least the + * isPatchSupported and initiatePatch entrypoints. + */ + + /*! + * (OPTIONAL) Checks to see if the vendor library supports patching the + * given stub type and size. + * + * \param type The type of entrypoints. This will be a one of the + * __GLDISPATCH_STUB_* values. + * \param stubSize The maximum size of the stub that the vendor library can + * write, in bytes. + * \param lookupStubOffset A callback into libglvnd to look up the address + * of each entrypoint. + */ + GLboolean (* isPatchSupported)(int type, int stubSize); + + /*! + * (OPTIONAL) Called by libglvnd to request that a vendor library patch its + * top-level entrypoints. + * + * The vendor library should use the \p lookupStubOffset callback to find + * the addresses of each entrypoint. + * + * This function may be called more than once to patch multiple sets of + * entrypoints. For example, depending on how they're built, libOpenGL.so + * or libGL.so may have their own entrypoints that are separate functions + * from the ones in libGLdispatch. + * + * Note that during this call is the only time that the entrypoints can be + * modified. After the call to \c initiatePatch returns, the vendor library + * should treat the entrypoints as read-only. + * + * \param type The type of entrypoints. This will be a one of the + * __GLDISPATCH_STUB_* values. + * \param stubSize The maximum size of the stub that the vendor library can + * write, in bytes. + * \param lookupStubOffset A callback into libglvnd to look up the address + * of each entrypoint. + * + * \return GL_TRUE if the vendor library supports patching with this type + * and size. + */ + GLboolean (*initiatePatch)(int type, + int stubSize, + DispatchPatchLookupStubOffset lookupStubOffset); + + /*! + * (OPTIONAL) Called by libglvnd to notify the current vendor that it no + * longer owns the top-level entrypoints. + * + * Libglvnd will take care of the restoring the entrypoints back to their + * original state. The vendor library must not try to modify them. + */ + void (*releasePatch)(void); + + /*! + * (OPTIONAL) Called at the start of window-system functions (GLX and EGL). + * This callback allows vendor libraries to perform any per-thread + * initialization. + * + * This is basically a workaround for broken applications. A lot of apps + * will make one or more invalid GLX/EGL calls on a thread (often including + * a MakeCurrent with invalid parameters), and then will try to call an + * OpenGL function. + * + * A non-libglvnd-based driver would be able to initialize any thread state + * even on a bogus GLX call, but with libglvnd, those calls wouldn't get + * past libGLX. + * + * This function is optional. If it's \c NULL, then libGLdispatch will + * simply ignore it. + * + * \note This function may be called concurrently from multiple threads. */ - const __GLdispatchPatchCallbacks *patchCallbacks; + void (*patchThreadAttach)(void); } __GLXapiImports; /*****************************************************************************/ +#define __GLX_MAIN_PROTO_NAME "__glx_Main" +#define __GLX_MAIN_PROTO(version, exports, vendor, imports) \ + Bool __glx_Main(uint32_t version, \ + const __GLXapiExports *exports, \ + __GLXvendorInfo *vendor, \ + __GLXapiImports *imports) + +typedef Bool (*__PFNGLXMAINPROC) + (uint32_t version, const __GLXapiExports *exports, __GLXvendorInfo *vendor, __GLXapiImports *imports); + /*! * Vendor libraries must export a function called __glx_Main() with the - * following prototype. This function also performs a handshake based on the ABI - * version number. This function receives a pointer to an exports table whose - * lifetime is only guaranteed to be at a minimum that of the call to - * __glx_Main(), in addition to the version number and a string identifying the - * vendor. If there is an ABI version mismatch or some other error occurs, this - * function returns NULL; otherwise this returns a pointer to a filled-in - * dispatch table. + * following prototype. + * + * This function also performs a handshake based on the ABI version number. + * Vendor libraries can optionally use the version number to support older + * versions of the ABI. + * + * \param[in] version The ABI version. The upper 16 bits contains the major version + * number, and the lower 16 bits contains the minor version number. + * + * \param[in] exports The table of functions provided by libGLX. This pointer will + * remain valid for as long as the vendor is loaded. + * + * \param[in] vendor The opaque pointer used to identify this vendor library. This + * may be used in future versions to provide additional per-vendor information. + * + * \param[out] imports The function table that the vendor library should fill + * in. The vendor library must assign every non-optional function in the + * struct. + * + * \return True on success. If the vendor library does not support the + * requested ABI version or if some other error occurs, then it should return + * False. */ -#define __GLX_MAIN_PROTO_NAME "__glx_Main" -#define __GLX_MAIN_PROTO(version, exports, vendorName) \ - const __GLXapiImports *__glx_Main(uint32_t version, \ - const __GLXapiExports *exports, \ - const char *vendorName, \ - int vendorID) - -typedef const __GLXapiImports *(*__PFNGLXMAINPROC) - (uint32_t, const __GLXapiExports *, const char *, int); +Bool __glx_Main(uint32_t version, + const __GLXapiExports *exports, + __GLXvendorInfo *vendor, + __GLXapiImports *imports); /*! * @} |