mojoshader_opengl.c
branchtrunk
changeset 262 0f1531ac2578
parent 255 796394130035
child 276 1d7437469c94
equal deleted inserted replaced
261:929496882e30 262:0f1531ac2578
    39 typedef int32_t int32;
    39 typedef int32_t int32;
    40 #endif
    40 #endif
    41 
    41 
    42 #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
    42 #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
    43 
    43 
       
    44 #ifndef SUPPORT_PROFILE_GLSL
       
    45 #define SUPPORT_PROFILE_GLSL 1
       
    46 #endif
       
    47 
    44 struct MOJOSHADER_glShader
    48 struct MOJOSHADER_glShader
    45 {
    49 {
    46     const MOJOSHADER_parseData *parseData;
    50     const MOJOSHADER_parseData *parseData;
    47     GLhandleARB handle;
    51     GLhandleARB handle;
    48     uint32 refcount;
    52     uint32 refcount;
    94 
    98 
    95     // GL stuff...
    99     // GL stuff...
    96     int opengl_major;
   100     int opengl_major;
    97     int opengl_minor;
   101     int opengl_minor;
    98     MOJOSHADER_glProgram *bound_program;
   102     MOJOSHADER_glProgram *bound_program;
    99     const char *profile;
   103     char profile[16];
   100 
   104 
   101     // Extensions...
   105     // Extensions...
   102     int have_base_opengl;
   106     int have_base_opengl;
   103     int have_GL_ARB_shader_objects;
   107     int have_GL_ARB_shader_objects;
   104     int have_GL_ARB_vertex_shader;
   108     int have_GL_ARB_vertex_shader;
   221                             int major, int minor)
   225                             int major, int minor)
   222 {
   226 {
   223     if (have == 0)
   227     if (have == 0)
   224         return 0;  // don't bother checking, we're missing an entry point.
   228         return 0;  // don't bother checking, we're missing an entry point.
   225 
   229 
       
   230     else if (!ctx->have_base_opengl)
       
   231         return 0;  // don't bother checking, we're missing basic functionality.
       
   232 
   226     // See if it's in the spec for this GL implementation's version.
   233     // See if it's in the spec for this GL implementation's version.
   227     if (major >= 0)
   234     if (major >= 0)
   228     {
   235     {
   229         if ( ((ctx->opengl_major << 16) | (ctx->opengl_minor & 0xFFFF)) >=
   236         if ( ((ctx->opengl_major << 16) | (ctx->opengl_minor & 0xFFFF)) >=
   230              ((major << 16) | (minor & 0xFFFF)) )
   237              ((major << 16) | (minor & 0xFFFF)) )
   251     else
   258     else
   252         sscanf(verstr, "%d.%d", &ctx->opengl_major, &ctx->opengl_minor);
   259         sscanf(verstr, "%d.%d", &ctx->opengl_major, &ctx->opengl_minor);
   253 } // parse_opengl_version
   260 } // parse_opengl_version
   254 
   261 
   255 
   262 
   256 static int check_extensions(void *(*lookup)(const char *fnname))
   263 static void load_extensions(void *(*lookup)(const char *fnname))
   257 {
   264 {
       
   265     const char *extlist = NULL;
       
   266 
   258     ctx->have_base_opengl = 1;
   267     ctx->have_base_opengl = 1;
   259     ctx->have_GL_ARB_shader_objects = 1;
   268     ctx->have_GL_ARB_shader_objects = 1;
   260     ctx->have_GL_ARB_vertex_shader = 1;
   269     ctx->have_GL_ARB_vertex_shader = 1;
   261     ctx->have_GL_ARB_fragment_shader = 1;
   270     ctx->have_GL_ARB_fragment_shader = 1;
   262     ctx->have_GL_ARB_shading_language_100 = 1;
   271     ctx->have_GL_ARB_shading_language_100 = 1;
   263     ctx->have_GL_NV_half_float = 1;
   272     ctx->have_GL_NV_half_float = 1;
   264 
   273 
   265     lookup_entry_points(lookup);
   274     lookup_entry_points(lookup);
   266 
   275 
   267     if (!ctx->have_base_opengl)   // a func we should definitely have is MIA?
   276     if (!ctx->have_base_opengl)
   268     {
       
   269         set_error("missing basic OpenGL entry points");
   277         set_error("missing basic OpenGL entry points");
   270         return 0;
   278     else
   271     } // if
   279     {
   272 
   280         parse_opengl_version((const char *) ctx->glGetString(GL_VERSION));
   273     parse_opengl_version((const char *) ctx->glGetString(GL_VERSION));
   281         extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
   274 
   282     } // else
   275     const char *extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
   283 
   276     if (extlist == NULL)
   284     if (extlist == NULL)
   277         extlist = "";  // just in case.
   285         extlist = "";  // just in case.
   278 
   286 
   279     #define VERIFY_EXT(ext, major, minor) \
   287     #define VERIFY_EXT(ext, major, minor) \
   280         ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor)
   288         ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor)
   284     VERIFY_EXT(GL_ARB_fragment_shader, 2, 0);
   292     VERIFY_EXT(GL_ARB_fragment_shader, 2, 0);
   285     VERIFY_EXT(GL_ARB_shading_language_100, 2, 0);
   293     VERIFY_EXT(GL_ARB_shading_language_100, 2, 0);
   286     VERIFY_EXT(GL_NV_half_float, -1, -1);
   294     VERIFY_EXT(GL_NV_half_float, -1, -1);
   287 
   295 
   288     #undef VERIFY_EXT
   296     #undef VERIFY_EXT
   289 
   297 } // load_extensions
   290     #define REQUIRE_GL_EXTENSION(x) \
   298 
   291         if (!ctx->have_##x) { set_error("profile requires " #x); return 0; }
   299 
   292 
   300 static int valid_profile(const char *profile)
   293     if (strcmp(ctx->profile, MOJOSHADER_PROFILE_GLSL) == 0)
   301 {
   294     {
   302     if (!ctx->have_base_opengl)
   295         REQUIRE_GL_EXTENSION(GL_ARB_shader_objects);
   303         return 0;
   296         REQUIRE_GL_EXTENSION(GL_ARB_vertex_shader);
   304 
   297         REQUIRE_GL_EXTENSION(GL_ARB_fragment_shader);
   305     #define MUST_HAVE(p, x) \
   298         REQUIRE_GL_EXTENSION(GL_ARB_shading_language_100);
   306         if (!ctx->have_##x) { set_error(#p " profile needs " #x); return 0; }
   299     } // if
   307 
       
   308     if (0) {}
       
   309 
       
   310     #if SUPPORT_PROFILE_GLSL
       
   311     else if (strcmp(profile, MOJOSHADER_PROFILE_GLSL) == 0)
       
   312     {
       
   313         MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shader_objects);
       
   314         MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_vertex_shader);
       
   315         MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_fragment_shader);
       
   316         MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shading_language_100);
       
   317     } // else if
       
   318     #endif
   300 
   319 
   301     else
   320     else
   302     {
   321     {
   303         set_error("unknown profile");
   322         set_error("unknown or unsupported profile");
   304         return 0;
   323         return 0;
   305     } // else
   324     } // else
   306 
   325 
   307     #undef REQUIRE_GL_EXTENSION
   326     #undef MUST_HAVE
   308 
   327 
   309     return 1;
   328     return 1;
   310 } // check_extensions
   329 } // valid_profile
   311 
   330 
   312 
   331 
   313 MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *_profile,
   332 const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname))
       
   333 {
       
   334     const char *retval = NULL;
       
   335     MOJOSHADER_glContext _ctx;
       
   336     MOJOSHADER_glContext *current_ctx = ctx;
       
   337 
       
   338     ctx = &_ctx;
       
   339     memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
       
   340     load_extensions(lookup);
       
   341 
       
   342     if (ctx->have_base_opengl)
       
   343     {
       
   344         static const char *priority[] = {
       
   345             MOJOSHADER_PROFILE_GLSL,
       
   346         };
       
   347 
       
   348         int i;
       
   349         for (i = 0; i < STATICARRAYLEN(priority); i++)
       
   350         {
       
   351             if (valid_profile(priority[i]))
       
   352             {
       
   353                 retval = priority[i];
       
   354                 break;
       
   355             } // if
       
   356         } // for
       
   357 
       
   358         if (retval == NULL)
       
   359             set_error("no profiles available");
       
   360     } // if
       
   361 
       
   362     ctx = current_ctx;
       
   363     return retval;
       
   364 } // MOJOSHADER_glBestProfile
       
   365 
       
   366 
       
   367 MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
   314                                         void *(*lookup)(const char *fnname),
   368                                         void *(*lookup)(const char *fnname),
   315                                         MOJOSHADER_malloc m, MOJOSHADER_free f,
   369                                         MOJOSHADER_malloc m, MOJOSHADER_free f,
   316                                         void *d)
   370                                         void *d)
   317 {
   371 {
   318     MOJOSHADER_glContext *retval = NULL;
   372     MOJOSHADER_glContext *retval = NULL;
   331 
   385 
   332     memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
   386     memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
   333     ctx->malloc_fn = m;
   387     ctx->malloc_fn = m;
   334     ctx->free_fn = f;
   388     ctx->free_fn = f;
   335     ctx->malloc_data = d;
   389     ctx->malloc_data = d;
   336 
   390     snprintf(ctx->profile, sizeof (ctx->profile), "%s", profile);
   337     if (strcmp(_profile, MOJOSHADER_PROFILE_GLSL) == 0)
   391 
   338         ctx->profile = MOJOSHADER_PROFILE_GLSL;
   392     load_extensions(lookup);
   339     else
   393     if (!valid_profile(profile))
   340     {
       
   341         set_error("unknown profile");
       
   342         goto init_fail;
       
   343     } // else
       
   344 
       
   345     if (!check_extensions(lookup))
       
   346         goto init_fail;
   394         goto init_fail;
   347 
   395 
   348     MOJOSHADER_glBindProgram(NULL);
   396     MOJOSHADER_glBindProgram(NULL);
   349 
   397 
   350     retval = ctx;
   398     retval = ctx;