mojoshader_opengl.c
branchtrunk
changeset 333 2b36a1d72fa1
parent 323 b60c88ec8182
child 339 4b1e0c45a6b8
equal deleted inserted replaced
332:8c7544035bd0 333:2b36a1d72fa1
   100 #endif
   100 #endif
   101 
   101 
   102 // Entry points in base OpenGL that lack function pointer prototypes...
   102 // Entry points in base OpenGL that lack function pointer prototypes...
   103 typedef WINGDIAPI void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
   103 typedef WINGDIAPI void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
   104 typedef WINGDIAPI const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
   104 typedef WINGDIAPI const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
       
   105 typedef WINGDIAPI GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
   105 
   106 
   106 struct MOJOSHADER_glContext
   107 struct MOJOSHADER_glContext
   107 {
   108 {
   108     // Allocators...
   109     // Allocators...
   109     MOJOSHADER_malloc malloc_fn;
   110     MOJOSHADER_malloc malloc_fn;
   136     int have_GL_ARB_shading_language_100;
   137     int have_GL_ARB_shading_language_100;
   137     int have_GL_NV_half_float;
   138     int have_GL_NV_half_float;
   138 
   139 
   139     // Entry points...
   140     // Entry points...
   140     PFNGLGETSTRINGPROC glGetString;
   141     PFNGLGETSTRINGPROC glGetString;
       
   142     PFNGLGETERRORPROC glGetError;
   141     PFNGLGETINTEGERVPROC glGetIntegerv;
   143     PFNGLGETINTEGERVPROC glGetIntegerv;
   142     PFNGLDELETEOBJECTARBPROC glDeleteObject;
   144     PFNGLDELETEOBJECTARBPROC glDeleteObject;
   143     PFNGLATTACHOBJECTARBPROC glAttachObject;
   145     PFNGLATTACHOBJECTARBPROC glAttachObject;
   144     PFNGLCOMPILESHADERARBPROC glCompileShader;
   146     PFNGLCOMPILESHADERARBPROC glCompileShader;
   145     PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
   147     PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
   155     PFNGLUNIFORM1IARBPROC glUniform1i;
   157     PFNGLUNIFORM1IARBPROC glUniform1i;
   156     PFNGLUNIFORM4FVARBPROC glUniform4fv;
   158     PFNGLUNIFORM4FVARBPROC glUniform4fv;
   157     PFNGLUNIFORM4IVARBPROC glUniform4iv;
   159     PFNGLUNIFORM4IVARBPROC glUniform4iv;
   158     PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
   160     PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
   159     PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer;
   161     PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer;
       
   162     PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
       
   163     PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
       
   164     PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
       
   165     PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
       
   166     PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
       
   167     PFNGLBINDPROGRAMARBPROC glBindProgramARB;
       
   168     PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
   160 
   169 
   161     // interface for profile-specific things.
   170     // interface for profile-specific things.
   162     int (*profileMaxUniforms)(MOJOSHADER_shaderType shader_type);
   171     int (*profileMaxUniforms)(MOJOSHADER_shaderType shader_type);
   163     int (*profileCompileShader)(const MOJOSHADER_parseData *pd);
   172     int (*profileCompileShader)(const MOJOSHADER_parseData *pd, GLuint *s);
   164     void (*profileDeleteShader)(const GLuint shader);
   173     void (*profileDeleteShader)(const GLuint shader);
   165     void (*profileDeleteProgram)(const GLuint program);
   174     void (*profileDeleteProgram)(const GLuint program);
       
   175     GLint (*profileGetUniformLocation)(GLuint, const MOJOSHADER_parseData *, int);
       
   176     GLuint (*profileLinkProgram)(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
       
   177     void (*profileUseProgramObject)(MOJOSHADER_glProgram *program);
       
   178     void (*profileUniform4fv)(GLint loc, GLsizei siz, GLfloat *v);
       
   179     void (*profileUniform4iv)(GLint loc, GLsizei siz, GLint *v);
       
   180     void (*profileUniform1i)(GLint loc, GLint v);
       
   181     void (*profileSetSampler)(GLint loc, GLuint sampler);
   166 };
   182 };
   167 
   183 
   168 // predeclare some profile implementation stuff...
   184 // predeclare some profile implementation stuff...
   169 static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type);
   185 static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type);
   170 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd);
   186 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s);
   171 static int impl_GLSL_DeleteShader(const GLuint shader);
   187 static void impl_GLSL_DeleteShader(const GLuint shader);
       
   188 static void impl_GLSL_DeleteProgram(const GLuint program);
       
   189 static GLint impl_GLSL_GetUniformLocation(GLuint, const MOJOSHADER_parseData *, int);
       
   190 static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
       
   191 static void impl_GLSL_UseProgramObject(MOJOSHADER_glProgram *program);
       
   192 static void impl_GLSL_Uniform4fv(GLint loc, GLsizei siz, GLfloat *v);
       
   193 static void impl_GLSL_Uniform4iv(GLint loc, GLsizei siz, GLint *v);
       
   194 static void impl_GLSL_Uniform1i(GLint loc, GLint v);
       
   195 static void impl_GLSL_SetSampler(GLint loc, GLuint sampler);
       
   196 
   172 static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type);
   197 static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type);
   173 static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd);
   198 static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s);
   174 static int impl_ARB1_DeleteShader(const GLuint shader);
   199 static void impl_ARB1_DeleteShader(const GLuint shader);
       
   200 static void impl_ARB1_DeleteProgram(const GLuint program);
       
   201 static GLint impl_ARB1_GetUniformLocation(GLuint, const MOJOSHADER_parseData *, int);
       
   202 static GLuint impl_ARB1_LinkProgram(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
       
   203 static void impl_ARB1_UseProgramObject(MOJOSHADER_glProgram *program);
       
   204 static void impl_ARB1_Uniform4fv(GLint loc, GLsizei siz, GLfloat *v);
       
   205 static void impl_ARB1_Uniform4iv(GLint loc, GLsizei siz, GLint *v);
       
   206 static void impl_ARB1_Uniform1i(GLint loc, GLint v);
       
   207 static void impl_ARB1_SetSampler(GLint loc, GLuint sampler);
   175 
   208 
   176 
   209 
   177 
   210 
   178 static MOJOSHADER_glContext *ctx = NULL;
   211 static MOJOSHADER_glContext *ctx = NULL;
   179 
   212 
   240 
   273 
   241 static void lookup_entry_points(void *(*lookup)(const char *fnname))
   274 static void lookup_entry_points(void *(*lookup)(const char *fnname))
   242 {
   275 {
   243     #define DO_LOOKUP(ext, typ, fn) ctx->fn = (typ) loadsym(lookup, #fn, &ctx->have_##ext)
   276     #define DO_LOOKUP(ext, typ, fn) ctx->fn = (typ) loadsym(lookup, #fn, &ctx->have_##ext)
   244     DO_LOOKUP(base_opengl, PFNGLGETSTRINGPROC, glGetString);
   277     DO_LOOKUP(base_opengl, PFNGLGETSTRINGPROC, glGetString);
       
   278     DO_LOOKUP(base_opengl, PFNGLGETERRORPROC, glGetError);
   245     DO_LOOKUP(base_opengl, PFNGLGETINTEGERVPROC, glGetIntegerv);
   279     DO_LOOKUP(base_opengl, PFNGLGETINTEGERVPROC, glGetIntegerv);
   246     DO_LOOKUP(GL_ARB_shader_objects, PFNGLDELETEOBJECTARBPROC, glDeleteObject);
   280     DO_LOOKUP(GL_ARB_shader_objects, PFNGLDELETEOBJECTARBPROC, glDeleteObject);
   247     DO_LOOKUP(GL_ARB_shader_objects, PFNGLATTACHOBJECTARBPROC, glAttachObject);
   281     DO_LOOKUP(GL_ARB_shader_objects, PFNGLATTACHOBJECTARBPROC, glAttachObject);
   248     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCOMPILESHADERARBPROC, glCompileShader);
   282     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCOMPILESHADERARBPROC, glCompileShader);
   249     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObject);
   283     DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObject);
   259     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObject);
   293     DO_LOOKUP(GL_ARB_shader_objects, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObject);
   260     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArray);
   294     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArray);
   261     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArray);
   295     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArray);
   262     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocation);
   296     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocation);
   263     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
   297     DO_LOOKUP(GL_ARB_vertex_shader, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
       
   298     DO_LOOKUP(GL_ARB_vertex_program, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObject);
       
   299     DO_LOOKUP(GL_ARB_vertex_program, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
       
   300     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGETPROGRAMIVARBPROC, glGetProgramivARB);
       
   301     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGETPROGRAMSTRINGARBPROC, glGetProgramStringARB);
       
   302     DO_LOOKUP(GL_ARB_vertex_program, PFNGLPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB);
       
   303     DO_LOOKUP(GL_ARB_vertex_program, PFNGLDELETEPROGRAMSARBPROC, glDeleteProgramsARB);
       
   304     DO_LOOKUP(GL_ARB_vertex_program, PFNGLGENPROGRAMSARBPROC, glGenProgramsARB);
       
   305     DO_LOOKUP(GL_ARB_vertex_program, PFNGLBINDPROGRAMARBPROC, glBindProgramARB);
       
   306     DO_LOOKUP(GL_ARB_vertex_program, PFNGLPROGRAMSTRINGARBPROC, glProgramStringARB);
       
   307 
   264     #undef DO_LOOKUP
   308     #undef DO_LOOKUP
   265 } // lookup_entry_points
   309 } // lookup_entry_points
   266 
   310 
   267 
   311 
   268 static int verify_extension(const char *ext, int have, const char *extlist,
   312 static int verify_extension(const char *ext, int have, const char *extlist,
   407         };
   451         };
   408 
   452 
   409         int i;
   453         int i;
   410         for (i = 0; i < STATICARRAYLEN(priority); i++)
   454         for (i = 0; i < STATICARRAYLEN(priority); i++)
   411         {
   455         {
       
   456             // !!! FIXME: if Mac OS X <= 10.4, don't ever pick GLSL, even if
       
   457             // !!! FIXME:  the system claims it is available.
   412             if (valid_profile(priority[i]))
   458             if (valid_profile(priority[i]))
   413             {
   459             {
   414                 retval = priority[i];
   460                 retval = priority[i];
   415                 break;
   461                 break;
   416             } // if
   462             } // if
   464     {
   510     {
   465         ctx->profileMaxUniforms = impl_GLSL_MaxUniforms;
   511         ctx->profileMaxUniforms = impl_GLSL_MaxUniforms;
   466         ctx->profileCompileShader = impl_GLSL_CompileShader;
   512         ctx->profileCompileShader = impl_GLSL_CompileShader;
   467         ctx->profileDeleteShader = impl_GLSL_DeleteShader;
   513         ctx->profileDeleteShader = impl_GLSL_DeleteShader;
   468         ctx->profileDeleteProgram = impl_GLSL_DeleteProgram;
   514         ctx->profileDeleteProgram = impl_GLSL_DeleteProgram;
       
   515         ctx->profileGetUniformLocation = impl_GLSL_GetUniformLocation;
       
   516         ctx->profileLinkProgram = impl_GLSL_LinkProgram;
       
   517         ctx->profileUseProgramObject = impl_GLSL_UseProgramObject;
       
   518         ctx->profileUniform4fv = impl_GLSL_Uniform4fv;
       
   519         ctx->profileUniform4iv = impl_GLSL_Uniform4iv;
       
   520         ctx->profileUniform1i = impl_GLSL_Uniform1i;
       
   521         ctx->profileSetSampler = impl_GLSL_SetSampler;
   469     } // if
   522     } // if
   470 #endif
   523 #endif
   471 
   524 
   472 #if SUPPORT_PROFILE_ARB1
   525 #if SUPPORT_PROFILE_ARB1
   473     else if (strcmp(profile, MOJOSHADER_PROFILE_ARB1) == 0)
   526     else if (strcmp(profile, MOJOSHADER_PROFILE_ARB1) == 0)
   474     {
   527     {
   475         ctx->profileMaxUniforms = impl_ARB1_MaxUniforms;
   528         ctx->profileMaxUniforms = impl_ARB1_MaxUniforms;
   476         ctx->profileCompileShader = impl_ARB1_CompileShader;
   529         ctx->profileCompileShader = impl_ARB1_CompileShader;
   477         ctx->profileDeleteShader = impl_ARB1_DeleteShader;
   530         ctx->profileDeleteShader = impl_ARB1_DeleteShader;
   478         ctx->profileDeleteProgram = impl_ARB1_DeleteProgram;
   531         ctx->profileDeleteProgram = impl_ARB1_DeleteProgram;
       
   532         ctx->profileGetUniformLocation = impl_ARB1_GetUniformLocation;
       
   533         ctx->profileLinkProgram = impl_ARB1_LinkProgram;
       
   534         ctx->profileUseProgramObject = impl_ARB1_UseProgramObject;
       
   535         ctx->profileUniform4fv = impl_ARB1_Uniform4fv;
       
   536         ctx->profileUniform4iv = impl_ARB1_Uniform4iv;
       
   537         ctx->profileUniform1i = impl_ARB1_Uniform1i;
       
   538         ctx->profileSetSampler = impl_ARB1_SetSampler;
   479     } // if
   539     } // if
   480 #endif
   540 #endif
   481 
   541 
   482     assert(ctx->profileMaxUniforms != NULL);
   542     assert(ctx->profileMaxUniforms != NULL);
   483     assert(ctx->profileCompileShader != NULL);
   543     assert(ctx->profileCompileShader != NULL);
   484     assert(ctx->profileDeleteShader != NULL);
   544     assert(ctx->profileDeleteShader != NULL);
   485     assert(ctx->profileDeleteProgram != NULL);
   545     assert(ctx->profileDeleteProgram != NULL);
       
   546     assert(ctx->profileMaxUniforms != NULL);
       
   547     assert(ctx->profileCompileShader != NULL);
       
   548     assert(ctx->profileDeleteShader != NULL);
       
   549     assert(ctx->profileDeleteProgram != NULL);
       
   550     assert(ctx->profileGetUniformLocation != NULL);
       
   551     assert(ctx->profileLinkProgram != NULL);
       
   552     assert(ctx->profileUseProgramObject != NULL);
       
   553     assert(ctx->profileUniform4fv != NULL);
       
   554     assert(ctx->profileUniform4iv != NULL);
       
   555     assert(ctx->profileUniform1i != NULL);
       
   556     assert(ctx->profileSetSampler != NULL);
   486 
   557 
   487     retval = ctx;
   558     retval = ctx;
   488     ctx = current_ctx;
   559     ctx = current_ctx;
   489     return retval;
   560     return retval;
   490 
   561 
   516     ctx->glGetIntegerv(pname, &val);
   587     ctx->glGetIntegerv(pname, &val);
   517     return (int) val;
   588     return (int) val;
   518 } // impl_GLSL_MaxUniforms
   589 } // impl_GLSL_MaxUniforms
   519 
   590 
   520 
   591 
       
   592 static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type)
       
   593 {
       
   594     GLint retval = 0;
       
   595     GLenum program_type = GL_NONE;
       
   596     if (shader_type == MOJOSHADER_TYPE_VERTEX)
       
   597         program_type = GL_VERTEX_PROGRAM_ARB;
       
   598     else if (shader_type == MOJOSHADER_TYPE_PIXEL)
       
   599         program_type = GL_FRAGMENT_PROGRAM_ARB;
       
   600     else
       
   601         return -1;
       
   602 
       
   603     ctx->glGetProgramivARB(program_type, GL_MAX_PROGRAM_PARAMETERS_ARB, &retval);
       
   604     return (int) retval;
       
   605 } // impl_ARB1_MaxUniforms
       
   606 
       
   607 
   521 int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type)
   608 int MOJOSHADER_glMaxUniforms(MOJOSHADER_shaderType shader_type)
   522 {
   609 {
   523     return ctx->profileMaxUniforms(shader_type);
   610     return ctx->profileMaxUniforms(shader_type);
   524 } // MOJOSHADER_glMaxUniforms
   611 } // MOJOSHADER_glMaxUniforms
   525 
   612 
   547     *s = shader;
   634     *s = shader;
   548     return 1;
   635     return 1;
   549 } // impl_GLSL_CompileShader
   636 } // impl_GLSL_CompileShader
   550 
   637 
   551 
   638 
       
   639 static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
       
   640 {
       
   641     GLint shaderlen = (GLint) pd->output_len;
       
   642     const GLenum shader_type = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? GL_FRAGMENT_PROGRAM_ARB : GL_VERTEX_PROGRAM_ARB;
       
   643     GLuint shader = 0;
       
   644     ctx->glGenProgramsARB(1, &shader);
       
   645 
       
   646     ctx->glGetError();  // flush any existing error state.
       
   647     ctx->glBindProgramARB(shader_type, shader);
       
   648     ctx->glProgramStringARB(shader_type, GL_PROGRAM_FORMAT_ASCII_ARB,
       
   649                             shaderlen, pd->output);
       
   650 
       
   651     if (ctx->glGetError() == GL_INVALID_OPERATION)
       
   652     { 
       
   653         GLint pos = 0;
       
   654         ctx->glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
       
   655         const GLubyte *errstr = ctx->glGetString(GL_PROGRAM_ERROR_STRING_ARB);
       
   656         snprintf(error_buffer, sizeof (error_buffer),
       
   657                   "ARB1 compile error at position %d: %s",
       
   658                   (int) pos, (const char *) errstr);
       
   659         ctx->glBindProgramARB(shader_type, 0);
       
   660         ctx->glDeleteProgramsARB(1, &shader);
       
   661         *s = 0;
       
   662         return 0;
       
   663     } // if
       
   664 
       
   665     *s = shader;
       
   666     return 1;
       
   667 } // impl_ARB1_CompileShader
       
   668 
       
   669 
   552 static void impl_GLSL_DeleteShader(const GLuint shader)
   670 static void impl_GLSL_DeleteShader(const GLuint shader)
   553 {
   671 {
   554     ctx->glDeleteObject(shader);
   672     ctx->glDeleteObject(shader);
   555 } // impl_GLSL_DeleteShader
   673 } // impl_GLSL_DeleteShader
   556 
   674 
   557 
   675 
       
   676 static void impl_ARB1_DeleteShader(const GLuint _shader)
       
   677 {
       
   678     GLuint shader = _shader;  // const removal.
       
   679     ctx->glDeleteProgramsARB(1, &shader);
       
   680 } // impl_ARB1_DeleteShader
       
   681 
       
   682 
   558 static void impl_GLSL_DeleteProgram(const GLuint program)
   683 static void impl_GLSL_DeleteProgram(const GLuint program)
   559 {
   684 {
   560     ctx->glDeleteObject(program);
   685     ctx->glDeleteObject(program);
       
   686 } // impl_GLSL_DeleteProgram
       
   687 
       
   688 
       
   689 static void impl_ARB1_DeleteProgram(const GLuint program)
       
   690 {
       
   691     // no-op. ARB1 doesn't have real linked programs.
   561 } // impl_GLSL_DeleteProgram
   692 } // impl_GLSL_DeleteProgram
   562 
   693 
   563 
   694 
   564 MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf,
   695 MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf,
   565                                                 const unsigned int bufsize)
   696                                                 const unsigned int bufsize)
   641         } // else
   772         } // else
   642     } // if
   773     } // if
   643 } // program_unref
   774 } // program_unref
   644 
   775 
   645 
   776 
       
   777 static GLint impl_GLSL_GetUniformLocation(GLuint handle,
       
   778                                        const MOJOSHADER_parseData *pd, int idx)
       
   779 {
       
   780     return ctx->glGetUniformLocation(handle, pd->uniforms[idx].name);
       
   781 } // impl_GLSL_GetUniformLocation
       
   782 
       
   783 static GLint impl_ARB1_GetUniformLocation(GLuint handle,
       
   784                                        const MOJOSHADER_parseData *pd, int idx)
       
   785 {
       
   786     // !!! FIXME: this only works if you have no bool or int uniforms.
       
   787     return idx;
       
   788 } // impl_ARB1_GetUniformLocation
       
   789 
       
   790 
   646 static void lookup_uniforms(MOJOSHADER_glProgram *program,
   791 static void lookup_uniforms(MOJOSHADER_glProgram *program,
   647                             MOJOSHADER_glShader *shader)
   792                             MOJOSHADER_glShader *shader)
   648 {
   793 {
   649     int i;
       
   650     const MOJOSHADER_parseData *pd = shader->parseData;
   794     const MOJOSHADER_parseData *pd = shader->parseData;
   651     const MOJOSHADER_uniform *u = pd->uniforms;
   795     const MOJOSHADER_uniform *u = pd->uniforms;
   652     const MOJOSHADER_shaderType shader_type = pd->shader_type;
   796     const MOJOSHADER_shaderType shader_type = pd->shader_type;
       
   797     const GLuint handle = program->handle;
       
   798     int i;
   653 
   799 
   654     for (i = 0; i < pd->uniform_count; i++)
   800     for (i = 0; i < pd->uniform_count; i++)
   655     {
   801     {
   656         const GLint loc = ctx->glGetUniformLocation(program->handle, u[i].name);
   802         const GLint loc = ctx->profileGetUniformLocation(handle, pd, i);
   657         if (loc != -1)  // maybe the Uniform was optimized out?
   803         if (loc != -1)  // maybe the Uniform was optimized out?
   658         {
   804         {
   659             UniformMap *map = &program->uniforms[program->uniform_count];
   805             UniformMap *map = &program->uniforms[program->uniform_count];
   660             map->shader_type = shader_type;
   806             map->shader_type = shader_type;
   661             map->uniform = &u[i];
   807             map->uniform = &u[i];
   707         } // if
   853         } // if
   708     } // for
   854     } // for
   709 } // lookup_attributes
   855 } // lookup_attributes
   710 
   856 
   711 
   857 
   712 MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader,
   858 static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *vshader,
   713                                                MOJOSHADER_glShader *pshader)
   859                                     MOJOSHADER_glShader *pshader)
   714 {
   860 {
   715     if ((vshader == NULL) && (pshader == NULL))
       
   716         return NULL;
       
   717 
       
   718     MOJOSHADER_glProgram *retval = NULL;
       
   719     const GLuint program = ctx->glCreateProgramObject();
   861     const GLuint program = ctx->glCreateProgramObject();
   720     int numregs = 0;
       
   721     int consts = 0;
       
   722 
   862 
   723     if (vshader != NULL) ctx->glAttachObject(program, vshader->handle);
   863     if (vshader != NULL) ctx->glAttachObject(program, vshader->handle);
   724     if (pshader != NULL) ctx->glAttachObject(program, pshader->handle);
   864     if (pshader != NULL) ctx->glAttachObject(program, pshader->handle);
   725 
   865 
   726     ctx->glLinkProgram(program);
   866     ctx->glLinkProgram(program);
   729     ctx->glGetObjectParameteriv(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
   869     ctx->glGetObjectParameteriv(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
   730     if (!ok)
   870     if (!ok)
   731     {
   871     {
   732         GLsizei len = 0;
   872         GLsizei len = 0;
   733         ctx->glGetInfoLog(program, sizeof (error_buffer), &len, (GLchar *) error_buffer);
   873         ctx->glGetInfoLog(program, sizeof (error_buffer), &len, (GLchar *) error_buffer);
       
   874         ctx->glDeleteObject(program);
       
   875         return 0;
       
   876     } // if
       
   877 
       
   878     return program;
       
   879 } // impl_GLSL_LinkProgram
       
   880 
       
   881 
       
   882 static GLuint impl_ARB1_LinkProgram(MOJOSHADER_glShader *vshader,
       
   883                                     MOJOSHADER_glShader *pshader)
       
   884 {
       
   885     // there is no formal linking in ARB1...just return a unique value.
       
   886     static GLuint retval = 1;
       
   887     return retval++;
       
   888 } // impl_ARB1_LinkProgram
       
   889 
       
   890 
       
   891 MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader,
       
   892                                                MOJOSHADER_glShader *pshader)
       
   893 {
       
   894     if ((vshader == NULL) && (pshader == NULL))
       
   895         return NULL;
       
   896 
       
   897     int numregs = 0;
       
   898     int consts = 0;
       
   899     MOJOSHADER_glProgram *retval = NULL;
       
   900     const GLuint program = ctx->profileLinkProgram(vshader, pshader);
       
   901     if (program == 0)
   734         goto link_program_fail;
   902         goto link_program_fail;
   735     } // if
       
   736 
   903 
   737     retval = (MOJOSHADER_glProgram *) Malloc(sizeof (MOJOSHADER_glProgram));
   904     retval = (MOJOSHADER_glProgram *) Malloc(sizeof (MOJOSHADER_glProgram));
   738     if (retval == NULL)
   905     if (retval == NULL)
   739         goto link_program_fail;
   906         goto link_program_fail;
   740     memset(retval, '\0', sizeof (MOJOSHADER_glProgram));
   907     memset(retval, '\0', sizeof (MOJOSHADER_glProgram));
   803         Free(retval->uniforms);
   970         Free(retval->uniforms);
   804         Free(retval->attributes);
   971         Free(retval->attributes);
   805         Free(retval);
   972         Free(retval);
   806     } // if
   973     } // if
   807 
   974 
   808     ctx->profileDeleteProgram(program);
   975     if (program != 0)
       
   976         ctx->profileDeleteProgram(program);
       
   977 
   809     return NULL;
   978     return NULL;
   810 } // MOJOSHADER_glLinkProgram
   979 } // MOJOSHADER_glLinkProgram
       
   980 
       
   981 
       
   982 static void impl_GLSL_UseProgramObject(MOJOSHADER_glProgram *program)
       
   983 {
       
   984     ctx->glUseProgramObject((program != NULL) ? program->handle : 0);
       
   985 } // impl_GLSL_UseProgramObject
       
   986 
       
   987 
       
   988 static void impl_ARB1_UseProgramObject(MOJOSHADER_glProgram *program)
       
   989 {
       
   990     GLuint vhandle = 0;
       
   991     GLuint phandle = 0;
       
   992     if (program != NULL)
       
   993     {
       
   994         if (program->vertex != NULL)
       
   995             vhandle = program->vertex->handle;
       
   996         if (program->fragment != NULL)
       
   997             phandle = program->fragment->handle;
       
   998     } // if
       
   999 
       
  1000     ctx->glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vhandle);
       
  1001     ctx->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, vhandle);
       
  1002 } // impl_GLSL_UseProgramObject
   811 
  1003 
   812 
  1004 
   813 void MOJOSHADER_glBindProgram(MOJOSHADER_glProgram *program)
  1005 void MOJOSHADER_glBindProgram(MOJOSHADER_glProgram *program)
   814 {
  1006 {
   815     GLuint handle = 0;
  1007     GLuint handle = 0;
   835     {
  1027     {
   836         handle = program->handle;
  1028         handle = program->handle;
   837         program->refcount++;
  1029         program->refcount++;
   838     } // if
  1030     } // if
   839 
  1031 
   840     ctx->glUseProgramObject(handle);
  1032     ctx->profileUseProgramObject(program);
   841     program_unref(ctx->bound_program);
  1033     program_unref(ctx->bound_program);
   842     ctx->bound_program = program;
  1034     ctx->bound_program = program;
   843 } // MOJOSHADER_glBindProgram
  1035 } // MOJOSHADER_glBindProgram
   844 
  1036 
   845 
  1037 
  1000 
  1192 
  1001         if (gl_index == 0)
  1193         if (gl_index == 0)
  1002             return;  // nothing to do, this shader doesn't use this stream.
  1194             return;  // nothing to do, this shader doesn't use this stream.
  1003     } // if
  1195     } // if
  1004 
  1196 
       
  1197     // these happen to work in both ARB1 and GLSL, but if something alien
       
  1198     //  shows up, we'll have to split these into profile*() functions.
  1005     ctx->glVertexAttribPointer(gl_index, size, gl_type, norm, stride, ptr);
  1199     ctx->glVertexAttribPointer(gl_index, size, gl_type, norm, stride, ptr);
  1006     ctx->glEnableVertexAttribArray(gl_index);
  1200     ctx->glEnableVertexAttribArray(gl_index);
  1007 } // MOJOSHADER_glSetVertexAttribute
  1201 } // MOJOSHADER_glSetVertexAttribute
       
  1202 
       
  1203 
       
  1204 static void impl_GLSL_Uniform4fv(GLint loc, GLsizei siz, GLfloat *v)
       
  1205 {
       
  1206     ctx->glUniform4fv(loc, siz, v);
       
  1207 } // impl_GLSL_Uniform4fv
       
  1208 
       
  1209 static void impl_GLSL_Uniform4iv(GLint loc, GLsizei siz, GLint *v)
       
  1210 {
       
  1211     ctx->glUniform4iv(loc, siz, v);
       
  1212 } // impl_GLSL_Uniform4iv
       
  1213 
       
  1214 static void impl_GLSL_Uniform1i(GLint loc, GLint v)
       
  1215 {
       
  1216     ctx->glUniform1i(loc, v);
       
  1217 } // impl_GLSL_Uniform1i
       
  1218 
       
  1219 static void impl_GLSL_SetSampler(GLint loc, GLuint sampler)
       
  1220 {
       
  1221     ctx->glUniform1i(loc, sampler);
       
  1222 } // impl_GLSL_SetSampler
       
  1223 
       
  1224 
       
  1225 static void impl_ARB1_Uniform4fv(GLint loc, GLsizei siz, GLfloat *v)
       
  1226 {
       
  1227     // !!! FIXME: write me
       
  1228 } // impl_ARB1_Uniform4fv
       
  1229 
       
  1230 static void impl_ARB1_Uniform4iv(GLint loc, GLsizei siz, GLint *v)
       
  1231 {
       
  1232     // !!! FIXME: write me
       
  1233 } // impl_ARB1_Uniform4iv
       
  1234 
       
  1235 static void impl_ARB1_Uniform1i(GLint loc, GLint v)
       
  1236 {
       
  1237     // !!! FIXME: write me
       
  1238 } // impl_ARB1_Uniform1i
       
  1239 
       
  1240 static void impl_ARB1_SetSampler(GLint loc, GLuint sampler)
       
  1241 {
       
  1242     // !!! FIXME: write me
       
  1243 } // impl_ARB1_SetSampler
  1008 
  1244 
  1009 
  1245 
  1010 void MOJOSHADER_glProgramReady(void)
  1246 void MOJOSHADER_glProgramReady(void)
  1011 {
  1247 {
  1012     int i;
  1248     int i;
  1026         const MOJOSHADER_uniformType type = u->type;
  1262         const MOJOSHADER_uniformType type = u->type;
  1027         const MOJOSHADER_shaderType shader_type = map->shader_type;
  1263         const MOJOSHADER_shaderType shader_type = map->shader_type;
  1028         const int index = u->index;
  1264         const int index = u->index;
  1029         const int size = u->array_count;
  1265         const int size = u->array_count;
  1030         const GLint location = map->location;
  1266         const GLint location = map->location;
       
  1267         const MOJOSHADER_constant *c;
       
  1268         float *regfilef;
       
  1269         GLint *regfilei;
       
  1270         GLint *regfileb;
       
  1271         int hi;
       
  1272 
       
  1273         if (shader_type == MOJOSHADER_TYPE_VERTEX)
       
  1274         {
       
  1275             c = ctx->bound_program->vertex->parseData->constants;
       
  1276             hi = ctx->bound_program->vertex->parseData->constant_count;
       
  1277             regfilef = ctx->vs_reg_file_f;
       
  1278             regfilei = ctx->vs_reg_file_i;
       
  1279             regfileb = ctx->vs_reg_file_b;
       
  1280         } // if
       
  1281         else
       
  1282         {
       
  1283             c = ctx->bound_program->fragment->parseData->constants;
       
  1284             hi = ctx->bound_program->fragment->parseData->constant_count;
       
  1285             regfilef = ctx->ps_reg_file_f;
       
  1286             regfilei = ctx->ps_reg_file_i;
       
  1287             regfileb = ctx->ps_reg_file_b;
       
  1288         } // else
  1031 
  1289 
  1032         // only use arrays for 'c' registers.
  1290         // only use arrays for 'c' registers.
  1033         assert((size == 0) || (type == MOJOSHADER_UNIFORM_FLOAT));
  1291         assert((size == 0) || (type == MOJOSHADER_UNIFORM_FLOAT));
  1034 
  1292 
  1035         if (size != 0)  // !!! FIXME: this code sucks.
  1293         if (size != 0)  // !!! FIXME: this code sucks.
  1036         {
  1294         {
  1037             // !!! FIXME: calculate this all at link time.
  1295             // !!! FIXME: calculate this all at link time.
  1038             if (shader_type == MOJOSHADER_TYPE_VERTEX)
  1296             int j;
       
  1297             GLfloat *ptr = ctx->bound_program->constants;
       
  1298 
       
  1299             for (j = 0; j < hi; j++)
  1039             {
  1300             {
  1040                 const MOJOSHADER_constant *c = ctx->bound_program->vertex->parseData->constants;
  1301                 if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
  1041                 int hi = ctx->bound_program->vertex->parseData->constant_count;
  1302                     continue;
  1042 
  1303 
  1043                 int j;
  1304                 const int idx = c[j].index;
  1044                 GLfloat *ptr = ctx->bound_program->constants;
  1305                 if ( (idx >= index) && (idx < (index + size)) )
  1045 
       
  1046                 for (j = 0; j < hi; j++)
       
  1047                 {
  1306                 {
  1048                     if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
  1307                     memcpy(ptr, &regfilef[idx * 4], 16);  // !!! FIXME: 16
  1049                         continue;
  1308                     memcpy(&regfilef[idx * 4], &c->value.f, 16);  // !!! FIXME: 16
  1050 
  1309                     ptr += 4;
  1051                     const int idx = c[j].index;
  1310                 } // if
  1052                     if ( (idx >= index) && (idx < (index + size)) )
  1311             } // for
  1053                     {
  1312 
  1054                         memcpy(ptr, &ctx->vs_reg_file_f[idx * 4], 16);  // !!! FIXME: 16
  1313             ctx->profileUniform4fv(location, size, &regfilef[index * 4]);
  1055                         memcpy(&ctx->vs_reg_file_f[idx * 4], &c->value.f, 16);  // !!! FIXME: 16
  1314 
  1056                         ptr += 4;
  1315             ptr = ctx->bound_program->constants;
  1057                     } // if
  1316             for (j = 0; j < hi; j++)
  1058                 } // for
  1317             {
  1059 
  1318                 if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
  1060                 ctx->glUniform4fv(location, size, &ctx->vs_reg_file_f[index * 4]);
  1319                     continue;
  1061 
  1320 
  1062                 ptr = ctx->bound_program->constants;
  1321                 const int idx = c[j].index;
  1063                 for (j = 0; j < hi; j++)
  1322                 if ( (idx >= index) && (idx < (index + size)) )
  1064                 {
  1323                 {
  1065                     if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
  1324                     memcpy(&regfilef[idx * 4], ptr, 16);  // !!! FIXME: 16
  1066                         continue;
  1325                     ptr += 4;
  1067 
  1326                 } // if
  1068                     const int idx = c[j].index;
  1327             } // for
  1069                     if ( (idx >= index) && (idx < (index + size)) )
       
  1070                     {
       
  1071                         memcpy(&ctx->vs_reg_file_f[idx * 4], ptr, 16);  // !!! FIXME: 16
       
  1072                         ptr += 4;
       
  1073                     } // if
       
  1074                 } // for
       
  1075             } // if
       
  1076 
       
  1077             else if (shader_type == MOJOSHADER_TYPE_PIXEL)
       
  1078             {
       
  1079                 const MOJOSHADER_constant *c = ctx->bound_program->fragment->parseData->constants;
       
  1080                 int hi = ctx->bound_program->fragment->parseData->constant_count;
       
  1081 
       
  1082                 int j;
       
  1083                 GLfloat *ptr = ctx->bound_program->constants;
       
  1084 
       
  1085                 for (j = 0; j < hi; j++)
       
  1086                 {
       
  1087                     if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
       
  1088                         continue;
       
  1089 
       
  1090                     const int idx = c[j].index;
       
  1091                     if ( (idx >= index) && (idx < (index + size)) )
       
  1092                     {
       
  1093                         memcpy(ptr, &ctx->ps_reg_file_f[idx * 4], 16);  // !!! FIXME: 16
       
  1094                         memcpy(&ctx->ps_reg_file_f[idx * 4], &c->value.f, 16);  // !!! FIXME: 16
       
  1095                         ptr += 4;
       
  1096                     } // if
       
  1097                 } // for
       
  1098 
       
  1099                 ctx->glUniform4fv(location, size, &ctx->ps_reg_file_f[index * 4]);
       
  1100 
       
  1101                 ptr = ctx->bound_program->constants;
       
  1102                 for (j = 0; j < hi; j++)
       
  1103                 {
       
  1104                     if (c[j].type != MOJOSHADER_UNIFORM_FLOAT)
       
  1105                         continue;
       
  1106 
       
  1107                     const int idx = c[j].index;
       
  1108                     if ( (idx >= index) && (idx < (index + size)) )
       
  1109                     {
       
  1110                         memcpy(&ctx->ps_reg_file_f[idx * 4], ptr, 16);  // !!! FIXME: 16
       
  1111                         ptr += 4;
       
  1112                     } // if
       
  1113                 } // for
       
  1114             } // else if
       
  1115         } // if
  1328         } // if
  1116 
  1329 
  1117         else if (shader_type == MOJOSHADER_TYPE_VERTEX)
  1330         else
  1118         {
  1331         {
  1119             if (type == MOJOSHADER_UNIFORM_FLOAT)
  1332             if (type == MOJOSHADER_UNIFORM_FLOAT)
  1120                 ctx->glUniform4fv(location, 1, &ctx->vs_reg_file_f[index * 4]);
  1333                 ctx->profileUniform4fv(location, 1, &regfilef[index * 4]);
  1121             else if (type == MOJOSHADER_UNIFORM_INT)
  1334             else if (type == MOJOSHADER_UNIFORM_INT)
  1122                 ctx->glUniform4iv(location, 1, &ctx->vs_reg_file_i[index * 4]);
  1335                 ctx->profileUniform4iv(location, 1, &regfilei[index * 4]);
  1123             else if (type == MOJOSHADER_UNIFORM_BOOL)
  1336             else if (type == MOJOSHADER_UNIFORM_BOOL)
  1124                 ctx->glUniform1i(location, ctx->vs_reg_file_b[index]);
  1337                 ctx->profileUniform1i(location, regfileb[index]);
  1125         } // if
  1338         } // if
  1126 
       
  1127         else if (shader_type == MOJOSHADER_TYPE_PIXEL)
       
  1128         {
       
  1129             if (type == MOJOSHADER_UNIFORM_FLOAT)
       
  1130                 ctx->glUniform4fv(location, 1, &ctx->ps_reg_file_f[index * 4]);
       
  1131             else if (type == MOJOSHADER_UNIFORM_INT)
       
  1132                 ctx->glUniform4iv(location, 1, &ctx->ps_reg_file_i[index * 4]);
       
  1133             else if (type == MOJOSHADER_UNIFORM_BOOL)
       
  1134                 ctx->glUniform1i(location, ctx->ps_reg_file_b[index]);
       
  1135         } // else if
       
  1136     } // for
  1339     } // for
  1137 
  1340 
  1138     // push Samplers to the program from our register files...
  1341     // push Samplers to the program from our register files...
  1139     count = ctx->bound_program->sampler_count;
  1342     count = ctx->bound_program->sampler_count;
  1140     for (i = 0; i < count; i++)
  1343     for (i = 0; i < count; i++)
  1141     {
  1344     {
  1142         const SamplerMap *map = &ctx->bound_program->samplers[i];
  1345         const SamplerMap *map = &ctx->bound_program->samplers[i];
  1143         const MOJOSHADER_sampler *s = map->sampler;
  1346         const MOJOSHADER_sampler *s = map->sampler;
  1144         ctx->glUniform1i(map->location, ctx->sampler_reg_file[s->index]);
  1347         ctx->profileSetSampler(map->location, ctx->sampler_reg_file[s->index]);
  1145     } // for
  1348     } // for
  1146 } // MOJOSHADER_glProgramReady
  1349 } // MOJOSHADER_glProgramReady
  1147 
  1350 
  1148 
  1351 
  1149 void MOJOSHADER_glDeleteProgram(MOJOSHADER_glProgram *program)
  1352 void MOJOSHADER_glDeleteProgram(MOJOSHADER_glProgram *program)