From e4c87aec92614779bb3c8dca0ac71f09a95e7659 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 30 Mar 2010 20:12:29 -0400 Subject: [PATCH] Added data argument to GL entry point lookup callback. Sorry to break the public API! --- mojoshader.h | 55 ++++++++++++++++++++++++++++----------- mojoshader_opengl.c | 38 ++++++++++++++------------- utils/availableprofiles.c | 10 +++++-- utils/bestprofile.c | 10 +++++-- utils/finderrors.c | 9 +++++-- 5 files changed, 83 insertions(+), 39 deletions(-) diff --git a/mojoshader.h b/mojoshader.h index 9e1c1cfa..b95d7696 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -884,6 +884,27 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *filename, /* OpenGL interface... */ +/* + * Signature for function lookup callbacks. MojoShader will call a function + * you provide to get OpenGL entry points (both standard functions and + * extensions). Through this, MojoShader never links directly to OpenGL, + * but relies on you to provide the implementation. This means you can + * swap in different drivers, or hook functions (log every GL call MojoShader + * makes, etc). + * + * (fnname) is the function name we want the address for ("glBegin" or + * whatever. (data) is a void pointer you provide, if this callback needs + * extra information. If you don't need it, you may specify NULL. + * + * Return the entry point on success, NULL if it couldn't be found. + * Note that this could ask for standard entry points like glEnable(), or + * extensions like glProgramLocalParameterI4ivNV(), so you might need + * to check two places to find the desired entry point, depending on your + * platform (Windows might need to look in OpenGL32.dll and use WGL, etc). + */ +typedef void *(*MOJOSHADER_glGetProcAddress)(const char *fnname, void *data); + + /* * "Contexts" map to OpenGL contexts...you need one per window, or whatever, * and need to inform MojoShader when you make a new one current. @@ -913,9 +934,9 @@ typedef struct MOJOSHADER_glProgram MOJOSHADER_glProgram; * * You can only call this AFTER you have successfully built your GL context * and made it current. This function will lookup the GL functions it needs - * through the callback you supply. The lookup function is neither stored nor - * used by MojoShader after this function returns, nor are the functions it - * might look up. + * through the callback you supply, via (lookup) and (d). The lookup function + * is neither stored nor used by MojoShader after this function returns, nor + * are the functions it might look up. * * You should not free any strings returned from this function; they are * pointers to internal, probably static, memory. @@ -924,7 +945,7 @@ typedef struct MOJOSHADER_glProgram MOJOSHADER_glProgram; * safe, you should probably only call this from the same thread that created * the GL context. */ -int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), +int MOJOSHADER_glAvailableProfiles(MOJOSHADER_glGetProcAddress lookup, void *d, const char **profs, const int size); @@ -933,9 +954,9 @@ int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), * * You can only call this AFTER you have successfully built your GL context * and made it current. This function will lookup the GL functions it needs - * through the callback you supply. The lookup function is neither stored nor - * used by MojoShader after this function returns, nor are the functions it - * might look up. + * through the callback you supply via (lookup) and (d). The lookup function + * is neither stored nor used by MojoShader after this function returns, nor + * are the functions it might look up. * * Returns the name of the "best" profile on success, NULL if none of the * available profiles will work on this system. "Best" is a relative term, @@ -950,7 +971,7 @@ int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), * safe, you should probably only call this from the same thread that created * the GL context. */ -const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)); +const char *MOJOSHADER_glBestProfile(MOJOSHADER_glGetProcAddress lookup, void *d); /* @@ -960,23 +981,26 @@ const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)); * * You must call this once AFTER you have successfully built your GL context * and made it current. This function will lookup the GL functions it needs - * through the callback you supply, after which it may call them at any time - * up until you call MOJOSHADER_glDestroyContext(). The lookup function is - * neither stored nor used by MojoShader after this function returns. + * through the callback you supply via (lookup) and (lookup_d), after which + * it may call them at any time up until you call + * MOJOSHADER_glDestroyContext(). The lookup function is neither stored nor + * used by MojoShader after this function returns. * * (profile) is an OpenGL-specific MojoShader profile, which decides how * Direct3D bytecode shaders get turned into OpenGL programs, and how they * are fed to the GL. * * (lookup) is a callback that is used to load GL entry points. This callback - * has to look up base GL functions and extension entry points. + * has to look up base GL functions and extension entry points. The pointer + * you supply in (lookup_d) is passed as-is to the callback. * * As MojoShader requires some memory to be allocated, you may provide a * custom allocator to this function, which will be used to allocate/free * memory. They function just like malloc() and free(). We do not use * realloc(). If you don't care, pass NULL in for the allocator functions. * If your allocator needs instance-specific data, you may supply it with the - * (d) parameter. This pointer is passed as-is to your (m) and (f) functions. + * (malloc_d) parameter. This pointer is passed as-is to your (m) and (f) + * functions. * * Returns a new context on success, NULL on error. If you get a new context, * you need to make it current before using it with @@ -988,9 +1012,10 @@ const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)); * thread that created the GL context. */ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, - void *(*lookup)(const char *fnname), + MOJOSHADER_glGetProcAddress lookup, + void *lookup_d, MOJOSHADER_malloc m, MOJOSHADER_free f, - void *d); + void *malloc_d); /* * You must call this before using the context that you got from diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index 3b6b4fc7..8386e319 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -748,17 +748,18 @@ const char *MOJOSHADER_glGetError(void) } // MOJOSHADER_glGetError -static void *loadsym(void *(*lookup)(const char *fn), const char *fn, int *ext) +static void *loadsym(MOJOSHADER_glGetProcAddress lookup, void *d, + const char *fn, int *ext) { void *retval = NULL; if (lookup != NULL) { - retval = lookup(fn); + retval = lookup(fn, d); if (retval == NULL) { char arbfn[64]; snprintf(arbfn, sizeof (arbfn), "%sARB", fn); - retval = lookup(arbfn); + retval = lookup(arbfn, d); } // if } // if @@ -768,11 +769,11 @@ static void *loadsym(void *(*lookup)(const char *fn), const char *fn, int *ext) return retval; } // loadsym -static void lookup_entry_points(void *(*lookup)(const char *fnname)) +static void lookup_entry_points(MOJOSHADER_glGetProcAddress lookup, void *d) { #define DO_LOOKUP(ext, typ, fn) { \ int exist = ctx->have_##ext; \ - ctx->fn = (typ) loadsym(lookup, #fn, &exist); \ + ctx->fn = (typ) loadsym(lookup, d, #fn, &exist); \ ctx->have_##ext = exist; \ } @@ -875,7 +876,7 @@ static int glsl_version_atleast(int maj, int min) #endif -static void load_extensions(void *(*lookup)(const char *fnname)) +static void load_extensions(MOJOSHADER_glGetProcAddress lookup, void *d) { const char *extlist = NULL; @@ -894,7 +895,7 @@ static void load_extensions(void *(*lookup)(const char *fnname)) ctx->have_GL_ARB_half_float_vertex = 1; ctx->have_GL_OES_vertex_half_float = 1; - lookup_entry_points(lookup); + lookup_entry_points(lookup, d); if (!ctx->have_base_opengl) set_error("missing basic OpenGL entry points"); @@ -1034,7 +1035,7 @@ static const char *profile_priorities[] = { #endif }; -int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), +int MOJOSHADER_glAvailableProfiles(MOJOSHADER_glGetProcAddress lookup, void *d, const char **profs, const int size) { int retval = 0; @@ -1043,7 +1044,7 @@ int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), ctx = &_ctx; memset(ctx, '\0', sizeof (MOJOSHADER_glContext)); - load_extensions(lookup); + load_extensions(lookup, d); if (ctx->have_base_opengl) { @@ -1065,10 +1066,10 @@ int MOJOSHADER_glAvailableProfiles(void *(*lookup)(const char *fnname), } // MOJOSHADER_glAvailableProfiles -const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)) +const char *MOJOSHADER_glBestProfile(MOJOSHADER_glGetProcAddress gpa, void *d) { const char *prof[STATICARRAYLEN(profile_priorities)]; - if (MOJOSHADER_glAvailableProfiles(lookup, prof, STATICARRAYLEN(prof)) <= 0) + if (MOJOSHADER_glAvailableProfiles(gpa, d, prof, STATICARRAYLEN(prof)) <= 0) { set_error("no profiles available"); return NULL; @@ -1079,9 +1080,10 @@ const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname)) MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, - void *(*lookup)(const char *fnname), + MOJOSHADER_glGetProcAddress lookup, + void *lookup_d, MOJOSHADER_malloc m, MOJOSHADER_free f, - void *d) + void *malloc_d) { MOJOSHADER_glContext *retval = NULL; MOJOSHADER_glContext *current_ctx = ctx; @@ -1091,7 +1093,7 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, if (m == NULL) m = MOJOSHADER_internal_malloc; if (f == NULL) f = MOJOSHADER_internal_free; - ctx = (MOJOSHADER_glContext *) m(sizeof (MOJOSHADER_glContext), d); + ctx = (MOJOSHADER_glContext *) m(sizeof (MOJOSHADER_glContext), malloc_d); if (ctx == NULL) { set_error("out of memory"); @@ -1101,10 +1103,10 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, memset(ctx, '\0', sizeof (MOJOSHADER_glContext)); ctx->malloc_fn = m; ctx->free_fn = f; - ctx->malloc_data = d; + ctx->malloc_data = malloc_d; snprintf(ctx->profile, sizeof (ctx->profile), "%s", profile); - load_extensions(lookup); + load_extensions(lookup, lookup_d); if (!valid_profile(profile)) goto init_fail; @@ -1184,7 +1186,7 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, init_fail: if (ctx != NULL) - f(ctx, d); + f(ctx, malloc_d); ctx = current_ctx; return NULL; } // MOJOSHADER_glCreateContext @@ -1909,7 +1911,7 @@ void MOJOSHADER_glDestroyContext(MOJOSHADER_glContext *_ctx) ctx = _ctx; MOJOSHADER_glBindProgram(NULL); update_enabled_arrays(); // disables all vertex arrays. - lookup_entry_points(NULL); + lookup_entry_points(NULL, NULL); Free(ctx); ctx = ((current_ctx == _ctx) ? NULL : current_ctx); } // MOJOSHADER_glDestroyContext diff --git a/utils/availableprofiles.c b/utils/availableprofiles.c index 674e1b9d..55b63eb9 100644 --- a/utils/availableprofiles.c +++ b/utils/availableprofiles.c @@ -11,14 +11,20 @@ #include "mojoshader.h" #include "SDL.h" +static void *lookup(const char *fnname, void *unused) +{ + (void) unused; + return SDL_GL_GetProcAddress(fnname); +} // lookup + static int check_available(void) { const char **avail = NULL; - int total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, NULL, 0); + int total = MOJOSHADER_glAvailableProfiles(lookup, NULL, NULL, 0); if (total > 0) { avail = (const char **) alloca(sizeof (const char *) * total); - total = MOJOSHADER_glAvailableProfiles(SDL_GL_GetProcAddress, avail, total); + total = MOJOSHADER_glAvailableProfiles(lookup, NULL, avail, total); } // if if (total <= 0) diff --git a/utils/bestprofile.c b/utils/bestprofile.c index 7ab1139d..7339c4a9 100644 --- a/utils/bestprofile.c +++ b/utils/bestprofile.c @@ -11,6 +11,12 @@ #include "mojoshader.h" #include "SDL.h" +static void *lookup(const char *fnname, void *unused) +{ + (void) unused; + return SDL_GL_GetProcAddress(fnname); +} // lookup + int main(int argc, char **argv) { int retval = 1; @@ -31,9 +37,9 @@ int main(int argc, char **argv) fprintf(stderr, "SDL_SetVideoMode() error: %s\n", SDL_GetError()); else { - const char *best = MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress); + const char *best = MOJOSHADER_glBestProfile(lookup, NULL); MOJOSHADER_glContext *ctx; - ctx = MOJOSHADER_glCreateContext(best, SDL_GL_GetProcAddress, 0, 0, 0); + ctx = MOJOSHADER_glCreateContext(best, lookup, 0, 0, 0, 0); if (ctx == NULL) printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError()); else diff --git a/utils/finderrors.c b/utils/finderrors.c index 28303931..b7cc175e 100644 --- a/utils/finderrors.c +++ b/utils/finderrors.c @@ -18,6 +18,11 @@ #if FINDERRORS_COMPILE_SHADERS #include "SDL.h" +static void *lookup(const char *fnname, void *unused) +{ + (void) unused; + return SDL_GL_GetProcAddress(fnname); +} // lookup #endif #ifdef _MSC_VER @@ -192,9 +197,9 @@ int main(int argc, char **argv) SDL_Init(SDL_INIT_VIDEO); SDL_GL_LoadLibrary(NULL); SDL_SetVideoMode(640, 480, 0, SDL_OPENGL); - printf("Best profile is '%s'\n", MOJOSHADER_glBestProfile(SDL_GL_GetProcAddress)); + printf("Best profile is '%s'\n", MOJOSHADER_glBestProfile(lookup, 0)); MOJOSHADER_glContext *ctx; - ctx = MOJOSHADER_glCreateContext(profile, SDL_GL_GetProcAddress, 0, 0, 0); + ctx = MOJOSHADER_glCreateContext(profile, lookup, 0, 0, 0, 0); if (ctx == NULL) { printf("MOJOSHADER_glCreateContext() fail: %s\n", MOJOSHADER_glGetError());