libglvnd/src/GLX/libglxmapping.c

969 lines
28 KiB
C
Raw Normal View History

2013-08-23 01:06:53 +02:00
/*
* 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.
2013-08-23 01:06:53 +02:00
*/
#include <X11/Xlibint.h>
#include <pthread.h>
#include <dlfcn.h>
#if defined(HASH_DEBUG)
# include <stdio.h>
#endif
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>
2013-11-26 00:21:41 +01:00
#include "libglxcurrent.h"
2013-08-23 01:06:53 +02:00
#include "libglxmapping.h"
#include "libglxnoop.h"
#include "libglxthread.h"
#include "libglxstring.h"
#include "trace.h"
2013-08-23 01:06:53 +02:00
#include "lkdhash.h"
#include "x11glvnd.h"
#define _GNU_SOURCE 1
2013-08-23 01:06:53 +02:00
/*
* Hash table containing a mapping from dispatch table index entries to
* entry point names. This is used in __glXFetchDispatchEntry() to query
* the appropriate vendor in the case where the entry hasn't been seen before
* by this vendor.
*/
typedef struct __GLXdispatchIndexHashRec {
int index;
GLubyte *procName;
UT_hash_handle hh;
} __GLXdispatchIndexHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXdispatchIndexHash, __glXDispatchIndexHash);
/*
* Monotonically-increasing number describing both the virtual "size" of the
* dynamic dispatch table and the next unused index. Must be accessed holding
* the __glXDispatchIndexHash lock.
*/
static int __glXNextUnusedHashIndex;
typedef struct __GLXdispatchFuncHashRec {
int index;
__GLXextFuncPtr addr;
UT_hash_handle hh;
} __GLXdispatchFuncHash;
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>
2013-11-26 00:21:41 +01:00
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
* use an array, though?
*/
DEFINE_LKDHASH(__GLXdispatchFuncHash, hash);
/*
* Pointer to the vendor library info, used by __glXFetchDispatchEntry()
*/
__GLXvendorInfo *vendor;
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>
2013-11-26 00:21:41 +01:00
};
/****************************************************************************/
/*
* __glXVendorScreenHash is a hash table which maps a Display+screen to a vendor.
* Look up this mapping from the X server once, the first time a unique
* Display+screen pair is seen.
*/
typedef struct {
Display *dpy;
int screen;
} __GLXvendorScreenHashKey;
typedef struct __GLXvendorScreenHashRec {
__GLXvendorScreenHashKey key;
__GLXvendorInfo *vendor;
// XXX for performance reasons we may want to stash the dispatch tables here
// as well
UT_hash_handle hh;
} __GLXvendorScreenHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXvendorScreenHash, __glXVendorScreenHash);
/*
* __glXVendorNameHash is a hash table mapping a vendor name to vendor info.
*/
typedef struct __GLXvendorNameHashRec {
const char *name;
__GLXvendorInfo *vendor;
UT_hash_handle hh;
} __GLXvendorNameHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXvendorNameHash, __glXVendorNameHash);
typedef struct __GLXdisplayInfoHashRec {
Display *dpy;
__GLXdisplayInfo info;
UT_hash_handle hh;
} __GLXdisplayInfoHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXdisplayInfoHash, __glXDisplayInfoHash);
static GLboolean AllocDispatchIndex(__GLXvendorInfo *vendor,
const GLubyte *procName)
{
__GLXdispatchIndexHash *pEntry = malloc(sizeof(*pEntry));
if (!pEntry) {
return GL_FALSE;
}
pEntry->procName = (GLubyte *)strdup((const char *)procName);
if (!pEntry->procName) {
free(pEntry);
return GL_FALSE;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
pEntry->index = __glXNextUnusedHashIndex++;
// Notify the vendor this is the index which should be used
vendor->staticDispatch->
glxvc.setDispatchIndex(procName, pEntry->index);
HASH_ADD_INT(_LH(__glXDispatchIndexHash),
index, pEntry);
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
return GL_TRUE;
}
/*!
* Callback function used when freeing the dispatch index hash table.
*/
static void CleanupDispatchIndexEntry(void *unused, __GLXdispatchIndexHash *pEntry)
{
assert(pEntry);
free(pEntry->procName);
}
/*!
* This function queries each loaded vendor to determine if there is
* a vendor-implemented dispatch function. The dispatch function
* uses the vendor <-> API library ABI to determine the screen given
* the parameters of the function and dispatch to the correct vendor's
* implementation.
2013-08-23 01:06:53 +02:00
*/
__GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName)
2013-08-23 01:06:53 +02:00
{
__GLXextFuncPtr addr = NULL;
__GLXvendorNameHash *pEntry, *tmp;
/*
* XXX for full correctness, we should probably load vendors
* on all screens up-front before doing this. However, that
* might be bad for performance?
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>
2013-11-26 00:21:41 +01:00
*
* 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) {
// See if the current vendor supports this GLX entry point
addr = pEntry->vendor->staticDispatch->
glxvc.getDispatchAddress(procName);
if (addr) {
// Allocate the new dispatch index.
if (!AllocDispatchIndex(pEntry->vendor, procName)) {
addr = NULL;
}
break;
}
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorNameHash);
return addr;
}
__GLXextFuncPtr __glXFetchDispatchEntry(__GLXvendorInfo *vendor,
int index)
{
__GLXextFuncPtr addr = NULL;
__GLXdispatchFuncHash *pEntry;
GLubyte *procName = NULL;
__GLXdispatchTableDynamic *dynDispatch = vendor->dynDispatch;
LKDHASH_RDLOCK(__glXPthreadFuncs, dynDispatch->hash);
HASH_FIND_INT(_LH(dynDispatch->hash), &index, pEntry);
if (pEntry) {
// This can be NULL, which indicates the vendor does not implement this
// entry. Vendor library provided dispatch functions are expected to
// default to a no-op in case dispatching fails.
addr = pEntry->addr;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, dynDispatch->hash);
if (!pEntry) {
// Not seen before by this vendor: query the vendor for the right
// address to use.
__GLXdispatchIndexHash *pdiEntry;
// First retrieve the procname of this index
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
HASH_FIND_INT(_LH(__glXDispatchIndexHash), &index, pdiEntry);
procName = pdiEntry->procName;
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
// This should have a valid entry point associated with it.
assert(procName);
if (procName) {
// Get the real address
addr = dynDispatch->vendor->staticDispatch->
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>
2013-11-26 00:21:41 +01:00
glxvc.getProcAddress(procName, GL_FALSE);
}
LKDHASH_WRLOCK(__glXPthreadFuncs, dynDispatch->hash);
HASH_FIND_INT(_LH(dynDispatch->hash), &index, pEntry);
if (!pEntry) {
pEntry = malloc(sizeof(*pEntry));
if (!pEntry) {
// Uh-oh!
assert(pEntry);
LKDHASH_UNLOCK(__glXPthreadFuncs, dynDispatch->hash);
return NULL;
}
pEntry->index = index;
pEntry->addr = addr;
HASH_ADD_INT(_LH(dynDispatch->hash), index, pEntry);
} else {
addr = pEntry->addr;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, dynDispatch->hash);
}
return addr;
}
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>
2013-11-26 00:21:41 +01:00
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 */
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>
2013-11-26 00:21:41 +01:00
glxExportsTable.getCurrentContext = glXGetCurrentContext;
glxExportsTable.addScreenContextMapping = __glXAddScreenContextMapping;
glxExportsTable.removeScreenContextMapping = __glXRemoveScreenContextMapping;
glxExportsTable.vendorFromContext = __glXVendorFromContext;
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>
2013-11-26 00:21:41 +01:00
glxExportsTable.addScreenFBConfigMapping = __glXAddScreenFBConfigMapping;
glxExportsTable.removeScreenFBConfigMapping = __glXRemoveScreenFBConfigMapping;
glxExportsTable.vendorFromFBConfig = __glXVendorFromFBConfig;
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>
2013-11-26 00:21:41 +01:00
glxExportsTable.addScreenVisualMapping = __glXAddScreenVisualMapping;
glxExportsTable.removeScreenVisualMapping = __glXRemoveScreenVisualMapping;
glxExportsTable.vendorFromVisual = __glXVendorFromVisual;
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>
2013-11-26 00:21:41 +01:00
glxExportsTable.addScreenDrawableMapping = __glXAddScreenDrawableMapping;
glxExportsTable.removeScreenDrawableMapping = __glXRemoveScreenDrawableMapping;
glxExportsTable.vendorFromDrawable = __glXVendorFromDrawable;
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>
2013-11-26 00:21:41 +01:00
}
static char *ConstructVendorLibraryFilename(const char *vendorName)
{
char *filename;
int ret;
ret = glvnd_asprintf(&filename, "libGLX_%s.so.0", vendorName);
if (ret < 0) {
return NULL;
}
return filename;
2013-08-23 01:06:53 +02:00
}
void TeardownVendor(__GLXvendorInfo *vendor, Bool doLibraryUnload)
{
free(vendor->name);
if (vendor->glDispatch) {
__glDispatchDestroyTable(vendor->glDispatch);
}
/* Clean up the dynamic dispatch table */
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXdispatchFuncHash,
vendor->dynDispatch->hash, NULL, NULL, True);
free(vendor->dynDispatch);
if (doLibraryUnload) {
dlclose(vendor->dlhandle);
}
free(vendor);
}
__GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
2013-08-23 01:06:53 +02:00
{
__GLXvendorNameHash *pEntry = NULL;
void *dlhandle = NULL;
__PFNGLXMAINPROC glxMainProc;
const __GLXdispatchTableStatic *dispatch;
__GLXdispatchTableDynamic *dynDispatch;
__GLXvendorInfo *vendor = NULL;
Bool locked = False;
int vendorID = -1;
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXVendorNameHash);
HASH_FIND(hh, _LH(__glXVendorNameHash), vendorName, strlen(vendorName), pEntry);
if (pEntry) {
vendor = pEntry->vendor;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorNameHash);
if (!pEntry) {
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXVendorNameHash);
locked = True;
// Do another lookup to check uniqueness
HASH_FIND(hh, _LH(__glXVendorNameHash), vendorName, strlen(vendorName), pEntry);
if (!pEntry) {
char *filename;
// Previously unseen vendor. dlopen() the new vendor and add it to the
// hash table.
pEntry = calloc(1, sizeof(*pEntry));
if (!pEntry) {
goto fail;
}
filename = ConstructVendorLibraryFilename(vendorName);
if (filename) {
dlhandle = dlopen(filename, RTLD_LAZY);
}
free(filename);
if (!dlhandle) {
goto fail;
}
glxMainProc = dlsym(dlhandle, __GLX_MAIN_PROTO_NAME);
if (!glxMainProc) {
goto fail;
}
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>
2013-11-26 00:21:41 +01:00
/* Initialize the glxExportsTable if we haven't already */
__glXPthreadFuncs.once(&glxExportsTableOnceControl,
InitExportsTable);
vendorID = __glDispatchNewVendorID();
assert(vendorID >= 0);
dispatch = (*glxMainProc)(GLX_VENDOR_ABI_VERSION,
&glxExportsTable,
vendorName,
vendorID);
if (!dispatch) {
goto fail;
}
vendor = pEntry->vendor
= calloc(1, sizeof(__GLXvendorInfo));
if (!vendor) {
goto fail;
}
pEntry->name = vendor->name = strdup(vendorName);
vendor->vendorID = vendorID;
if (!vendor->name) {
goto fail;
}
vendor->dlhandle = dlhandle;
vendor->staticDispatch = dispatch;
vendor->glDispatch = (__GLdispatchTable *)
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>
2013-11-26 00:21:41 +01:00
__glDispatchCreateTable(
dispatch->glxvc.getProcAddress
);
if (!vendor->glDispatch) {
goto fail;
}
dynDispatch = vendor->dynDispatch
= malloc(sizeof(__GLXdispatchTableDynamic));
if (!dynDispatch) {
goto fail;
}
/* Initialize the dynamic dispatch table */
LKDHASH_INIT(__glXPthreadFuncs, dynDispatch->hash);
dynDispatch->vendor = vendor;
HASH_ADD_KEYPTR(hh, _LH(__glXVendorNameHash), vendor->name,
strlen(vendor->name), pEntry);
} else {
/* Some other thread added a vendor */
vendor = pEntry->vendor;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorNameHash);
}
return vendor;
fail:
if (locked) {
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorNameHash);
}
if (dlhandle) {
dlclose(dlhandle);
}
if (vendor) {
TeardownVendor(vendor, False/* doLibraryUnload */);
}
free(pEntry);
return NULL;
2013-08-23 01:06:53 +02:00
}
static void CleanupVendorNameEntry(void *unused,
__GLXvendorNameHash *pEntry)
{
TeardownVendor(pEntry->vendor, True/* doLibraryUnload */);
}
__GLXvendorInfo *__glXLookupVendorByScreen(Display *dpy, const int screen)
{
__GLXvendorInfo *vendor = NULL;
__GLXvendorScreenHash *pEntry = NULL;
__GLXvendorScreenHashKey key;
if (screen < 0) {
return NULL;
}
memset(&key, 0, sizeof(key));
key.dpy = dpy;
key.screen = screen;
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXVendorScreenHash);
HASH_FIND(hh, _LH(__glXVendorScreenHash), &key,
sizeof(key), pEntry);
if (pEntry) {
vendor = pEntry->vendor;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorScreenHash);
if (!pEntry) {
/*
* If we have specified a vendor library, use that. Otherwise,
* try to lookup the vendor based on the current screen.
*/
const char *preloadedVendorName = getenv("__GLX_VENDOR_LIBRARY_NAME");
char *queriedVendorName;
assert(!vendor);
if (preloadedVendorName) {
vendor = __glXLookupVendorByName(preloadedVendorName);
}
if (!vendor && (dpy != NULL)) {
queriedVendorName = XGLVQueryScreenVendorMapping(dpy, screen);
vendor = __glXLookupVendorByName(queriedVendorName);
Xfree(queriedVendorName);
}
if (!vendor) {
/* No vendor available */
return NULL;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXVendorScreenHash);
HASH_FIND(hh, _LH(__glXVendorScreenHash), &key, sizeof(key), pEntry);
if (!pEntry) {
pEntry = malloc(sizeof(*pEntry));
if (!pEntry) {
return NULL;
}
pEntry->key.dpy = dpy;
pEntry->key.screen = screen;
pEntry->vendor = vendor;
HASH_ADD(hh, _LH(__glXVendorScreenHash), key,
sizeof(__GLXvendorScreenHashKey), pEntry);
} else {
/* Some other thread already added a vendor */
vendor = pEntry->vendor;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXVendorScreenHash);
}
DBG_PRINTF(10, "Found vendor \"%s\" for screen %d\n",
vendor->name, screen);
return vendor;
}
2013-08-23 01:06:53 +02:00
const __GLXdispatchTableStatic *__glXGetStaticDispatch(Display *dpy, const int screen)
2013-08-23 01:06:53 +02:00
{
__GLXvendorInfo *vendor = __glXLookupVendorByScreen(dpy, screen);
2013-08-23 01:06:53 +02:00
if (vendor) {
assert(vendor->staticDispatch);
return vendor->staticDispatch;
} else {
2013-08-23 01:06:53 +02:00
return __glXDispatchNoopPtr;
}
}
const __GLXdispatchTableStatic * __glXGetDrawableStaticDispatch(Display *dpy,
GLXDrawable drawable)
{
int screen = __glXScreenFromDrawable(dpy, drawable);
return __glXGetStaticDispatch(dpy, screen);
}
__GLdispatchTable *__glXGetGLDispatch(Display *dpy, const int screen)
2013-08-23 01:06:53 +02:00
{
__GLXvendorInfo *vendor = __glXLookupVendorByScreen(dpy, screen);
2013-08-23 01:06:53 +02:00
if (vendor) {
assert(vendor->glDispatch);
return vendor->glDispatch;
} else {
return NULL;
2013-08-23 01:06:53 +02:00
}
}
2013-08-23 01:06:53 +02:00
__GLXvendorInfo *__glXGetDynDispatch(Display *dpy, const int screen)
{
__glXThreadInitialize();
__GLXvendorInfo *vendor = __glXLookupVendorByScreen(dpy, screen);
return vendor;
}
2013-08-23 01:06:53 +02:00
__GLXdisplayInfo *__glXLookupDisplay(Display *dpy)
{
__GLXdisplayInfoHash *pEntry = NULL;
if (dpy == NULL) {
return NULL;
}
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
HASH_FIND_PTR(_LH(__glXDisplayInfoHash), &dpy, pEntry);
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
if (pEntry != NULL) {
return &pEntry->info;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
HASH_FIND_PTR(_LH(__glXDisplayInfoHash), &dpy, pEntry);
if (pEntry == NULL) {
pEntry = (__GLXdisplayInfoHash *) malloc(sizeof(*pEntry));
if (pEntry != NULL) {
memset(pEntry, 0, sizeof(*pEntry));
pEntry->dpy = dpy;
HASH_ADD_PTR(_LH(__glXDisplayInfoHash), dpy, pEntry);
}
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
if (pEntry != NULL) {
return &pEntry->info;
} else {
return NULL;
}
}
void __glXFreeDisplay(Display *dpy)
{
__GLXdisplayInfoHash *pEntry = NULL;
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
HASH_FIND_PTR(_LH(__glXDisplayInfoHash), &dpy, pEntry);
if (pEntry != NULL) {
HASH_DEL(_LH(__glXDisplayInfoHash), pEntry);
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDisplayInfoHash);
if (pEntry != NULL) {
int i;
for (i=0; i<GLX_CLIENT_STRING_LAST_ATTRIB; i++) {
if (pEntry->info.clientStrings[i] != NULL) {
free(pEntry->info.clientStrings[i]);
}
}
free(pEntry);
}
}
/****************************************************************************/
/*
* __glXScreenPointerMappingHash is a hash table that maps a void*
* (either GLXContext or GLXFBConfig) to a screen index. Note this
* stores both GLXContext and GLXFBConfig in this table.
*/
typedef struct {
void *ptr;
int screen;
UT_hash_handle hh;
} __GLXscreenPointerMappingHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXscreenPointerMappingHash, __glXScreenPointerMappingHash);
static void AddScreenPointerMapping(void *ptr, int screen)
{
__GLXscreenPointerMappingHash *pEntry;
if (ptr == NULL) {
return;
}
if (screen < 0) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
HASH_FIND_PTR(_LH(__glXScreenPointerMappingHash), &ptr, pEntry);
if (pEntry == NULL) {
pEntry = malloc(sizeof(*pEntry));
pEntry->ptr = ptr;
pEntry->screen = screen;
HASH_ADD_PTR(_LH(__glXScreenPointerMappingHash), ptr, pEntry);
} else {
pEntry->screen = screen;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
2013-08-23 01:06:53 +02:00
}
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>
2013-11-26 00:21:41 +01:00
static void RemoveScreenPointerMapping(void *ptr)
2013-08-23 01:06:53 +02:00
{
__GLXscreenPointerMappingHash *pEntry;
if (ptr == NULL) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
HASH_FIND_PTR(_LH(__glXScreenPointerMappingHash), &ptr, pEntry);
if (pEntry != NULL) {
HASH_DELETE(hh, _LH(__glXScreenPointerMappingHash), pEntry);
free(pEntry);
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
2013-08-23 01:06:53 +02:00
}
static int ScreenFromPointer(void *ptr)
{
__GLXscreenPointerMappingHash *pEntry;
int screen = -1;
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
HASH_FIND_PTR(_LH(__glXScreenPointerMappingHash), &ptr, pEntry);
if (pEntry != NULL) {
screen = pEntry->screen;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenPointerMappingHash);
return screen;
2013-08-23 01:06:53 +02:00
}
/**
* Common function for the various __glXVendorFrom* functions.
*/
static int CommonVendorFromScreen(Display *dpy, int screen, int *retScreen, __GLXvendorInfo **retVendor)
{
if (retScreen != NULL) {
*retScreen = screen;
}
if (retVendor != NULL) {
if (screen >= 0) {
*retVendor = __glXLookupVendorByScreen(dpy, screen);
} else {
*retVendor = NULL;
}
}
return (screen >= 0 ? 0 : -1);
}
2013-08-23 01:06:53 +02:00
void __glXAddScreenContextMapping(Display *dpy, GLXContext context, int screen, __GLXvendorInfo *vendor)
2013-08-23 01:06:53 +02:00
{
AddScreenPointerMapping(context, screen);
}
void __glXRemoveScreenContextMapping(Display *dpy, GLXContext context)
2013-08-23 01:06:53 +02:00
{
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>
2013-11-26 00:21:41 +01:00
RemoveScreenPointerMapping(context);
2013-08-23 01:06:53 +02:00
}
int __glXScreenFromContext(GLXContext context)
{
return ScreenFromPointer(context);
}
int __glXVendorFromContext(Display *dpy, GLXContext context, int *retScreen, __GLXvendorInfo **retVendor)
{
int screen = ScreenFromPointer(context);
return CommonVendorFromScreen(dpy, screen, retScreen, retVendor);
}
2013-08-23 01:06:53 +02:00
void __glXAddScreenFBConfigMapping(Display *dpy, GLXFBConfig config, int screen, __GLXvendorInfo *vendor)
2013-08-23 01:06:53 +02:00
{
AddScreenPointerMapping(config, screen);
}
void __glXRemoveScreenFBConfigMapping(Display *dpy, GLXFBConfig config)
2013-08-23 01:06:53 +02:00
{
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>
2013-11-26 00:21:41 +01:00
RemoveScreenPointerMapping(config);
2013-08-23 01:06:53 +02:00
}
int __glXScreenFromFBConfig(GLXFBConfig config)
{
return ScreenFromPointer(config);
}
int __glXVendorFromFBConfig(Display *dpy, GLXFBConfig config, int *retScreen, __GLXvendorInfo **retVendor)
{
int screen = ScreenFromPointer(config);
return CommonVendorFromScreen(dpy, screen, retScreen, retVendor);
}
// Internally, we use the screen number to look up a vendor, so we don't need
// to record anything else for an XVisualInfo.
void __glXAddScreenVisualMapping(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo *vendor)
{
}
void __glXRemoveScreenVisualMapping(Display *dpy, const XVisualInfo *visual)
{
}
int __glXVendorFromVisual(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor)
{
if (retVendor != NULL) {
*retVendor = __glXLookupVendorByScreen(dpy, visual->screen);
}
return 0;
}
2013-08-23 01:06:53 +02:00
/****************************************************************************/
/*
* __glXScreenXIDMappingHash is a hash table which maps XIDs to screens.
*/
typedef struct {
XID xid;
int screen;
UT_hash_handle hh;
} __GLXscreenXIDMappingHash;
static DEFINE_INITIALIZED_LKDHASH(__GLXscreenXIDMappingHash, __glXScreenXIDMappingHash);
2013-08-23 01:06:53 +02:00
static void AddScreenXIDMapping(XID xid, int screen)
{
__GLXscreenXIDMappingHash *pEntry = NULL;
if (xid == None) {
return;
}
if (screen < 0) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
HASH_FIND(hh, _LH(__glXScreenXIDMappingHash), &xid, sizeof(xid), pEntry);
if (pEntry == NULL) {
pEntry = malloc(sizeof(*pEntry));
pEntry->xid = xid;
pEntry->screen = screen;
HASH_ADD(hh, _LH(__glXScreenXIDMappingHash), xid, sizeof(xid), pEntry);
} else {
pEntry->screen = screen;
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
2013-08-23 01:06:53 +02:00
}
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>
2013-11-26 00:21:41 +01:00
static void RemoveScreenXIDMapping(XID xid)
2013-08-23 01:06:53 +02:00
{
__GLXscreenXIDMappingHash *pEntry;
if (xid == None) {
return;
}
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
HASH_FIND(hh, _LH(__glXScreenXIDMappingHash), &xid, sizeof(xid), pEntry);
if (pEntry != NULL) {
HASH_DELETE(hh, _LH(__glXScreenXIDMappingHash), pEntry);
free(pEntry);
}
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
2013-08-23 01:06:53 +02:00
}
static int ScreenFromXID(Display *dpy, XID xid)
2013-08-23 01:06:53 +02:00
{
__GLXscreenXIDMappingHash *pEntry;
int screen = -1;
LKDHASH_RDLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
HASH_FIND(hh, _LH(__glXScreenXIDMappingHash), &xid, sizeof(xid), pEntry);
if (pEntry) {
screen = pEntry->screen;
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
} else {
screen = XGLVQueryXIDScreenMapping(dpy, xid);
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXScreenXIDMappingHash);
AddScreenXIDMapping(xid, screen);
}
return screen;
2013-08-23 01:06:53 +02:00
}
void __glXAddScreenDrawableMapping(Display *dpy, GLXDrawable drawable, int screen, __GLXvendorInfo *vendor)
2013-08-23 01:06:53 +02:00
{
AddScreenXIDMapping(drawable, screen);
}
void __glXRemoveScreenDrawableMapping(Display *dpy, GLXDrawable drawable)
2013-08-23 01:06:53 +02:00
{
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>
2013-11-26 00:21:41 +01:00
RemoveScreenXIDMapping(drawable);
2013-08-23 01:06:53 +02:00
}
int __glXScreenFromDrawable(Display *dpy, GLXDrawable drawable)
2013-08-23 01:06:53 +02:00
{
return ScreenFromXID(dpy, drawable);
2013-08-23 01:06:53 +02:00
}
int __glXVendorFromDrawable(Display *dpy, GLXDrawable drawable, int *retScreen, __GLXvendorInfo **retVendor)
{
int screen = ScreenFromXID(dpy, drawable);
return CommonVendorFromScreen(dpy, screen, retScreen, retVendor);
}
/*!
* This handles freeing all mapping state during library teardown
* or resetting locks on fork recovery.
*/
void __glXMappingTeardown(Bool doReset)
{
if (doReset) {
/*
* If we're just doing fork recovery, we don't actually want to unload
* any currently loaded vendors _or_ remove any mappings (they should
* still be valid in the new process, and may be needed if the child
* tries using pointers/XIDs that were created in the parent). Just
* reset the corresponding locks.
*/
__glXPthreadFuncs.rwlock_init(&__glXDispatchIndexHash.lock, NULL);
__glXPthreadFuncs.rwlock_init(&__glXVendorScreenHash.lock, NULL);
__glXPthreadFuncs.rwlock_init(&__glXScreenPointerMappingHash.lock, NULL);
__glXPthreadFuncs.rwlock_init(&__glXScreenXIDMappingHash.lock, NULL);
__glXPthreadFuncs.rwlock_init(&__glXVendorNameHash.lock, NULL);
__glXPthreadFuncs.rwlock_init(&__glXDisplayInfoHash.lock, NULL);
} else {
/* Tear down all hashtables used in this file */
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXdispatchIndexHash,
__glXDispatchIndexHash, CleanupDispatchIndexEntry,
NULL, False);
LKDHASH_WRLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
__glXNextUnusedHashIndex = 0;
LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDispatchIndexHash);
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXvendorScreenHash,
__glXVendorScreenHash, NULL, NULL, False);
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXdisplayInfoHash,
__glXDisplayInfoHash, NULL, NULL, False);
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXscreenPointerMappingHash,
__glXScreenPointerMappingHash, NULL, NULL, False);
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXscreenXIDMappingHash,
__glXScreenXIDMappingHash, NULL, NULL, False);
/*
* This implicitly unloads vendor libraries that were loaded when
* they were added to this hashtable.
*/
LKDHASH_TEARDOWN(__glXPthreadFuncs, __GLXvendorNameHash,
__glXVendorNameHash, CleanupVendorNameEntry,
NULL, False);
}
}