Skip to content
Permalink
Browse files
Implemented MOJOSHADER_glBestProfile().
--HG--
branch : trunk
  • Loading branch information
icculus committed Apr 30, 2008
1 parent fab8a44 commit 914863f14bed00cab8c85abd04a58ecb9ca8336f
Showing with 107 additions and 30 deletions.
  1. +1 −0 finderrors.c
  2. +28 −0 mojoshader.h
  3. +78 −30 mojoshader_opengl.c
@@ -148,6 +148,7 @@ 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));
MOJOSHADER_glContext *ctx;
ctx = MOJOSHADER_glCreateContext(profile, SDL_GL_GetProcAddress, 0, 0, 0);
if (ctx == NULL)
@@ -355,6 +355,34 @@ typedef struct MOJOSHADER_glContext MOJOSHADER_glContext;
typedef struct MOJOSHADER_glShader MOJOSHADER_glShader;
typedef struct MOJOSHADER_glProgram MOJOSHADER_glProgram;


/*
* Determine the best profile to use for the current system.
*
* You do not need to call this if all you want is MOJOSHADER_parse().
*
* 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.
*
* 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,
* but it generally means the best trade off between feature set and
* performance. The selection algorithm may be arbitrary and complex.
*
* The returned value is an internal static string, and should not be free()'d
* by the caller. If you get a NULL, calling MOJOSHADER_glGetError() might
* shed some light on why.
*
* This call is NOT thread safe! As most OpenGL implementations are not thread
* 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));


/*
* Prepare MojoShader to manage OpenGL shaders.
*
@@ -41,6 +41,10 @@ typedef int32_t int32;

#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )

#ifndef SUPPORT_PROFILE_GLSL
#define SUPPORT_PROFILE_GLSL 1
#endif

struct MOJOSHADER_glShader
{
const MOJOSHADER_parseData *parseData;
@@ -96,7 +100,7 @@ struct MOJOSHADER_glContext
int opengl_major;
int opengl_minor;
MOJOSHADER_glProgram *bound_program;
const char *profile;
char profile[16];

// Extensions...
int have_base_opengl;
@@ -223,6 +227,9 @@ static int verify_extension(const char *ext, int have, const char *extlist,
if (have == 0)
return 0; // don't bother checking, we're missing an entry point.

else if (!ctx->have_base_opengl)
return 0; // don't bother checking, we're missing basic functionality.

// See if it's in the spec for this GL implementation's version.
if (major >= 0)
{
@@ -253,8 +260,10 @@ static void parse_opengl_version(const char *verstr)
} // parse_opengl_version


static int check_extensions(void *(*lookup)(const char *fnname))
static void load_extensions(void *(*lookup)(const char *fnname))
{
const char *extlist = NULL;

ctx->have_base_opengl = 1;
ctx->have_GL_ARB_shader_objects = 1;
ctx->have_GL_ARB_vertex_shader = 1;
@@ -264,15 +273,14 @@ static int check_extensions(void *(*lookup)(const char *fnname))

lookup_entry_points(lookup);

if (!ctx->have_base_opengl) // a func we should definitely have is MIA?
{
if (!ctx->have_base_opengl)
set_error("missing basic OpenGL entry points");
return 0;
} // if

parse_opengl_version((const char *) ctx->glGetString(GL_VERSION));
else
{
parse_opengl_version((const char *) ctx->glGetString(GL_VERSION));
extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
} // else

const char *extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
if (extlist == NULL)
extlist = ""; // just in case.

@@ -286,31 +294,77 @@ static int check_extensions(void *(*lookup)(const char *fnname))
VERIFY_EXT(GL_NV_half_float, -1, -1);

#undef VERIFY_EXT
} // load_extensions

#define REQUIRE_GL_EXTENSION(x) \
if (!ctx->have_##x) { set_error("profile requires " #x); return 0; }

if (strcmp(ctx->profile, MOJOSHADER_PROFILE_GLSL) == 0)
static int valid_profile(const char *profile)
{
if (!ctx->have_base_opengl)
return 0;

#define MUST_HAVE(p, x) \
if (!ctx->have_##x) { set_error(#p " profile needs " #x); return 0; }

if (0) {}

#if SUPPORT_PROFILE_GLSL
else if (strcmp(profile, MOJOSHADER_PROFILE_GLSL) == 0)
{
REQUIRE_GL_EXTENSION(GL_ARB_shader_objects);
REQUIRE_GL_EXTENSION(GL_ARB_vertex_shader);
REQUIRE_GL_EXTENSION(GL_ARB_fragment_shader);
REQUIRE_GL_EXTENSION(GL_ARB_shading_language_100);
} // if
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shader_objects);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_vertex_shader);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_fragment_shader);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shading_language_100);
} // else if
#endif

else
{
set_error("unknown profile");
set_error("unknown or unsupported profile");
return 0;
} // else

#undef REQUIRE_GL_EXTENSION
#undef MUST_HAVE

return 1;
} // check_extensions
} // valid_profile


MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *_profile,
const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname))
{
const char *retval = NULL;
MOJOSHADER_glContext _ctx;
MOJOSHADER_glContext *current_ctx = ctx;

ctx = &_ctx;
memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
load_extensions(lookup);

if (ctx->have_base_opengl)
{
static const char *priority[] = {
MOJOSHADER_PROFILE_GLSL,
};

int i;
for (i = 0; i < STATICARRAYLEN(priority); i++)
{
if (valid_profile(priority[i]))
{
retval = priority[i];
break;
} // if
} // for

if (retval == NULL)
set_error("no profiles available");
} // if

ctx = current_ctx;
return retval;
} // MOJOSHADER_glBestProfile


MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
void *(*lookup)(const char *fnname),
MOJOSHADER_malloc m, MOJOSHADER_free f,
void *d)
@@ -333,16 +387,10 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *_profile,
ctx->malloc_fn = m;
ctx->free_fn = f;
ctx->malloc_data = d;
snprintf(ctx->profile, sizeof (ctx->profile), "%s", profile);

if (strcmp(_profile, MOJOSHADER_PROFILE_GLSL) == 0)
ctx->profile = MOJOSHADER_PROFILE_GLSL;
else
{
set_error("unknown profile");
goto init_fail;
} // else

if (!check_extensions(lookup))
load_extensions(lookup);
if (!valid_profile(profile))
goto init_fail;

MOJOSHADER_glBindProgram(NULL);

0 comments on commit 914863f

Please sign in to comment.