rework extension handling in GLEW so that they are put into a hash structure for faster lookup and also handle getting extensions in a core context.

This commit is contained in:
Edward Rudd 2014-11-21 16:26:34 -05:00
parent 6722500d95
commit b5fce8d088
7 changed files with 201 additions and 68 deletions

View File

@ -140,6 +140,7 @@ $(I.DEST)/glew.h: $(EXT)/.dummy
echo -e "#if defined(GLEW_MX) && defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */" >> $@
$(BIN)/make_struct_fun.pl GLEW_FUN_EXPORT $(GL_CORE_SPEC) $(GL_EXT_SPEC) >> $@
echo -e "\n#if defined(GLEW_MX) && !defined(_WIN32)\nstruct GLEWContextStruct\n{\n#endif /* GLEW_MX */\n" >> $@
echo -e "\n#if defined(GLEW_MX)\nGLEWHashList *GLEW_GL_EXTENSIONS;\n#endif /* GLEW_MX */\n" >> $@
$(BIN)/make_struct_var.pl GLEW_VAR_EXPORT $(GL_CORE_SPEC) $(GL_EXT_SPEC) >> $@
echo -e "\n#ifdef GLEW_MX\n}; /* GLEWContextStruct */\n#endif /* GLEW_MX */\n" >> $@
perl -e "s/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/GLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_1;\nGLEW_VAR_EXPORT GLboolean __GLEW_VERSION_1_2;/" -pi $@
@ -157,6 +158,7 @@ $(I.DEST)/wglew.h: $(EXT)/.dummy
cat $(SRC)/wglew_mid.h >> $@
echo -e "\n#ifdef GLEW_MX\nstruct WGLEWContextStruct\n{\n#endif /* GLEW_MX */" >> $@
$(BIN)/make_struct_fun.pl WGLEW_FUN_EXPORT $(WGL_EXT_SPEC) >> $@
echo -e "\n#if defined(GLEW_MX)\nGLEWHashList *GLEW_WGL_EXTENSIONS;\n#endif /* GLEW_MX */\n" >> $@
$(BIN)/make_struct_var.pl WGLEW_VAR_EXPORT $(WGL_EXT_SPEC) >> $@
echo -e "\n#ifdef GLEW_MX\n}; /* WGLEWContextStruct */\n#endif /* GLEW_MX */\n" >> $@
cat $(SRC)/wglew_tail.h >> $@
@ -174,6 +176,7 @@ $(I.DEST)/glxew.h: $(EXT)/.dummy
cat $(SRC)/glxew_mid.h >> $@
$(BIN)/make_struct_fun.pl GLXEW_FUN_EXPORT $(GLX_CORE_SPEC) $(GLX_EXT_SPEC) >> $@
echo -e "\n#if defined(GLEW_MX)\nstruct GLXEWContextStruct\n{\n#endif /* GLEW_MX */\n" >> $@
echo -e "\n#if defined(GLEW_MX)\nGLEWHashList *GLEW_GLX_EXTENSIONS;\n#endif /* GLEW_MX */\n" >> $@
$(BIN)/make_struct_var.pl GLXEW_VAR_EXPORT $(GLX_CORE_SPEC) $(GLX_EXT_SPEC) >> $@
echo -e "\n#ifdef GLEW_MX\n}; /* GLXEWContextStruct */\n#endif /* GLEW_MX */\n" >> $@
perl -e "s/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/GLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_0;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_1;\nGLXEW_VAR_EXPORT GLboolean __GLXEW_VERSION_1_2;/" -pi $@

View File

@ -46,7 +46,7 @@ if (@ARGV)
if (length($extstring))
{
print " " . $extvar . " = _glewSearchExtension(\"$extstring\", extStart, extEnd);\n";
print " " . $extvar . " = _glewHashListExists(ext_hashlist, (const GLubyte *)\"$extstring\");\n";
}
if (keys %$functions)

View File

@ -7,6 +7,7 @@
#endif
#include <stddef.h> /* For size_t */
#include <stdlib.h> /* For free and calloc */
/*
* Define glewGetContext and related helper macros.
@ -56,7 +57,6 @@ static void * (*regalGetProcAddress) (const GLchar *) = glGetProcAddressREGAL;
#elif defined(__sgi) || defined (__sun) || defined(__HAIKU__) || defined(GLEW_APPLE_GLX)
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
void* dlGetProcAddress (const GLubyte* name)
{
@ -77,7 +77,6 @@ void* dlGetProcAddress (const GLubyte* name)
#endif /* __sgi || __sun || GLEW_APPLE_GLX */
#if defined(__APPLE__)
#include <stdlib.h>
#include <string.h>
#include <AvailabilityMacros.h>
@ -264,22 +263,150 @@ static GLboolean _glewStrSame3 (const GLubyte** a, GLuint* na, const GLubyte* b,
return GL_FALSE;
}
/*
* Search for name in the extensions string. Use of strstr()
* is not sufficient because extension names can be prefixes of
* other extension names. Could use strtok() but the constant
* string returned by glGetString might be in read-only memory.
*/
static GLboolean _glewSearchExtension (const char* name, const GLubyte *start, const GLubyte *end)
struct GLEWHashListStruct
{
const GLubyte* p;
GLuint len = _glewStrLen((const GLubyte*)name);
p = start;
while (p < end)
const GLubyte **list;
GLuint size;
};
#if !defined(GLEW_MX)
GLEWHashList *GLEW_GL_EXTENSIONS;
#if defined(_WIN32)
GLEWHashList *GLEW_WGL_EXTENSIONS;
#elif !defined(__ANDROID__) && !defined(__native_client__) && !defined(__HAIKU__) && (!defined(__APPLE__) || defined(GLEW_APPLE_GLX))
GLEWHashList *GLEW_GLX_EXTENSIONS;
#endif
#endif // !defined(GLEW_MX)
/* A simple open addressing hashset for extensions */
static GLuint hash_string(const GLubyte * key)
{
GLuint hash = 0;
GLuint i = 0;
GLuint len = _glewStrCLen(key, ' ');
for (; i < len; ++i)
{
GLuint n = _glewStrCLen(p, ' ');
if (len == n && _glewStrSame((const GLubyte*)name, p, n)) return GL_TRUE;
p += n+1;
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
static void _glewHashListFree(GLEWHashList *list)
{
if (list->list != NULL) {
free(list->list);
list->list = NULL;
list->size = 0;
}
}
static void _glewHashListAlloc(GLEWHashList *list, GLuint nelts)
{
GLuint size = nelts * 3 / 2;
_glewHashListFree(list);
list->list = calloc(size, sizeof(const GLubyte*));
list->size = size;
}
static void _glewHashListInsert(GLEWHashList *list, const GLubyte *name)
{
GLuint hash = hash_string(name);
if (list->list == NULL) return;
while(list->list[hash % list->size] != NULL)
hash++;
list->list[hash % list->size] = name;
}
static GLboolean _glewHashListExists(GLEWHashList *list, const GLubyte *name)
{
GLuint hash;
GLuint len;
if (list->list == NULL) return GL_FALSE;
hash = hash_string((const GLubyte*)name);
len = _glewStrLen((const GLubyte*)name);
/*
* As the hashset is bigger than the number of extensions
* this will eventually break.
*/
while(1)
{
GLuint index = hash % list->size;
GLuint n;
if (list->list[index] == NULL)
break;
n = _glewStrCLen(list->list[index], ' ');
if (len == n && _glewStrSame(list->list[index], (const GLubyte*)name, n)) return GL_TRUE;
++hash;
}
return GL_FALSE;
}
static GLboolean _glewBuildGL3ExtensionList(GLEWHashList *list)
{
GLint n, i;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
glGetStringi = (PFNGLGETSTRINGIPROC)glewGetProcAddress((const GLubyte*)"glGetStringi");
_glewHashListAlloc(list, n);
for (i = 0; i < n; ++i)
{
const GLubyte* extension = glGetStringi(GL_EXTENSIONS, i);
_glewHashListInsert(list, extension);
}
return GL_TRUE;
}
/*
* initialize the extension list hash from a extension string list
*/
static GLboolean _glewBuildHashListFromString(const GLubyte* extensions, GLEWHashList *list)
{
const GLubyte* extStart;
const GLubyte* extEnd;
const GLubyte* p;
GLuint extCount = 0;
extStart = extensions;
if (extStart == 0)
extStart = (const GLubyte*)"";
extEnd = extStart + _glewStrLen(extStart);
// first scan to determine number of extensions
p = extStart;
while (p < extEnd)
{
GLuint n = _glewStrCLen(p, ' ');
p += n + 1;
++extCount;
}
_glewHashListAlloc(list, extCount);
// Second scan to populate the hash set
p = extStart;
while (p < extEnd)
{
GLuint n = _glewStrCLen(p, ' ');
_glewHashListInsert(list, p);
p += n+1;
}
return GL_TRUE;
}

View File

@ -188,6 +188,8 @@ typedef _W64 int ptrdiff_t;
extern "C" {
#endif
typedef struct GLEWHashListStruct GLEWHashList;
/* ----------------------------- GL_VERSION_1_1 ---------------------------- */
#ifndef GL_VERSION_1_1

View File

@ -1,14 +1,11 @@
/* ------------------------------------------------------------------------- */
GLboolean GLEWAPIENTRY glewGetExtension (const char* name)
{
const GLubyte* start;
const GLubyte* end;
start = (const GLubyte*)glGetString(GL_EXTENSIONS);
if (start == 0)
return GL_FALSE;
end = start + _glewStrLen(start);
return _glewSearchExtension(name, start, end);
{
#if GLEW_MX
GLEWContext *ctx = glewGetContext();
#endif
return _glewHashListExists(GLEW_GET_VAR(GLEW_GL_EXTENSIONS), (const GLubyte*)name);
}
/* ------------------------------------------------------------------------- */
@ -21,8 +18,8 @@ GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
const GLubyte* s;
GLuint dot;
GLint major, minor;
const GLubyte* extStart;
const GLubyte* extEnd;
GLEWHashList *ext_hashlist;
/* query opengl version */
s = glGetString(GL_VERSION);
dot = _glewStrCLen(s, '.');
@ -65,9 +62,18 @@ GLenum GLEWAPIENTRY glewContextInit (GLEW_CONTEXT_ARG_DEF_LIST)
}
/* query opengl extensions string */
extStart = glGetString(GL_EXTENSIONS);
if (extStart == 0)
extStart = (const GLubyte*)"";
extEnd = extStart + _glewStrLen(extStart);
GLEW_GET_VAR(GLEW_GL_EXTENSIONS) = calloc(1, sizeof(GLEWHashList));
ext_hashlist = GLEW_GET_VAR(GLEW_GL_EXTENSIONS);
if (major >= 3)
{
_glewBuildGL3ExtensionList(ext_hashlist);
}
else
{
const GLubyte* extensions = glGetString(GL_EXTENSIONS);
_glewBuildHashListFromString(extensions, ext_hashlist);
}
/* initialize extensions */

View File

@ -1,22 +1,18 @@
/* ------------------------------------------------------------------------ */
GLboolean glxewGetExtension (const char* name)
{
const GLubyte* start;
const GLubyte* end;
if (glXGetCurrentDisplay == NULL) return GL_FALSE;
start = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
if (0 == start) return GL_FALSE;
end = start + _glewStrLen(start);
return _glewSearchExtension(name, start, end);
{
#if GLEW_MX
GLXEWContext *ctx = glxewGetContext();
#endif
return _glewHashListExists(GLXEW_GET_VAR(GLEW_GLX_EXTENSIONS), name);
}
GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
{
int major, minor;
const GLubyte* extStart;
const GLubyte* extEnd;
const GLubyte* extensions;
GLEWHashList *ext_hashlist;
/* initialize core GLX 1.2 */
if (_glewInit_GLX_VERSION_1_2(GLEW_CONTEXT_ARG_VAR_INIT)) return GLEW_ERROR_GLX_VERSION_11_ONLY;
/* initialize flags */
@ -44,10 +40,11 @@ GLenum glxewContextInit (GLXEW_CONTEXT_ARG_DEF_LIST)
}
}
/* query GLX extension string */
extStart = 0;
if (glXGetCurrentDisplay != NULL)
extStart = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
if (extStart == 0)
extStart = (const GLubyte *)"";
extEnd = extStart + _glewStrLen(extStart);
GLXEW_GET_VAR(GLEW_GLX_EXTENSIONS) = calloc(1, sizeof(GLEWHashList));
ext_hashlist = GLXEW_GET_VAR(GLEW_GLX_EXTENSIONS);
extensions = (const GLubyte*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS);
_glewBuildHashListFromString(extensions, ext_hashlist);
/* initialize extensions */

View File

@ -4,38 +4,36 @@ static PFNWGLGETEXTENSIONSSTRINGARBPROC _wglewGetExtensionsStringARB = NULL;
static PFNWGLGETEXTENSIONSSTRINGEXTPROC _wglewGetExtensionsStringEXT = NULL;
GLboolean GLEWAPIENTRY wglewGetExtension (const char* name)
{
const GLubyte* start;
const GLubyte* end;
if (_wglewGetExtensionsStringARB == NULL)
if (_wglewGetExtensionsStringEXT == NULL)
return GL_FALSE;
else
start = (const GLubyte*)_wglewGetExtensionsStringEXT();
else
start = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
if (start == 0)
return GL_FALSE;
end = start + _glewStrLen(start);
return _glewSearchExtension(name, start, end);
{
#if GLEW_MX
WGLEWContext *ctx = wglewGetContext();
#endif
return _glewHashListExists(WGLEW_GET_VAR(GLEW_WGL_EXTENSIONS), name);
}
GLenum GLEWAPIENTRY wglewContextInit (WGLEW_CONTEXT_ARG_DEF_LIST)
{
GLboolean crippled;
const GLubyte* extStart;
const GLubyte* extEnd;
const GLubyte* extensions;
GLEWHashList *ext_hashlist;
/* find wgl extension string query functions */
_wglewGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringARB");
_wglewGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)glewGetProcAddress((const GLubyte*)"wglGetExtensionsStringEXT");
/* query wgl extension string */
if (_wglewGetExtensionsStringARB == NULL)
if (_wglewGetExtensionsStringEXT == NULL)
extStart = (const GLubyte*)"";
extensions = (const GLubyte*)"";
else
extStart = (const GLubyte*)_wglewGetExtensionsStringEXT();
extensions = (const GLubyte*)_wglewGetExtensionsStringEXT();
else
extStart = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
extEnd = extStart + _glewStrLen(extStart);
extensions = (const GLubyte*)_wglewGetExtensionsStringARB(wglGetCurrentDC());
WGLEW_GET_VAR(GLEW_WGL_EXTENSIONS) = calloc(1, sizeof(GLEWHashList));
ext_hashlist = WGLEW_GET_VAR(GLEW_WGL_EXTENSIONS);
_glewBuildHashListFromString(extensions, ext_hashlist);
/* initialize extensions */
crippled = _wglewGetExtensionsStringARB == NULL && _wglewGetExtensionsStringEXT == NULL;