Simplify vendor-library ABI for libglx

- Pull GL dispatch callback typedefs into GLdispatchABI.h.  This is
  a common header which will be shared between the libGLX and libEGL
  ABIs.

- Add extern "C" blocks to libglxabi.h and GLdispatchABI.h so these
  headers may be used with vendor libraries that are built C++.

- Remove support for auxiliary dispatch table management
  (libglxgldispatch.[ch] and __GLdispatchExports).  This can be added
  back in later on if it proves useful.

- In libglxmappings.c, replace static initialization of glxExportsTable
  with one-time runtime initialization of the table.

- In libglxmappings.c, use __glDispatchCreateTable() directly to create
  the initial dispatch table.

- In libglxnoopdefs.h, remove unnecessary includes of libglxabipriv.h
  and libglxnoop.h.

- Add screen mapping functions to the GLX exports table.  Some extension
  functions not implemented by libglvnd, e.g. glXCreateContextAttribsARB()
  from GLX_ARB_create_context, may need to update the mappings from
  context or drawable to screen that are managed by libglvnd in order to
  work properly.  Additionally, dispatch functions implemented by vendor
  libraries for GLX extension functions may want to query these mappings
  in order to properly dispatch the call.

- Remove the getDispatchProto() vendor callback.  This is not needed by
  libglvnd since libglvnd does not support mapping more than one
  entrypoint to a single dispatch stub.  See GLdispatch.c for the
  rationale behind this decision.

- Remove redundant typedefs to prevent build errors.

- Delete the vendorData parameter from the getProcAddress() vendor
  callback, which isn't useful if there is no support for more than one
  libglvnd dispatch table per context.  Add the isClientAPI parameter,
  which can be used to distinguish between getProcAddress() requests for
  GLX functions versus getProcAddress() requests for client API
  functions.

- Remove the "screen" argument from Remove.*Mapping() functions.  This
  is unnecessary, as the hash key used to lookup the mapping object in
  libglvnd's hashtables doesn't depend on the screen (which is the hash
  value).  It's problematic since in some cases we don't actually know
  the value of the screen mapped to by a key.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
This commit is contained in:
Brian Nguyen 2013-11-25 15:21:41 -08:00 committed by brnguyen
parent 6153c410e8
commit 7a25ae5456
16 changed files with 158 additions and 400 deletions

View file

@ -29,7 +29,6 @@ noinst_HEADERS = \
libglxabi.h \
libglxabipriv.h \
libglxcurrent.h \
libglxgldispatch.h \
libglxmapping.h \
libglxnoop.h \
libglxnoopdefs.h \
@ -71,5 +70,4 @@ libGLX_la_LDFLAGS = -shared
libGLX_la_SOURCES = \
libglx.c \
libglxmapping.c \
libglxnoop.c \
libglxgldispatch.c
libglxnoop.c

View file

@ -172,7 +172,7 @@ PUBLIC void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pix)
const int screen = __glXScreenFromDrawable(dpy, pix);
const __GLXdispatchTableStatic *pDispatch = __glXGetStaticDispatch(dpy, screen);
__glXRemoveScreenDrawableMapping(pix, screen);
__glXRemoveScreenDrawableMapping(pix);
pDispatch->glx14ep.destroyGLXPixmap(dpy, pix);
}
@ -298,14 +298,10 @@ void __glXNotifyContextDestroyed(GLXContext ctx)
if (canUnmap) {
/*
* XXX: kludge. We should probably remove the screen argument
* from the Remove.*Mapping commands.
*
* XXX: Note: this implies a lock ordering: the current context
* Note: this implies a lock ordering: the current context
* hash lock must be taken before the screen pointer hash lock!
*/
int screen = __glXScreenFromContext(ctx);
__glXRemoveScreenContextMapping(ctx, screen);
__glXRemoveScreenContextMapping(ctx);
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXCurrentContextHash);
@ -392,12 +388,7 @@ static void UntrackCurrentContext(GLXContext ctx)
free(pEntry);
if (needsUnmap) {
/*
* XXX: kludge. We should probably remove the screen argument
* from the Remove.*Mapping commands.
*/
int screen = __glXScreenFromContext(ctx);
__glXRemoveScreenContextMapping(ctx, screen);
__glXRemoveScreenContextMapping(ctx);
}
}
@ -854,7 +845,7 @@ PUBLIC void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
const int screen = __glXScreenFromDrawable(dpy, pbuf);
const __GLXdispatchTableStatic *pDispatch = __glXGetStaticDispatch(dpy, screen);
__glXRemoveScreenDrawableMapping(pbuf, screen);
__glXRemoveScreenDrawableMapping(pbuf);
pDispatch->glx14ep.destroyPbuffer(dpy, pbuf);
}
@ -865,7 +856,7 @@ PUBLIC void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
const int screen = __glXScreenFromDrawable(dpy, pixmap);
const __GLXdispatchTableStatic *pDispatch = __glXGetStaticDispatch(dpy, screen);
__glXRemoveScreenDrawableMapping(pixmap, screen);
__glXRemoveScreenDrawableMapping(pixmap);
pDispatch->glx14ep.destroyPixmap(dpy, pixmap);
}
@ -876,7 +867,7 @@ PUBLIC void glXDestroyWindow(Display *dpy, GLXWindow win)
const int screen = __glXScreenFromDrawable(dpy, win);
const __GLXdispatchTableStatic *pDispatch = __glXGetStaticDispatch(dpy, screen);
__glXRemoveScreenDrawableMapping(win, screen);
__glXRemoveScreenDrawableMapping(win);
pDispatch->glx14ep.destroyWindow(dpy, win);
}

View file

@ -33,6 +33,12 @@
#include <stdint.h>
#include <GL/glx.h>
#include "GLdispatchABI.h"
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* \defgroup glxvendorabi GLX Vendor ABI
*
@ -47,10 +53,6 @@
* present in the static table.
* - core GL dispatch table: this is a structure maintained by the API library
* which contains both GL core (static) and GL extension (dynamic) functions.
* There is always a fixed top-level core dispatch table which is plugged in
* by the API library at make current time, but the vendor may optionally
* specify auxiliary core dispatch tables using the API described below
* with different entrypoints and install them while its context is current.
*
* @{
*/
@ -68,11 +70,6 @@
*/
typedef struct __GLXdispatchTableDynamicRec __GLXdispatchTableDynamic;
/*!
* This opaque structure describes the core GL dispatch table.
*/
typedef struct __GLXcoreDispatchTableRec __GLXcoreDispatchTable;
/*!
* Forward declaration for createGLDispatch export.
*/
@ -120,69 +117,21 @@ typedef struct __GLXapiExportsRec {
GLXContext (*getCurrentContext)(void);
/************************************************************************
* When a context is current, for performance reasons it may be desirable
* for a vendor to use different entrypoints for that context depending on
* the current GL state. The following routines allow a vendor to create and
* manage auxiliary dispatch tables for this purpose.
* These routines are used by vendor dispatch functions to look up
* and add mappings between various objects and screens.
************************************************************************/
/*!
* This retrieves the current core GL dispatch table.
*/
__GLXcoreDispatchTable *(*getCurrentGLDispatch)(void);
void (*addScreenContextMapping)(GLXContext context, int screen);
void (*removeScreenContextMapping)(GLXContext context);
int (*screenFromContext)(GLXContext context);
/*!
* This retrieves the top-level GL dispatch table for the current vendor.
* This must always be defined for the lifetime of the vendor library.
*/
__GLXcoreDispatchTable *(*getTopLevelDispatch)(void);
void (*addScreenFBConfigMapping)(GLXFBConfig config, int screen);
void (*removeScreenFBConfigMapping)(GLXFBConfig config);
int (*screenFromFBConfig)(GLXFBConfig config);
/*!
* This creates an auxiliary core GL dispatch table using the given
* vendor-specific callbacks and data. This data will be passed to the
* getProcAddress callback during dispatch table construction and can be
* used to discriminate between different flavors of entrypoints in the
* vendor.
* XXX: is the getProcAddress callback method too slow? Should we have
* a way for vendor libraries to declare fixed tables at startup that
* can be read quickly?
*/
__GLXcoreDispatchTable *(*createGLDispatch)(
const __GLXvendorCallbacks *cb,
void *data
);
/*!
* This retrieves the offset into the GL dispatch table for the given
* function name, or -1 if the function is not found.
* If a valid offset is returned, the offset is valid for all dispatch
* tables for the lifetime of the API library.
* XXX: should there be a way for vendor libraries to pre-load procs
* they care about?
*/
GLint (*getGLDispatchOffset)(const GLubyte *procName);
/*!
* This sets the given entry in the GL dispatch table to the function
* address pointed to by addr.
*/
void (*setGLDispatchEntry)(__GLXcoreDispatchTable *table,
GLint offset,
__GLXextFuncPtr addr);
/*!
* This makes the given GL dispatch table current. Note this operation
* is only valid when there is a GL context owned by the vendor which
* is current.
*/
void (*makeGLDispatchCurrent)(__GLXcoreDispatchTable *table);
/*!
* This destroys the given GL dispatch table, and returns GL_TRUE on
* success. Note it is an error to attempt to destroy the top-level
* dispatch.
*/
GLboolean (*destroyGLDispatch)(__GLXcoreDispatchTable *table);
void (*addScreenDrawableMapping)(GLXDrawable drawable, int screen);
void (*removeScreenDrawableMapping)(GLXDrawable drawable);
int (*screenFromDrawable)(Display *dpy, GLXDrawable drawable);
} __GLXapiExports;
@ -323,20 +272,15 @@ typedef struct __GLX14EntryPointsRec {
/*!
* This structure stores required vendor library callbacks.
*/
typedef struct __GLXvendorCallbacksRec {
struct __GLXvendorCallbacksRec {
/*!
* This retrieves the pointer to the real GLX or core GL function. data can
* optionally point to vendor-specific information. If data is NULL this is
* expected to retrieve a function suitable for use in the top-level
* dispatch; otherwise the resulting function is implementation-dependent.
* This retrieves the pointer to the real GLX or core GL function.
* isClientAPI indicates whether libglvnd thinks this function is
* from GLX or a client API. This can be used in vendor libraries
* for internal consistency checks.
*/
void *(*getProcAddress) (const GLubyte *procName, void *data);
/*!
* This callback destroys the vendor-specific data pointed to by data,
* which was passed into a createDispatchTable() request.
*/
void (*destroyDispatchData) (void *data);
void *(*getProcAddress) (const GLubyte *procName,
int isClientAPI);
/*!
* This retrieves vendor-neutral functions which use the
@ -349,39 +293,7 @@ typedef struct __GLXvendorCallbacksRec {
* assigned to a particular GLX extension function.
*/
void (*setDispatchIndex) (const GLubyte *procName, int index);
/*!
* This retrieves a function prototype spec (as described by
* _glapi_add_dispatch()) from the vendor library for the given
* function name.
*
* \param [in] procName The name of the function whose spec we are
* interested in.
*
* \param [out] function_names If GL_TRUE is returned, a list of
* null-terminated strings, terminated by NULL, which contain aliases for
* the given function which should share the same dispatch offset. Both the
* strings and the list itself should be free(3)d after they are no longer
* needed.
*
* \param [out] parameter_signature If GL_TRUE is returned, a string
* representing the types of parameters passed into the named function.
* Characters are converted into parameter types using the following rules:
*
* - 'i' for \c GLint, \c GLuint, and \c GLenum
* - 'p' for any pointer type
* - 'f' for \c GLfloat and \c GLclampf
* - 'd' for \c GLdouble and \c GLclampd
*
* This string should be free(3)d after it is no longer needed.
*
* \return GL_TRUE if the vendor library recognized this function and
* provided a prototype, GL_FALSE otherwise.
*/
GLboolean (*getDispatchProto) (const GLubyte *procName,
char ***function_names,
char **parameter_signature);
} __GLXvendorCallbacks;
};
typedef struct __GLXapiImportsRec {
__GLX14EntryPoints glx14ep;
@ -413,4 +325,8 @@ typedef const __GLXapiImports *(*__PFNGLXMAINPROC)
* @}
*/
#if defined(__cplusplus)
}
#endif
#endif /* __LIB_GLX_ABI_H */

View file

@ -1,106 +0,0 @@
/*
* Copyright (c) 2013, 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 "libglxabi.h"
#include "libglxcurrent.h"
#include "libglxmapping.h"
/*
* XXX hack: cast (__GLXcoreDispatchTable *) to the real type (__GLdispatchTable
* *). Maybe cleaner to just expose __GLdispatchTable to the ABI, or have the
* relevant functions take in (void *)?
*/
__GLXcoreDispatchTable *__glXGetCurrentGLDispatch(void)
{
__GLXAPIState *apiState = __glXGetCurrentAPIState();
return (__GLXcoreDispatchTable *)apiState->glas.dispatch;
}
__GLXcoreDispatchTable *__glXGetTopLevelDispatch(void)
{
__GLXAPIState *apiState;
__GLXvendorInfo *vendor;
apiState = __glXGetCurrentAPIState();
vendor = apiState ? apiState->currentVendor : NULL;
return (__GLXcoreDispatchTable *)vendor->glDispatch;
}
__GLXcoreDispatchTable *__glXCreateGLDispatch(const __GLXvendorCallbacks *cb,
void *data)
{
__GLdispatchTable *dispatch = __glDispatchCreateTable(
cb->getProcAddress,
cb->getDispatchProto,
cb->destroyDispatchData,
data
);
return (__GLXcoreDispatchTable *)dispatch;
}
GLint __glXGetGLDispatchOffset(const GLubyte *procName)
{
return __glDispatchGetOffset((const char *)procName);
}
void __glXSetGLDispatchEntry(__GLXcoreDispatchTable *table,
GLint offset,
__GLXextFuncPtr addr)
{
__glDispatchSetEntry((__GLdispatchTable *)table,
offset,
(__GLdispatchProc)addr);
}
void __glXMakeGLDispatchCurrent(__GLXcoreDispatchTable *table)
{
__GLXAPIState *apiState = __glXGetCurrentAPIState();
if (apiState) {
apiState->glas.dispatch = (__GLdispatchTable *)table;
__glDispatchMakeCurrent(&apiState->glas,
apiState->glas.dispatch,
apiState->glas.context);
}
}
GLboolean __glXDestroyGLDispatch(__GLXcoreDispatchTable *table)
{
if (table == __glXGetTopLevelDispatch()) {
return GL_FALSE;
}
__glDispatchDestroyTable((__GLdispatchTable *)table);
return GL_TRUE;
}

View file

@ -36,8 +36,8 @@
# include <stdio.h>
#endif
#include "libglxcurrent.h"
#include "libglxmapping.h"
#include "libglxgldispatch.h"
#include "libglxnoop.h"
#include "libglxthread.h"
#include "trace.h"
@ -74,7 +74,7 @@ typedef struct __GLXdispatchFuncHashRec {
UT_hash_handle hh;
} __GLXdispatchFuncHash;
typedef struct __GLXdispatchTableDynamicRec {
struct __GLXdispatchTableDynamicRec {
/*
* Hash table containing the dynamic dispatch funcs. This is used instead of
* a flat array to avoid sparse array usage. XXX might be more performant to
@ -86,7 +86,7 @@ typedef struct __GLXdispatchTableDynamicRec {
* Pointer to the vendor library info, used by __glXFetchDispatchEntry()
*/
__GLXvendorInfo *vendor;
} __GLXdispatchTableDynamic;
};
/****************************************************************************/
/*
@ -165,6 +165,10 @@ __GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName)
* XXX for full correctness, we should probably load vendors
* on all screens up-front before doing this. However, that
* might be bad for performance?
*
* A better way to solve this issue might be to tweak the ABI slightly
* to allow vendors to provide a standalone DSO which only
* exports vendor-neutral dispatch functions, and nothing else.
*/
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXVendorNameHash);
HASH_ITER(hh, _LH(__glXVendorNameHash), pEntry, tmp) {
@ -222,7 +226,7 @@ __GLXextFuncPtr __glXFetchDispatchEntry(__GLXdispatchTableDynamic *dynDispatch,
if (procName) {
// Get the real address
addr = dynDispatch->vendor->staticDispatch->
glxvc.getProcAddress(procName, NULL);
glxvc.getProcAddress(procName, GL_FALSE);
}
LKDHASH_WRLOCK(__glXPthreadFuncs, dynDispatch->hash);
@ -248,21 +252,31 @@ __GLXextFuncPtr __glXFetchDispatchEntry(__GLXdispatchTableDynamic *dynDispatch,
return addr;
}
static __GLXapiExports glxExportsTable = {
.getDynDispatch = __glXGetDynDispatch,
.fetchDispatchEntry = __glXFetchDispatchEntry,
static __GLXapiExports glxExportsTable;
static glvnd_once_t glxExportsTableOnceControl = GLVND_ONCE_INIT;
static void InitExportsTable(void)
{
glxExportsTable.getDynDispatch = __glXGetDynDispatch;
glxExportsTable.getCurrentDynDispatch = __glXGetCurrentDynDispatch;
glxExportsTable.fetchDispatchEntry = __glXFetchDispatchEntry;
/* We use the real function since __glXGetCurrentContext is inline */
.getCurrentContext = glXGetCurrentContext,
glxExportsTable.getCurrentContext = glXGetCurrentContext;
/* GL dispatch management */
.getCurrentGLDispatch = __glXGetCurrentGLDispatch,
.getTopLevelDispatch = __glXGetTopLevelDispatch,
.createGLDispatch = __glXCreateGLDispatch,
.getGLDispatchOffset = __glXGetGLDispatchOffset,
.makeGLDispatchCurrent = __glXMakeGLDispatchCurrent,
.destroyGLDispatch = __glXDestroyGLDispatch
};
glxExportsTable.addScreenContextMapping = __glXAddScreenContextMapping;
glxExportsTable.removeScreenContextMapping = __glXRemoveScreenContextMapping;
glxExportsTable.screenFromContext = __glXScreenFromContext;
glxExportsTable.addScreenFBConfigMapping = __glXAddScreenFBConfigMapping;
glxExportsTable.removeScreenFBConfigMapping = __glXRemoveScreenFBConfigMapping;
glxExportsTable.screenFromFBConfig = __glXScreenFromFBConfig;
glxExportsTable.addScreenDrawableMapping = __glXAddScreenDrawableMapping;
glxExportsTable.removeScreenDrawableMapping = __glXRemoveScreenDrawableMapping;
glxExportsTable.screenFromDrawable = __glXScreenFromDrawable;
}
static char *ConstructVendorLibraryFilename(const char *vendorName)
{
@ -322,6 +336,10 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
goto fail;
}
/* Initialize the glxExportsTable if we haven't already */
__glXPthreadFuncs.once(&glxExportsTableOnceControl,
InitExportsTable);
dispatch = (*glxMainProc)(GLX_VENDOR_ABI_VERSION,
&glxExportsTable,
vendorName);
@ -343,7 +361,9 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
vendor->staticDispatch = dispatch;
vendor->glDispatch = (__GLdispatchTable *)
__glXCreateGLDispatch(&dispatch->glxvc, NULL);
__glDispatchCreateTable(
dispatch->glxvc.getProcAddress
);
if (!vendor->glDispatch) {
goto fail;
}
@ -556,7 +576,7 @@ static void AddScreenPointerMapping(void *ptr, int screen)
}
static void RemoveScreenPointerMapping(void *ptr, int screen)
static void RemoveScreenPointerMapping(void *ptr)
{
__GLXscreenPointerMappingHash *pEntry;
@ -564,10 +584,6 @@ static void RemoveScreenPointerMapping(void *ptr, int screen)
return;
}
if (screen < 0) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
HASH_FIND_PTR(_LH(__glXScreenPointerMappingHash), &ptr, pEntry);
@ -606,9 +622,9 @@ void __glXAddScreenContextMapping(GLXContext context, int screen)
}
void __glXRemoveScreenContextMapping(GLXContext context, int screen)
void __glXRemoveScreenContextMapping(GLXContext context)
{
RemoveScreenPointerMapping(context, screen);
RemoveScreenPointerMapping(context);
}
@ -624,9 +640,9 @@ void __glXAddScreenFBConfigMapping(GLXFBConfig config, int screen)
}
void __glXRemoveScreenFBConfigMapping(GLXFBConfig config, int screen)
void __glXRemoveScreenFBConfigMapping(GLXFBConfig config)
{
RemoveScreenPointerMapping(config, screen);
RemoveScreenPointerMapping(config);
}
@ -682,7 +698,7 @@ static void AddScreenXIDMapping(XID xid, int screen)
}
static void RemoveScreenXIDMapping(XID xid, int screen)
static void RemoveScreenXIDMapping(XID xid)
{
__GLXscreenXIDMappingHash *pEntry;
@ -690,10 +706,6 @@ static void RemoveScreenXIDMapping(XID xid, int screen)
return;
}
if (screen < 0) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
HASH_FIND(hh, _LH(__glXScreenXIDMappingHash), &xid, sizeof(xid), pEntry);
@ -735,9 +747,9 @@ void __glXAddScreenDrawableMapping(GLXDrawable drawable, int screen)
}
void __glXRemoveScreenDrawableMapping(GLXDrawable drawable, int screen)
void __glXRemoveScreenDrawableMapping(GLXDrawable drawable)
{
RemoveScreenXIDMapping(drawable, screen);
RemoveScreenXIDMapping(drawable);
}

View file

@ -60,15 +60,15 @@ __GLdispatchTable *__glXGetGLDispatch(Display *dpy, const int screen);
* of a particular GLX call.
*/
void __glXAddScreenContextMapping(GLXContext context, int screen);
void __glXRemoveScreenContextMapping(GLXContext context, int screen);
void __glXRemoveScreenContextMapping(GLXContext context);
int __glXScreenFromContext(GLXContext context);
void __glXAddScreenFBConfigMapping(GLXFBConfig config, int screen);
void __glXRemoveScreenFBConfigMapping(GLXFBConfig config, int screen);
void __glXRemoveScreenFBConfigMapping(GLXFBConfig config);
int __glXScreenFromFBConfig(GLXFBConfig config);
void __glXAddScreenDrawableMapping(GLXDrawable drawable, int screen);
void __glXRemoveScreenDrawableMapping(GLXDrawable drawable, int screen);
void __glXRemoveScreenDrawableMapping(GLXDrawable drawable);
int __glXScreenFromDrawable(Display *dpy, GLXDrawable drawable);
__GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName);

View file

@ -35,9 +35,6 @@
* libglxnoop.c and the libGL filter library code.
*/
#include "libglxabipriv.h"
#include "libglxnoop.h"
GLXNOOP XVisualInfo* NOOP_FUNC(ChooseVisual)(Display *dpy, int screen,
int *attrib_list)
{

View file

@ -157,42 +157,44 @@ static void FixupDispatchTable(__GLdispatchTable *dispatch)
CheckDispatchLocked();
__GLdispatchProcEntry *curProc, *tmpProc;
char **function_name, **function_names, *parameter_signature;
const char *function_names[2];
void *procAddr;
void **tbl = (void **)dispatch->table;
/*
* For each proc in the newProcList, request a dispatch prototype from the
* vendor library and plug it into glapi. If we succeed, move the proc
* from the newProcList to the extProcList, and do some cleanup.
* For each proc in the newProcList, attempt to create a dispatch stub in
* glapi, then move the proc from the newProcList to the extProcList and do
* some cleanup.
*/
glvnd_list_for_each_entry_safe(curProc, tmpProc, &newProcList, entry) {
DBG_PRINTF(20, "newProc procName=%s\n", curProc->procName);
if ((*dispatch->getDispatchProto)((const GLubyte *)curProc->procName,
&function_names,
&parameter_signature)) {
curProc->offset =
_glapi_add_dispatch((const char * const *)function_names,
(const char *)parameter_signature);
DBG_PRINTF(20, "newProc offset=%d\n", curProc->offset);
/*
* _glapi_add_dispatch() has support for mapping multiple "equivalent"
* function names (for example, glUniform1fv() and glUniform1fvARB()) to
* one dispatch stub. However, this becomes problematic in a
* multi-vendor scenario, as vendors may have differing viewpoints on
* whether two entrypoints are identical. The GLX_ARB_create_context
* extension, for example, defines "forward-compatible" contexts in
* which calling the ARB version of a function is an error if the
* non-ARB version is available. For vendors that support this
* extension, the ARB and non-ARB entrypoints are not identical.
*
* Hence, we only pass one function name per entrypoint to glapi.
*/
function_names[0] = curProc->procName;
function_names[1] = NULL;
assert(curProc->offset != -1);
curProc->offset =
_glapi_add_dispatch((const char * const *)function_names);
DBG_PRINTF(20, "newProc offset=%d\n", curProc->offset);
glvnd_list_del(&curProc->entry);
glvnd_list_add(&curProc->entry, &extProcList);
assert(curProc->offset != -1);
for (function_name = function_names;
*function_name; function_name++) {
free(*function_name);
}
glvnd_list_del(&curProc->entry);
glvnd_list_add(&curProc->entry, &extProcList);
free(function_names);
free(parameter_signature);
}
}
/*
@ -208,8 +210,7 @@ static void FixupDispatchTable(__GLdispatchTable *dispatch)
assert(curProc->procName);
procAddr = (void*)(*dispatch->getProcAddress)(
(const GLubyte *)curProc->procName,
dispatch->vendorData);
(const GLubyte *)curProc->procName, GL_TRUE);
tbl[curProc->offset] = procAddr ? procAddr : (void *)noop_func;
DBG_PRINTF(20, "extProc procName=%s, addr=%p, noop=%p\n",
@ -305,15 +306,12 @@ PUBLIC void __glDispatchSetEntry(__GLdispatchTable *dispatch,
UnlockDispatch();
}
GLint __glDispatchGetOffset(const char *procName)
GLint __glDispatchGetOffset(const GLubyte *procName)
{
return _glapi_get_proc_offset(procName);
return _glapi_get_proc_offset((const char *)procName);
}
PUBLIC __GLdispatchTable *__glDispatchCreateTable(__GLgetProcAddressCallback getProcAddress,
__GLgetDispatchProtoCallback getDispatchProto,
__GLdestroyVendorDataCallback destroyVendorData,
void *vendorData)
PUBLIC __GLdispatchTable *__glDispatchCreateTable(__GLgetProcAddressCallback getProcAddress)
{
__GLdispatchTable *dispatch = malloc(sizeof(__GLdispatchTable));
@ -322,10 +320,6 @@ PUBLIC __GLdispatchTable *__glDispatchCreateTable(__GLgetProcAddressCallback get
dispatch->table = NULL;
dispatch->getProcAddress = getProcAddress;
dispatch->getDispatchProto = getDispatchProto;
dispatch->destroyVendorData = destroyVendorData;
dispatch->vendorData = vendorData;
return dispatch;
}
@ -336,15 +330,13 @@ PUBLIC void __glDispatchDestroyTable(__GLdispatchTable *dispatch)
// TODO: delete the global lists
// TODO: this is currently unused...
LockDispatch();
dispatch->destroyVendorData(dispatch->vendorData);
free(dispatch->table);
free(dispatch);
UnlockDispatch();
}
static struct _glapi_table
*CreateGLAPITable(__GLgetProcAddressCallback getProcAddress,
void *vendorData)
*CreateGLAPITable(__GLgetProcAddressCallback getProcAddress)
{
size_t entries = _glapi_get_dispatch_table_size();
struct _glapi_table *table = (struct _glapi_table *)
@ -355,8 +347,7 @@ static struct _glapi_table
if (table) {
_glapi_init_table_from_callback(table,
entries,
getProcAddress,
vendorData);
getProcAddress);
}
return table;
@ -380,8 +371,7 @@ PUBLIC void __glDispatchMakeCurrent(__GLdispatchAPIState *apiState,
// Lazily create the dispatch table if we haven't already
if (!dispatch->table) {
dispatch->table = CreateGLAPITable(dispatch->getProcAddress,
dispatch->vendorData);
dispatch->table = CreateGLAPITable(dispatch->getProcAddress);
}
FixupDispatchTable(dispatch);

View file

@ -33,6 +33,7 @@
#include "glheader.h"
#include "compiler.h"
#include "glvnd_pthread.h"
#include "GLdispatchABI.h"
/*!
* \defgroup gldispatch core GL/GLES dispatch and TLS module
@ -53,19 +54,6 @@
PUBLIC void *_glapi_get_current(int index);
typedef void (*__GLdispatchProc)(void);
typedef void *(*__GLgetProcAddressCallback)(const GLubyte *procName,
void *vendorData);
typedef void *(*__GLgetProcAddressCallback)(const GLubyte *procName,
void *vendorData);
typedef GLboolean (*__GLgetDispatchProtoCallback)(const GLubyte *procName,
char ***function_names,
char **parameter_signature);
typedef void (*__GLdestroyVendorDataCallback)(void *vendorData);
/* Opaque dispatch table structure. */
typedef struct __GLdispatchTableRec __GLdispatchTable;
/* Namespaces for API state */
enum {
GLDISPATCH_API_GLX,
@ -124,18 +112,13 @@ PUBLIC __GLdispatchProc __glDispatchGetProcAddress(const char *procName);
* \param [in] getProcAddress a vendor library callback GLdispatch can use to
* query addresses of functions from the vendor. This callback also takes
* a pointer to vendor-private data.
* \param [in] getDispatchProto a vendor library callback GLdispatch can use to
* query prototypes of functions it doesn't know about from the vendor.
* \param [in] destroyVendorData a vendor library callback to destroy private
* data when the dispatch table is destroyed.
* \param [in] vendorData a pointer to vendor library private data, which can
* be used by the getProcAddress callback.
*/
PUBLIC __GLdispatchTable *__glDispatchCreateTable(
__GLgetProcAddressCallback getProcAddress,
__GLgetDispatchProtoCallback getDispatchProto,
__GLdestroyVendorDataCallback destroyVendorData,
void *vendorData
__GLgetProcAddressCallback getProcAddress
);
/*!
@ -186,7 +169,7 @@ static inline void *__glDispatchGetCurrentContext(void)
* describes a real offset. If the call succeeds, the offset remains valid for
* the lifetime of libglvnd for all GL dispatch tables used by libglvnd.
*/
PUBLIC GLint __glDispatchGetOffset(const char *procName);
PUBLIC GLint __glDispatchGetOffset(const GLubyte *procName);
/*!
* This sets the dispatch table entry given by <offset> to the entrypoint

View file

@ -27,26 +27,35 @@
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#ifndef __LIBGLX_GL_DISPATCH_H__
#define __LIBGLX_GL_DISPATCH_H__
#include <GL/gl.h>
#include "libglxabi.h"
#if !defined(__GL_DISPATCH_ABI_H)
#define __GL_DISPATCH_ABI_H
/*
* These functions define the interface by which a vendor library can install
* and manage its own collection of dispatch tables. See libglxabi.h for
* a more detailed explanation of these functions.
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* \defgroup gldispatchabi GL dispatching ABI
*
* This is not a complete ABI, but rather a fragment common to the libEGL and
* libGLX ABIs. Changes to this file should be accompanied by a version bump to
* these client ABIs.
*/
__GLXcoreDispatchTable *__glXGetCurrentGLDispatch(void);
__GLXcoreDispatchTable *__glXGetTopLevelDispatch(void);
__GLXcoreDispatchTable *__glXCreateGLDispatch(const __GLXvendorCallbacks *cb,
void *data);
GLint __glXGetGLDispatchOffset(const GLubyte *procName);
void __glXSetGLDispatchEntry(__GLXcoreDispatchTable *table,
GLint offset,
__GLXextFuncPtr addr);
void __glXMakeGLDispatchCurrent(__GLXcoreDispatchTable *table);
GLboolean __glXDestroyGLDispatch(__GLXcoreDispatchTable *table);
/*!
* This opaque structure describes the core GL dispatch table.
*/
typedef struct __GLdispatchTableRec __GLdispatchTable;
#endif // __LIBGLX_GL_DISPATCH_H__
typedef void (*__GLdispatchProc)(void);
typedef void *(*__GLgetProcAddressCallback)(const GLubyte *procName,
int isClientAPI);
#if defined(__cplusplus)
}
#endif
#endif // __GL_DISPATCH_ABI_H

View file

@ -38,7 +38,7 @@
* Private dispatch table structure. This is used by GLdispatch for tracking
* and updating dispatch tables.
*/
typedef struct __GLdispatchTableRec {
struct __GLdispatchTableRec {
/*! Number of threads this dispatch is current on */
int currentThreads;
@ -47,17 +47,12 @@ typedef struct __GLdispatchTableRec {
/*! Saved vendor library callbacks */
__GLgetProcAddressCallback getProcAddress;
__GLgetDispatchProtoCallback getDispatchProto;
__GLdestroyVendorDataCallback destroyVendorData;
/*! A pointer to vendor-specific data */
void *vendorData;
/*! The real dispatch table */
struct _glapi_table *table;
/*! List handle */
struct glvnd_list entry;
} __GLdispatchTable;
};
#endif

View file

@ -114,8 +114,7 @@ void
_glapi_init_table_from_callback(struct _glapi_table *table,
size_t entries,
void *(*get_proc_addr)(const unsigned char *name,
void *private_data),
void *private_data)
int isClientAPI))
{
"""
@ -128,7 +127,7 @@ body_template = """
if(!table->%(name)s) {
void ** procp = (void **) &table->%(name)s;
*procp = (*get_proc_addr)((const unsigned char *)"gl%(entry_point)s",
private_data);
GL_TRUE);
}
"""

View file

@ -168,8 +168,7 @@ _glapi_get_dispatch_table_size(void);
_GLAPI_EXPORT int
_glapi_add_dispatch( const char * const * function_names,
const char * parameter_signature );
_glapi_add_dispatch(const char * const * function_names);
_GLAPI_EXPORT int
_glapi_get_proc_offset(const char *funcName);
@ -190,8 +189,7 @@ _GLAPI_EXPORT void
_glapi_init_table_from_callback(struct _glapi_table *table,
size_t entries,
void *(*get_proc_addr)(const unsigned char *name,
void *private_data),
void *private_data);
int isClientAPI));
_GLAPI_EXPORT unsigned long

View file

@ -124,8 +124,7 @@ _glapi_get_dispatch_table_size(void)
* Check parameter_signature.
*/
int
_glapi_add_dispatch( const char * const * function_names,
const char * parameter_signature )
_glapi_add_dispatch( const char * const * function_names)
{
const struct mapi_stub *function_stubs[8];
const struct mapi_stub *alias = NULL;

View file

@ -439,7 +439,8 @@ static void dummyNopStub (void)
}
// XXX non-entry point ABI functions
static void *dummyGetProcAddress (const GLubyte *procName, void *data)
static void *dummyGetProcAddress (const GLubyte *procName,
int isClientAPI)
{
int i;
for (i = 0; i < ARRAY_LEN(procAddresses); i++) {
@ -451,11 +452,6 @@ static void *dummyGetProcAddress (const GLubyte *procName, void
return (void *)dummyNopStub;
}
static void dummyDestroyDispatchData(void *data)
{
// nop
}
static void *dummyGetDispatchAddress (const GLubyte *procName)
{
if (!strcmp((const char *)procName, "glXExampleExtensionFunction")) {
@ -472,24 +468,6 @@ static void dummySetDispatchIndex (const GLubyte *procName, int ind
}
}
static GLboolean dummyGetDispatchProto (const GLubyte *procName,
char ***function_names,
char **parameter_signature)
{
// We only export one extension function here
// TODO: Maybe a good idea to test a bunch of different protos?
if (!strcmp((const char *)procName, "glMakeCurrentTestResults")) {
*function_names = malloc(2 * sizeof(char *));
(*function_names)[0] = strdup("glMakeCurrentTestResults");
(*function_names)[1] = NULL;
*parameter_signature = strdup("ipp");
return GL_TRUE;
}
return GL_FALSE;
}
static const __GLXapiImports dummyImports =
{
/* Entry points */
@ -531,10 +509,8 @@ static const __GLXapiImports dummyImports =
/* Non-entry points */
.glxvc = {
.getProcAddress = dummyGetProcAddress,
.destroyDispatchData = dummyDestroyDispatchData,
.getDispatchAddress = dummyGetDispatchAddress,
.setDispatchIndex = dummySetDispatchIndex,
.getDispatchProto = dummyGetDispatchProto
}
};

View file

@ -11,8 +11,9 @@ libGLX_dummy_copy : libGLX_dummy.la
cp .libs/libGLX_dummy.so.0.0.0 .libs/libGLX_dummy_1.so.0
libGLX_dummy_la_CFLAGS = \
libGLX_dummy_la_CFLAGS = \
-I$(top_srcdir)/src/GLX \
-I$(top_srcdir)/src/GLdispatch \
-I$(top_srcdir)/src/util \
-I$(top_srcdir)/src/util/trace \
-I$(top_srcdir)/include \