mojoshader_opengl.c
changeset 1072 3400f252c4e0
parent 1071 0021ff95cab4
child 1073 6eccf031c7e6
equal deleted inserted replaced
1071:0021ff95cab4 1072:3400f252c4e0
   166     int glsl_minor;
   166     int glsl_minor;
   167     MOJOSHADER_glProgram *bound_program;
   167     MOJOSHADER_glProgram *bound_program;
   168     char profile[16];
   168     char profile[16];
   169 
   169 
   170     // Extensions...
   170     // Extensions...
   171     int have_base_opengl;
   171     int have_core_opengl;
       
   172     int have_opengl_2;  // different entry points than ARB extensions.
   172     int have_GL_ARB_vertex_program;
   173     int have_GL_ARB_vertex_program;
   173     int have_GL_ARB_fragment_program;
   174     int have_GL_ARB_fragment_program;
   174     int have_GL_NV_vertex_program2_option;
   175     int have_GL_NV_vertex_program2_option;
   175     int have_GL_NV_fragment_program2;
   176     int have_GL_NV_fragment_program2;
   176     int have_GL_NV_vertex_program3;
   177     int have_GL_NV_vertex_program3;
   187     PFNGLGETSTRINGPROC glGetString;
   188     PFNGLGETSTRINGPROC glGetString;
   188     PFNGLGETERRORPROC glGetError;
   189     PFNGLGETERRORPROC glGetError;
   189     PFNGLGETINTEGERVPROC glGetIntegerv;
   190     PFNGLGETINTEGERVPROC glGetIntegerv;
   190     PFNGLENABLEPROC glEnable;
   191     PFNGLENABLEPROC glEnable;
   191     PFNGLDISABLEPROC glDisable;
   192     PFNGLDISABLEPROC glDisable;
   192     PFNGLDELETEOBJECTARBPROC glDeleteObject;
   193     PFNGLDELETESHADERPROC glDeleteShader;
   193     PFNGLATTACHOBJECTARBPROC glAttachObject;
   194     PFNGLDELETEPROGRAMPROC glDeleteProgram;
   194     PFNGLCOMPILESHADERARBPROC glCompileShader;
   195     PFNGLATTACHSHADERPROC glAttachShader;
   195     PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
   196     PFNGLCOMPILESHADERPROC glCompileShader;
   196     PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject;
   197     PFNGLCREATESHADERPROC glCreateShader;
   197     PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArray;
   198     PFNGLCREATEPROGRAMPROC glCreateProgram;
   198     PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArray;
   199     PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
   199     PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocation;
   200     PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
   200     PFNGLGETINFOLOGARBPROC glGetInfoLog;
   201     PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
   201     PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv;
   202     PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
   202     PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
   203     PFNGLGETSHADERIVPROC glGetShaderiv;
   203     PFNGLLINKPROGRAMARBPROC glLinkProgram;
   204     PFNGLGETPROGRAMIVPROC glGetProgramiv;
   204     PFNGLSHADERSOURCEARBPROC glShaderSource;
   205     PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
   205     PFNGLUNIFORM1IARBPROC glUniform1i;
   206     PFNGLLINKPROGRAMPROC glLinkProgram;
   206     PFNGLUNIFORM1IVARBPROC glUniform1iv;
   207     PFNGLSHADERSOURCEPROC glShaderSource;
   207     PFNGLUNIFORM4FVARBPROC glUniform4fv;
   208     PFNGLUNIFORM1IPROC glUniform1i;
   208     PFNGLUNIFORM4IVARBPROC glUniform4iv;
   209     PFNGLUNIFORM1IVPROC glUniform1iv;
   209     PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
   210     PFNGLUNIFORM4FVPROC glUniform4fv;
   210     PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer;
   211     PFNGLUNIFORM4IVPROC glUniform4iv;
       
   212     PFNGLUSEPROGRAMPROC glUseProgram;
       
   213     PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
       
   214     PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
       
   215     PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
       
   216     PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
       
   217     PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
       
   218     PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
       
   219     PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
       
   220     PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
       
   221     PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
       
   222     PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
       
   223     PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
       
   224     PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
       
   225     PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
       
   226     PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
       
   227     PFNGLUNIFORM1IARBPROC glUniform1iARB;
       
   228     PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
       
   229     PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
       
   230     PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
       
   231     PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
       
   232     PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
   211     PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
   233     PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
   212     PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
   234     PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
   213     PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC glProgramLocalParameterI4ivNV;
   235     PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC glProgramLocalParameterI4ivNV;
   214     PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
   236     PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
   215     PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
   237     PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
   224     GLint (*profileGetAttribLocation)(MOJOSHADER_glProgram *program, int idx);
   246     GLint (*profileGetAttribLocation)(MOJOSHADER_glProgram *program, int idx);
   225     GLint (*profileGetUniformLocation)(MOJOSHADER_glProgram *program, MOJOSHADER_glShader *shader, int idx);
   247     GLint (*profileGetUniformLocation)(MOJOSHADER_glProgram *program, MOJOSHADER_glShader *shader, int idx);
   226     GLint (*profileGetSamplerLocation)(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
   248     GLint (*profileGetSamplerLocation)(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
   227     GLuint (*profileLinkProgram)(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
   249     GLuint (*profileLinkProgram)(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
   228     void (*profileFinalInitProgram)(MOJOSHADER_glProgram *program);
   250     void (*profileFinalInitProgram)(MOJOSHADER_glProgram *program);
   229     void (*profileUseProgramObject)(MOJOSHADER_glProgram *program);
   251     void (*profileUseProgram)(MOJOSHADER_glProgram *program);
   230     void (*profilePushConstantArray)(MOJOSHADER_glProgram *, const MOJOSHADER_uniform *, const GLfloat *);
   252     void (*profilePushConstantArray)(MOJOSHADER_glProgram *, const MOJOSHADER_uniform *, const GLfloat *);
   231     void (*profilePushUniforms)(void);
   253     void (*profilePushUniforms)(void);
   232     void (*profilePushSampler)(GLint loc, GLuint sampler);
   254     void (*profilePushSampler)(GLint loc, GLuint sampler);
   233     int (*profileMustPushConstantArrays)(void);
   255     int (*profileMustPushConstantArrays)(void);
   234     int (*profileMustPushSamplers)(void);
   256     int (*profileMustPushSamplers)(void);
   321 // profile-specific implementations...
   343 // profile-specific implementations...
   322 
   344 
   323 #if SUPPORT_PROFILE_GLSL
   345 #if SUPPORT_PROFILE_GLSL
   324 static inline GLenum glsl_shader_type(const MOJOSHADER_shaderType t)
   346 static inline GLenum glsl_shader_type(const MOJOSHADER_shaderType t)
   325 {
   347 {
       
   348     // these enums match between core 2.0 and the ARB extensions.
   326     if (t == MOJOSHADER_TYPE_VERTEX)
   349     if (t == MOJOSHADER_TYPE_VERTEX)
   327         return GL_VERTEX_SHADER;
   350         return GL_VERTEX_SHADER;
   328     else if (t == MOJOSHADER_TYPE_PIXEL)
   351     else if (t == MOJOSHADER_TYPE_PIXEL)
   329         return GL_FRAGMENT_SHADER;
   352         return GL_FRAGMENT_SHADER;
   330 
   353 
   336 static int impl_GLSL_MustPushConstantArrays(void) { return 1; }
   359 static int impl_GLSL_MustPushConstantArrays(void) { return 1; }
   337 static int impl_GLSL_MustPushSamplers(void) { return 1; }
   360 static int impl_GLSL_MustPushSamplers(void) { return 1; }
   338 
   361 
   339 static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type)
   362 static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type)
   340 {
   363 {
       
   364     // these enums match between core 2.0 and the ARB extensions.
   341     GLenum pname = GL_NONE;
   365     GLenum pname = GL_NONE;
   342     GLint val = 0;
   366     GLint val = 0;
   343     if (shader_type == MOJOSHADER_TYPE_VERTEX)
   367     if (shader_type == MOJOSHADER_TYPE_VERTEX)
   344         pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB;
   368         pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
   345     else if (shader_type == MOJOSHADER_TYPE_PIXEL)
   369     else if (shader_type == MOJOSHADER_TYPE_PIXEL)
   346         pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB;
   370         pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
   347     else
   371     else
   348         return -1;
   372         return -1;
   349 
   373 
   350     ctx->glGetIntegerv(pname, &val);
   374     ctx->glGetIntegerv(pname, &val);
   351     return (int) val;
   375     return (int) val;
   353 
   377 
   354 
   378 
   355 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
   379 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
   356 {
   380 {
   357     GLint ok = 0;
   381     GLint ok = 0;
   358     GLint shaderlen = (GLint) pd->output_len;
   382     const GLint codelen = (GLint) pd->output_len;
   359     const GLenum shader_type = glsl_shader_type(pd->shader_type);
   383     const GLenum shader_type = glsl_shader_type(pd->shader_type);
   360     GLuint shader = ctx->glCreateShaderObject(shader_type);
   384 
   361 
   385     if (ctx->have_opengl_2)
   362     ctx->glShaderSource(shader, 1, (const GLchar **) &pd->output, &shaderlen);
   386     {
   363     ctx->glCompileShader(shader);
   387         const GLuint shader = ctx->glCreateShader(shader_type);
   364     ctx->glGetObjectParameteriv(shader, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
   388         ctx->glShaderSource(shader, 1, (const GLchar**) &pd->output, &codelen);
   365 
   389         ctx->glCompileShader(shader);
   366     if (!ok)
   390         ctx->glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
   367     {
   391         if (!ok)
   368         GLsizei len = 0;
   392         {
   369         ctx->glGetInfoLog(shader, sizeof (error_buffer), &len,
   393             GLsizei len = 0;
   370                           (GLchar *) error_buffer);
   394             ctx->glGetInfoLogARB(shader, sizeof (error_buffer), &len,
   371         *s = 0;
   395                                  (GLchar *) error_buffer);
   372         return 0;
   396             *s = 0;
   373     } // if
   397             return 0;
   374 
   398         } // if
   375     *s = shader;
   399 
       
   400         *s = shader;
       
   401     } // if
       
   402     else
       
   403     {
       
   404         const GLhandleARB shader = ctx->glCreateShaderObjectARB(shader_type);
       
   405         assert(sizeof (shader) == sizeof (*s));  // not always true on OS X!
       
   406         ctx->glShaderSourceARB(shader, 1,
       
   407                               (const GLcharARB **) &pd->output, &codelen);
       
   408         ctx->glCompileShaderARB(shader);
       
   409         ctx->glGetObjectParameterivARB(shader,GL_OBJECT_COMPILE_STATUS_ARB,&ok);
       
   410         if (!ok)
       
   411         {
       
   412             GLsizei len = 0;
       
   413             ctx->glGetInfoLogARB(shader, sizeof (error_buffer), &len,
       
   414                                  (GLcharARB *) error_buffer);
       
   415             *s = 0;
       
   416             return 0;
       
   417         } // if
       
   418 
       
   419         *s = (GLuint) shader;
       
   420     } // else
       
   421 
   376     return 1;
   422     return 1;
   377 } // impl_GLSL_CompileShader
   423 } // impl_GLSL_CompileShader
   378 
   424 
   379 
   425 
   380 static void impl_GLSL_DeleteShader(const GLuint shader)
   426 static void impl_GLSL_DeleteShader(const GLuint shader)
   381 {
   427 {
   382     ctx->glDeleteObject(shader);
   428     if (ctx->have_opengl_2)
       
   429         ctx->glDeleteShader(shader);
       
   430     else
       
   431         ctx->glDeleteObjectARB((GLhandleARB) shader);
   383 } // impl_GLSL_DeleteShader
   432 } // impl_GLSL_DeleteShader
   384 
   433 
   385 
   434 
   386 static void impl_GLSL_DeleteProgram(const GLuint program)
   435 static void impl_GLSL_DeleteProgram(const GLuint program)
   387 {
   436 {
   388     ctx->glDeleteObject(program);
   437     if (ctx->have_opengl_2)
       
   438         ctx->glDeleteProgram(program);
       
   439     else
       
   440         ctx->glDeleteObjectARB((GLhandleARB) program);
   389 } // impl_GLSL_DeleteProgram
   441 } // impl_GLSL_DeleteProgram
   390 
   442 
   391 
   443 
   392 static GLint impl_GLSL_GetUniformLocation(MOJOSHADER_glProgram *program,
   444 static GLint impl_GLSL_GetUniformLocation(MOJOSHADER_glProgram *program,
   393                                           MOJOSHADER_glShader *shader, int idx)
   445                                           MOJOSHADER_glShader *shader, int idx)
   394 {
   446 {
   395     return 0;  // no-op, we push this as one big-ass array now.
   447     return 0;  // no-op, we push this as one big-ass array now.
   396 } // impl_GLSL_GetUniformLocation
   448 } // impl_GLSL_GetUniformLocation
   397 
   449 
   398 
   450 
       
   451 static inline GLint glsl_uniform_loc(MOJOSHADER_glProgram *program,
       
   452                                           const char *name)
       
   453 {
       
   454     return ctx->have_opengl_2 ?
       
   455         ctx->glGetUniformLocation(program->handle, name) :
       
   456         ctx->glGetUniformLocationARB((GLhandleARB) program->handle, name);
       
   457 } // glsl_uniform_loc
       
   458 
       
   459 
   399 static GLint impl_GLSL_GetSamplerLocation(MOJOSHADER_glProgram *program,
   460 static GLint impl_GLSL_GetSamplerLocation(MOJOSHADER_glProgram *program,
   400                                           MOJOSHADER_glShader *shader, int idx)
   461                                           MOJOSHADER_glShader *shader, int idx)
   401 {
   462 {
   402     return ctx->glGetUniformLocation(program->handle,
   463     return glsl_uniform_loc(program, shader->parseData->samplers[idx].name);
   403                                      shader->parseData->samplers[idx].name);
       
   404 } // impl_GLSL_GetSamplerLocation
   464 } // impl_GLSL_GetSamplerLocation
   405 
   465 
   406 
   466 
   407 static GLint impl_GLSL_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
   467 static GLint impl_GLSL_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
   408 {
   468 {
   409     const MOJOSHADER_parseData *pd = program->vertex->parseData;
   469     const MOJOSHADER_parseData *pd = program->vertex->parseData;
   410     const MOJOSHADER_attribute *a = pd->attributes;
   470     const MOJOSHADER_attribute *a = pd->attributes;
   411     return ctx->glGetAttribLocation(program->handle, a[idx].name);
   471 
       
   472     if (ctx->have_opengl_2)
       
   473     {
       
   474         return ctx->glGetAttribLocation(program->handle,
       
   475                                         (const GLchar *) a[idx].name);
       
   476     } // if
       
   477 
       
   478     return ctx->glGetAttribLocationARB((GLhandleARB) program->handle,
       
   479                                         (const GLcharARB *) a[idx].name);
   412 } // impl_GLSL_GetAttribLocation
   480 } // impl_GLSL_GetAttribLocation
   413 
   481 
   414 
   482 
   415 static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *vshader,
   483 static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *vshader,
   416                                     MOJOSHADER_glShader *pshader)
   484                                     MOJOSHADER_glShader *pshader)
   417 {
   485 {
   418     const GLuint program = ctx->glCreateProgramObject();
       
   419 
       
   420     if (vshader != NULL) ctx->glAttachObject(program, vshader->handle);
       
   421     if (pshader != NULL) ctx->glAttachObject(program, pshader->handle);
       
   422 
       
   423     ctx->glLinkProgram(program);
       
   424 
       
   425     GLint ok = 0;
   486     GLint ok = 0;
   426     ctx->glGetObjectParameteriv(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
   487 
   427     if (!ok)
   488     if (ctx->have_opengl_2)
   428     {
   489     {
   429         GLsizei len = 0;
   490         const GLuint program = ctx->glCreateProgram();
   430         ctx->glGetInfoLog(program, sizeof (error_buffer), &len, (GLchar *) error_buffer);
   491 
   431         ctx->glDeleteObject(program);
   492         if (vshader != NULL) ctx->glAttachShader(program, vshader->handle);
   432         return 0;
   493         if (pshader != NULL) ctx->glAttachShader(program, pshader->handle);
   433     } // if
   494 
   434 
   495         ctx->glLinkProgram(program);
   435     return program;
   496 
       
   497         ctx->glGetProgramiv(program, GL_LINK_STATUS, &ok);
       
   498         if (!ok)
       
   499         {
       
   500             GLsizei len = 0;
       
   501             ctx->glGetProgramInfoLog(program, sizeof (error_buffer),
       
   502                                      &len, (GLchar *) error_buffer);
       
   503             ctx->glDeleteProgram(program);
       
   504             return 0;
       
   505         } // if
       
   506 
       
   507         return program;
       
   508     } // if
       
   509     else
       
   510     {
       
   511         const GLhandleARB program = ctx->glCreateProgramObjectARB();
       
   512         assert(sizeof(program) == sizeof(GLuint));  // not always true on OS X!
       
   513 
       
   514         if (vshader != NULL)
       
   515             ctx->glAttachObjectARB(program, (GLhandleARB) vshader->handle);
       
   516 
       
   517         if (pshader != NULL)
       
   518             ctx->glAttachObjectARB(program, (GLhandleARB) pshader->handle);
       
   519 
       
   520         ctx->glLinkProgramARB(program);
       
   521 
       
   522         ctx->glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
       
   523         if (!ok)
       
   524         {
       
   525             GLsizei len = 0;
       
   526             ctx->glGetInfoLogARB(program, sizeof (error_buffer),
       
   527                                  &len, (GLcharARB *) error_buffer);
       
   528             ctx->glDeleteObjectARB(program);
       
   529             return 0;
       
   530         } // if
       
   531 
       
   532         return (GLuint) program;
       
   533     } // else
   436 } // impl_GLSL_LinkProgram
   534 } // impl_GLSL_LinkProgram
   437 
   535 
   438 
       
   439 static void impl_GLSL_FinalInitProgram(MOJOSHADER_glProgram *program)
   536 static void impl_GLSL_FinalInitProgram(MOJOSHADER_glProgram *program)
   440 {
   537 {
   441     program->vs_float4_loc =
   538     
   442         ctx->glGetUniformLocation(program->handle, "vs_uniforms_vec4");
   539     program->vs_float4_loc = glsl_uniform_loc(program, "vs_uniforms_vec4");
   443     program->vs_int4_loc =
   540     program->vs_int4_loc = glsl_uniform_loc(program, "vs_uniforms_ivec4");
   444         ctx->glGetUniformLocation(program->handle, "vs_uniforms_ivec4");
   541     program->vs_bool_loc = glsl_uniform_loc(program, "vs_uniforms_bool");
   445     program->vs_bool_loc =
   542     program->ps_float4_loc = glsl_uniform_loc(program, "ps_uniforms_vec4");
   446         ctx->glGetUniformLocation(program->handle, "vs_uniforms_bool");
   543     program->ps_int4_loc = glsl_uniform_loc(program, "ps_uniforms_ivec4");
   447     program->ps_float4_loc =
   544     program->ps_bool_loc = glsl_uniform_loc(program, "ps_uniforms_bool");
   448         ctx->glGetUniformLocation(program->handle, "ps_uniforms_vec4");
       
   449     program->ps_int4_loc =
       
   450         ctx->glGetUniformLocation(program->handle, "ps_uniforms_ivec4");
       
   451     program->ps_bool_loc =
       
   452         ctx->glGetUniformLocation(program->handle, "ps_uniforms_bool");
       
   453 } // impl_GLSL_FinalInitProgram
   545 } // impl_GLSL_FinalInitProgram
   454 
   546 
   455 
   547 
   456 static void impl_GLSL_UseProgramObject(MOJOSHADER_glProgram *program)
   548 static void impl_GLSL_UseProgram(MOJOSHADER_glProgram *program)
   457 {
   549 {
   458     ctx->glUseProgramObject((program != NULL) ? program->handle : 0);
   550     if (ctx->have_opengl_2)
   459 } // impl_GLSL_UseProgramObject
   551         ctx->glUseProgram(program ? program->handle : 0);
       
   552     else
       
   553         ctx->glUseProgramObjectARB((GLhandleARB) (program ? program->handle : 0));
       
   554 } // impl_GLSL_UseProgram
   460 
   555 
   461 
   556 
   462 static void impl_GLSL_PushConstantArray(MOJOSHADER_glProgram *program,
   557 static void impl_GLSL_PushConstantArray(MOJOSHADER_glProgram *program,
   463                                         const MOJOSHADER_uniform *u,
   558                                         const MOJOSHADER_uniform *u,
   464                                         const GLfloat *f)
   559                                         const GLfloat *f)
   465 {
   560 {
   466     const GLint loc = ctx->glGetUniformLocation(program->handle, u->name);
   561     const GLint loc = glsl_uniform_loc(program, u->name);
   467     if (loc >= 0)   // not optimized out?
   562     if (loc >= 0)   // not optimized out?
   468         ctx->glUniform4fv(loc, u->array_count, f);
   563         ctx->glUniform4fv(loc, u->array_count, f);
   469 } // impl_GLSL_PushConstantArray
   564 } // impl_GLSL_PushConstantArray
   470 
   565 
   471 
   566 
   629 {
   724 {
   630     // no-op.
   725     // no-op.
   631 } // impl_ARB1_FinalInitProgram
   726 } // impl_ARB1_FinalInitProgram
   632 
   727 
   633 
   728 
   634 static void impl_ARB1_UseProgramObject(MOJOSHADER_glProgram *program)
   729 static void impl_ARB1_UseProgram(MOJOSHADER_glProgram *program)
   635 {
   730 {
   636     GLuint vhandle = 0;
   731     GLuint vhandle = 0;
   637     GLuint phandle = 0;
   732     GLuint phandle = 0;
   638     if (program != NULL)
   733     if (program != NULL)
   639     {
   734     {
   646     toggle_gl_state(GL_VERTEX_PROGRAM_ARB, vhandle != 0);
   741     toggle_gl_state(GL_VERTEX_PROGRAM_ARB, vhandle != 0);
   647     toggle_gl_state(GL_FRAGMENT_PROGRAM_ARB, phandle != 0);
   742     toggle_gl_state(GL_FRAGMENT_PROGRAM_ARB, phandle != 0);
   648 
   743 
   649     ctx->glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vhandle);
   744     ctx->glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vhandle);
   650     ctx->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, phandle);
   745     ctx->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, phandle);
   651 } // impl_ARB1_UseProgramObject
   746 } // impl_ARB1_UseProgram
   652 
   747 
   653 
   748 
   654 static void impl_ARB1_PushConstantArray(MOJOSHADER_glProgram *program,
   749 static void impl_ARB1_PushConstantArray(MOJOSHADER_glProgram *program,
   655                                         const MOJOSHADER_uniform *u,
   750                                         const MOJOSHADER_uniform *u,
   656                                         const GLfloat *f)
   751                                         const GLfloat *f)
   778 static void *loadsym(MOJOSHADER_glGetProcAddress lookup, void *d,
   873 static void *loadsym(MOJOSHADER_glGetProcAddress lookup, void *d,
   779                      const char *fn, int *ext)
   874                      const char *fn, int *ext)
   780 {
   875 {
   781     void *retval = NULL;
   876     void *retval = NULL;
   782     if (lookup != NULL)
   877     if (lookup != NULL)
   783     {
       
   784         retval = lookup(fn, d);
   878         retval = lookup(fn, d);
   785         if (retval == NULL)
       
   786         {
       
   787             char arbfn[64];
       
   788             snprintf(arbfn, sizeof (arbfn), "%sARB", fn);
       
   789             retval = lookup(arbfn, d);
       
   790         } // if
       
   791     } // if
       
   792 
   879 
   793     if (retval == NULL)
   880     if (retval == NULL)
   794         *ext = 0;
   881         *ext = 0;
   795 
   882 
   796     return retval;
   883     return retval;
   800 {
   887 {
   801     #define DO_LOOKUP(ext, typ, fn) { \
   888     #define DO_LOOKUP(ext, typ, fn) { \
   802         ctx->fn = (typ) loadsym(lookup, d, #fn, &ctx->have_##ext); \
   889         ctx->fn = (typ) loadsym(lookup, d, #fn, &ctx->have_##ext); \
   803     }
   890     }
   804 
   891 
   805     DO_LOOKUP(base_opengl, PFNGLGETSTRINGPROC, glGetString);
   892     DO_LOOKUP(core_opengl, PFNGLGETSTRINGPROC, glGetString);
   806     DO_LOOKUP(base_opengl, PFNGLGETERRORPROC, glGetError);
   893     DO_LOOKUP(core_opengl, PFNGLGETERRORPROC, glGetError);
   807     DO_LOOKUP(base_opengl, PFNGLGETINTEGERVPROC, glGetIntegerv);
   894     DO_LOOKUP(core_opengl, PFNGLGETINTEGERVPROC, glGetIntegerv);
   808     DO_LOOKUP(base_opengl, PFNGLENABLEPROC, glEnable);
   895     DO_LOOKUP(core_opengl, PFNGLENABLEPROC, glEnable);
   809     DO_LOOKUP(base_opengl, PFNGLDISABLEPROC, glDisable);
   896     DO_LOOKUP(core_opengl, PFNGLDISABLEPROC, glDisable);
   810     DO_LOOKUP(GL_ARB_shader_objects, PFNGLDELETEOBJECTARBPROC, glDeleteObject);
   897     DO_LOOKUP(opengl_2, PFNGLDELETESHADERPROC, glDeleteShader);
   811     DO_LOOKUP(GL_ARB_shader_objects, PFNGLATTACHOBJECTARBPROC, glAttachObject);
   898     DO_LOOKUP(opengl_2, PFNGLDELETEPROGRAMPROC, glDeleteProgram);
   812     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCOMPILESHADERARBPROC, glCompileShader);
   899     DO_LOOKUP(opengl_2, PFNGLATTACHSHADERPROC, glAttachShader);
   813     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObject);
   900     DO_LOOKUP(opengl_2, PFNGLCOMPILESHADERPROC, glCompileShader);
   814     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObject);
   901     DO_LOOKUP(opengl_2, PFNGLCREATESHADERPROC, glCreateShader);
   815     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETINFOLOGARBPROC, glGetInfoLog);
   902     DO_LOOKUP(opengl_2, PFNGLCREATEPROGRAMPROC, glCreateProgram);
   816     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameteriv);
   903     DO_LOOKUP(opengl_2, PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray);
   817     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocation);
   904     DO_LOOKUP(opengl_2, PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray);
   818     DO_LOOKUP(GL_ARB_shader_objects, PFNGLLINKPROGRAMARBPROC, glLinkProgram);
   905     DO_LOOKUP(opengl_2, PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation);
   819     DO_LOOKUP(GL_ARB_shader_objects, PFNGLSHADERSOURCEARBPROC, glShaderSource);
   906     DO_LOOKUP(opengl_2, PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog);
   820     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM1IARBPROC, glUniform1i);
   907     DO_LOOKUP(opengl_2, PFNGLGETSHADERIVPROC, glGetShaderiv);
   821     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM1IVARBPROC, glUniform1iv);
   908     DO_LOOKUP(opengl_2, PFNGLGETPROGRAMIVPROC, glGetProgramiv);
   822     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4FVARBPROC, glUniform4fv);
   909     DO_LOOKUP(opengl_2, PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation);
   823     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4IVARBPROC, glUniform4iv);
   910     DO_LOOKUP(opengl_2, PFNGLLINKPROGRAMPROC, glLinkProgram);
   824     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObject);
   911     DO_LOOKUP(opengl_2, PFNGLSHADERSOURCEPROC, glShaderSource);
   825     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArray);
   912     DO_LOOKUP(opengl_2, PFNGLUNIFORM1IPROC, glUniform1i);
   826     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArray);
   913     DO_LOOKUP(opengl_2, PFNGLUNIFORM1IVPROC, glUniform1iv);
   827     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocation);
   914     DO_LOOKUP(opengl_2, PFNGLUNIFORM4FVPROC, glUniform4fv);
   828     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
   915     DO_LOOKUP(opengl_2, PFNGLUNIFORM4IVPROC, glUniform4iv);
   829     DO_LOOKUP(GL_ARB_vertex_program, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
   916     DO_LOOKUP(opengl_2, PFNGLUSEPROGRAMPROC, glUseProgram);
       
   917     DO_LOOKUP(opengl_2, PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer);
       
   918     DO_LOOKUP(GL_ARB_shader_objects, PFNGLDELETEOBJECTARBPROC, glDeleteObjectARB);
       
   919     DO_LOOKUP(GL_ARB_shader_objects, PFNGLATTACHOBJECTARBPROC, glAttachObjectARB);
       
   920     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCOMPILESHADERARBPROC, glCompileShaderARB);
       
   921     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB);
       
   922     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB);
       
   923     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETINFOLOGARBPROC, glGetInfoLogARB);
       
   924     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB);
       
   925     DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB);
       
   926     DO_LOOKUP(GL_ARB_shader_objects, PFNGLLINKPROGRAMARBPROC, glLinkProgramARB);
       
   927     DO_LOOKUP(GL_ARB_shader_objects, PFNGLSHADERSOURCEARBPROC, glShaderSourceARB);
       
   928     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM1IARBPROC, glUniform1iARB);
       
   929     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM1IVARBPROC, glUniform1ivARB);
       
   930     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4FVARBPROC, glUniform4fvARB);
       
   931     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4IVARBPROC, glUniform4ivARB);
       
   932     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB);
       
   933     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB);
       
   934     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB);
       
   935     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocationARB);
       
   936     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB);
       
   937     DO_LOOKUP(GL_ARB_vertex_program, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB);
   830     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGETPROGRAMIVARBPROC, glGetProgramivARB);
   938     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGETPROGRAMIVARBPROC, glGetProgramivARB);
   831     DO_LOOKUP(GL_ARB_vertex_program, PFNGLPROGRAMLOCALPARAMETER4FVARBPROC, glProgramLocalParameter4fvARB);
   939     DO_LOOKUP(GL_ARB_vertex_program, PFNGLPROGRAMLOCALPARAMETER4FVARBPROC, glProgramLocalParameter4fvARB);
   832     DO_LOOKUP(GL_ARB_vertex_program, PFNGLDELETEPROGRAMSARBPROC, glDeleteProgramsARB);
   940     DO_LOOKUP(GL_ARB_vertex_program, PFNGLDELETEPROGRAMSARBPROC, glDeleteProgramsARB);
   833     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGENPROGRAMSARBPROC, glGenProgramsARB);
   941     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGENPROGRAMSARBPROC, glGenProgramsARB);
   834     DO_LOOKUP(GL_ARB_vertex_program, PFNGLBINDPROGRAMARBPROC, glBindProgramARB);
   942     DO_LOOKUP(GL_ARB_vertex_program, PFNGLBINDPROGRAMARBPROC, glBindProgramARB);
   836     DO_LOOKUP(GL_NV_gpu_program4, PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC, glProgramLocalParameterI4ivNV);
   944     DO_LOOKUP(GL_NV_gpu_program4, PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC, glProgramLocalParameterI4ivNV);
   837 
   945 
   838     #undef DO_LOOKUP
   946     #undef DO_LOOKUP
   839 } // lookup_entry_points
   947 } // lookup_entry_points
   840 
   948 
       
   949 static inline int opengl_version_atleast(const int major, const int minor)
       
   950 {
       
   951     return ( ((ctx->opengl_major << 16) | (ctx->opengl_minor & 0xFFFF)) >=
       
   952              ((major << 16) | (minor & 0xFFFF)) );
       
   953 } // opengl_version_atleast
   841 
   954 
   842 static int verify_extension(const char *ext, int have, const char *extlist,
   955 static int verify_extension(const char *ext, int have, const char *extlist,
   843                             int major, int minor)
   956                             int major, int minor)
   844 {
   957 {
   845     if (have == 0)
   958     if (have == 0)
   846         return 0;  // don't bother checking, we're missing an entry point.
   959         return 0;  // don't bother checking, we're missing an entry point.
   847 
   960 
   848     else if (!ctx->have_base_opengl)
   961     else if (!ctx->have_core_opengl)
   849         return 0;  // don't bother checking, we're missing basic functionality.
   962         return 0;  // don't bother checking, we're missing basic functionality.
   850 
   963 
   851     // See if it's in the spec for this GL implementation's version.
   964     // See if it's in the spec for this GL implementation's version.
   852     if (major >= 0)
   965     if ((major > 0) && (opengl_version_atleast(major, minor)))
   853     {
   966         return 1;
   854         if ( ((ctx->opengl_major << 16) | (ctx->opengl_minor & 0xFFFF)) >=
       
   855              ((major << 16) | (minor & 0xFFFF)) )
       
   856             return 1;
       
   857     } // if
       
   858 
   967 
   859     // Not available in the GL version, check the extension list.
   968     // Not available in the GL version, check the extension list.
   860     const char *ptr = strstr(extlist, ext);
   969     const char *ptr = strstr(extlist, ext);
   861     if (ptr == NULL)
   970     if (ptr == NULL)
   862         return 0;
   971         return 0;
   889 static void detect_glsl_version(void)
   998 static void detect_glsl_version(void)
   890 {
   999 {
   891     ctx->glsl_major = ctx->glsl_minor = 0;
  1000     ctx->glsl_major = ctx->glsl_minor = 0;
   892 
  1001 
   893 #if SUPPORT_PROFILE_GLSL
  1002 #if SUPPORT_PROFILE_GLSL
       
  1003     if (!ctx->have_core_opengl)
       
  1004         return;  // everything's busted, give up.
       
  1005 
   894     #if PLATFORM_MACOSX
  1006     #if PLATFORM_MACOSX
   895     // If running on Mac OS X <= 10.4, don't ever use GLSL, even if
  1007     // If running on Mac OS X <= 10.4, don't ever use GLSL, even if
   896     //  the system claims it is available.
  1008     //  the system claims it is available.
   897     if (!macosx_version_atleast(10, 5, 0))
  1009     if (!macosx_version_atleast(10, 5, 0))
   898         return;
  1010         return;
   899     #endif
  1011     #endif
   900 
  1012 
   901     if ( 0/* !!! FIXME: (ctx->opengl_major >= 2)*/ ||
  1013     if ( ctx->have_opengl_2 ||
   902          ( ctx->have_GL_ARB_shader_objects &&
  1014          ( ctx->have_GL_ARB_shader_objects &&
   903            ctx->have_GL_ARB_vertex_shader &&
  1015            ctx->have_GL_ARB_vertex_shader &&
   904            ctx->have_GL_ARB_fragment_shader &&
  1016            ctx->have_GL_ARB_fragment_shader &&
   905            ctx->have_GL_ARB_shading_language_100 ) )
  1017            ctx->have_GL_ARB_shading_language_100 ) )
   906     {
  1018     {
   907         // the GL2.0 and ARB enum is the same value.
  1019         // the GL2.0 and ARB enum is the same value.
   908         const GLenum enumval = GL_SHADING_LANGUAGE_VERSION_ARB;
  1020         const GLenum enumval = GL_SHADING_LANGUAGE_VERSION;
   909         ctx->glGetError();  // flush any existing error state.
  1021         ctx->glGetError();  // flush any existing error state.
   910         const char *str = (const char *) ctx->glGetString(enumval);
  1022         const char *str = (const char *) ctx->glGetString(enumval);
   911         if (ctx->glGetError() == GL_INVALID_ENUM)
  1023         if (ctx->glGetError() == GL_INVALID_ENUM)
   912             str = NULL;
  1024             str = NULL;
   913         parse_opengl_version_str(str, &ctx->glsl_major, &ctx->glsl_minor);
  1025         parse_opengl_version_str(str, &ctx->glsl_major, &ctx->glsl_minor);
   918 
  1030 
   919 static void load_extensions(MOJOSHADER_glGetProcAddress lookup, void *d)
  1031 static void load_extensions(MOJOSHADER_glGetProcAddress lookup, void *d)
   920 {
  1032 {
   921     const char *extlist = NULL;
  1033     const char *extlist = NULL;
   922 
  1034 
   923     ctx->have_base_opengl = 1;
  1035     ctx->have_core_opengl = 1;
       
  1036     ctx->have_opengl_2 = 1;
   924     ctx->have_GL_ARB_vertex_program = 1;
  1037     ctx->have_GL_ARB_vertex_program = 1;
   925     ctx->have_GL_ARB_fragment_program = 1;
  1038     ctx->have_GL_ARB_fragment_program = 1;
   926     ctx->have_GL_NV_vertex_program2_option = 1;
  1039     ctx->have_GL_NV_vertex_program2_option = 1;
   927     ctx->have_GL_NV_fragment_program2 = 1;
  1040     ctx->have_GL_NV_fragment_program2 = 1;
   928     ctx->have_GL_NV_vertex_program3 = 1;
  1041     ctx->have_GL_NV_vertex_program3 = 1;
   935     ctx->have_GL_ARB_half_float_vertex = 1;
  1048     ctx->have_GL_ARB_half_float_vertex = 1;
   936     ctx->have_GL_OES_vertex_half_float = 1;
  1049     ctx->have_GL_OES_vertex_half_float = 1;
   937 
  1050 
   938     lookup_entry_points(lookup, d);
  1051     lookup_entry_points(lookup, d);
   939 
  1052 
   940     if (!ctx->have_base_opengl)
  1053     if (!ctx->have_core_opengl)
   941         set_error("missing basic OpenGL entry points");
  1054         set_error("missing basic OpenGL entry points");
   942     else
  1055     else
   943     {
  1056     {
   944         const char *str = (const char *) ctx->glGetString(GL_VERSION);
  1057         const char *str = (const char *) ctx->glGetString(GL_VERSION);
   945         parse_opengl_version_str(str, &ctx->opengl_major, &ctx->opengl_minor);
  1058         parse_opengl_version_str(str, &ctx->opengl_major, &ctx->opengl_minor);
   946         extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
  1059         extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
   947     } // else
  1060     } // else
   948 
  1061 
   949     if (extlist == NULL)
  1062     if (extlist == NULL)
   950         extlist = "";  // just in case.
  1063         extlist = "";  // just in case.
       
  1064 
       
  1065     if ((ctx->have_opengl_2) && (!opengl_version_atleast(2, 0)))
       
  1066     {
       
  1067         ctx->have_opengl_2 = 0;  // Not GL2! must have the ARB extensions!
       
  1068 
       
  1069         // Force compatible ARB function pointers in...this keeps the code
       
  1070         //  cleaner when they are identical, so we don't have to if/else
       
  1071         //  every function call, but we definitely have the right entry
       
  1072         //  point. Be careful what you add here.
       
  1073         // These may be NULL, btw.
       
  1074         ctx->glUniform1i = ctx->glUniform1iARB;
       
  1075         ctx->glUniform4fv = ctx->glUniform4fvARB;
       
  1076         ctx->glUniform4iv = ctx->glUniform4ivARB;
       
  1077         ctx->glDisableVertexAttribArray = ctx->glDisableVertexAttribArrayARB;
       
  1078         ctx->glEnableVertexAttribArray = ctx->glEnableVertexAttribArrayARB;
       
  1079         ctx->glVertexAttribPointer = ctx->glVertexAttribPointerARB;
       
  1080     } // if
   951 
  1081 
   952     #define VERIFY_EXT(ext, major, minor) \
  1082     #define VERIFY_EXT(ext, major, minor) \
   953         ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor)
  1083         ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor)
   954 
  1084 
   955     VERIFY_EXT(GL_ARB_vertex_program, -1, -1);
  1085     VERIFY_EXT(GL_ARB_vertex_program, -1, -1);
   971 } // load_extensions
  1101 } // load_extensions
   972 
  1102 
   973 
  1103 
   974 static int valid_profile(const char *profile)
  1104 static int valid_profile(const char *profile)
   975 {
  1105 {
   976     if (!ctx->have_base_opengl)
  1106     if (!ctx->have_core_opengl)
   977         return 0;
  1107         return 0;
   978 
  1108 
   979     #define MUST_HAVE(p, x) \
  1109     #define MUST_HAVE(p, x) \
   980         if (!ctx->have_##x) { set_error(#p " profile needs " #x); return 0; }
  1110         if (!ctx->have_##x) { set_error(#p " profile needs " #x); return 0; }
   981 
  1111 
  1074 
  1204 
  1075     ctx = &_ctx;
  1205     ctx = &_ctx;
  1076     memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
  1206     memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
  1077     load_extensions(lookup, d);
  1207     load_extensions(lookup, d);
  1078 
  1208 
  1079     if (ctx->have_base_opengl)
  1209     if (ctx->have_core_opengl)
  1080     {
  1210     {
  1081         size_t i;
  1211         size_t i;
  1082         for (i = 0; i < STATICARRAYLEN(profile_priorities); i++)
  1212         for (i = 0; i < STATICARRAYLEN(profile_priorities); i++)
  1083         {
  1213         {
  1084             const char *profile = profile_priorities[i];
  1214             const char *profile = profile_priorities[i];
  1157         ctx->profileGetAttribLocation = impl_GLSL_GetAttribLocation;
  1287         ctx->profileGetAttribLocation = impl_GLSL_GetAttribLocation;
  1158         ctx->profileGetUniformLocation = impl_GLSL_GetUniformLocation;
  1288         ctx->profileGetUniformLocation = impl_GLSL_GetUniformLocation;
  1159         ctx->profileGetSamplerLocation = impl_GLSL_GetSamplerLocation;
  1289         ctx->profileGetSamplerLocation = impl_GLSL_GetSamplerLocation;
  1160         ctx->profileLinkProgram = impl_GLSL_LinkProgram;
  1290         ctx->profileLinkProgram = impl_GLSL_LinkProgram;
  1161         ctx->profileFinalInitProgram = impl_GLSL_FinalInitProgram;
  1291         ctx->profileFinalInitProgram = impl_GLSL_FinalInitProgram;
  1162         ctx->profileUseProgramObject = impl_GLSL_UseProgramObject;
  1292         ctx->profileUseProgram = impl_GLSL_UseProgram;
  1163         ctx->profilePushConstantArray = impl_GLSL_PushConstantArray;
  1293         ctx->profilePushConstantArray = impl_GLSL_PushConstantArray;
  1164         ctx->profilePushUniforms = impl_GLSL_PushUniforms;
  1294         ctx->profilePushUniforms = impl_GLSL_PushUniforms;
  1165         ctx->profilePushSampler = impl_GLSL_PushSampler;
  1295         ctx->profilePushSampler = impl_GLSL_PushSampler;
  1166         ctx->profileMustPushConstantArrays = impl_GLSL_MustPushConstantArrays;
  1296         ctx->profileMustPushConstantArrays = impl_GLSL_MustPushConstantArrays;
  1167         ctx->profileMustPushSamplers = impl_GLSL_MustPushSamplers;
  1297         ctx->profileMustPushSamplers = impl_GLSL_MustPushSamplers;
  1182         ctx->profileGetAttribLocation = impl_ARB1_GetAttribLocation;
  1312         ctx->profileGetAttribLocation = impl_ARB1_GetAttribLocation;
  1183         ctx->profileGetUniformLocation = impl_ARB1_GetUniformLocation;
  1313         ctx->profileGetUniformLocation = impl_ARB1_GetUniformLocation;
  1184         ctx->profileGetSamplerLocation = impl_ARB1_GetSamplerLocation;
  1314         ctx->profileGetSamplerLocation = impl_ARB1_GetSamplerLocation;
  1185         ctx->profileLinkProgram = impl_ARB1_LinkProgram;
  1315         ctx->profileLinkProgram = impl_ARB1_LinkProgram;
  1186         ctx->profileFinalInitProgram = impl_ARB1_FinalInitProgram;
  1316         ctx->profileFinalInitProgram = impl_ARB1_FinalInitProgram;
  1187         ctx->profileUseProgramObject = impl_ARB1_UseProgramObject;
  1317         ctx->profileUseProgram = impl_ARB1_UseProgram;
  1188         ctx->profilePushConstantArray = impl_ARB1_PushConstantArray;
  1318         ctx->profilePushConstantArray = impl_ARB1_PushConstantArray;
  1189         ctx->profilePushUniforms = impl_ARB1_PushUniforms;
  1319         ctx->profilePushUniforms = impl_ARB1_PushUniforms;
  1190         ctx->profilePushSampler = impl_ARB1_PushSampler;
  1320         ctx->profilePushSampler = impl_ARB1_PushSampler;
  1191         ctx->profileMustPushConstantArrays = impl_ARB1_MustPushConstantArrays;
  1321         ctx->profileMustPushConstantArrays = impl_ARB1_MustPushConstantArrays;
  1192         ctx->profileMustPushSamplers = impl_ARB1_MustPushSamplers;
  1322         ctx->profileMustPushSamplers = impl_ARB1_MustPushSamplers;
  1201     assert(ctx->profileGetAttribLocation != NULL);
  1331     assert(ctx->profileGetAttribLocation != NULL);
  1202     assert(ctx->profileGetUniformLocation != NULL);
  1332     assert(ctx->profileGetUniformLocation != NULL);
  1203     assert(ctx->profileGetSamplerLocation != NULL);
  1333     assert(ctx->profileGetSamplerLocation != NULL);
  1204     assert(ctx->profileLinkProgram != NULL);
  1334     assert(ctx->profileLinkProgram != NULL);
  1205     assert(ctx->profileFinalInitProgram != NULL);
  1335     assert(ctx->profileFinalInitProgram != NULL);
  1206     assert(ctx->profileUseProgramObject != NULL);
  1336     assert(ctx->profileUseProgram != NULL);
  1207     assert(ctx->profilePushConstantArray != NULL);
  1337     assert(ctx->profilePushConstantArray != NULL);
  1208     assert(ctx->profilePushUniforms != NULL);
  1338     assert(ctx->profilePushUniforms != NULL);
  1209     assert(ctx->profilePushSampler != NULL);
  1339     assert(ctx->profilePushSampler != NULL);
  1210     assert(ctx->profileMustPushConstantArrays != NULL);
  1340     assert(ctx->profileMustPushConstantArrays != NULL);
  1211     assert(ctx->profileMustPushSamplers != NULL);
  1341     assert(ctx->profileMustPushSamplers != NULL);
  1372                 const int size = u->array_count;
  1502                 const int size = u->array_count;
  1373                 GLfloat *f = (GLfloat *) alloca(sizeof (GLfloat) * (size * 4));
  1503                 GLfloat *f = (GLfloat *) alloca(sizeof (GLfloat) * (size * 4));
  1374                 fill_constant_array(f, base, size, pd);
  1504                 fill_constant_array(f, base, size, pd);
  1375                 if (!(*bound))
  1505                 if (!(*bound))
  1376                 {
  1506                 {
  1377                     ctx->profileUseProgramObject(program);
  1507                     ctx->profileUseProgram(program);
  1378                     *bound = 1;
  1508                     *bound = 1;
  1379                 } // if
  1509                 } // if
  1380                 ctx->profilePushConstantArray(program, u, f);
  1510                 ctx->profilePushConstantArray(program, u, f);
  1381             } // if
  1511             } // if
  1382         } // if
  1512         } // if
  1478     // Link up the Samplers. These never change after link time, since they
  1608     // Link up the Samplers. These never change after link time, since they
  1479     //  are meant to be constant texture unit ids and not textures.
  1609     //  are meant to be constant texture unit ids and not textures.
  1480 
  1610 
  1481     if (!(*bound))
  1611     if (!(*bound))
  1482     {
  1612     {
  1483         ctx->profileUseProgramObject(program);
  1613         ctx->profileUseProgram(program);
  1484         *bound = 1;
  1614         *bound = 1;
  1485     } // if
  1615     } // if
  1486 
  1616 
  1487     for (i = 0; i < pd->sampler_count; i++)
  1617     for (i = 0; i < pd->sampler_count; i++)
  1488     {
  1618     {
  1637 
  1767 
  1638     if (!build_constants_lists(retval))
  1768     if (!build_constants_lists(retval))
  1639         goto link_program_fail;
  1769         goto link_program_fail;
  1640 
  1770 
  1641     if (bound)  // reset the old binding.
  1771     if (bound)  // reset the old binding.
  1642         ctx->profileUseProgramObject(ctx->bound_program);
  1772         ctx->profileUseProgram(ctx->bound_program);
  1643 
  1773 
  1644     ctx->profileFinalInitProgram(retval);
  1774     ctx->profileFinalInitProgram(retval);
  1645 
  1775 
  1646     return retval;
  1776     return retval;
  1647 
  1777 
  1661 
  1791 
  1662     if (program != 0)
  1792     if (program != 0)
  1663         ctx->profileDeleteProgram(program);
  1793         ctx->profileDeleteProgram(program);
  1664 
  1794 
  1665     if (bound)
  1795     if (bound)
  1666         ctx->profileUseProgramObject(ctx->bound_program);
  1796         ctx->profileUseProgram(ctx->bound_program);
  1667 
  1797 
  1668     return NULL;
  1798     return NULL;
  1669 } // MOJOSHADER_glLinkProgram
  1799 } // MOJOSHADER_glLinkProgram
  1670 
  1800 
  1671 
  1801 
  1712     //  fixed function pipeline. Otherwise, we try to minimize state changes
  1842     //  fixed function pipeline. Otherwise, we try to minimize state changes
  1713     //  by toggling just the changed set of needed arrays in ProgramReady().
  1843     //  by toggling just the changed set of needed arrays in ProgramReady().
  1714     if (program == NULL)
  1844     if (program == NULL)
  1715         update_enabled_arrays();
  1845         update_enabled_arrays();
  1716 
  1846 
  1717     ctx->profileUseProgramObject(program);
  1847     ctx->profileUseProgram(program);
  1718     program_unref(ctx->bound_program);
  1848     program_unref(ctx->bound_program);
  1719     ctx->bound_program = program;
  1849     ctx->bound_program = program;
  1720 } // MOJOSHADER_glBindProgram
  1850 } // MOJOSHADER_glBindProgram
  1721 
  1851 
  1722 
  1852