Add support for ARB_vertex_shader attrib binding and query.
authorMichal Krol <mjkrol@gmail.org>
Tue, 18 Apr 2006 10:30:29 +0000 (10:30 +0000)
committerMichal Krol <mjkrol@gmail.org>
Tue, 18 Apr 2006 10:30:29 +0000 (10:30 +0000)
Clean-up ARB_shaderobjects code a bit.

src/mesa/shader/shaderobjects.c
src/mesa/shader/shaderobjects.h
src/mesa/shader/shaderobjects_3dlabs.c
src/mesa/shader/shaderobjects_3dlabs.h
src/mesa/shader/slang/slang_export.c
src/mesa/shader/slang/slang_export.h
src/mesa/shader/slang/slang_link.c
src/mesa/shader/slang/slang_link.h

index a98c310bac4636c925bb596dcb5c995409566ea0..fee259a9f38582ae0a9ea67ee5efe6511c40fe5a 100644 (file)
@@ -99,9 +99,9 @@
                _QUERY_INTERFACE(x, I_SHADER, UIID_SHADER, function);\
        } while (0)
 
-#define _LINKED_PROGRAM(x, function)\
+#define _LINKED_PROGRAM(x, function, release)\
        if ((**x).GetLinkStatus (x) == GL_FALSE) {\
-               RELEASE_PROGRAM(x);\
+               if (release) RELEASE_PROGRAM(x);\
                _mesa_error (ctx, GL_INVALID_OPERATION, function);\
                break;\
        }
        do {\
                _LOOKUP_HANDLE(handle, function);\
                _QUERY_INTERFACE(x, I_PROGRAM, UIID_PROGRAM, function);\
-               _LINKED_PROGRAM(x, function);\
+               _LINKED_PROGRAM(x, function, GL_TRUE);\
        } while (0)
 
 #define _CURRENT_PROGRAM(x, function)\
        I_PROGRAM x = NULL;\
        do {\
                _CURRENT_PROGRAM(x, function);\
-               _LINKED_PROGRAM(x, function);\
+               _LINKED_PROGRAM(x, function, GL_FALSE);\
        } while (0)
 
+#define IS_NAME_WITH_GL_PREFIX(x) ((x)[0] == 'g' && (x)[1] == 'l' && (x)[2] == '_')
+
 
 GLvoid GLAPIENTRY
 _mesa_DeleteObjectARB (GLhandleARB obj)
@@ -379,7 +381,7 @@ _mesa_Uniform1fARB (GLint location, GLfloat v0)
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, 1, &v0, GL_FLOAT))
+               if (!(**pro).WriteUniform (pro, location, 1, &v0, GL_FLOAT))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform1fARB");
        }
 }
@@ -398,7 +400,7 @@ _mesa_Uniform2fARB (GLint location, GLfloat v0, GLfloat v1)
                v[0] = v0;
                v[1] = v1;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_FLOAT_VEC2))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_FLOAT_VEC2))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform2fARB");
        }
 }
@@ -418,7 +420,7 @@ _mesa_Uniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
                v[1] = v1;
                v[2] = v2;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_FLOAT_VEC3))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_FLOAT_VEC3))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform3fARB");
        }
 }
@@ -439,7 +441,7 @@ _mesa_Uniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat
                v[2] = v2;
                v[3] = v3;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_FLOAT_VEC4))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_FLOAT_VEC4))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform4fARB");
        }
 }
@@ -454,7 +456,7 @@ _mesa_Uniform1iARB (GLint location, GLint v0)
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, 1, &v0, GL_INT))
+               if (!(**pro).WriteUniform (pro, location, 1, &v0, GL_INT))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform1iARB");
        }
 }
@@ -473,7 +475,7 @@ _mesa_Uniform2iARB (GLint location, GLint v0, GLint v1)
                v[0] = v0;
                v[1] = v1;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_INT_VEC2))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_INT_VEC2))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform2iARB");
        }
 }
@@ -493,7 +495,7 @@ _mesa_Uniform3iARB (GLint location, GLint v0, GLint v1, GLint v2)
                v[1] = v1;
                v[2] = v2;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_INT_VEC3))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_INT_VEC3))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform3iARB");
        }
 }
@@ -514,7 +516,7 @@ _mesa_Uniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
                v[2] = v2;
                v[3] = v3;
 
-               if (!_slang_write_uniform (pro, location, 1, v, GL_INT_VEC4))
+               if (!(**pro).WriteUniform (pro, location, 1, v, GL_INT_VEC4))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform4iARB");
        }
 }
@@ -525,11 +527,17 @@ _mesa_Uniform1fvARB (GLint location, GLsizei count, const GLfloat *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform1fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform1fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform1fvARB");
        }
 }
@@ -540,11 +548,17 @@ _mesa_Uniform2fvARB (GLint location, GLsizei count, const GLfloat *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform2fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform2fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_VEC2))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_VEC2))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform2fvARB");
        }
 }
@@ -555,11 +569,17 @@ _mesa_Uniform3fvARB (GLint location, GLsizei count, const GLfloat *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform3fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform3fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_VEC3))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_VEC3))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform3fvARB");
        }
 }
@@ -570,11 +590,17 @@ _mesa_Uniform4fvARB (GLint location, GLsizei count, const GLfloat *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform4fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform4fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_VEC4))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_VEC4))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform4fvARB");
        }
 }
@@ -585,11 +611,17 @@ _mesa_Uniform1ivARB (GLint location, GLsizei count, const GLint *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform1ivARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform1ivARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_INT))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_INT))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform1ivARB");
        }
 }
@@ -600,11 +632,17 @@ _mesa_Uniform2ivARB (GLint location, GLsizei count, const GLint *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform2ivARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform2ivARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_INT_VEC2))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_INT_VEC2))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform2ivARB");
        }
 }
@@ -615,11 +653,17 @@ _mesa_Uniform3ivARB (GLint location, GLsizei count, const GLint *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform3ivARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform3ivARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_INT_VEC3))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_INT_VEC3))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform3ivARB");
        }
 }
@@ -630,11 +674,17 @@ _mesa_Uniform4ivARB (GLint location, GLsizei count, const GLint *value)
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniform4ivARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniform4ivARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
        {
-               if (!_slang_write_uniform (pro, location, count, value, GL_INT_VEC4))
+               if (!(**pro).WriteUniform (pro, location, count, value, GL_INT_VEC4))
                        _mesa_error (ctx, GL_INVALID_OPERATION, "glUniform4ivARB");
        }
 }
@@ -645,6 +695,12 @@ _mesa_UniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, c
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniformMatrix2fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniformMatrix2fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
@@ -667,13 +723,13 @@ _mesa_UniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, c
                                pt[2] = pv[1];
                                pt[3] = pv[3];
                        }
-                       if (!_slang_write_uniform (pro, location, count, trans, GL_FLOAT_MAT2))
+                       if (!(**pro).WriteUniform (pro, location, count, trans, GL_FLOAT_MAT2))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix2fvARB");
                        _mesa_free (trans);
                }
                else
                {
-                       if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_MAT2))
+                       if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_MAT2))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix2fvARB");
                }
        }
@@ -685,6 +741,12 @@ _mesa_UniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, c
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniformMatrix3fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniformMatrix3fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
@@ -712,13 +774,13 @@ _mesa_UniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, c
                                pt[7] = pv[5];
                                pt[8] = pv[8];
                        }
-                       if (!_slang_write_uniform (pro, location, count, trans, GL_FLOAT_MAT3))
+                       if (!(**pro).WriteUniform (pro, location, count, trans, GL_FLOAT_MAT3))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix3fvARB");
                        _mesa_free (trans);
                }
                else
                {
-                       if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_MAT3))
+                       if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_MAT3))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix3fvARB");
                }
        }
@@ -730,6 +792,12 @@ _mesa_UniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, c
        GET_CURRENT_CONTEXT(ctx);
        GET_CURRENT_LINKED_PROGRAM(pro, "glUniformMatrix4fvARB");
 
+       if (value == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glUniformMatrix4fvARB");
+               return;
+       }
+
        FLUSH_VERTICES(ctx, _NEW_PROGRAM);
 
        if (pro != NULL)
@@ -749,13 +817,13 @@ _mesa_UniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, c
                        {
                                _math_transposef (pt, pv);
                        }
-                       if (!_slang_write_uniform (pro, location, count, trans, GL_FLOAT_MAT4))
+                       if (!(**pro).WriteUniform (pro, location, count, trans, GL_FLOAT_MAT4))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix4fvARB");
                        _mesa_free (trans);
                }
                else
                {
-                       if (!_slang_write_uniform (pro, location, count, value, GL_FLOAT_MAT4))
+                       if (!(**pro).WriteUniform (pro, location, count, value, GL_FLOAT_MAT4))
                                _mesa_error (ctx, GL_INVALID_OPERATION, "glUniformMatrix4fvARB");
                }
        }
@@ -861,10 +929,16 @@ _mesa_get_object_parameter (GLhandleARB obj, GLenum pname, GLvoid *params, GLboo
                                *ipar = (**pro)._container.GetAttachedCount ((I_CONTAINER) pro);
                                break;
                        case GL_OBJECT_ACTIVE_UNIFORMS_ARB:
-                               *ipar = _slang_get_active_uniform_count (pro);
+                               *ipar = (**pro).GetActiveUniformCount (pro);
                                break;
                        case GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB:
-                               *ipar = _slang_get_active_uniform_max_length (pro);
+                               *ipar = (**pro).GetActiveUniformMaxLength (pro);
+                               break;
+                       case GL_OBJECT_ACTIVE_ATTRIBUTES_ARB:
+                               *ipar = (**pro).GetActiveAttribCount (pro);
+                               break;
+                       case GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB:
+                               *ipar = (**pro).GetActiveAttribMaxLength (pro);
                                break;
                        }
 
@@ -882,9 +956,16 @@ _mesa_get_object_parameter (GLhandleARB obj, GLenum pname, GLvoid *params, GLboo
 GLvoid GLAPIENTRY
 _mesa_GetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params)
 {
+       GET_CURRENT_CONTEXT(ctx);
        GLboolean integral;
        GLint size;
 
+       if (params == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetObjectParameterfvARB");
+               return;
+       }
+
        assert (sizeof (GLfloat) == sizeof (GLint));
 
        if (_mesa_get_object_parameter (obj, pname, (GLvoid *) params, &integral, &size))
@@ -900,9 +981,16 @@ _mesa_GetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params)
 GLvoid GLAPIENTRY
 _mesa_GetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params)
 {
+       GET_CURRENT_CONTEXT(ctx);
        GLboolean integral;
        GLint size;
 
+       if (params == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
+               return;
+       }
+
        assert (sizeof (GLfloat) == sizeof (GLint));
 
        if (_mesa_get_object_parameter (obj, pname, (GLvoid *) params, &integral, &size))
@@ -944,11 +1032,14 @@ _mesa_GetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLchar
        GET_CURRENT_CONTEXT(ctx);
        GET_GENERIC(gen, obj, "glGetInfoLogARB");
 
-       if (gen != NULL)
-       {
-               copy_string((**gen).GetInfoLog (gen), maxLength, length, infoLog);
-               RELEASE_GENERIC(gen);
-       }
+       if (gen == NULL)
+               return;
+
+       if (infoLog == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetInfoLogARB");
+       else
+               copy_string ((**gen).GetInfoLog (gen), maxLength, length, infoLog);
+       RELEASE_GENERIC(gen);
 }
 
 GLvoid GLAPIENTRY
@@ -956,11 +1047,17 @@ _mesa_GetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei
                                                         GLhandleARB *obj)
 {
        GET_CURRENT_CONTEXT(ctx);
-       GLsizei cnt, i;
        GET_CONTAINER(con, containerObj, "glGetAttachedObjectsARB");
 
-       if (con != NULL)
+       if (con == NULL)
+               return;
+
+       if (obj == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetAttachedObjectsARB");
+       else
        {
+               GLsizei cnt, i;
+
                cnt = (**con).GetAttachedCount (con);
                if (cnt > maxCount)
                        cnt = maxCount;
@@ -973,8 +1070,8 @@ _mesa_GetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei
                        obj[i] = (**x).GetName (x);
                        RELEASE_GENERIC(x);
                }
-               RELEASE_CONTAINER(con);
        }
+       RELEASE_CONTAINER(con);
 }
 
 GLint GLAPIENTRY
@@ -984,12 +1081,17 @@ _mesa_GetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name)
        GLint loc = -1;
        GET_LINKED_PROGRAM(pro, programObj, "glGetUniformLocationARB");
 
-       if (pro != NULL)
+       if (pro == NULL)
+               return -1;
+
+       if (name == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetUniformLocationARB");
+       else
        {
-               if (name != NULL && (name[0] != 'g' || name[1] != 'l' || name[2] != '_'))
-                       loc = _slang_get_uniform_location (pro, name);
-               RELEASE_PROGRAM(pro);
+               if (!IS_NAME_WITH_GL_PREFIX(name))
+                       loc = (**pro).GetUniformLocation (pro, name);
        }
+       RELEASE_PROGRAM(pro);
        return loc;
 }
 
@@ -1000,14 +1102,19 @@ _mesa_GetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLeng
        GET_CURRENT_CONTEXT(ctx);
        GET_PROGRAM(pro, programObj, "glGetActiveUniformARB");
 
-       if (pro != NULL)
+       if (pro == NULL)
+               return;
+
+       if (size == NULL || type == NULL || name == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetActiveUniformARB");
+       else
        {
-               if (index < _slang_get_active_uniform_count (pro))
-                       _slang_get_active_uniform (pro, index, maxLength, length, size, type, name);
+               if (index < (**pro).GetActiveUniformCount (pro))
+                       (**pro).GetActiveUniform (pro, index, maxLength, length, size, type, name);
                else
                        _mesa_error (ctx, GL_INVALID_VALUE, "glGetActiveUniformARB");
-               RELEASE_PROGRAM(pro);
        }
+       RELEASE_PROGRAM(pro);
 }
 
 GLvoid GLAPIENTRY
@@ -1042,11 +1149,14 @@ _mesa_GetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, G
        GET_CURRENT_CONTEXT(ctx);
        GET_SHADER(sha, obj, "glGetShaderSourceARB");
 
-       if (sha != NULL)
-       {
-               copy_string((**sha).GetSource (sha), maxLength, length, source);
-               RELEASE_SHADER(sha);
-       }
+       if (sha == NULL)
+               return;
+
+       if (source == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetShaderSourceARB");
+       else
+               copy_string ((**sha).GetSource (sha), maxLength, length, source);
+       RELEASE_SHADER(sha);
 }
 
 /* GL_ARB_vertex_shader */
@@ -1057,28 +1167,33 @@ _mesa_BindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharA
        GET_CURRENT_CONTEXT(ctx);
        GET_PROGRAM(pro, programObj, "glBindAttribLocationARB");
 
-       if (pro != NULL)
-       {
-               if (name != NULL && (name[0] != 'g' || name[1] != 'l' || name[2] != '_'))
-               {
-                       /* TODO */
-               }
-               RELEASE_PROGRAM(pro);
-       }
+       if (pro == NULL)
+               return;
+
+       if (name == NULL || index >= MAX_VERTEX_ATTRIBS)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glBindAttribLocationARB");
+       else if (IS_NAME_WITH_GL_PREFIX(name))
+               _mesa_error (ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB");
+       else
+               (**pro).OverrideAttribBinding (pro, index, name);
+       RELEASE_PROGRAM(pro);
 }
 
 GLvoid GLAPIENTRY
 _mesa_GetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length,
-                                                 GLint *size, GLenum *type, GLcharARB *name)
+                          GLint *size, GLenum *type, GLcharARB *name)
 {
        GET_CURRENT_CONTEXT(ctx);
        GET_PROGRAM(pro, programObj, "glGetActiveAttribARB");
 
-       if (pro != NULL)
-       {
-               /* TODO */
-               RELEASE_PROGRAM(pro);
-       }
+       if (pro == NULL)
+               return;
+
+       if (name == NULL || index >= (**pro).GetActiveAttribCount (pro))
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetActiveAttribARB");
+       else
+               (**pro).GetActiveAttrib (pro, index, maxLength, length, size, type, name);
+       RELEASE_PROGRAM(pro);
 }
 
 GLint GLAPIENTRY
@@ -1086,16 +1201,16 @@ _mesa_GetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name)
 {
        GET_CURRENT_CONTEXT(ctx);
        GLint loc = -1;
-       GET_PROGRAM(pro, programObj, "glGetAttribLocationARB");
+       GET_LINKED_PROGRAM(pro, programObj, "glGetAttribLocationARB");
 
-       if (pro != NULL)
-       {
-               if (name != NULL && (name[0] != 'g' || name[1] != 'l' || name[2] != '_'))
-               {
-                       /* TODO */
-               }
-               RELEASE_PROGRAM(pro);
-       }
+       if (pro == NULL)
+               return -1;
+
+       if (name == NULL)
+               _mesa_error (ctx, GL_INVALID_VALUE, "glGetAttribLocationARB");
+       else if (!IS_NAME_WITH_GL_PREFIX(name))
+               loc = (**pro).GetAttribLocation (pro, name);
+       RELEASE_PROGRAM(pro);
        return loc;
 }
 
index 19c4e8d3f8a49ef4537c86b42b311a389a67e64d..86a069ad6a9d22b87f0f1f823a0a6dcb559b2e6a 100644 (file)
@@ -88,11 +88,24 @@ struct gl2_program_intf
    GLvoid (* Validate) (struct gl2_program_intf **);
    GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **);
    GLvoid (* UpdateFixedAttribute) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
-      GLboolean);
+                                    GLboolean);
    GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
-      GLboolean);
+                                  GLboolean);
    GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *);
    GLboolean (* IsShaderPresent) (struct gl2_program_intf **, GLenum);
+   GLvoid (* GetActiveUniform) (struct gl2_program_intf **, GLuint index, GLsizei maxLength,
+                                GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+   GLuint (* GetActiveUniformMaxLength) (struct gl2_program_intf **);
+   GLuint (* GetActiveUniformCount) (struct gl2_program_intf **);
+   GLint (* GetUniformLocation) (struct gl2_program_intf **, const GLchar *name);
+   GLboolean (* WriteUniform) (struct gl2_program_intf **, GLint loc, GLsizei count,
+                               const GLvoid *data, GLenum type);
+   GLvoid (* GetActiveAttrib) (struct gl2_program_intf **, GLuint index, GLsizei maxLength,
+                               GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+   GLuint (* GetActiveAttribMaxLength) (struct gl2_program_intf **);
+   GLuint (* GetActiveAttribCount) (struct gl2_program_intf **);
+   GLint (* GetAttribLocation) (struct gl2_program_intf **, const GLchar *name);
+   GLvoid (* OverrideAttribBinding) (struct gl2_program_intf **, GLuint, const GLchar *);
    GLvoid (* UpdateVarying) (struct gl2_program_intf **, GLuint, GLfloat *, GLboolean);
 };
 
index fa38a1c9af33a1269a257a40bccf9d77e161ed10..73c9e7d4367cf29abef8eb496d12dd341a98acf4 100755 (executable)
-/*\r
- * Mesa 3-D graphics library\r
- * Version:  6.5\r
- *\r
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-/**\r
- * \file shaderobjects_3dlabs.c\r
- * shader objects definitions for 3dlabs compiler\r
- * \author Michal Krol\r
- */\r
-\r
-/* Set this to 1 when we are ready to use 3dlabs' front-end */\r
-#define USE_3DLABS_FRONTEND 0\r
-\r
-#include "imports.h"\r
-#include "hash.h"\r
-#include "macros.h"\r
-#include "shaderobjects.h"\r
-#include "shaderobjects_3dlabs.h"\r
-\r
-#if USE_3DLABS_FRONTEND\r
-#include "slang_mesa.h"\r
-#include "Public/ShaderLang.h"\r
-#else\r
-#include "slang_link.h"\r
-#endif\r
-\r
-struct gl2_unknown_obj\r
-{\r
-       GLuint reference_count;\r
-       void (* _destructor) (struct gl2_unknown_intf **);\r
-};\r
-\r
-struct gl2_unknown_impl\r
-{\r
-       struct gl2_unknown_intf *_vftbl;\r
-       struct gl2_unknown_obj _obj;\r
-};\r
-\r
-static void\r
-_unknown_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-}\r
-\r
-static void\r
-_unknown_AddRef (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;\r
-\r
-       impl->_obj.reference_count++;\r
-}\r
-\r
-static void\r
-_unknown_Release (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;\r
-\r
-       impl->_obj.reference_count--;\r
-       if (impl->_obj.reference_count == 0)\r
-       {\r
-               impl->_obj._destructor (intf);\r
-               _mesa_free ((void *) intf);\r
-       }\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_unknown_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_UNKNOWN)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-static struct gl2_unknown_intf _unknown_vftbl = {\r
-       _unknown_AddRef,\r
-       _unknown_Release,\r
-       _unknown_QueryInterface\r
-};\r
-\r
-static void\r
-_unknown_constructor (struct gl2_unknown_impl *impl)\r
-{\r
-       impl->_vftbl = &_unknown_vftbl;\r
-       impl->_obj.reference_count = 1;\r
-       impl->_obj._destructor = _unknown_destructor;\r
-}\r
-\r
-struct gl2_unkinner_obj\r
-{\r
-       struct gl2_unknown_intf **unkouter;\r
-};\r
-\r
-struct gl2_unkinner_impl\r
-{\r
-       struct gl2_unknown_intf *_vftbl;\r
-       struct gl2_unkinner_obj _obj;\r
-};\r
-\r
-static void\r
-_unkinner_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-}\r
-\r
-static void\r
-_unkinner_AddRef (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       (**impl->_obj.unkouter).AddRef (impl->_obj.unkouter);\r
-}\r
-\r
-static void\r
-_unkinner_Release (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       (**impl->_obj.unkouter).Release (impl->_obj.unkouter);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_unkinner_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       return (**impl->_obj.unkouter).QueryInterface (impl->_obj.unkouter, uiid);\r
-}\r
-\r
-static struct gl2_unknown_intf _unkinner_vftbl = {\r
-       _unkinner_AddRef,\r
-       _unkinner_Release,\r
-       _unkinner_QueryInterface\r
-};\r
-\r
-static void\r
-_unkinner_constructor (struct gl2_unkinner_impl *impl, struct gl2_unknown_intf **outer)\r
-{\r
-       impl->_vftbl = &_unkinner_vftbl;\r
-       impl->_obj.unkouter = outer;\r
-}\r
-\r
-struct gl2_generic_obj\r
-{\r
-       struct gl2_unknown_obj _unknown;\r
-       GLhandleARB name;\r
-       GLboolean delete_status;\r
-       GLcharARB *info_log;\r
-};\r
-\r
-struct gl2_generic_impl\r
-{\r
-       struct gl2_generic_intf *_vftbl;\r
-       struct gl2_generic_obj _obj;\r
-};\r
-\r
-static void\r
-_generic_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.info_log);\r
-\r
-       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);\r
-       _mesa_HashRemove (ctx->Shared->GL2Objects, impl->_obj.name);\r
-       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);\r
-\r
-       _unknown_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_generic_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_GENERIC)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _unknown_QueryInterface (intf, uiid);\r
-}\r
-\r
-static void\r
-_generic_Delete (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       if (impl->_obj.delete_status == GL_FALSE)\r
-       {\r
-               impl->_obj.delete_status = GL_TRUE;\r
-               (**intf)._unknown.Release ((struct gl2_unknown_intf **) intf);\r
-       }\r
-}\r
-\r
-static GLhandleARB\r
-_generic_GetName (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.name;\r
-}\r
-\r
-static GLboolean\r
-_generic_GetDeleteStatus (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.delete_status;\r
-}\r
-\r
-static const GLcharARB *\r
-_generic_GetInfoLog (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.info_log;\r
-}\r
-\r
-static struct gl2_generic_intf _generic_vftbl = {\r
-       {\r
-               _unknown_AddRef,\r
-               _unknown_Release,\r
-               _generic_QueryInterface\r
-       },\r
-       _generic_Delete,\r
-       NULL,           /* abstract GetType */\r
-       _generic_GetName,\r
-       _generic_GetDeleteStatus,\r
-       _generic_GetInfoLog\r
-};\r
-\r
-static void\r
-_generic_constructor (struct gl2_generic_impl *impl)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-\r
-       _unknown_constructor ((struct gl2_unknown_impl *) impl);\r
-       impl->_vftbl = &_generic_vftbl;\r
-       impl->_obj._unknown._destructor = _generic_destructor;\r
-       impl->_obj.delete_status = GL_FALSE;\r
-       impl->_obj.info_log = NULL;\r
-\r
-       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);\r
-       impl->_obj.name = _mesa_HashFindFreeKeyBlock (ctx->Shared->GL2Objects, 1);\r
-       _mesa_HashInsert (ctx->Shared->GL2Objects, impl->_obj.name, (void *) impl);\r
-       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);\r
-}\r
-\r
-struct gl2_container_obj\r
-{\r
-       struct gl2_generic_obj _generic;\r
-       struct gl2_generic_intf ***attached;\r
-       GLuint attached_count;\r
-};\r
-\r
-struct gl2_container_impl\r
-{\r
-       struct gl2_container_intf *_vftbl;\r
-       struct gl2_container_obj _obj;\r
-};\r
-\r
-static void\r
-_container_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-       {\r
-               struct gl2_generic_intf **x = impl->_obj.attached[i];\r
-               (**x)._unknown.Release ((struct gl2_unknown_intf **) x);\r
-       }\r
-\r
-       _generic_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_container_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_CONTAINER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _generic_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLboolean\r
-_container_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-               if (impl->_obj.attached[i] == att)\r
-               {\r
-                       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Attach");\r
-                       return GL_FALSE;\r
-               }\r
-\r
-       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,\r
-               impl->_obj.attached_count * sizeof (*impl->_obj.attached), (impl->_obj.attached_count + 1) *\r
-               sizeof (*impl->_obj.attached));\r
-       if (impl->_obj.attached == NULL)\r
-               return GL_FALSE;\r
-\r
-       impl->_obj.attached[impl->_obj.attached_count] = att;\r
-       impl->_obj.attached_count++;\r
-       (**att)._unknown.AddRef ((struct gl2_unknown_intf **) att);\r
-       return GL_TRUE;\r
-}\r
-\r
-static GLboolean\r
-_container_Detach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i, j;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-               if (impl->_obj.attached[i] == att)\r
-               {\r
-                       for (j = i; j < impl->_obj.attached_count - 1; j++)\r
-                               impl->_obj.attached[j] = impl->_obj.attached[j + 1];\r
-                       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,\r
-                               impl->_obj.attached_count * sizeof (*impl->_obj.attached),\r
-                               (impl->_obj.attached_count - 1) * sizeof (*impl->_obj.attached));\r
-                       impl->_obj.attached_count--;\r
-                       (**att)._unknown.Release ((struct gl2_unknown_intf **) att);\r
-                       return GL_TRUE;\r
-               }\r
-\r
-       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Detach");\r
-       return GL_FALSE;\r
-}\r
-\r
-static GLsizei\r
-_container_GetAttachedCount (struct gl2_container_intf **intf)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-\r
-       return impl->_obj.attached_count;\r
-}\r
-\r
-static struct gl2_generic_intf **\r
-_container_GetAttached (struct gl2_container_intf **intf, GLuint index)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-\r
-       (**impl->_obj.attached[index])._unknown.AddRef (\r
-               (struct gl2_unknown_intf **)impl->_obj.attached[index]);\r
-       return impl->_obj.attached[index];\r
-}\r
-\r
-static struct gl2_container_intf _container_vftbl = {\r
-       {\r
-               {\r
-                       _unknown_AddRef,\r
-                       _unknown_Release,\r
-                       _container_QueryInterface\r
-               },\r
-               _generic_Delete,\r
-               NULL,           /* abstract GetType */\r
-               _generic_GetName,\r
-               _generic_GetDeleteStatus,\r
-               _generic_GetInfoLog\r
-       },\r
-       _container_Attach,\r
-       _container_Detach,\r
-       _container_GetAttachedCount,\r
-       _container_GetAttached\r
-};\r
-\r
-static void\r
-_container_constructor (struct gl2_container_impl *impl)\r
-{\r
-       _generic_constructor ((struct gl2_generic_impl *) impl);\r
-       impl->_vftbl = &_container_vftbl;\r
-       impl->_obj._generic._unknown._destructor = _container_destructor;\r
-       impl->_obj.attached = NULL;\r
-       impl->_obj.attached_count = 0;\r
-}\r
-\r
-struct gl2_3dlabs_shhandle_obj\r
-{\r
-       struct gl2_unkinner_obj _unknown;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle handle;\r
-#endif\r
-};\r
-\r
-struct gl2_3dlabs_shhandle_impl\r
-{\r
-       struct gl2_3dlabs_shhandle_intf *_vftbl;\r
-       struct gl2_3dlabs_shhandle_obj _obj;\r
-};\r
-\r
-static void\r
-_3dlabs_shhandle_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;\r
-       ShDestruct (impl->_obj.handle);\r
-#endif\r
-       _unkinner_destructor (intf);\r
-}\r
-\r
-static GLvoid *\r
-_3dlabs_shhandle_GetShHandle (struct gl2_3dlabs_shhandle_intf **intf)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;\r
-       return impl->_obj.handle;\r
-#else\r
-       return NULL;\r
-#endif\r
-}\r
-\r
-static struct gl2_3dlabs_shhandle_intf _3dlabs_shhandle_vftbl = {\r
-       {\r
-               _unkinner_AddRef,\r
-               _unkinner_Release,\r
-               _unkinner_QueryInterface\r
-       },\r
-       _3dlabs_shhandle_GetShHandle\r
-};\r
-\r
-static void\r
-_3dlabs_shhandle_constructor (struct gl2_3dlabs_shhandle_impl *impl, struct gl2_unknown_intf **outer)\r
-{\r
-       _unkinner_constructor ((struct gl2_unkinner_impl *) impl, outer);\r
-       impl->_vftbl = &_3dlabs_shhandle_vftbl;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj.handle = NULL;\r
-#endif\r
-}\r
-\r
-struct gl2_shader_obj\r
-{\r
-       struct gl2_generic_obj _generic;\r
-       struct gl2_3dlabs_shhandle_impl _3dlabs_shhandle;\r
-       GLboolean compile_status;\r
-       GLcharARB *source;\r
-       GLint *offsets;\r
-       GLsizei offset_count;\r
-       slang_translation_unit unit;\r
-};\r
-\r
-struct gl2_shader_impl\r
-{\r
-       struct gl2_shader_intf *_vftbl;\r
-       struct gl2_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.source);\r
-       _mesa_free ((void *) impl->_obj.offsets);\r
-       _3dlabs_shhandle_destructor ((struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl);\r
-       _generic_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-#endif\r
-\r
-       if (uiid == UIID_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-#if USE_3DLABS_FRONTEND\r
-       if (uiid == UIID_3DLABS_SHHANDLE)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return (struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl;\r
-       }\r
-#endif\r
-       return _generic_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_shader_GetType (struct gl2_generic_intf **intf)\r
-{\r
-       return GL_SHADER_OBJECT_ARB;\r
-}\r
-\r
-static GLboolean\r
-_shader_GetCompileStatus (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       return impl->_obj.compile_status;\r
-}\r
-\r
-static GLvoid\r
-_shader_SetSource (struct gl2_shader_intf **intf, GLcharARB *src, GLint *off, GLsizei cnt)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.source);\r
-       impl->_obj.source = src;\r
-       _mesa_free ((void *) impl->_obj.offsets);\r
-       impl->_obj.offsets = off;\r
-       impl->_obj.offset_count = cnt;\r
-}\r
-\r
-static const GLcharARB *\r
-_shader_GetSource (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       return impl->_obj.source;\r
-}\r
-\r
-static GLvoid\r
-_shader_Compile (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       char **strings;\r
-       TBuiltInResource res;\r
-#else\r
-       slang_unit_type type;\r
-       slang_info_log info_log;\r
-#endif\r
-\r
-       impl->_obj.compile_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._generic.info_log);\r
-       impl->_obj._generic.info_log = NULL;\r
-\r
-#if USE_3DLABS_FRONTEND\r
-       /* 3dlabs compiler expects us to feed it with null-terminated string array,\r
-       we've got only one big string with offsets, so we must split it; but when\r
-       there's only one string to deal with, we pass its address directly */\r
-\r
-       if (impl->_obj.offset_count <= 1)\r
-               strings = &impl->_obj.source;\r
-       else\r
-       {\r
-               GLsizei i, offset = 0;\r
-\r
-               strings = (char **) _mesa_malloc (impl->_obj.offset_count * sizeof (char *));\r
-               if (strings == NULL)\r
-                       return;\r
-\r
-               for (i = 0; i < impl->_obj.offset_count; i++)\r
-               {\r
-                       GLsizei size = impl->_obj.offsets[i] - offset;\r
-\r
-                       strings[i] = (char *) _mesa_malloc ((size + 1) * sizeof (char));\r
-                       if (strings[i] == NULL)\r
-                       {\r
-                               GLsizei j;\r
-\r
-                               for (j = 0; j < i; j++)\r
-                                       _mesa_free (strings[j]);\r
-                               _mesa_free (strings);\r
-                               return;\r
-                       }\r
-\r
-                       _mesa_memcpy (strings[i], impl->_obj.source + offset, size * sizeof (char));\r
-                       strings[i][size] = '\0';\r
-                       offset = impl->_obj.offsets[i];\r
-               }\r
-       }\r
-\r
-       /* TODO set these fields to some REAL numbers */\r
-       res.maxLights = 8;\r
-       res.maxClipPlanes = 6;\r
-       res.maxTextureUnits = 2;\r
-       res.maxTextureCoords = 2;\r
-       res.maxVertexAttribs = 8;\r
-       res.maxVertexUniformComponents = 64;\r
-       res.maxVaryingFloats = 8;\r
-       res.maxVertexTextureImageUnits = 2;\r
-       res.maxCombinedTextureImageUnits = 2;\r
-       res.maxTextureImageUnits = 2;\r
-       res.maxFragmentUniformComponents = 64;\r
-       res.maxDrawBuffers = 1;\r
-\r
-       if (ShCompile (impl->_obj._3dlabs_shhandle._obj.handle, strings, impl->_obj.offset_count,\r
-                       EShOptFull, &res, 0))\r
-               impl->_obj.compile_status = GL_TRUE;\r
-       if (impl->_obj.offset_count > 1)\r
-       {\r
-               GLsizei i;\r
-\r
-               for (i = 0; i < impl->_obj.offset_count; i++)\r
-                       _mesa_free (strings[i]);\r
-               _mesa_free (strings);\r
-       }\r
-\r
-       impl->_obj._generic.info_log = _mesa_strdup (ShGetInfoLog (\r
-               impl->_obj._3dlabs_shhandle._obj.handle));\r
-#else\r
-       if (impl->_vftbl->GetSubType (intf) == GL_FRAGMENT_SHADER)\r
-               type = slang_unit_fragment_shader;\r
-       else\r
-               type = slang_unit_vertex_shader;\r
-       slang_info_log_construct (&info_log);\r
-       if (_slang_compile (impl->_obj.source, &impl->_obj.unit, type, &info_log))\r
-       {\r
-               impl->_obj.compile_status = GL_TRUE;\r
-       }\r
-       if (info_log.text != NULL)\r
-               impl->_obj._generic.info_log = _mesa_strdup (info_log.text);\r
-       else\r
-               impl->_obj._generic.info_log = _mesa_strdup ("");\r
-       slang_info_log_destruct (&info_log);\r
-#endif\r
-}\r
-\r
-static struct gl2_shader_intf _shader_vftbl = {\r
-       {\r
-               {\r
-                       _unknown_AddRef,\r
-                       _unknown_Release,\r
-                       _shader_QueryInterface\r
-               },\r
-               _generic_Delete,\r
-               _shader_GetType,\r
-               _generic_GetName,\r
-               _generic_GetDeleteStatus,\r
-               _generic_GetInfoLog\r
-       },\r
-       NULL,           /* abstract GetSubType */\r
-       _shader_GetCompileStatus,\r
-       _shader_SetSource,\r
-       _shader_GetSource,\r
-       _shader_Compile\r
-};\r
-\r
-static void\r
-_shader_constructor (struct gl2_shader_impl *impl)\r
-{\r
-       _generic_constructor ((struct gl2_generic_impl *) impl);\r
-       _3dlabs_shhandle_constructor (&impl->_obj._3dlabs_shhandle, (struct gl2_unknown_intf **)\r
-               &impl->_vftbl);\r
-       impl->_vftbl = &_shader_vftbl;\r
-       impl->_obj._generic._unknown._destructor = _shader_destructor;\r
-       impl->_obj.compile_status = GL_FALSE;\r
-       impl->_obj.source = NULL;\r
-       impl->_obj.offsets = NULL;\r
-       impl->_obj.offset_count = 0;\r
-}\r
-\r
-struct gl2_program_obj\r
-{\r
-       struct gl2_container_obj _container;\r
-       GLboolean link_status;\r
-       GLboolean validate_status;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle linker;\r
-       ShHandle uniforms;\r
-#endif\r
-       slang_program prog;\r
-};\r
-\r
-struct gl2_program_impl\r
-{\r
-       struct gl2_program_intf *_vftbl;\r
-       struct gl2_program_obj _obj;\r
-};\r
-\r
-static void\r
-_program_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       ShDestruct (impl->_obj.linker);\r
-       ShDestruct (impl->_obj.uniforms);\r
-#endif\r
-       _container_destructor (intf);\r
-       slang_program_dtr (&impl->_obj.prog);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_program_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_PROGRAM)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _container_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_program_GetType (struct gl2_generic_intf **intf)\r
-{\r
-       return GL_PROGRAM_OBJECT_ARB;\r
-}\r
-\r
-static GLboolean\r
-_program_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_unknown_intf **sha;\r
-\r
-       sha = (**att)._unknown.QueryInterface ((struct gl2_unknown_intf **) att, UIID_SHADER);\r
-       if (sha == NULL)\r
-       {\r
-               _mesa_error (ctx, GL_INVALID_OPERATION, "_program_Attach");\r
-               return GL_FALSE;\r
-       }\r
-\r
-       (**sha).Release (sha);\r
-       return _container_Attach (intf, att);\r
-}\r
-\r
-static GLboolean\r
-_program_GetLinkStatus (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       return impl->_obj.link_status;\r
-}\r
-\r
-static GLboolean\r
-_program_GetValidateStatus (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       return impl->_obj.validate_status;\r
-}\r
-\r
-static GLvoid\r
-_program_Link (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle *handles;\r
-#endif\r
-       GLuint i, count;\r
-       slang_translation_unit *units[2];\r
-\r
-       impl->_obj.link_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._container._generic.info_log);\r
-       impl->_obj._container._generic.info_log = NULL;\r
-       slang_program_dtr (&impl->_obj.prog);\r
-       slang_program_ctr (&impl->_obj.prog);\r
-\r
-#if USE_3DLABS_FRONTEND\r
-       handles = (ShHandle *) _mesa_malloc (impl->_obj._container.attached_count * sizeof (ShHandle));\r
-       if (handles == NULL)\r
-               return;\r
-\r
-       for (i = 0; i < impl->_obj._container.attached_count; i++)\r
-       {\r
-               struct gl2_generic_intf **gen = impl->_obj._container.attached[i];\r
-               struct gl2_3dlabs_shhandle_intf **sh;\r
-\r
-               sh = (struct gl2_3dlabs_shhandle_intf **) (**gen)._unknown.QueryInterface (\r
-                       (struct gl2_unknown_intf **) gen, UIID_3DLABS_SHHANDLE);\r
-               if (sh != NULL)\r
-               {\r
-                       handles[i] = (**sh).GetShHandle (sh);\r
-                       (**sh)._unknown.Release ((struct gl2_unknown_intf **) sh);\r
-               }\r
-               else\r
-               {\r
-                       _mesa_free (handles);\r
-                       return;\r
-               }\r
-       }\r
-\r
-       if (ShLink (impl->_obj.linker, handles, impl->_obj._container.attached_count,\r
-                       impl->_obj.uniforms, NULL, NULL))\r
-               impl->_obj.link_status = GL_TRUE;\r
-\r
-       impl->_obj._container._generic.info_log = _mesa_strdup (ShGetInfoLog (impl->_obj.linker));\r
-#else\r
-       count = impl->_obj._container.attached_count;\r
-       if (count == 0 || count > 2)\r
-               return;\r
-       for (i = 0; i < count; i++)\r
-       {\r
-               struct gl2_generic_intf **obj;\r
-               struct gl2_unknown_intf **unk;\r
-               struct gl2_shader_impl *sha;\r
-\r
-               obj = impl->_obj._container.attached[i];\r
-               unk = (**obj)._unknown.QueryInterface ((struct gl2_unknown_intf **) obj, UIID_SHADER);\r
-               (**obj)._unknown.Release ((struct gl2_unknown_intf **) obj);\r
-               if (unk == NULL)\r
-                       return;\r
-               sha = (struct gl2_shader_impl *) unk;\r
-               units[i] = &sha->_obj.unit;\r
-               (**unk).Release (unk);\r
-       }\r
-\r
-       impl->_obj.link_status = _slang_link (&impl->_obj.prog, units, count);\r
-       if (impl->_obj.link_status)\r
-               impl->_obj._container._generic.info_log = _mesa_strdup ("Link OK.\n");\r
-       else\r
-               impl->_obj._container._generic.info_log = _mesa_strdup ("Link failed.\n");\r
-#endif\r
-}\r
-\r
-static GLvoid\r
-_program_Validate (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       impl->_obj.validate_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._container._generic.info_log);\r
-       impl->_obj._container._generic.info_log = NULL;\r
-\r
-       /* TODO validate */\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed (slang_program *pro, GLuint index, const GLvoid *src, GLuint off, GLuint size)\r
-{\r
-       GLuint i;\r
-\r
-       for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-       {\r
-               GLuint addr;\r
-\r
-               addr = pro->common_fixed_entries[i][index];\r
-               if (addr != ~0)\r
-               {\r
-                       GLubyte *dst;\r
-\r
-                       dst = (GLubyte *) pro->machines[i]->mem + addr + off * size;\r
-                       _mesa_memcpy (dst, src, size);\r
-               }\r
-       }\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_mat4 (slang_program *pro, GLmatrix *matrix, GLuint off, GLuint i, GLuint ii,\r
-                         GLuint it, GLuint iit)\r
-{\r
-       GLfloat mat[16];\r
-\r
-       /* we want inverse matrix */\r
-       if (!matrix->inv)\r
-       {\r
-               /* allocate inverse matrix and make it dirty */\r
-               _math_matrix_alloc_inv (matrix);\r
-               _math_matrix_loadf (matrix, matrix->m);\r
-       }\r
-       _math_matrix_analyse (matrix);\r
-\r
-       write_common_fixed (pro, i, matrix->m, off, 16 * sizeof (GLfloat));\r
-\r
-       /* inverse */\r
-       write_common_fixed (pro, ii, matrix->inv, off, 16 * sizeof (GLfloat));\r
-\r
-       /* transpose */\r
-       _math_transposef (mat, matrix->m);\r
-       write_common_fixed (pro, it, mat, off, 16 * sizeof (GLfloat));\r
-\r
-       /* inverse transpose */\r
-       _math_transposef (mat, matrix->inv);\r
-       write_common_fixed (pro, iit, mat, off, 16 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_material (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e, GLuint a,\r
-                             GLuint d, GLuint sp, GLuint sh)\r
-{\r
-       GLfloat v[17];\r
-\r
-       COPY_4FV(v, ctx->Light.Material.Attrib[e]);\r
-       COPY_4FV((v + 4), ctx->Light.Material.Attrib[a]);\r
-       COPY_4FV((v + 8), ctx->Light.Material.Attrib[d]);\r
-       COPY_4FV((v + 12), ctx->Light.Material.Attrib[sp]);\r
-       v[16] = ctx->Light.Material.Attrib[sh][0];\r
-       write_common_fixed (pro, i, v, 0, 17 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_light_model_product (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e,\r
-                                        GLuint a)\r
-{\r
-       GLfloat v[4];\r
-\r
-       SCALE_4V(v,     ctx->Light.Material.Attrib[a], ctx->Light.Model.Ambient);\r
-       ACC_4V(v, ctx->Light.Material.Attrib[e]);\r
-       write_common_fixed (pro, i, v, 0, 4 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_light_product (GLcontext *ctx, slang_program *pro, GLuint off, GLuint i, GLuint a,\r
-                                  GLuint d, GLuint s)\r
-{\r
-       GLfloat v[12];\r
-\r
-       SCALE_4V(v, ctx->Light.Light[off].Ambient, ctx->Light.Material.Attrib[a]);\r
-       SCALE_4V((v + 4), ctx->Light.Light[off].Diffuse, ctx->Light.Material.Attrib[d]);\r
-       SCALE_4V((v + 8), ctx->Light.Light[off].Specular, ctx->Light.Material.Attrib[s]);\r
-       write_common_fixed (pro, i, v, off, 12 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedUniforms (struct gl2_program_intf **intf)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint i;\r
-       GLfloat v[29];\r
-       GLfloat *p;\r
-\r
-       /* MODELVIEW matrix */\r
-       write_common_fixed_mat4 (pro, ctx->ModelviewMatrixStack.Top, 0,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIX,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE);\r
-\r
-       /* PROJECTION matrix */\r
-       write_common_fixed_mat4 (pro, ctx->ProjectionMatrixStack.Top, 0,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIX,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE);\r
-\r
-       /* MVP matrix */\r
-       write_common_fixed_mat4 (pro, &ctx->_ModelProjectMatrix, 0,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE);\r
-\r
-       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)\r
-       {\r
-               /* TEXTURE matrix */\r
-               write_common_fixed_mat4 (pro, ctx->TextureMatrixStack[i].Top, i,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIX,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE);\r
-\r
-               /* EYE_PLANE texture-coordinate generation */\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANES, ctx->Texture.Unit[i].EyePlaneS,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANET, ctx->Texture.Unit[i].EyePlaneT,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANER, ctx->Texture.Unit[i].EyePlaneR,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANEQ, ctx->Texture.Unit[i].EyePlaneQ,\r
-                       i, 4 * sizeof (GLfloat));\r
-\r
-               /* OBJECT_PLANE texture-coordinate generation */\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANES, ctx->Texture.Unit[i].ObjectPlaneS,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANET, ctx->Texture.Unit[i].ObjectPlaneT,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANER, ctx->Texture.Unit[i].ObjectPlaneR,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANEQ, ctx->Texture.Unit[i].ObjectPlaneQ,\r
-                       i, 4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* NORMAL matrix - upper 3x3 inverse transpose of MODELVIEW matrix */\r
-       p = ctx->ModelviewMatrixStack.Top->inv;\r
-       v[0] = p[0];\r
-       v[1] = p[4];\r
-       v[2] = p[8];\r
-       v[3] = p[1];\r
-       v[4] = p[5];\r
-       v[5] = p[9];\r
-       v[6] = p[2];\r
-       v[7] = p[6];\r
-       v[8] = p[10];\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALMATRIX, v, 0, 9 * sizeof (GLfloat));\r
-\r
-       /* normal scale */\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALSCALE, &ctx->_ModelViewInvScale, 0, sizeof (GLfloat));\r
-\r
-       /* depth range parameters */\r
-       v[0] = ctx->Viewport.Near;\r
-       v[1] = ctx->Viewport.Far;\r
-       v[2] = ctx->Viewport.Far - ctx->Viewport.Near;\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_DEPTHRANGE, v, 0, 3 * sizeof (GLfloat));\r
-\r
-       /* CLIP_PLANEi */\r
-       for (i = 0; i < ctx->Const.MaxClipPlanes; i++)\r
-       {\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_CLIPPLANE, ctx->Transform.EyeUserPlane[i], i,\r
-                       4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* point parameters */\r
-       v[0] = ctx->Point.Size;\r
-       v[1] = ctx->Point.MinSize;\r
-       v[2] = ctx->Point.MaxSize;\r
-       v[3] = ctx->Point.Threshold;\r
-       COPY_3FV((v + 4), ctx->Point.Params);\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_POINT, v, 0, 7 * sizeof (GLfloat));\r
-\r
-       /* material parameters */\r
-       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_FRONTMATERIAL,\r
-               MAT_ATTRIB_FRONT_EMISSION,\r
-               MAT_ATTRIB_FRONT_AMBIENT,\r
-               MAT_ATTRIB_FRONT_DIFFUSE,\r
-               MAT_ATTRIB_FRONT_SPECULAR,\r
-               MAT_ATTRIB_FRONT_SHININESS);\r
-       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_BACKMATERIAL,\r
-               MAT_ATTRIB_BACK_EMISSION,\r
-               MAT_ATTRIB_BACK_AMBIENT,\r
-               MAT_ATTRIB_BACK_DIFFUSE,\r
-               MAT_ATTRIB_BACK_SPECULAR,\r
-               MAT_ATTRIB_BACK_SHININESS);\r
-\r
-       for (i = 0; i < ctx->Const.MaxLights; i++)\r
-       {\r
-               /* light source parameters */\r
-               COPY_4FV(v, ctx->Light.Light[i].Ambient);\r
-               COPY_4FV((v + 4), ctx->Light.Light[i].Diffuse);\r
-               COPY_4FV((v + 8), ctx->Light.Light[i].Specular);\r
-               COPY_4FV((v + 12), ctx->Light.Light[i].EyePosition);\r
-               COPY_2FV((v + 16), ctx->Light.Light[i].EyePosition);\r
-               v[18] = ctx->Light.Light[i].EyePosition[2] + 1.0f;\r
-               NORMALIZE_3FV((v + 16));\r
-               v[19] = 0.0f;\r
-               COPY_3V((v + 20), ctx->Light.Light[i].EyeDirection);\r
-               v[23] = ctx->Light.Light[i].SpotExponent;\r
-               v[24] = ctx->Light.Light[i].SpotCutoff;\r
-               v[25] = ctx->Light.Light[i]._CosCutoffNeg;\r
-               v[26] = ctx->Light.Light[i].ConstantAttenuation;\r
-               v[27] = ctx->Light.Light[i].LinearAttenuation;\r
-               v[28] = ctx->Light.Light[i].QuadraticAttenuation;\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTSOURCE, v, i, 29 * sizeof (GLfloat));\r
-\r
-               /* light product */\r
-               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT,\r
-                       MAT_ATTRIB_FRONT_AMBIENT,\r
-                       MAT_ATTRIB_FRONT_DIFFUSE,\r
-                       MAT_ATTRIB_FRONT_SPECULAR);\r
-               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_BACKLIGHTPRODUCT,\r
-                       MAT_ATTRIB_BACK_AMBIENT,\r
-                       MAT_ATTRIB_BACK_DIFFUSE,\r
-                       MAT_ATTRIB_BACK_SPECULAR);\r
-       }\r
-\r
-       /* light model parameters */\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTMODEL, ctx->Light.Model.Ambient, 0, 4 * sizeof (GLfloat));\r
-\r
-       /* light model product */\r
-       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT,\r
-               MAT_ATTRIB_FRONT_EMISSION,\r
-               MAT_ATTRIB_FRONT_AMBIENT);\r
-       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT,\r
-               MAT_ATTRIB_BACK_EMISSION,\r
-               MAT_ATTRIB_BACK_AMBIENT);\r
-\r
-       /* TEXTURE_ENV_COLOR */\r
-       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)\r
-       {\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_TEXTUREENVCOLOR, ctx->Texture.Unit[i].EnvColor,\r
-                       i, 4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* fog parameters */\r
-       COPY_4FV(v, ctx->Fog.Color);\r
-       v[4] = ctx->Fog.Density;\r
-       v[5] = ctx->Fog.Start;\r
-       v[6] = ctx->Fog.End;\r
-       v[7] = ctx->Fog._Scale;\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_FOG, v, 0, 8 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedAttribute (struct gl2_program_intf **intf, GLuint index, GLvoid *data,\r
-                                                         GLuint offset, GLuint size, GLboolean write)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       addr = pro->vertex_fixed_entries[index];\r
-       if (addr != ~0)\r
-       {\r
-               GLubyte *mem;\r
-\r
-               mem = (GLubyte *) pro->machines[SLANG_SHADER_VERTEX]->mem + addr + offset * size;\r
-               if (write)\r
-                       _mesa_memcpy (mem, data, size);\r
-               else\r
-                       _mesa_memcpy (data, mem, size);\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedVarying (struct gl2_program_intf **intf, GLuint index, GLvoid *data,\r
-                                                       GLuint offset, GLuint size, GLboolean write)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       addr = pro->fragment_fixed_entries[index];\r
-       if (addr != ~0)\r
-       {\r
-               GLubyte *mem;\r
-\r
-               mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + offset * size;\r
-               if (write)\r
-                       _mesa_memcpy (mem, data, size);\r
-               else\r
-                       _mesa_memcpy (data, mem, size);\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_GetTextureImageUsage (struct gl2_program_intf **intf, GLbitfield *teximageusage)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)\r
-               teximageusage[i] = 0;\r
-\r
-       for (i = 0; i < pro->texture_usage.count; i++)\r
-       {\r
-               GLuint n, addr, j;\r
-\r
-               n = slang_export_data_quant_elements (pro->texture_usage.table[i].quant);\r
-               addr = pro->texture_usage.table[i].frag_address;\r
-               for (j = 0; j < n; j++)\r
-               {\r
-                       GLubyte *mem;\r
-                       GLuint image;\r
-\r
-                       mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + j * 4;\r
-                       image = (GLuint) *((GLfloat *) mem);\r
-                       if (image >= 0 && image < ctx->Const.MaxTextureImageUnits)\r
-                       {\r
-                               switch (slang_export_data_quant_type (pro->texture_usage.table[i].quant))\r
-                               {\r
-                               case GL_SAMPLER_1D_ARB:\r
-                               case GL_SAMPLER_1D_SHADOW_ARB:\r
-                                       teximageusage[image] |= TEXTURE_1D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_2D_ARB:\r
-                               case GL_SAMPLER_2D_SHADOW_ARB:\r
-                                       teximageusage[image] |= TEXTURE_2D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_3D_ARB:\r
-                                       teximageusage[image] |= TEXTURE_3D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_CUBE_ARB:\r
-                                       teximageusage[image] |= TEXTURE_CUBE_BIT;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* TODO: make sure that for 0<=i<=MaxTextureImageUint bitcount(teximageuint[i])<=0 */\r
-}\r
-\r
-static GLboolean\r
-_program_IsShaderPresent (struct gl2_program_intf **intf, GLenum subtype)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-\r
-       switch (subtype)\r
-       {\r
-       case GL_VERTEX_SHADER_ARB:\r
-               return pro->machines[SLANG_SHADER_VERTEX] != NULL;\r
-       case GL_FRAGMENT_SHADER_ARB:\r
-               return pro->machines[SLANG_SHADER_FRAGMENT] != NULL;\r
-       default:\r
-               return GL_FALSE;\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateVarying (struct gl2_program_intf **intf, GLuint index, GLfloat *value,\r
-       GLboolean vert)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       if (index >= pro->varyings.total)\r
-               return;\r
-       if (vert)\r
-               addr = pro->varyings.slots[index].vert_addr / 4;\r
-       else\r
-               addr = pro->varyings.slots[index].frag_addr / 4;\r
-       if (addr != ~0)\r
-       {\r
-               if (vert)\r
-                       *value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float;\r
-               else\r
-                       pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value;\r
-       }\r
-}\r
-\r
-static struct gl2_program_intf _program_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _program_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _program_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _program_Attach,\r
-               _container_Detach,\r
-               _container_GetAttachedCount,\r
-               _container_GetAttached\r
-       },\r
-       _program_GetLinkStatus,\r
-       _program_GetValidateStatus,\r
-       _program_Link,\r
-       _program_Validate,\r
-       _program_UpdateFixedUniforms,\r
-       _program_UpdateFixedAttribute,\r
-       _program_UpdateFixedVarying,\r
-       _program_GetTextureImageUsage,\r
-       _program_IsShaderPresent,\r
-       _program_UpdateVarying\r
-};\r
-\r
-static void\r
-_program_constructor (struct gl2_program_impl *impl)\r
-{\r
-       _container_constructor ((struct gl2_container_impl *) impl);\r
-       impl->_vftbl = &_program_vftbl;\r
-       impl->_obj._container._generic._unknown._destructor = _program_destructor;\r
-       impl->_obj.link_status = GL_FALSE;\r
-       impl->_obj.validate_status = GL_FALSE;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj.linker = ShConstructLinker (EShExVertexFragment, 0);\r
-       impl->_obj.uniforms = ShConstructUniformMap ();\r
-#endif\r
-       slang_program_ctr (&impl->_obj.prog);\r
-}\r
-\r
-struct gl2_fragment_shader_obj\r
-{\r
-       struct gl2_shader_obj _shader;\r
-};\r
-\r
-struct gl2_fragment_shader_impl\r
-{\r
-       struct gl2_fragment_shader_intf *_vftbl;\r
-       struct gl2_fragment_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_fragment_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_fragment_shader_impl *impl = (struct gl2_fragment_shader_impl *) intf;\r
-\r
-       (void) impl;\r
-       /* TODO free fragment shader data */\r
-\r
-       _shader_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_fragment_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_FRAGMENT_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _shader_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_fragment_shader_GetSubType (struct gl2_shader_intf **intf)\r
-{\r
-       return GL_FRAGMENT_SHADER_ARB;\r
-}\r
-\r
-static struct gl2_fragment_shader_intf _fragment_shader_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _fragment_shader_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _shader_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _fragment_shader_GetSubType,\r
-               _shader_GetCompileStatus,\r
-               _shader_SetSource,\r
-               _shader_GetSource,\r
-               _shader_Compile\r
-       }\r
-};\r
-\r
-static void\r
-_fragment_shader_constructor (struct gl2_fragment_shader_impl *impl)\r
-{\r
-       _shader_constructor ((struct gl2_shader_impl *) impl);\r
-       impl->_vftbl = &_fragment_shader_vftbl;\r
-       impl->_obj._shader._generic._unknown._destructor = _fragment_shader_destructor;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangFragment, 0);\r
-#endif\r
-}\r
-\r
-struct gl2_vertex_shader_obj\r
-{\r
-       struct gl2_shader_obj _shader;\r
-};\r
-\r
-struct gl2_vertex_shader_impl\r
-{\r
-       struct gl2_vertex_shader_intf *_vftbl;\r
-       struct gl2_vertex_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_vertex_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_vertex_shader_impl *impl = (struct gl2_vertex_shader_impl *) intf;\r
-\r
-       (void) impl;\r
-       /* TODO free vertex shader data */\r
-\r
-       _shader_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_vertex_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_VERTEX_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _shader_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_vertex_shader_GetSubType (struct gl2_shader_intf **intf)\r
-{\r
-       return GL_VERTEX_SHADER_ARB;\r
-}\r
-\r
-static struct gl2_vertex_shader_intf _vertex_shader_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _vertex_shader_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _shader_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _vertex_shader_GetSubType,\r
-               _shader_GetCompileStatus,\r
-               _shader_SetSource,\r
-               _shader_GetSource,\r
-               _shader_Compile\r
-       }\r
-};\r
-\r
-static void\r
-_vertex_shader_constructor (struct gl2_vertex_shader_impl *impl)\r
-{\r
-       _shader_constructor ((struct gl2_shader_impl *) impl);\r
-       impl->_vftbl = &_vertex_shader_vftbl;\r
-       impl->_obj._shader._generic._unknown._destructor = _vertex_shader_destructor;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangVertex, 0);\r
-#endif\r
-}\r
-\r
-GLhandleARB\r
-_mesa_3dlabs_create_shader_object (GLenum shaderType)\r
-{\r
-       switch (shaderType)\r
-       {\r
-       case GL_FRAGMENT_SHADER_ARB:\r
-               {\r
-                       struct gl2_fragment_shader_impl *x = (struct gl2_fragment_shader_impl *)\r
-                               _mesa_malloc (sizeof (struct gl2_fragment_shader_impl));\r
-\r
-                       if (x != NULL)\r
-                       {\r
-                               _fragment_shader_constructor (x);\r
-                               return x->_obj._shader._generic.name;\r
-                       }\r
-               }\r
-               break;\r
-       case GL_VERTEX_SHADER_ARB:\r
-               {\r
-                       struct gl2_vertex_shader_impl *x = (struct gl2_vertex_shader_impl *)\r
-                               _mesa_malloc (sizeof (struct gl2_vertex_shader_impl));\r
-\r
-                       if (x != NULL)\r
-                       {\r
-                               _vertex_shader_constructor (x);\r
-                               return x->_obj._shader._generic.name;\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-GLhandleARB\r
-_mesa_3dlabs_create_program_object (void)\r
-{\r
-       struct gl2_program_impl *x = (struct gl2_program_impl *) \r
-               _mesa_malloc (sizeof (struct gl2_program_impl));\r
-\r
-       if (x != NULL)\r
-       {\r
-               _program_constructor (x);\r
-               return x->_obj._container._generic.name;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-#include "slang_assemble.h"\r
-#include "slang_execute.h"\r
-\r
-int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val)\r
-{\r
-       struct gl2_program_impl *impl;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       *val = impl->_obj.prog.machines[SLANG_SHADER_FRAGMENT]->kill ? GL_TRUE : GL_FALSE;\r
-       return 1;\r
-}\r
-\r
-static GLvoid exec_shader (struct gl2_program_intf **pro, GLuint i)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_program *p;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       p = &impl->_obj.prog;\r
-\r
-       slang_machine_init (p->machines[i]);\r
-       p->machines[i]->ip = p->code[i][SLANG_COMMON_CODE_MAIN];\r
-\r
-       _slang_execute2 (p->assemblies[i], p->machines[i]);\r
-}\r
-\r
-GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro)\r
-{\r
-       exec_shader (pro, SLANG_SHADER_FRAGMENT);\r
-}\r
-\r
-GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro)\r
-{\r
-       exec_shader (pro, SLANG_SHADER_VERTEX);\r
-}\r
-\r
-GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_uniform_bindings *bind;\r
-       GLuint i;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       bind = &impl->_obj.prog.uniforms;\r
-       for (i = 0; i < bind->count; i++)\r
-               if (_mesa_strcmp (bind->table[i].name, name) == 0)\r
-                       return i;\r
-       return -1;\r
-}\r
-\r
-GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count,\r
-       const GLvoid *data, GLenum type)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_uniform_bindings *bind;\r
-       slang_uniform_binding *b;\r
-       GLuint i;\r
-       GLboolean convert_float_to_bool = GL_FALSE;\r
-       GLboolean convert_int_to_bool = GL_FALSE;\r
-       GLboolean convert_int_to_float = GL_FALSE;\r
-       GLboolean types_match = GL_FALSE;\r
-\r
-       if (loc == -1)\r
-               return GL_TRUE;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       bind = &impl->_obj.prog.uniforms;\r
-       if (loc >= bind->count)\r
-               return GL_FALSE;\r
-\r
-       b = &bind->table[loc];\r
-       /* TODO: check sizes */\r
-       if (slang_export_data_quant_struct (b->quant))\r
-               return GL_FALSE;\r
-\r
-       switch (slang_export_data_quant_type (b->quant))\r
-       {\r
-       case GL_BOOL_ARB:\r
-               types_match = (type == GL_FLOAT) || (type == GL_INT);\r
-               if (type == GL_FLOAT)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC2_ARB:\r
-               types_match = (type == GL_FLOAT_VEC2_ARB) || (type == GL_INT_VEC2_ARB);\r
-               if (type == GL_FLOAT_VEC2_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC3_ARB:\r
-               types_match = (type == GL_FLOAT_VEC3_ARB) || (type == GL_INT_VEC3_ARB);\r
-               if (type == GL_FLOAT_VEC3_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC4_ARB:\r
-               types_match = (type == GL_FLOAT_VEC4_ARB) || (type == GL_INT_VEC4_ARB);\r
-               if (type == GL_FLOAT_VEC4_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_SAMPLER_1D_ARB:\r
-       case GL_SAMPLER_2D_ARB:\r
-       case GL_SAMPLER_3D_ARB:\r
-       case GL_SAMPLER_CUBE_ARB:\r
-       case GL_SAMPLER_1D_SHADOW_ARB:\r
-       case GL_SAMPLER_2D_SHADOW_ARB:\r
-               types_match = (type == GL_INT);\r
-               break;\r
-       default:\r
-               types_match = (type == slang_export_data_quant_type (b->quant));\r
-               break;\r
-       }\r
-\r
-       if (!types_match)\r
-               return GL_FALSE;\r
-\r
-       switch (type)\r
-       {\r
-       case GL_INT:\r
-       case GL_INT_VEC2_ARB:\r
-       case GL_INT_VEC3_ARB:\r
-       case GL_INT_VEC4_ARB:\r
-               convert_int_to_float = GL_TRUE;\r
-               break;\r
-       }\r
-\r
-       if (convert_float_to_bool)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLfloat *src = (GLfloat *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;\r
-                       }\r
-       }\r
-       else if (convert_int_to_bool)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLuint *src = (GLuint *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = src[j] ? 1.0f : 0.0f;\r
-                       }\r
-       }\r
-       else if (convert_int_to_float)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLuint *src = (GLuint *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = (GLfloat) src[j];\r
-                       }\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               _mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data,\r
-                                       count * slang_export_data_quant_size (b->quant));\r
-                       }\r
-       }\r
-       return GL_TRUE;\r
-}\r
-\r
-GLuint _slang_get_active_uniform_count (struct gl2_program_intf **pro)\r
-{\r
-       struct gl2_program_impl *impl;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       return impl->_obj.prog.active_uniforms.count;\r
-}\r
-\r
-GLuint _slang_get_active_uniform_max_length (struct gl2_program_intf **pro)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       GLuint i, len = 0;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       for (i = 0; i < impl->_obj.prog.active_uniforms.count; i++)\r
-       {\r
-               GLuint n = _mesa_strlen (impl->_obj.prog.active_uniforms.table[i].name);\r
-               if (n > len)\r
-                       len = n;\r
-       }\r
-       return len;\r
-}\r
-\r
-GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, GLsizei maxLength,\r
-       GLsizei *length, GLint *size, GLenum *type, char *name)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_active_uniform *u;\r
-       GLsizei len;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       u = &impl->_obj.prog.active_uniforms.table[index];\r
-\r
-       len = _mesa_strlen (u->name);\r
-       if (len >= maxLength)\r
-               len = maxLength - 1;\r
-       _mesa_memcpy (name, u->name, len);\r
-       name[len] = '\0';\r
-       if (length != NULL)\r
-               *length = len;\r
-       *type = slang_export_data_quant_type (u->quant);\r
-       *size = slang_export_data_quant_elements (u->quant);\r
-}\r
-\r
-void\r
-_mesa_init_shaderobjects_3dlabs (GLcontext *ctx)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       _glslang_3dlabs_InitProcess ();\r
-       _glslang_3dlabs_ShInitialize ();\r
-#endif\r
-}\r
-\r
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file shaderobjects_3dlabs.c
+ * shader objects definitions for 3dlabs compiler
+ * \author Michal Krol
+ */
+
+/* Set this to 1 when we are ready to use 3dlabs' front-end */
+#define USE_3DLABS_FRONTEND 0
+
+#include "imports.h"
+#include "hash.h"
+#include "macros.h"
+#include "shaderobjects.h"
+#include "shaderobjects_3dlabs.h"
+
+#if USE_3DLABS_FRONTEND
+#include "slang_mesa.h"
+#include "Public/ShaderLang.h"
+#else
+#include "slang_link.h"
+#endif
+
+struct gl2_unknown_obj
+{
+       GLuint reference_count;
+       void (* _destructor) (struct gl2_unknown_intf **);
+};
+
+struct gl2_unknown_impl
+{
+       struct gl2_unknown_intf *_vftbl;
+       struct gl2_unknown_obj _obj;
+};
+
+static void
+_unknown_destructor (struct gl2_unknown_intf **intf)
+{
+}
+
+static void
+_unknown_AddRef (struct gl2_unknown_intf **intf)
+{
+       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;
+
+       impl->_obj.reference_count++;
+}
+
+static void
+_unknown_Release (struct gl2_unknown_intf **intf)
+{
+       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;
+
+       impl->_obj.reference_count--;
+       if (impl->_obj.reference_count == 0)
+       {
+               impl->_obj._destructor (intf);
+               _mesa_free ((void *) intf);
+       }
+}
+
+static struct gl2_unknown_intf **
+_unknown_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_UNKNOWN)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return NULL;
+}
+
+static struct gl2_unknown_intf _unknown_vftbl = {
+       _unknown_AddRef,
+       _unknown_Release,
+       _unknown_QueryInterface
+};
+
+static void
+_unknown_constructor (struct gl2_unknown_impl *impl)
+{
+       impl->_vftbl = &_unknown_vftbl;
+       impl->_obj.reference_count = 1;
+       impl->_obj._destructor = _unknown_destructor;
+}
+
+struct gl2_unkinner_obj
+{
+       struct gl2_unknown_intf **unkouter;
+};
+
+struct gl2_unkinner_impl
+{
+       struct gl2_unknown_intf *_vftbl;
+       struct gl2_unkinner_obj _obj;
+};
+
+static void
+_unkinner_destructor (struct gl2_unknown_intf **intf)
+{
+}
+
+static void
+_unkinner_AddRef (struct gl2_unknown_intf **intf)
+{
+       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
+
+       (**impl->_obj.unkouter).AddRef (impl->_obj.unkouter);
+}
+
+static void
+_unkinner_Release (struct gl2_unknown_intf **intf)
+{
+       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
+
+       (**impl->_obj.unkouter).Release (impl->_obj.unkouter);
+}
+
+static struct gl2_unknown_intf **
+_unkinner_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;
+
+       return (**impl->_obj.unkouter).QueryInterface (impl->_obj.unkouter, uiid);
+}
+
+static struct gl2_unknown_intf _unkinner_vftbl = {
+       _unkinner_AddRef,
+       _unkinner_Release,
+       _unkinner_QueryInterface
+};
+
+static void
+_unkinner_constructor (struct gl2_unkinner_impl *impl, struct gl2_unknown_intf **outer)
+{
+       impl->_vftbl = &_unkinner_vftbl;
+       impl->_obj.unkouter = outer;
+}
+
+struct gl2_generic_obj
+{
+       struct gl2_unknown_obj _unknown;
+       GLhandleARB name;
+       GLboolean delete_status;
+       GLcharARB *info_log;
+};
+
+struct gl2_generic_impl
+{
+       struct gl2_generic_intf *_vftbl;
+       struct gl2_generic_obj _obj;
+};
+
+static void
+_generic_destructor (struct gl2_unknown_intf **intf)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
+
+       _mesa_free ((void *) impl->_obj.info_log);
+
+       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);
+       _mesa_HashRemove (ctx->Shared->GL2Objects, impl->_obj.name);
+       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);
+
+       _unknown_destructor (intf);
+}
+
+static struct gl2_unknown_intf **
+_generic_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_GENERIC)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return _unknown_QueryInterface (intf, uiid);
+}
+
+static void
+_generic_Delete (struct gl2_generic_intf **intf)
+{
+       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
+
+       if (impl->_obj.delete_status == GL_FALSE)
+       {
+               impl->_obj.delete_status = GL_TRUE;
+               (**intf)._unknown.Release ((struct gl2_unknown_intf **) intf);
+       }
+}
+
+static GLhandleARB
+_generic_GetName (struct gl2_generic_intf **intf)
+{
+       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
+
+       return impl->_obj.name;
+}
+
+static GLboolean
+_generic_GetDeleteStatus (struct gl2_generic_intf **intf)
+{
+       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
+
+       return impl->_obj.delete_status;
+}
+
+static const GLcharARB *
+_generic_GetInfoLog (struct gl2_generic_intf **intf)
+{
+       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;
+
+       return impl->_obj.info_log;
+}
+
+static struct gl2_generic_intf _generic_vftbl = {
+       {
+               _unknown_AddRef,
+               _unknown_Release,
+               _generic_QueryInterface
+       },
+       _generic_Delete,
+       NULL,           /* abstract GetType */
+       _generic_GetName,
+       _generic_GetDeleteStatus,
+       _generic_GetInfoLog
+};
+
+static void
+_generic_constructor (struct gl2_generic_impl *impl)
+{
+       GET_CURRENT_CONTEXT(ctx);
+
+       _unknown_constructor ((struct gl2_unknown_impl *) impl);
+       impl->_vftbl = &_generic_vftbl;
+       impl->_obj._unknown._destructor = _generic_destructor;
+       impl->_obj.delete_status = GL_FALSE;
+       impl->_obj.info_log = NULL;
+
+       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);
+       impl->_obj.name = _mesa_HashFindFreeKeyBlock (ctx->Shared->GL2Objects, 1);
+       _mesa_HashInsert (ctx->Shared->GL2Objects, impl->_obj.name, (void *) impl);
+       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);
+}
+
+struct gl2_container_obj
+{
+       struct gl2_generic_obj _generic;
+       struct gl2_generic_intf ***attached;
+       GLuint attached_count;
+};
+
+struct gl2_container_impl
+{
+       struct gl2_container_intf *_vftbl;
+       struct gl2_container_obj _obj;
+};
+
+static void
+_container_destructor (struct gl2_unknown_intf **intf)
+{
+       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
+       GLuint i;
+
+       for (i = 0; i < impl->_obj.attached_count; i++)
+       {
+               struct gl2_generic_intf **x = impl->_obj.attached[i];
+               (**x)._unknown.Release ((struct gl2_unknown_intf **) x);
+       }
+
+       _generic_destructor (intf);
+}
+
+static struct gl2_unknown_intf **
+_container_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_CONTAINER)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return _generic_QueryInterface (intf, uiid);
+}
+
+static GLboolean
+_container_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
+       GLuint i;
+
+       for (i = 0; i < impl->_obj.attached_count; i++)
+               if (impl->_obj.attached[i] == att)
+               {
+                       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Attach");
+                       return GL_FALSE;
+               }
+
+       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,
+               impl->_obj.attached_count * sizeof (*impl->_obj.attached), (impl->_obj.attached_count + 1) *
+               sizeof (*impl->_obj.attached));
+       if (impl->_obj.attached == NULL)
+               return GL_FALSE;
+
+       impl->_obj.attached[impl->_obj.attached_count] = att;
+       impl->_obj.attached_count++;
+       (**att)._unknown.AddRef ((struct gl2_unknown_intf **) att);
+       return GL_TRUE;
+}
+
+static GLboolean
+_container_Detach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
+       GLuint i, j;
+
+       for (i = 0; i < impl->_obj.attached_count; i++)
+               if (impl->_obj.attached[i] == att)
+               {
+                       for (j = i; j < impl->_obj.attached_count - 1; j++)
+                               impl->_obj.attached[j] = impl->_obj.attached[j + 1];
+                       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,
+                               impl->_obj.attached_count * sizeof (*impl->_obj.attached),
+                               (impl->_obj.attached_count - 1) * sizeof (*impl->_obj.attached));
+                       impl->_obj.attached_count--;
+                       (**att)._unknown.Release ((struct gl2_unknown_intf **) att);
+                       return GL_TRUE;
+               }
+
+       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Detach");
+       return GL_FALSE;
+}
+
+static GLsizei
+_container_GetAttachedCount (struct gl2_container_intf **intf)
+{
+       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
+
+       return impl->_obj.attached_count;
+}
+
+static struct gl2_generic_intf **
+_container_GetAttached (struct gl2_container_intf **intf, GLuint index)
+{
+       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;
+
+       (**impl->_obj.attached[index])._unknown.AddRef (
+               (struct gl2_unknown_intf **)impl->_obj.attached[index]);
+       return impl->_obj.attached[index];
+}
+
+static struct gl2_container_intf _container_vftbl = {
+       {
+               {
+                       _unknown_AddRef,
+                       _unknown_Release,
+                       _container_QueryInterface
+               },
+               _generic_Delete,
+               NULL,           /* abstract GetType */
+               _generic_GetName,
+               _generic_GetDeleteStatus,
+               _generic_GetInfoLog
+       },
+       _container_Attach,
+       _container_Detach,
+       _container_GetAttachedCount,
+       _container_GetAttached
+};
+
+static void
+_container_constructor (struct gl2_container_impl *impl)
+{
+       _generic_constructor ((struct gl2_generic_impl *) impl);
+       impl->_vftbl = &_container_vftbl;
+       impl->_obj._generic._unknown._destructor = _container_destructor;
+       impl->_obj.attached = NULL;
+       impl->_obj.attached_count = 0;
+}
+
+struct gl2_3dlabs_shhandle_obj
+{
+       struct gl2_unkinner_obj _unknown;
+#if USE_3DLABS_FRONTEND
+       ShHandle handle;
+#endif
+};
+
+struct gl2_3dlabs_shhandle_impl
+{
+       struct gl2_3dlabs_shhandle_intf *_vftbl;
+       struct gl2_3dlabs_shhandle_obj _obj;
+};
+
+static void
+_3dlabs_shhandle_destructor (struct gl2_unknown_intf **intf)
+{
+#if USE_3DLABS_FRONTEND
+       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;
+       ShDestruct (impl->_obj.handle);
+#endif
+       _unkinner_destructor (intf);
+}
+
+static GLvoid *
+_3dlabs_shhandle_GetShHandle (struct gl2_3dlabs_shhandle_intf **intf)
+{
+#if USE_3DLABS_FRONTEND
+       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;
+       return impl->_obj.handle;
+#else
+       return NULL;
+#endif
+}
+
+static struct gl2_3dlabs_shhandle_intf _3dlabs_shhandle_vftbl = {
+       {
+               _unkinner_AddRef,
+               _unkinner_Release,
+               _unkinner_QueryInterface
+       },
+       _3dlabs_shhandle_GetShHandle
+};
+
+static void
+_3dlabs_shhandle_constructor (struct gl2_3dlabs_shhandle_impl *impl, struct gl2_unknown_intf **outer)
+{
+       _unkinner_constructor ((struct gl2_unkinner_impl *) impl, outer);
+       impl->_vftbl = &_3dlabs_shhandle_vftbl;
+#if USE_3DLABS_FRONTEND
+       impl->_obj.handle = NULL;
+#endif
+}
+
+struct gl2_shader_obj
+{
+       struct gl2_generic_obj _generic;
+       struct gl2_3dlabs_shhandle_impl _3dlabs_shhandle;
+       GLboolean compile_status;
+       GLcharARB *source;
+       GLint *offsets;
+       GLsizei offset_count;
+       slang_translation_unit unit;
+};
+
+struct gl2_shader_impl
+{
+       struct gl2_shader_intf *_vftbl;
+       struct gl2_shader_obj _obj;
+};
+
+static void
+_shader_destructor (struct gl2_unknown_intf **intf)
+{
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+
+       _mesa_free ((void *) impl->_obj.source);
+       _mesa_free ((void *) impl->_obj.offsets);
+       _3dlabs_shhandle_destructor ((struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl);
+       _generic_destructor (intf);
+}
+
+static struct gl2_unknown_intf **
+_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+#if USE_3DLABS_FRONTEND
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+#endif
+
+       if (uiid == UIID_SHADER)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+#if USE_3DLABS_FRONTEND
+       if (uiid == UIID_3DLABS_SHHANDLE)
+       {
+               (**intf).AddRef (intf);
+               return (struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl;
+       }
+#endif
+       return _generic_QueryInterface (intf, uiid);
+}
+
+static GLenum
+_shader_GetType (struct gl2_generic_intf **intf)
+{
+       return GL_SHADER_OBJECT_ARB;
+}
+
+static GLboolean
+_shader_GetCompileStatus (struct gl2_shader_intf **intf)
+{
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+
+       return impl->_obj.compile_status;
+}
+
+static GLvoid
+_shader_SetSource (struct gl2_shader_intf **intf, GLcharARB *src, GLint *off, GLsizei cnt)
+{
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+
+       _mesa_free ((void *) impl->_obj.source);
+       impl->_obj.source = src;
+       _mesa_free ((void *) impl->_obj.offsets);
+       impl->_obj.offsets = off;
+       impl->_obj.offset_count = cnt;
+}
+
+static const GLcharARB *
+_shader_GetSource (struct gl2_shader_intf **intf)
+{
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+
+       return impl->_obj.source;
+}
+
+static GLvoid
+_shader_Compile (struct gl2_shader_intf **intf)
+{
+       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;
+#if USE_3DLABS_FRONTEND
+       char **strings;
+       TBuiltInResource res;
+#else
+       slang_unit_type type;
+       slang_info_log info_log;
+#endif
+
+       impl->_obj.compile_status = GL_FALSE;
+       _mesa_free ((void *) impl->_obj._generic.info_log);
+       impl->_obj._generic.info_log = NULL;
+
+#if USE_3DLABS_FRONTEND
+       /* 3dlabs compiler expects us to feed it with null-terminated string array,
+       we've got only one big string with offsets, so we must split it; but when
+       there's only one string to deal with, we pass its address directly */
+
+       if (impl->_obj.offset_count <= 1)
+               strings = &impl->_obj.source;
+       else
+       {
+               GLsizei i, offset = 0;
+
+               strings = (char **) _mesa_malloc (impl->_obj.offset_count * sizeof (char *));
+               if (strings == NULL)
+                       return;
+
+               for (i = 0; i < impl->_obj.offset_count; i++)
+               {
+                       GLsizei size = impl->_obj.offsets[i] - offset;
+
+                       strings[i] = (char *) _mesa_malloc ((size + 1) * sizeof (char));
+                       if (strings[i] == NULL)
+                       {
+                               GLsizei j;
+
+                               for (j = 0; j < i; j++)
+                                       _mesa_free (strings[j]);
+                               _mesa_free (strings);
+                               return;
+                       }
+
+                       _mesa_memcpy (strings[i], impl->_obj.source + offset, size * sizeof (char));
+                       strings[i][size] = '\0';
+                       offset = impl->_obj.offsets[i];
+               }
+       }
+
+       /* TODO set these fields to some REAL numbers */
+       res.maxLights = 8;
+       res.maxClipPlanes = 6;
+       res.maxTextureUnits = 2;
+       res.maxTextureCoords = 2;
+       res.maxVertexAttribs = 8;
+       res.maxVertexUniformComponents = 64;
+       res.maxVaryingFloats = 8;
+       res.maxVertexTextureImageUnits = 2;
+       res.maxCombinedTextureImageUnits = 2;
+       res.maxTextureImageUnits = 2;
+       res.maxFragmentUniformComponents = 64;
+       res.maxDrawBuffers = 1;
+
+       if (ShCompile (impl->_obj._3dlabs_shhandle._obj.handle, strings, impl->_obj.offset_count,
+                       EShOptFull, &res, 0))
+               impl->_obj.compile_status = GL_TRUE;
+       if (impl->_obj.offset_count > 1)
+       {
+               GLsizei i;
+
+               for (i = 0; i < impl->_obj.offset_count; i++)
+                       _mesa_free (strings[i]);
+               _mesa_free (strings);
+       }
+
+       impl->_obj._generic.info_log = _mesa_strdup (ShGetInfoLog (
+               impl->_obj._3dlabs_shhandle._obj.handle));
+#else
+       if (impl->_vftbl->GetSubType (intf) == GL_FRAGMENT_SHADER)
+               type = slang_unit_fragment_shader;
+       else
+               type = slang_unit_vertex_shader;
+       slang_info_log_construct (&info_log);
+       if (_slang_compile (impl->_obj.source, &impl->_obj.unit, type, &info_log))
+       {
+               impl->_obj.compile_status = GL_TRUE;
+       }
+       if (info_log.text != NULL)
+               impl->_obj._generic.info_log = _mesa_strdup (info_log.text);
+       else
+               impl->_obj._generic.info_log = _mesa_strdup ("");
+       slang_info_log_destruct (&info_log);
+#endif
+}
+
+static struct gl2_shader_intf _shader_vftbl = {
+       {
+               {
+                       _unknown_AddRef,
+                       _unknown_Release,
+                       _shader_QueryInterface
+               },
+               _generic_Delete,
+               _shader_GetType,
+               _generic_GetName,
+               _generic_GetDeleteStatus,
+               _generic_GetInfoLog
+       },
+       NULL,           /* abstract GetSubType */
+       _shader_GetCompileStatus,
+       _shader_SetSource,
+       _shader_GetSource,
+       _shader_Compile
+};
+
+static void
+_shader_constructor (struct gl2_shader_impl *impl)
+{
+       _generic_constructor ((struct gl2_generic_impl *) impl);
+       _3dlabs_shhandle_constructor (&impl->_obj._3dlabs_shhandle, (struct gl2_unknown_intf **)
+               &impl->_vftbl);
+       impl->_vftbl = &_shader_vftbl;
+       impl->_obj._generic._unknown._destructor = _shader_destructor;
+       impl->_obj.compile_status = GL_FALSE;
+       impl->_obj.source = NULL;
+       impl->_obj.offsets = NULL;
+       impl->_obj.offset_count = 0;
+}
+
+struct gl2_program_obj
+{
+       struct gl2_container_obj _container;
+       GLboolean link_status;
+       GLboolean validate_status;
+#if USE_3DLABS_FRONTEND
+       ShHandle linker;
+       ShHandle uniforms;
+#endif
+       slang_program prog;
+};
+
+struct gl2_program_impl
+{
+       struct gl2_program_intf *_vftbl;
+       struct gl2_program_obj _obj;
+};
+
+static void
+_program_destructor (struct gl2_unknown_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+#if USE_3DLABS_FRONTEND
+       ShDestruct (impl->_obj.linker);
+       ShDestruct (impl->_obj.uniforms);
+#endif
+       _container_destructor (intf);
+       slang_program_dtr (&impl->_obj.prog);
+}
+
+static struct gl2_unknown_intf **
+_program_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_PROGRAM)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return _container_QueryInterface (intf, uiid);
+}
+
+static GLenum
+_program_GetType (struct gl2_generic_intf **intf)
+{
+       return GL_PROGRAM_OBJECT_ARB;
+}
+
+static GLboolean
+_program_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_unknown_intf **sha;
+
+       sha = (**att)._unknown.QueryInterface ((struct gl2_unknown_intf **) att, UIID_SHADER);
+       if (sha == NULL)
+       {
+               _mesa_error (ctx, GL_INVALID_OPERATION, "_program_Attach");
+               return GL_FALSE;
+       }
+
+       (**sha).Release (sha);
+       return _container_Attach (intf, att);
+}
+
+static GLboolean
+_program_GetLinkStatus (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+
+       return impl->_obj.link_status;
+}
+
+static GLboolean
+_program_GetValidateStatus (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+
+       return impl->_obj.validate_status;
+}
+
+static GLvoid
+_program_Link (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+#if USE_3DLABS_FRONTEND
+       ShHandle *handles;
+#endif
+       GLuint i, count;
+       slang_translation_unit *units[2];
+
+       impl->_obj.link_status = GL_FALSE;
+       _mesa_free ((void *) impl->_obj._container._generic.info_log);
+       impl->_obj._container._generic.info_log = NULL;
+       slang_program_dtr (&impl->_obj.prog);
+       slang_program_ctr (&impl->_obj.prog);
+
+#if USE_3DLABS_FRONTEND
+       handles = (ShHandle *) _mesa_malloc (impl->_obj._container.attached_count * sizeof (ShHandle));
+       if (handles == NULL)
+               return;
+
+       for (i = 0; i < impl->_obj._container.attached_count; i++)
+       {
+               struct gl2_generic_intf **gen = impl->_obj._container.attached[i];
+               struct gl2_3dlabs_shhandle_intf **sh;
+
+               sh = (struct gl2_3dlabs_shhandle_intf **) (**gen)._unknown.QueryInterface (
+                       (struct gl2_unknown_intf **) gen, UIID_3DLABS_SHHANDLE);
+               if (sh != NULL)
+               {
+                       handles[i] = (**sh).GetShHandle (sh);
+                       (**sh)._unknown.Release ((struct gl2_unknown_intf **) sh);
+               }
+               else
+               {
+                       _mesa_free (handles);
+                       return;
+               }
+       }
+
+       if (ShLink (impl->_obj.linker, handles, impl->_obj._container.attached_count,
+                       impl->_obj.uniforms, NULL, NULL))
+               impl->_obj.link_status = GL_TRUE;
+
+       impl->_obj._container._generic.info_log = _mesa_strdup (ShGetInfoLog (impl->_obj.linker));
+#else
+       count = impl->_obj._container.attached_count;
+       if (count == 0 || count > 2)
+               return;
+       for (i = 0; i < count; i++)
+       {
+               struct gl2_generic_intf **obj;
+               struct gl2_unknown_intf **unk;
+               struct gl2_shader_impl *sha;
+
+               obj = impl->_obj._container.attached[i];
+               unk = (**obj)._unknown.QueryInterface ((struct gl2_unknown_intf **) obj, UIID_SHADER);
+               (**obj)._unknown.Release ((struct gl2_unknown_intf **) obj);
+               if (unk == NULL)
+                       return;
+               sha = (struct gl2_shader_impl *) unk;
+               units[i] = &sha->_obj.unit;
+               (**unk).Release (unk);
+       }
+
+       impl->_obj.link_status = _slang_link (&impl->_obj.prog, units, count);
+       if (impl->_obj.link_status)
+               impl->_obj._container._generic.info_log = _mesa_strdup ("Link OK.\n");
+       else
+               impl->_obj._container._generic.info_log = _mesa_strdup ("Link failed.\n");
+#endif
+}
+
+static GLvoid
+_program_Validate (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+
+       impl->_obj.validate_status = GL_FALSE;
+       _mesa_free ((void *) impl->_obj._container._generic.info_log);
+       impl->_obj._container._generic.info_log = NULL;
+
+       /* TODO validate */
+}
+
+static GLvoid
+write_common_fixed (slang_program *pro, GLuint index, const GLvoid *src, GLuint off, GLuint size)
+{
+       GLuint i;
+
+       for (i = 0; i < SLANG_SHADER_MAX; i++)
+       {
+               GLuint addr;
+
+               addr = pro->common_fixed_entries[i][index];
+               if (addr != ~0)
+               {
+                       GLubyte *dst;
+
+                       dst = (GLubyte *) pro->machines[i]->mem + addr + off * size;
+                       _mesa_memcpy (dst, src, size);
+               }
+       }
+}
+
+static GLvoid
+write_common_fixed_mat4 (slang_program *pro, GLmatrix *matrix, GLuint off, GLuint i, GLuint ii,
+                         GLuint it, GLuint iit)
+{
+       GLfloat mat[16];
+
+       /* we want inverse matrix */
+       if (!matrix->inv)
+       {
+               /* allocate inverse matrix and make it dirty */
+               _math_matrix_alloc_inv (matrix);
+               _math_matrix_loadf (matrix, matrix->m);
+       }
+       _math_matrix_analyse (matrix);
+
+       write_common_fixed (pro, i, matrix->m, off, 16 * sizeof (GLfloat));
+
+       /* inverse */
+       write_common_fixed (pro, ii, matrix->inv, off, 16 * sizeof (GLfloat));
+
+       /* transpose */
+       _math_transposef (mat, matrix->m);
+       write_common_fixed (pro, it, mat, off, 16 * sizeof (GLfloat));
+
+       /* inverse transpose */
+       _math_transposef (mat, matrix->inv);
+       write_common_fixed (pro, iit, mat, off, 16 * sizeof (GLfloat));
+}
+
+static GLvoid
+write_common_fixed_material (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e, GLuint a,
+                             GLuint d, GLuint sp, GLuint sh)
+{
+       GLfloat v[17];
+
+       COPY_4FV(v, ctx->Light.Material.Attrib[e]);
+       COPY_4FV((v + 4), ctx->Light.Material.Attrib[a]);
+       COPY_4FV((v + 8), ctx->Light.Material.Attrib[d]);
+       COPY_4FV((v + 12), ctx->Light.Material.Attrib[sp]);
+       v[16] = ctx->Light.Material.Attrib[sh][0];
+       write_common_fixed (pro, i, v, 0, 17 * sizeof (GLfloat));
+}
+
+static GLvoid
+write_common_fixed_light_model_product (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e,
+                                        GLuint a)
+{
+       GLfloat v[4];
+
+       SCALE_4V(v,     ctx->Light.Material.Attrib[a], ctx->Light.Model.Ambient);
+       ACC_4V(v, ctx->Light.Material.Attrib[e]);
+       write_common_fixed (pro, i, v, 0, 4 * sizeof (GLfloat));
+}
+
+static GLvoid
+write_common_fixed_light_product (GLcontext *ctx, slang_program *pro, GLuint off, GLuint i, GLuint a,
+                                  GLuint d, GLuint s)
+{
+       GLfloat v[12];
+
+       SCALE_4V(v, ctx->Light.Light[off].Ambient, ctx->Light.Material.Attrib[a]);
+       SCALE_4V((v + 4), ctx->Light.Light[off].Diffuse, ctx->Light.Material.Attrib[d]);
+       SCALE_4V((v + 8), ctx->Light.Light[off].Specular, ctx->Light.Material.Attrib[s]);
+       write_common_fixed (pro, i, v, off, 12 * sizeof (GLfloat));
+}
+
+static GLvoid
+_program_UpdateFixedUniforms (struct gl2_program_intf **intf)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+       GLuint i;
+       GLfloat v[29];
+       GLfloat *p;
+
+       /* MODELVIEW matrix */
+       write_common_fixed_mat4 (pro, ctx->ModelviewMatrixStack.Top, 0,
+               SLANG_COMMON_FIXED_MODELVIEWMATRIX,
+               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE,
+               SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE,
+               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE);
+
+       /* PROJECTION matrix */
+       write_common_fixed_mat4 (pro, ctx->ProjectionMatrixStack.Top, 0,
+               SLANG_COMMON_FIXED_PROJECTIONMATRIX,
+               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE,
+               SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE,
+               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE);
+
+       /* MVP matrix */
+       write_common_fixed_mat4 (pro, &ctx->_ModelProjectMatrix, 0,
+               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX,
+               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE,
+               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE,
+               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE);
+
+       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
+       {
+               /* TEXTURE matrix */
+               write_common_fixed_mat4 (pro, ctx->TextureMatrixStack[i].Top, i,
+                       SLANG_COMMON_FIXED_TEXTUREMATRIX,
+                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE,
+                       SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE,
+                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE);
+
+               /* EYE_PLANE texture-coordinate generation */
+               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANES, ctx->Texture.Unit[i].EyePlaneS,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANET, ctx->Texture.Unit[i].EyePlaneT,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANER, ctx->Texture.Unit[i].EyePlaneR,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANEQ, ctx->Texture.Unit[i].EyePlaneQ,
+                       i, 4 * sizeof (GLfloat));
+
+               /* OBJECT_PLANE texture-coordinate generation */
+               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANES, ctx->Texture.Unit[i].ObjectPlaneS,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANET, ctx->Texture.Unit[i].ObjectPlaneT,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANER, ctx->Texture.Unit[i].ObjectPlaneR,
+                       i, 4 * sizeof (GLfloat));
+               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANEQ, ctx->Texture.Unit[i].ObjectPlaneQ,
+                       i, 4 * sizeof (GLfloat));
+       }
+
+       /* NORMAL matrix - upper 3x3 inverse transpose of MODELVIEW matrix */
+       p = ctx->ModelviewMatrixStack.Top->inv;
+       v[0] = p[0];
+       v[1] = p[4];
+       v[2] = p[8];
+       v[3] = p[1];
+       v[4] = p[5];
+       v[5] = p[9];
+       v[6] = p[2];
+       v[7] = p[6];
+       v[8] = p[10];
+       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALMATRIX, v, 0, 9 * sizeof (GLfloat));
+
+       /* normal scale */
+       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALSCALE, &ctx->_ModelViewInvScale, 0, sizeof (GLfloat));
+
+       /* depth range parameters */
+       v[0] = ctx->Viewport.Near;
+       v[1] = ctx->Viewport.Far;
+       v[2] = ctx->Viewport.Far - ctx->Viewport.Near;
+       write_common_fixed (pro, SLANG_COMMON_FIXED_DEPTHRANGE, v, 0, 3 * sizeof (GLfloat));
+
+       /* CLIP_PLANEi */
+       for (i = 0; i < ctx->Const.MaxClipPlanes; i++)
+       {
+               write_common_fixed (pro, SLANG_COMMON_FIXED_CLIPPLANE, ctx->Transform.EyeUserPlane[i], i,
+                       4 * sizeof (GLfloat));
+       }
+
+       /* point parameters */
+       v[0] = ctx->Point.Size;
+       v[1] = ctx->Point.MinSize;
+       v[2] = ctx->Point.MaxSize;
+       v[3] = ctx->Point.Threshold;
+       COPY_3FV((v + 4), ctx->Point.Params);
+       write_common_fixed (pro, SLANG_COMMON_FIXED_POINT, v, 0, 7 * sizeof (GLfloat));
+
+       /* material parameters */
+       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_FRONTMATERIAL,
+               MAT_ATTRIB_FRONT_EMISSION,
+               MAT_ATTRIB_FRONT_AMBIENT,
+               MAT_ATTRIB_FRONT_DIFFUSE,
+               MAT_ATTRIB_FRONT_SPECULAR,
+               MAT_ATTRIB_FRONT_SHININESS);
+       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_BACKMATERIAL,
+               MAT_ATTRIB_BACK_EMISSION,
+               MAT_ATTRIB_BACK_AMBIENT,
+               MAT_ATTRIB_BACK_DIFFUSE,
+               MAT_ATTRIB_BACK_SPECULAR,
+               MAT_ATTRIB_BACK_SHININESS);
+
+       for (i = 0; i < ctx->Const.MaxLights; i++)
+       {
+               /* light source parameters */
+               COPY_4FV(v, ctx->Light.Light[i].Ambient);
+               COPY_4FV((v + 4), ctx->Light.Light[i].Diffuse);
+               COPY_4FV((v + 8), ctx->Light.Light[i].Specular);
+               COPY_4FV((v + 12), ctx->Light.Light[i].EyePosition);
+               COPY_2FV((v + 16), ctx->Light.Light[i].EyePosition);
+               v[18] = ctx->Light.Light[i].EyePosition[2] + 1.0f;
+               NORMALIZE_3FV((v + 16));
+               v[19] = 0.0f;
+               COPY_3V((v + 20), ctx->Light.Light[i].EyeDirection);
+               v[23] = ctx->Light.Light[i].SpotExponent;
+               v[24] = ctx->Light.Light[i].SpotCutoff;
+               v[25] = ctx->Light.Light[i]._CosCutoffNeg;
+               v[26] = ctx->Light.Light[i].ConstantAttenuation;
+               v[27] = ctx->Light.Light[i].LinearAttenuation;
+               v[28] = ctx->Light.Light[i].QuadraticAttenuation;
+               write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTSOURCE, v, i, 29 * sizeof (GLfloat));
+
+               /* light product */
+               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT,
+                       MAT_ATTRIB_FRONT_AMBIENT,
+                       MAT_ATTRIB_FRONT_DIFFUSE,
+                       MAT_ATTRIB_FRONT_SPECULAR);
+               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_BACKLIGHTPRODUCT,
+                       MAT_ATTRIB_BACK_AMBIENT,
+                       MAT_ATTRIB_BACK_DIFFUSE,
+                       MAT_ATTRIB_BACK_SPECULAR);
+       }
+
+       /* light model parameters */
+       write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTMODEL, ctx->Light.Model.Ambient, 0, 4 * sizeof (GLfloat));
+
+       /* light model product */
+       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT,
+               MAT_ATTRIB_FRONT_EMISSION,
+               MAT_ATTRIB_FRONT_AMBIENT);
+       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT,
+               MAT_ATTRIB_BACK_EMISSION,
+               MAT_ATTRIB_BACK_AMBIENT);
+
+       /* TEXTURE_ENV_COLOR */
+       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)
+       {
+               write_common_fixed (pro, SLANG_COMMON_FIXED_TEXTUREENVCOLOR, ctx->Texture.Unit[i].EnvColor,
+                       i, 4 * sizeof (GLfloat));
+       }
+
+       /* fog parameters */
+       COPY_4FV(v, ctx->Fog.Color);
+       v[4] = ctx->Fog.Density;
+       v[5] = ctx->Fog.Start;
+       v[6] = ctx->Fog.End;
+       v[7] = ctx->Fog._Scale;
+       write_common_fixed (pro, SLANG_COMMON_FIXED_FOG, v, 0, 8 * sizeof (GLfloat));
+}
+
+static GLvoid
+_program_UpdateFixedAttribute (struct gl2_program_intf **intf, GLuint index, GLvoid *data,
+                               GLuint offset, GLuint size, GLboolean write)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+       GLuint addr;
+
+       addr = pro->vertex_fixed_entries[index];
+       if (addr != ~0)
+       {
+               GLubyte *mem;
+
+               mem = (GLubyte *) pro->machines[SLANG_SHADER_VERTEX]->mem + addr + offset * size;
+               if (write)
+                       _mesa_memcpy (mem, data, size);
+               else
+                       _mesa_memcpy (data, mem, size);
+       }
+}
+
+static GLvoid
+_program_UpdateFixedVarying (struct gl2_program_intf **intf, GLuint index, GLvoid *data,
+                             GLuint offset, GLuint size, GLboolean write)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+       GLuint addr;
+
+       addr = pro->fragment_fixed_entries[index];
+       if (addr != ~0)
+       {
+               GLubyte *mem;
+
+               mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + offset * size;
+               if (write)
+                       _mesa_memcpy (mem, data, size);
+               else
+                       _mesa_memcpy (data, mem, size);
+       }
+}
+
+static GLvoid
+_program_GetTextureImageUsage (struct gl2_program_intf **intf, GLbitfield *teximageusage)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+       GLuint i;
+
+       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)
+               teximageusage[i] = 0;
+
+       for (i = 0; i < pro->texture_usage.count; i++)
+       {
+               GLuint n, addr, j;
+
+               n = slang_export_data_quant_elements (pro->texture_usage.table[i].quant);
+               addr = pro->texture_usage.table[i].frag_address;
+               for (j = 0; j < n; j++)
+               {
+                       GLubyte *mem;
+                       GLuint image;
+
+                       mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + j * 4;
+                       image = (GLuint) *((GLfloat *) mem);
+                       if (image >= 0 && image < ctx->Const.MaxTextureImageUnits)
+                       {
+                               switch (slang_export_data_quant_type (pro->texture_usage.table[i].quant))
+                               {
+                               case GL_SAMPLER_1D_ARB:
+                               case GL_SAMPLER_1D_SHADOW_ARB:
+                                       teximageusage[image] |= TEXTURE_1D_BIT;
+                                       break;
+                               case GL_SAMPLER_2D_ARB:
+                               case GL_SAMPLER_2D_SHADOW_ARB:
+                                       teximageusage[image] |= TEXTURE_2D_BIT;
+                                       break;
+                               case GL_SAMPLER_3D_ARB:
+                                       teximageusage[image] |= TEXTURE_3D_BIT;
+                                       break;
+                               case GL_SAMPLER_CUBE_ARB:
+                                       teximageusage[image] |= TEXTURE_CUBE_BIT;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* TODO: make sure that for 0<=i<=MaxTextureImageUint bitcount(teximageuint[i])<=0 */
+}
+
+static GLboolean
+_program_IsShaderPresent (struct gl2_program_intf **intf, GLenum subtype)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+
+       switch (subtype)
+       {
+       case GL_VERTEX_SHADER_ARB:
+               return pro->machines[SLANG_SHADER_VERTEX] != NULL;
+       case GL_FRAGMENT_SHADER_ARB:
+               return pro->machines[SLANG_SHADER_FRAGMENT] != NULL;
+       default:
+               return GL_FALSE;
+       }
+}
+
+static GLvoid
+get_active_variable (slang_active_variable *var, GLsizei maxLength, GLsizei *length, GLint *size,
+                     GLenum *type, GLchar *name)
+{
+       GLsizei len;
+
+       len = _mesa_strlen (var->name);
+       if (len >= maxLength)
+               len = maxLength - 1;
+       if (length != NULL)
+               *length = len;
+       *size = slang_export_data_quant_elements (var->quant);
+       *type = slang_export_data_quant_type (var->quant);
+       _mesa_memcpy (name, var->name, len);
+       name[len] = '\0';
+}
+
+static GLuint
+get_active_variable_max_length (slang_active_variables *vars)
+{
+       GLuint i, len = 0;
+
+       for (i = 0; i < vars->count; i++)
+       {
+               GLuint n = _mesa_strlen (vars->table[i].name);
+               if (n > len)
+                       len = n;
+       }
+       return len;
+}
+
+static GLvoid
+_program_GetActiveUniform (struct gl2_program_intf **intf, GLuint index, GLsizei maxLength,
+                           GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_active_variable *u = &impl->_obj.prog.active_uniforms.table[index];
+
+       get_active_variable (u, maxLength, length, size, type, name);
+}
+
+static GLuint
+_program_GetActiveUniformMaxLength (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+
+       return get_active_variable_max_length (&impl->_obj.prog.active_uniforms);
+}
+
+static GLuint
+_program_GetActiveUniformCount (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+
+       return impl->_obj.prog.active_uniforms.count;
+}
+
+static GLint
+_program_GetUniformLocation (struct gl2_program_intf **intf, const GLchar *name)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_uniform_bindings *bind = &impl->_obj.prog.uniforms;
+       GLuint i;
+
+       for (i = 0; i < bind->count; i++)
+               if (_mesa_strcmp (bind->table[i].name, name) == 0)
+                       return i;
+       return -1;
+}
+
+static GLboolean
+_program_WriteUniform (struct gl2_program_intf **intf, GLint loc, GLsizei count, const GLvoid *data,
+                       GLenum type)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_uniform_bindings *uniforms = &impl->_obj.prog.uniforms;
+       slang_uniform_binding *uniform;
+       GLuint i;
+       GLboolean convert_float_to_bool = GL_FALSE;
+       GLboolean convert_int_to_bool = GL_FALSE;
+       GLboolean convert_int_to_float = GL_FALSE;
+       GLboolean types_match = GL_FALSE;
+
+       if (loc == -1)
+               return GL_TRUE;
+       if (loc >= uniforms->count)
+               return GL_FALSE;
+
+       uniform = &uniforms->table[loc];
+       /* TODO: check sizes */
+       if (slang_export_data_quant_struct (uniform->quant))
+               return GL_FALSE;
+
+       switch (slang_export_data_quant_type (uniform->quant))
+       {
+       case GL_BOOL_ARB:
+               types_match = (type == GL_FLOAT) || (type == GL_INT);
+               if (type == GL_FLOAT)
+                       convert_float_to_bool = GL_TRUE;
+               else
+                       convert_int_to_bool = GL_TRUE;
+               break;
+       case GL_BOOL_VEC2_ARB:
+               types_match = (type == GL_FLOAT_VEC2_ARB) || (type == GL_INT_VEC2_ARB);
+               if (type == GL_FLOAT_VEC2_ARB)
+                       convert_float_to_bool = GL_TRUE;
+               else
+                       convert_int_to_bool = GL_TRUE;
+               break;
+       case GL_BOOL_VEC3_ARB:
+               types_match = (type == GL_FLOAT_VEC3_ARB) || (type == GL_INT_VEC3_ARB);
+               if (type == GL_FLOAT_VEC3_ARB)
+                       convert_float_to_bool = GL_TRUE;
+               else
+                       convert_int_to_bool = GL_TRUE;
+               break;
+       case GL_BOOL_VEC4_ARB:
+               types_match = (type == GL_FLOAT_VEC4_ARB) || (type == GL_INT_VEC4_ARB);
+               if (type == GL_FLOAT_VEC4_ARB)
+                       convert_float_to_bool = GL_TRUE;
+               else
+                       convert_int_to_bool = GL_TRUE;
+               break;
+       case GL_SAMPLER_1D_ARB:
+       case GL_SAMPLER_2D_ARB:
+       case GL_SAMPLER_3D_ARB:
+       case GL_SAMPLER_CUBE_ARB:
+       case GL_SAMPLER_1D_SHADOW_ARB:
+       case GL_SAMPLER_2D_SHADOW_ARB:
+               types_match = (type == GL_INT);
+               break;
+       default:
+               types_match = (type == slang_export_data_quant_type (uniform->quant));
+               break;
+       }
+
+       if (!types_match)
+               return GL_FALSE;
+
+       switch (type)
+       {
+       case GL_INT:
+       case GL_INT_VEC2_ARB:
+       case GL_INT_VEC3_ARB:
+       case GL_INT_VEC4_ARB:
+               convert_int_to_float = GL_TRUE;
+               break;
+       }
+
+       if (convert_float_to_bool)
+       {
+               for (i = 0; i < SLANG_SHADER_MAX; i++)
+                       if (uniform->address[i] != ~0)
+                       {
+                               const GLfloat *src = (GLfloat *) (data);
+                               GLfloat *dst = (GLfloat *)
+                                       (&impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4]);
+                               GLuint j;
+                               GLuint total = count * slang_export_data_quant_components (uniform->quant);
+
+                               for (j = 0; j < total; j++)
+                                       dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;
+                       }
+       }
+       else if (convert_int_to_bool)
+       {
+               for (i = 0; i < SLANG_SHADER_MAX; i++)
+                       if (uniform->address[i] != ~0)
+                       {
+                               const GLuint *src = (GLuint *) (data);
+                               GLfloat *dst = (GLfloat *)
+                                       (&impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4]);
+                               GLuint j;
+                               GLuint total = count * slang_export_data_quant_components (uniform->quant);
+
+                               for (j = 0; j < total; j++)
+                                       dst[j] = src[j] ? 1.0f : 0.0f;
+                       }
+       }
+       else if (convert_int_to_float)
+       {
+               for (i = 0; i < SLANG_SHADER_MAX; i++)
+                       if (uniform->address[i] != ~0)
+                       {
+                               const GLuint *src = (GLuint *) (data);
+                               GLfloat *dst = (GLfloat *)
+                                       (&impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4]);
+                               GLuint j;
+                               GLuint total = count * slang_export_data_quant_components (uniform->quant);
+
+                               for (j = 0; j < total; j++)
+                                       dst[j] = (GLfloat) src[j];
+                       }
+       }
+       else
+       {
+               for (i = 0; i < SLANG_SHADER_MAX; i++)
+                       if (uniform->address[i] != ~0)
+                       {
+                               _mesa_memcpy (&impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4], data,
+                                       count * slang_export_data_quant_size (uniform->quant));
+                       }
+       }
+       return GL_TRUE;
+}
+
+static GLvoid
+_program_GetActiveAttrib (struct gl2_program_intf **intf, GLuint index, GLsizei maxLength,
+                          GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_active_variable *a = &impl->_obj.prog.active_attribs.table[index];
+
+       get_active_variable (a, maxLength, length, size, type, name);
+}
+
+static GLuint
+_program_GetActiveAttribMaxLength (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+
+       return get_active_variable_max_length (&impl->_obj.prog.active_attribs);
+}
+
+static GLuint
+_program_GetActiveAttribCount (struct gl2_program_intf **intf)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+
+       return impl->_obj.prog.active_attribs.count;
+}
+
+static GLint
+_program_GetAttribLocation (struct gl2_program_intf **intf, const GLchar *name)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_attrib_bindings *attribs = &impl->_obj.prog.attribs;
+       GLuint i;
+
+       for (i = 0; i < attribs->binding_count; i++)
+               if (_mesa_strcmp (attribs->bindings[i].name, name) == 0)
+                       return attribs->bindings[i].first_slot_index;
+       return -1;
+}
+
+static GLvoid
+_program_OverrideAttribBinding (struct gl2_program_intf **intf, GLuint index, const GLchar *name)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+       slang_program *pro = &impl->_obj.prog;
+
+       if (!slang_attrib_overrides_add (&pro->attrib_overrides, index, name))
+               _mesa_error (ctx, GL_OUT_OF_MEMORY, "_program_OverrideAttribBinding");
+}
+
+static GLvoid
+_program_UpdateVarying (struct gl2_program_intf **intf, GLuint index, GLfloat *value,
+                        GLboolean vert)
+{
+       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
+       slang_program *pro = &impl->_obj.prog;
+       GLuint addr;
+
+       if (index >= pro->varyings.slot_count)
+               return;
+       if (vert)
+               addr = pro->varyings.slots[index].vert_addr / 4;
+       else
+               addr = pro->varyings.slots[index].frag_addr / 4;
+       if (addr != ~0)
+       {
+               if (vert)
+                       *value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float;
+               else
+                       pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value;
+       }
+}
+
+static struct gl2_program_intf _program_vftbl = {
+       {
+               {
+                       {
+                               _unknown_AddRef,
+                               _unknown_Release,
+                               _program_QueryInterface
+                       },
+                       _generic_Delete,
+                       _program_GetType,
+                       _generic_GetName,
+                       _generic_GetDeleteStatus,
+                       _generic_GetInfoLog
+               },
+               _program_Attach,
+               _container_Detach,
+               _container_GetAttachedCount,
+               _container_GetAttached
+       },
+       _program_GetLinkStatus,
+       _program_GetValidateStatus,
+       _program_Link,
+       _program_Validate,
+       _program_UpdateFixedUniforms,
+       _program_UpdateFixedAttribute,
+       _program_UpdateFixedVarying,
+       _program_GetTextureImageUsage,
+       _program_IsShaderPresent,
+       _program_GetActiveUniform,
+       _program_GetActiveUniformMaxLength,
+       _program_GetActiveUniformCount,
+       _program_GetUniformLocation,
+       _program_WriteUniform,
+       _program_GetActiveAttrib,
+       _program_GetActiveAttribMaxLength,
+       _program_GetActiveAttribCount,
+       _program_GetAttribLocation,
+       _program_OverrideAttribBinding,
+       _program_UpdateVarying  
+};
+
+static void
+_program_constructor (struct gl2_program_impl *impl)
+{
+       _container_constructor ((struct gl2_container_impl *) impl);
+       impl->_vftbl = &_program_vftbl;
+       impl->_obj._container._generic._unknown._destructor = _program_destructor;
+       impl->_obj.link_status = GL_FALSE;
+       impl->_obj.validate_status = GL_FALSE;
+#if USE_3DLABS_FRONTEND
+       impl->_obj.linker = ShConstructLinker (EShExVertexFragment, 0);
+       impl->_obj.uniforms = ShConstructUniformMap ();
+#endif
+       slang_program_ctr (&impl->_obj.prog);
+}
+
+struct gl2_fragment_shader_obj
+{
+       struct gl2_shader_obj _shader;
+};
+
+struct gl2_fragment_shader_impl
+{
+       struct gl2_fragment_shader_intf *_vftbl;
+       struct gl2_fragment_shader_obj _obj;
+};
+
+static void
+_fragment_shader_destructor (struct gl2_unknown_intf **intf)
+{
+       struct gl2_fragment_shader_impl *impl = (struct gl2_fragment_shader_impl *) intf;
+
+       (void) impl;
+       /* TODO free fragment shader data */
+
+       _shader_destructor (intf);
+}
+
+static struct gl2_unknown_intf **
+_fragment_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_FRAGMENT_SHADER)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return _shader_QueryInterface (intf, uiid);
+}
+
+static GLenum
+_fragment_shader_GetSubType (struct gl2_shader_intf **intf)
+{
+       return GL_FRAGMENT_SHADER_ARB;
+}
+
+static struct gl2_fragment_shader_intf _fragment_shader_vftbl = {
+       {
+               {
+                       {
+                               _unknown_AddRef,
+                               _unknown_Release,
+                               _fragment_shader_QueryInterface
+                       },
+                       _generic_Delete,
+                       _shader_GetType,
+                       _generic_GetName,
+                       _generic_GetDeleteStatus,
+                       _generic_GetInfoLog
+               },
+               _fragment_shader_GetSubType,
+               _shader_GetCompileStatus,
+               _shader_SetSource,
+               _shader_GetSource,
+               _shader_Compile
+       }
+};
+
+static void
+_fragment_shader_constructor (struct gl2_fragment_shader_impl *impl)
+{
+       _shader_constructor ((struct gl2_shader_impl *) impl);
+       impl->_vftbl = &_fragment_shader_vftbl;
+       impl->_obj._shader._generic._unknown._destructor = _fragment_shader_destructor;
+#if USE_3DLABS_FRONTEND
+       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangFragment, 0);
+#endif
+}
+
+struct gl2_vertex_shader_obj
+{
+       struct gl2_shader_obj _shader;
+};
+
+struct gl2_vertex_shader_impl
+{
+       struct gl2_vertex_shader_intf *_vftbl;
+       struct gl2_vertex_shader_obj _obj;
+};
+
+static void
+_vertex_shader_destructor (struct gl2_unknown_intf **intf)
+{
+       struct gl2_vertex_shader_impl *impl = (struct gl2_vertex_shader_impl *) intf;
+
+       (void) impl;
+       /* TODO free vertex shader data */
+
+       _shader_destructor (intf);
+}
+
+static struct gl2_unknown_intf **
+_vertex_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+       if (uiid == UIID_VERTEX_SHADER)
+       {
+               (**intf).AddRef (intf);
+               return intf;
+       }
+       return _shader_QueryInterface (intf, uiid);
+}
+
+static GLenum
+_vertex_shader_GetSubType (struct gl2_shader_intf **intf)
+{
+       return GL_VERTEX_SHADER_ARB;
+}
+
+static struct gl2_vertex_shader_intf _vertex_shader_vftbl = {
+       {
+               {
+                       {
+                               _unknown_AddRef,
+                               _unknown_Release,
+                               _vertex_shader_QueryInterface
+                       },
+                       _generic_Delete,
+                       _shader_GetType,
+                       _generic_GetName,
+                       _generic_GetDeleteStatus,
+                       _generic_GetInfoLog
+               },
+               _vertex_shader_GetSubType,
+               _shader_GetCompileStatus,
+               _shader_SetSource,
+               _shader_GetSource,
+               _shader_Compile
+       }
+};
+
+static void
+_vertex_shader_constructor (struct gl2_vertex_shader_impl *impl)
+{
+       _shader_constructor ((struct gl2_shader_impl *) impl);
+       impl->_vftbl = &_vertex_shader_vftbl;
+       impl->_obj._shader._generic._unknown._destructor = _vertex_shader_destructor;
+#if USE_3DLABS_FRONTEND
+       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangVertex, 0);
+#endif
+}
+
+GLhandleARB
+_mesa_3dlabs_create_shader_object (GLenum shaderType)
+{
+       switch (shaderType)
+       {
+       case GL_FRAGMENT_SHADER_ARB:
+               {
+                       struct gl2_fragment_shader_impl *x = (struct gl2_fragment_shader_impl *)
+                               _mesa_malloc (sizeof (struct gl2_fragment_shader_impl));
+
+                       if (x != NULL)
+                       {
+                               _fragment_shader_constructor (x);
+                               return x->_obj._shader._generic.name;
+                       }
+               }
+               break;
+       case GL_VERTEX_SHADER_ARB:
+               {
+                       struct gl2_vertex_shader_impl *x = (struct gl2_vertex_shader_impl *)
+                               _mesa_malloc (sizeof (struct gl2_vertex_shader_impl));
+
+                       if (x != NULL)
+                       {
+                               _vertex_shader_constructor (x);
+                               return x->_obj._shader._generic.name;
+                       }
+               }
+               break;
+       }
+
+       return 0;
+}
+
+GLhandleARB
+_mesa_3dlabs_create_program_object (void)
+{
+       struct gl2_program_impl *x = (struct gl2_program_impl *) 
+               _mesa_malloc (sizeof (struct gl2_program_impl));
+
+       if (x != NULL)
+       {
+               _program_constructor (x);
+               return x->_obj._container._generic.name;
+       }
+
+       return 0;
+}
+
+#include "slang_assemble.h"
+#include "slang_execute.h"
+
+int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val)
+{
+       struct gl2_program_impl *impl;
+
+       impl = (struct gl2_program_impl *) pro;
+       *val = impl->_obj.prog.machines[SLANG_SHADER_FRAGMENT]->kill ? GL_TRUE : GL_FALSE;
+       return 1;
+}
+
+static GLvoid exec_shader (struct gl2_program_intf **pro, GLuint i)
+{
+       struct gl2_program_impl *impl;
+       slang_program *p;
+
+       impl = (struct gl2_program_impl *) pro;
+       p = &impl->_obj.prog;
+
+       slang_machine_init (p->machines[i]);
+       p->machines[i]->ip = p->code[i][SLANG_COMMON_CODE_MAIN];
+
+       _slang_execute2 (p->assemblies[i], p->machines[i]);
+}
+
+GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro)
+{
+       exec_shader (pro, SLANG_SHADER_FRAGMENT);
+}
+
+GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro)
+{
+       exec_shader (pro, SLANG_SHADER_VERTEX);
+}
+
+void
+_mesa_init_shaderobjects_3dlabs (GLcontext *ctx)
+{
+#if USE_3DLABS_FRONTEND
+       _glslang_3dlabs_InitProcess ();
+       _glslang_3dlabs_ShInitialize ();
+#endif
+}
+
index d82079d8f31a142e421b154ed918da1554d3f354..8bf273ae9d75dfb9b1b8749d573c2ef97de4d081 100755 (executable)
@@ -1,56 +1,44 @@
-/*\r
- * Mesa 3-D graphics library\r
- * Version:  6.5\r
- *\r
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-#ifndef SHADEROBJECTS_3DLABS_H\r
-#define SHADEROBJECTS_3DLABS_H\r
-\r
-extern int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val);\r
-\r
-extern GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro);\r
-\r
-extern GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro);\r
-\r
-extern GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name);\r
-\r
-extern GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count,\r
-       const GLvoid *data, GLenum type);\r
-\r
-extern GLuint _slang_get_active_uniform_count (struct gl2_program_intf **pro);\r
-\r
-extern GLuint _slang_get_active_uniform_max_length (struct gl2_program_intf **pro);\r
-\r
-extern GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, GLsizei maxLength,\r
-       GLsizei *length, GLint *size, GLenum *type, char *name);\r
-\r
-extern GLhandleARB\r
-_mesa_3dlabs_create_shader_object (GLenum);\r
-\r
-extern GLhandleARB\r
-_mesa_3dlabs_create_program_object (GLvoid);\r
-\r
-extern void\r
-_mesa_init_shaderobjects_3dlabs (GLcontext *ctx);\r
-\r
-#endif\r
-\r
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SHADEROBJECTS_3DLABS_H
+#define SHADEROBJECTS_3DLABS_H
+
+extern int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val);
+
+extern GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro);
+
+extern GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro);
+
+extern GLhandleARB
+_mesa_3dlabs_create_shader_object (GLenum);
+
+extern GLhandleARB
+_mesa_3dlabs_create_program_object (GLvoid);
+
+extern void
+_mesa_init_shaderobjects_3dlabs (GLcontext *ctx);
+
+#endif
+
index 515c03fb6412053e0ebda5ad35bf064185c25c53..dcf64244b7485ccc1ba11ff320eb1741c9839d50 100644 (file)
@@ -79,6 +79,11 @@ GLboolean slang_export_data_quant_struct (slang_export_data_quant *self)
        return self->structure != NULL;\r
 }\r
 \r
+GLboolean slang_export_data_quant_simple (slang_export_data_quant *self)\r
+{\r
+       return self->array_len == 0 && self->structure == NULL;\r
+}\r
+\r
 GLenum slang_export_data_quant_type (slang_export_data_quant *self)\r
 {\r
        assert (self->structure == NULL);\r
index c158eb444318be7f6ec039020d57532b94d00360..aaf00773c1ea1698080f43f080d1772a1301a4d7 100644 (file)
@@ -68,6 +68,11 @@ GLboolean slang_export_data_quant_array (slang_export_data_quant *);
  */\r
 GLboolean slang_export_data_quant_struct (slang_export_data_quant *);\r
 \r
+/*\r
+ * Returns GL_TRUE if the quant is neither an array nor a structure.\r
+ */\r
+GLboolean slang_export_data_quant_simple (slang_export_data_quant *);\r
+\r
 /*\r
  * Returns basic type of the quant. It must not be a structure.\r
  */\r
@@ -81,7 +86,7 @@ GLuint slang_export_data_quant_fields (slang_export_data_quant *);
 /*\r
  * Return number of elements in the quant.\r
  * For arrays, return the size of the array.\r
- * For scalars, return 1.\r
+ * Otherwise, return 1.\r
  */\r
 GLuint slang_export_data_quant_elements (slang_export_data_quant *);\r
 \r
index a72ec2eaa0bf9f27862edf820c7428923e9891b1..9d61a29e9128e24006e579f55b9928463d48c488 100644 (file)
 #include "slang_link.h"\r
 #include "slang_analyse.h"\r
 \r
+static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms)\r
+{\r
+       const char *str = slang_atom_pool_id (atoms, name);\r
+       return str[0] == 'g' && str[1] == 'l' && str[2] == '_';\r
+}\r
+\r
+/*\r
+ * slang_active_variables\r
+ */\r
+\r
+static GLvoid slang_active_variables_ctr (slang_active_variables *self)\r
+{\r
+       self->table = NULL;\r
+       self->count = 0;\r
+}\r
+\r
+static GLvoid slang_active_variables_dtr (slang_active_variables *self)\r
+{\r
+       GLuint i;\r
+\r
+       for (i = 0; i < self->count; i++)\r
+               slang_alloc_free (self->table[i].name);\r
+       slang_alloc_free (self->table);\r
+}\r
+\r
+static GLboolean add_simple_variable (slang_active_variables *self, slang_export_data_quant *q,\r
+       const char *name)\r
+{\r
+       const GLuint n = self->count;\r
+\r
+       self->table = (slang_active_variable *) slang_alloc_realloc (self->table,\r
+               n * sizeof (slang_active_variable), (n + 1) * sizeof (slang_active_variable));\r
+       if (self->table == NULL)\r
+               return GL_FALSE;\r
+\r
+       self->table[n].quant = q;\r
+       self->table[n].name = slang_string_duplicate (name);\r
+       if (self->table[n].name == NULL)\r
+               return GL_FALSE;\r
+       self->count++;\r
+\r
+       return GL_TRUE;\r
+}\r
+\r
+static GLboolean add_complex_variable (slang_active_variables *self, slang_export_data_quant *q,\r
+       char *name, slang_atom_pool *atoms)\r
+{\r
+       slang_string_concat (name, slang_atom_pool_id (atoms, q->name));\r
+       if (slang_export_data_quant_array (q))\r
+               slang_string_concat (name, "[0]");\r
+\r
+       if (slang_export_data_quant_struct (q))\r
+       {\r
+               GLuint dot_pos, i;\r
+               const GLuint fields = slang_export_data_quant_fields (q);\r
+\r
+               slang_string_concat (name, ".");\r
+               dot_pos = slang_string_length (name);\r
+\r
+               for (i = 0; i < fields; i++)\r
+               {\r
+                       if (!add_complex_variable (self, &q->structure[i], name, atoms))\r
+                               return GL_FALSE;\r
+\r
+                       name[dot_pos] = '\0';\r
+               }\r
+\r
+               return GL_TRUE;\r
+       }\r
+\r
+       return add_simple_variable (self, q, name);\r
+}\r
+\r
+static GLboolean gather_active_variables (slang_active_variables *self,\r
+       slang_export_data_table *tbl, slang_export_data_access access)\r
+{\r
+       GLuint i;\r
+\r
+       for (i = 0; i < tbl->count; i++)\r
+               if (tbl->entries[i].access == access)\r
+               {\r
+                       char name[1024] = "";\r
+\r
+                       if (!add_complex_variable (self, &tbl->entries[i].quant, name, tbl->atoms))\r
+                               return GL_FALSE;\r
+               }\r
+\r
+       return GL_TRUE;\r
+}\r
+\r
+/*\r
+ * slang_attrib_overrides\r
+ */\r
+\r
+static GLvoid slang_attrib_overrides_ctr (slang_attrib_overrides *self)\r
+{\r
+       self->table = NULL;\r
+       self->count = 0;\r
+}\r
+\r
+static GLvoid slang_attrib_overrides_dtr (slang_attrib_overrides *self)\r
+{\r
+       GLuint i;\r
+\r
+       for (i = 0; i < self->count; i++)\r
+               slang_alloc_free (self->table[i].name);\r
+       slang_alloc_free (self->table);\r
+}\r
+\r
+GLboolean slang_attrib_overrides_add (slang_attrib_overrides *self, GLuint index, const GLchar *name)\r
+{\r
+       const GLuint n = self->count;\r
+       GLuint i;\r
+\r
+       for (i = 0; i < n; i++)\r
+               if (slang_string_compare (name, self->table[i].name) == 0)\r
+               {\r
+                       self->table[i].index = index;\r
+                       return GL_TRUE;\r
+               }\r
+\r
+       self->table = (slang_attrib_override *) slang_alloc_realloc (self->table,\r
+               n * sizeof (slang_attrib_override), (n + 1) * sizeof (slang_attrib_override));\r
+       if (self->table == NULL)\r
+               return GL_FALSE;\r
+\r
+       self->table[n].index = index;\r
+       self->table[n].name = slang_string_duplicate (name);\r
+       if (self->table[n].name == NULL)\r
+               return GL_FALSE;\r
+       self->count++;\r
+\r
+       return GL_TRUE;\r
+}\r
+\r
+static GLuint lookup_attrib_override (slang_attrib_overrides *self, const GLchar *name)\r
+{\r
+       GLuint i;\r
+\r
+       for (i = 0; self->count; i++)\r
+               if (slang_string_compare (name, self->table[i].name) == 0)\r
+                       return self->table[i].index;\r
+       return MAX_VERTEX_ATTRIBS;\r
+}\r
+\r
 /*\r
  * slang_uniform_bindings\r
  */\r
@@ -51,8 +196,8 @@ static GLvoid slang_uniform_bindings_dtr (slang_uniform_bindings *self)
        slang_alloc_free (self->table);\r
 }\r
 \r
-static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang_export_data_quant *q,\r
-       const char *name, GLuint index, GLuint address)\r
+static GLboolean add_simple_uniform_binding (slang_uniform_bindings *self,\r
+       slang_export_data_quant *q, const char *name, GLuint index, GLuint addr)\r
 {\r
        const GLuint n = self->count;\r
        GLuint i;\r
@@ -60,7 +205,7 @@ static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang
        for (i = 0; i < n; i++)\r
                if (slang_string_compare (self->table[i].name, name) == 0)\r
                {\r
-                       self->table[i].address[index] = address;\r
+                       self->table[i].address[index] = addr;\r
                        return GL_TRUE;\r
                }\r
 \r
@@ -68,19 +213,21 @@ static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang
                n * sizeof (slang_uniform_binding), (n + 1) * sizeof (slang_uniform_binding));\r
        if (self->table == NULL)\r
                return GL_FALSE;\r
+\r
        self->table[n].quant = q;\r
        self->table[n].name = slang_string_duplicate (name);\r
-       for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-               self->table[n].address[i] = ~0;\r
-       self->table[n].address[index] = address;\r
        if (self->table[n].name == NULL)\r
                return GL_FALSE;\r
+       for (i = 0; i < SLANG_SHADER_MAX; i++)\r
+               self->table[n].address[i] = ~0;\r
+       self->table[n].address[index] = addr;\r
        self->count++;\r
+\r
        return GL_TRUE;\r
 }\r
 \r
-static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,\r
-       char *name, slang_atom_pool *atoms, GLuint index, GLuint addr)\r
+static GLboolean add_complex_uniform_binding (slang_uniform_bindings *self,\r
+       slang_export_data_quant *q, char *name, slang_atom_pool *atoms, GLuint index, GLuint addr)\r
 {\r
        GLuint count, i;\r
 \r
@@ -88,41 +235,44 @@ static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_exp
        count = slang_export_data_quant_elements (q);\r
        for (i = 0; i < count; i++)\r
        {\r
-               GLuint save;\r
+               GLuint bracket_pos;\r
 \r
-               save = slang_string_length (name);\r
+               bracket_pos = slang_string_length (name);\r
                if (slang_export_data_quant_array (q))\r
                        _mesa_sprintf (name + slang_string_length (name), "[%d]", i);\r
 \r
                if (slang_export_data_quant_struct (q))\r
                {\r
-                       GLuint save, i;\r
+                       GLuint dot_pos, i;\r
                        const GLuint fields = slang_export_data_quant_fields (q);\r
 \r
                        slang_string_concat (name, ".");\r
-                       save = slang_string_length (name);\r
+                       dot_pos = slang_string_length (name);\r
 \r
                        for (i = 0; i < fields; i++)\r
                        {\r
-                               if (!insert_uniform_binding (bind, &q->structure[i], name, atoms, index, addr))\r
+                               if (!add_complex_uniform_binding (self, &q->structure[i], name, atoms, index, addr))\r
                                        return GL_FALSE;\r
-                               name[save] = '\0';\r
+\r
+                               name[dot_pos] = '\0';\r
                                addr += slang_export_data_quant_size (&q->structure[i]);\r
                        }\r
                }\r
                else\r
                {\r
-                       if (!slang_uniform_bindings_add (bind, q, name, index, addr))\r
+                       if (!add_simple_uniform_binding (self, q, name, index, addr))\r
                                return GL_FALSE;\r
+\r
                        addr += slang_export_data_quant_size (q);\r
                }\r
-               name[save] = '\0';\r
+\r
+               name[bracket_pos] = '\0';\r
        }\r
 \r
        return GL_TRUE;\r
 }\r
 \r
-static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind,\r
+static GLboolean gather_uniform_bindings (slang_uniform_bindings *self,\r
        slang_export_data_table *tbl, GLuint index)\r
 {\r
        GLuint i;\r
@@ -132,8 +282,8 @@ static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind,
                {\r
                        char name[1024] = "";\r
 \r
-                       if (!insert_uniform_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,\r
-                                       tbl->entries[i].address))\r
+                       if (!add_complex_uniform_binding (self, &tbl->entries[i].quant, name, tbl->atoms, index,\r
+                               tbl->entries[i].address))\r
                                return GL_FALSE;\r
                }\r
 \r
@@ -141,80 +291,145 @@ static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind,
 }\r
 \r
 /*\r
- * slang_active_uniforms\r
+ * slang_attrib_bindings\r
  */\r
 \r
-static GLvoid slang_active_uniforms_ctr (slang_active_uniforms *self)\r
+static GLvoid slang_attrib_bindings_ctr (slang_attrib_bindings *self)\r
 {\r
-       self->table = NULL;\r
-       self->count = 0;\r
+       GLuint i;\r
+\r
+       self->binding_count = 0;\r
+       for (i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
+               self->slots[i].addr = ~0;\r
 }\r
 \r
-static GLvoid slang_active_uniforms_dtr (slang_active_uniforms *self)\r
+static GLvoid slang_attrib_bindings_dtr (slang_attrib_bindings *self)\r
 {\r
        GLuint i;\r
 \r
-       for (i = 0; i < self->count; i++)\r
-               slang_alloc_free (self->table[i].name);\r
-       slang_alloc_free (self->table);\r
+       for (i = 0; i < self->binding_count; i++)\r
+               slang_alloc_free (self->bindings[i].name);\r
 }\r
 \r
-static GLboolean slang_active_uniforms_add (slang_active_uniforms *self, slang_export_data_quant *q,\r
-       const char *name)\r
+static GLuint can_allocate_attrib_slots (slang_attrib_bindings *self, GLuint index, GLuint count)\r
 {\r
-       const GLuint n = self->count;\r
+       GLuint i;\r
 \r
-       self->table = (slang_active_uniform *) slang_alloc_realloc (self->table,\r
-               n * sizeof (slang_active_uniform), (n + 1) * sizeof (slang_active_uniform));\r
-       if (self->table == NULL)\r
-               return GL_FALSE;\r
-       self->table[n].quant = q;\r
-       self->table[n].name = slang_string_duplicate (name);\r
-       if (self->table[n].name == NULL)\r
-               return GL_FALSE;\r
-       self->count++;\r
-       return GL_TRUE;\r
+       for (i = 0; i < count; i++)\r
+               if (self->slots[index + i].addr != ~0)\r
+                       break;\r
+       return i;\r
 }\r
 \r
-static GLboolean insert_uniform (slang_active_uniforms *u, slang_export_data_quant *q, char *name,\r
-       slang_atom_pool *atoms)\r
+static GLuint allocate_attrib_slots (slang_attrib_bindings *self, GLuint count)\r
 {\r
-       slang_string_concat (name, slang_atom_pool_id (atoms, q->name));\r
-       if (slang_export_data_quant_array (q))\r
-               slang_string_concat (name, "[0]");\r
+       GLuint i;\r
 \r
-       if (slang_export_data_quant_struct (q))\r
+       for (i = 0; i <= MAX_VERTEX_ATTRIBS - count; i++)\r
        {\r
-               GLuint save, i;\r
-               const GLuint fields = slang_export_data_quant_fields (q);\r
+               GLuint size;\r
+               \r
+               size = can_allocate_attrib_slots (self, i, count);\r
+               if (size == count)\r
+                       return i;\r
+\r
+               /* speed-up the search a bit */\r
+               i += count;\r
+       }\r
+       return MAX_VERTEX_ATTRIBS;\r
+}\r
 \r
-               slang_string_concat (name, ".");\r
-               save = slang_string_length (name);\r
+static GLboolean add_attrib_binding (slang_attrib_bindings *self, slang_export_data_quant *q,\r
+       const char *name, GLuint addr, GLuint index_override)\r
+{\r
+       const GLuint n = self->binding_count;\r
+       GLuint slot_span, slot_index;\r
+       GLuint i;\r
 \r
-               for (i = 0; i < fields; i++)\r
-               {\r
-                       if (!insert_uniform (u, &q->structure[i], name, atoms))\r
-                               return GL_FALSE;\r
-                       name[save] = '\0';\r
-               }\r
+       assert (slang_export_data_quant_simple (q));\r
 \r
-               return GL_TRUE;\r
+       switch (slang_export_data_quant_type (q))\r
+       {\r
+       case GL_FLOAT:\r
+       case GL_FLOAT_VEC2:\r
+       case GL_FLOAT_VEC3:\r
+       case GL_FLOAT_VEC4:\r
+               slot_span = 1;\r
+               break;\r
+       case GL_FLOAT_MAT2:\r
+               slot_span = 2;\r
+               break;\r
+       case GL_FLOAT_MAT3:\r
+               slot_span = 3;\r
+               break;\r
+       case GL_FLOAT_MAT4:\r
+               slot_span = 4;\r
+               break;\r
+       default:\r
+               assert (0);\r
        }\r
 \r
-       return slang_active_uniforms_add (u, q, name);\r
+       if (index_override == MAX_VERTEX_ATTRIBS)\r
+               slot_index = allocate_attrib_slots (self, slot_span);\r
+       else if (can_allocate_attrib_slots (self, index_override, slot_span) == slot_span)\r
+               slot_index = index_override;\r
+       else\r
+               slot_index = MAX_VERTEX_ATTRIBS;\r
+                       \r
+       if (slot_index == MAX_VERTEX_ATTRIBS)\r
+       {\r
+               /* TODO: info log: error: MAX_VERTEX_ATTRIBS exceeded */\r
+               return GL_FALSE;\r
+       }\r
+\r
+       self->bindings[n].quant = q;\r
+       self->bindings[n].name = slang_string_duplicate (name);\r
+       if (self->bindings[n].name == NULL)\r
+               return GL_FALSE;\r
+       self->bindings[n].first_slot_index = slot_index;\r
+       self->binding_count++;\r
+\r
+       for (i = 0; i < slot_span; i++)\r
+               self->slots[self->bindings[n].first_slot_index + i].addr = addr + i * 4;\r
+\r
+       return GL_TRUE;\r
 }\r
 \r
-static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_data_table *tbl)\r
+static GLboolean gather_attrib_bindings (slang_attrib_bindings *self, slang_export_data_table *tbl,\r
+       slang_attrib_overrides *ovr)\r
 {\r
        GLuint i;\r
 \r
+       /* First pass. Gather attribs that have overriden index slots. */\r
        for (i = 0; i < tbl->count; i++)\r
-               if (tbl->entries[i].access == slang_exp_uniform)\r
+               if (tbl->entries[i].access == slang_exp_attribute &&\r
+                       !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms))\r
                {\r
-                       char name[1024] = "";\r
+                       slang_export_data_quant *quant = &tbl->entries[i].quant;\r
+                       const GLchar *id = slang_atom_pool_id (tbl->atoms, quant->name);\r
+                       GLuint index = lookup_attrib_override (ovr, id);\r
 \r
-                       if (!insert_uniform (u, &tbl->entries[i].quant, name, tbl->atoms))\r
-                               return GL_FALSE;\r
+                       if (index != MAX_VERTEX_ATTRIBS)\r
+                       {\r
+                               if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, index))\r
+                                       return GL_FALSE;\r
+                       }\r
+               }\r
+\r
+       /* Second pass. Gather attribs that have *NOT* overriden index slots. */\r
+       for (i = 0; i < tbl->count; i++)\r
+               if (tbl->entries[i].access == slang_exp_attribute &&\r
+                       !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms))\r
+               {\r
+                       slang_export_data_quant *quant = &tbl->entries[i].quant;\r
+                       const GLchar *id = slang_atom_pool_id (tbl->atoms, quant->name);\r
+                       GLuint index = lookup_attrib_override (ovr, id);\r
+\r
+                       if (index == MAX_VERTEX_ATTRIBS)\r
+                       {\r
+                               if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, index))\r
+                                       return GL_FALSE;\r
+                       }\r
                }\r
 \r
        return GL_TRUE;\r
@@ -226,75 +441,68 @@ static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_
 \r
 static GLvoid slang_varying_bindings_ctr (slang_varying_bindings *self)\r
 {\r
-       self->count = 0;\r
-       self->total = 0;\r
+       self->binding_count = 0;\r
+       self->slot_count = 0;\r
 }\r
 \r
 static GLvoid slang_varying_bindings_dtr (slang_varying_bindings *self)\r
 {\r
        GLuint i;\r
 \r
-       for (i = 0; i < self->count; i++)\r
-               slang_alloc_free (self->table[i].name);\r
+       for (i = 0; i < self->binding_count; i++)\r
+               slang_alloc_free (self->bindings[i].name);\r
 }\r
 \r
-static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean vert,\r
-       GLuint address, GLuint do_offset)\r
+static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean is_vert,\r
+       GLuint addr, GLuint do_offset)\r
 {\r
        GLuint i;\r
 \r
        for (i = 0; i < count; i++)\r
-               if (vert)\r
-                       slots[i].vert_addr = address + i * 4 * do_offset;\r
-               else\r
-                       slots[i].frag_addr = address + i * 4 * do_offset;\r
+               *(is_vert ? &slots[i].vert_addr : &slots[i].frag_addr) = addr + i * 4 * do_offset;\r
 }\r
 \r
-static GLboolean slang_varying_bindings_add (slang_varying_bindings *self,\r
-       slang_export_data_quant *q, const char *name, GLboolean vert, GLuint address)\r
+static GLboolean add_varying_binding (slang_varying_bindings *self,\r
+       slang_export_data_quant *q, const char *name, GLboolean is_vert, GLuint addr)\r
 {\r
-       const GLuint n = self->count;\r
-       const GLuint total_components =\r
+       const GLuint n = self->binding_count;\r
+       const GLuint slot_span =\r
                slang_export_data_quant_components (q) * slang_export_data_quant_elements (q);\r
        GLuint i;\r
 \r
        for (i = 0; i < n; i++)\r
-               if (slang_string_compare (self->table[i].name, name) == 0)\r
+               if (slang_string_compare (self->bindings[i].name, name) == 0)\r
                {\r
                        /* TODO: data quantities must match, or else link fails */\r
-                       update_varying_slots (&self->slots[self->table[i].slot], total_components, vert,\r
-                               address, 1);\r
+                       update_varying_slots (&self->slots[self->bindings[i].first_slot_index], slot_span,\r
+                               is_vert, addr, 1);\r
                        return GL_TRUE;\r
                }\r
 \r
-       if (self->total + total_components > MAX_VARYING_FLOATS)\r
+       if (self->slot_count + slot_span > MAX_VARYING_FLOATS)\r
        {\r
                /* TODO: info log: error: MAX_VARYING_FLOATS exceeded */\r
                return GL_FALSE;\r
        }\r
 \r
-       self->table[n].quant = q;\r
-       self->table[n].slot = self->total;\r
-       self->table[n].name = slang_string_duplicate (name);\r
-       if (self->table[n].name == NULL)\r
+       self->bindings[n].quant = q;\r
+       self->bindings[n].name = slang_string_duplicate (name);\r
+       if (self->bindings[n].name == NULL)\r
                return GL_FALSE;\r
-       self->count++;\r
+       self->bindings[n].first_slot_index = self->slot_count;\r
+       self->binding_count++;\r
 \r
-       update_varying_slots (&self->slots[self->table[n].slot], total_components, vert, address, 1);\r
-       update_varying_slots (&self->slots[self->table[n].slot], total_components, !vert, ~0, 0);\r
-       self->total += total_components;\r
+       update_varying_slots (&self->slots[self->bindings[n].first_slot_index], slot_span, is_vert,\r
+               addr, 1);\r
+       update_varying_slots (&self->slots[self->bindings[n].first_slot_index], slot_span, !is_vert,\r
+               ~0, 0);\r
+       self->slot_count += slot_span;\r
 \r
        return GL_TRUE;\r
 }\r
 \r
-static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms)\r
-{\r
-       const char *str = slang_atom_pool_id (atoms, name);\r
-       return str[0] == 'g' && str[1] == 'l' && str[2] == '_';\r
-}\r
-\r
-static GLboolean gather_varying_bindings (slang_varying_bindings *bind,\r
-       slang_export_data_table *tbl, GLboolean vert)\r
+static GLboolean gather_varying_bindings (slang_varying_bindings *self,\r
+       slang_export_data_table *tbl, GLboolean is_vert)\r
 {\r
        GLuint i;\r
 \r
@@ -302,9 +510,8 @@ static GLboolean gather_varying_bindings (slang_varying_bindings *bind,
                if (tbl->entries[i].access == slang_exp_varying &&\r
                        !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms))\r
                {\r
-                       if (!slang_varying_bindings_add (bind, &tbl->entries[i].quant,\r
-                               slang_atom_pool_id (tbl->atoms, tbl->entries[i].quant.name), vert,\r
-                               tbl->entries[i].address))\r
+                       if (!add_varying_binding (self, &tbl->entries[i].quant, slang_atom_pool_id (tbl->atoms,\r
+                               tbl->entries[i].quant.name), is_vert, tbl->entries[i].address))\r
                                return GL_FALSE;\r
                }\r
 \r
@@ -334,8 +541,11 @@ GLvoid slang_program_ctr (slang_program *self)
 {\r
        GLuint i;\r
 \r
+       slang_active_variables_ctr (&self->active_uniforms);\r
+       slang_active_variables_ctr (&self->active_attribs);\r
+       slang_attrib_overrides_ctr (&self->attrib_overrides);\r
        slang_uniform_bindings_ctr (&self->uniforms);\r
-       slang_active_uniforms_ctr (&self->active_uniforms);\r
+       slang_attrib_bindings_ctr (&self->attribs);\r
        slang_varying_bindings_ctr (&self->varyings);\r
        slang_texture_usages_ctr (&self->texture_usage);\r
        for (i = 0; i < SLANG_SHADER_MAX; i++)\r
@@ -357,12 +567,47 @@ GLvoid slang_program_ctr (slang_program *self)
 \r
 GLvoid slang_program_dtr (slang_program *self)\r
 {\r
+       slang_active_variables_dtr (&self->active_uniforms);\r
+       slang_active_variables_dtr (&self->active_attribs);\r
+       slang_attrib_overrides_dtr (&self->attrib_overrides);\r
        slang_uniform_bindings_dtr (&self->uniforms);\r
-       slang_active_uniforms_dtr (&self->active_uniforms);\r
+       slang_attrib_bindings_dtr (&self->attribs);\r
        slang_varying_bindings_dtr (&self->varyings);\r
        slang_texture_usages_dtr (&self->texture_usage);\r
 }\r
 \r
+static GLvoid slang_program_rst (slang_program *self)\r
+{\r
+       GLuint i;\r
+\r
+       slang_active_variables_dtr (&self->active_uniforms);\r
+       slang_active_variables_dtr (&self->active_attribs);\r
+       slang_uniform_bindings_dtr (&self->uniforms);\r
+       slang_attrib_bindings_dtr (&self->attribs);\r
+       slang_varying_bindings_dtr (&self->varyings);\r
+       slang_texture_usages_dtr (&self->texture_usage);\r
+\r
+       slang_active_variables_ctr (&self->active_uniforms);\r
+       slang_active_variables_ctr (&self->active_attribs);\r
+       slang_uniform_bindings_ctr (&self->uniforms);\r
+       slang_attrib_bindings_ctr (&self->attribs);\r
+       slang_varying_bindings_ctr (&self->varyings);\r
+       slang_texture_usages_ctr (&self->texture_usage);\r
+       for (i = 0; i < SLANG_SHADER_MAX; i++)\r
+       {\r
+               GLuint j;\r
+\r
+               for (j = 0; j < SLANG_COMMON_FIXED_MAX; j++)\r
+                       self->common_fixed_entries[i][j] = ~0;\r
+               for (j = 0; j < SLANG_COMMON_CODE_MAX; j++)\r
+                       self->code[i][j] = ~0;\r
+       }\r
+       for (i = 0; i < SLANG_VERTEX_FIXED_MAX; i++)\r
+               self->vertex_fixed_entries[i] = ~0;\r
+       for (i = 0; i < SLANG_FRAGMENT_FIXED_MAX; i++)\r
+               self->fragment_fixed_entries[i] = ~0;\r
+}\r
+\r
 /*\r
  * _slang_link()\r
  */\r
@@ -494,6 +739,8 @@ GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLui
 {\r
        GLuint i;\r
 \r
+       slang_program_rst (prog);\r
+\r
        for (i = 0; i < count; i++)\r
        {\r
                GLuint index;\r
@@ -507,11 +754,18 @@ GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLui
                {\r
                        index = SLANG_SHADER_VERTEX;\r
                        resolve_vertex_fixed (prog->vertex_fixed_entries, &units[i]->exp_data);\r
+                       if (!gather_attrib_bindings (&prog->attribs, &units[i]->exp_data,\r
+                               &prog->attrib_overrides))\r
+                               return GL_FALSE;\r
                }\r
 \r
-               if (!gather_uniform_bindings (&prog->uniforms, &units[i]->exp_data, index))\r
+               if (!gather_active_variables (&prog->active_uniforms, &units[i]->exp_data,\r
+                       slang_exp_uniform))\r
+                       return GL_FALSE;\r
+               if (!gather_active_variables (&prog->active_attribs, &units[i]->exp_data,\r
+                       slang_exp_attribute))\r
                        return GL_FALSE;\r
-               if (!gather_active_uniforms (&prog->active_uniforms, &units[i]->exp_data))\r
+               if (!gather_uniform_bindings (&prog->uniforms, &units[i]->exp_data, index))\r
                        return GL_FALSE;\r
                if (!gather_varying_bindings (&prog->varyings, &units[i]->exp_data,\r
                        index == SLANG_SHADER_VERTEX))\r
index e74c2565621d5f334f7098c93e70eb7a5857eb33..6f63a9d31ddd7f1fb9680aafb2c4a8bec36e65b7 100644 (file)
@@ -38,6 +38,61 @@ enum
        SLANG_SHADER_MAX\r
 };\r
 \r
+/* Active variables.\r
+ *\r
+ * Active uniforms or attribs can be queried by the application to get a list of uniforms\r
+ * or attribs actually used by shaders (uniforms) or vertex shader (attribs).\r
+ */\r
+\r
+typedef struct\r
+{\r
+       slang_export_data_quant *quant;\r
+       char *name;\r
+} slang_active_variable;\r
+\r
+typedef struct\r
+{\r
+       slang_active_variable *table;\r
+       GLuint count;\r
+} slang_active_variables;\r
+\r
+/*\r
+ * Attrib binding override.\r
+ *\r
+ * The application can override GL attrib binding by specifying its preferred index assignment\r
+ * for a given attrib name. Those overrides are taken into account while linking the program.\r
+ */\r
+\r
+typedef struct\r
+{\r
+       GLuint index;\r
+       GLchar *name;\r
+} slang_attrib_override;\r
+\r
+typedef struct\r
+{\r
+       slang_attrib_override *table;\r
+       GLuint count;\r
+} slang_attrib_overrides;\r
+\r
+GLboolean slang_attrib_overrides_add (slang_attrib_overrides *, GLuint, const GLchar *);\r
+\r
+/*\r
+ * Uniform bindings.\r
+ *\r
+ * Each slang_uniform_binding holds an array of addresses to actual memory locations in those\r
+ * shader types that use that uniform. Uniform bindings are held in an array and accessed\r
+ * by array index which is seen to the application as a uniform location.\r
+ *\r
+ * When the application writes to a particular uniform, it specifies its location.\r
+ * This location is treated as an array index to slang_uniform_bindings::table and tested\r
+ * against slang_uniform_bindings::count limit. The result is a pointer to slang_uniform_binding.\r
+ * The type of data being written to uniform is tested against slang_uniform_binding::quant.\r
+ * If the types are compatible, the array slang_uniform_binding::address is iterated for\r
+ * each shader type and if the address is valid (i.e. the uniform is used by this shader type),\r
+ * the new uniform value is written at that address.\r
+ */\r
+\r
 typedef struct\r
 {\r
        slang_export_data_quant *quant;\r
@@ -51,17 +106,42 @@ typedef struct
        GLuint count;\r
 } slang_uniform_bindings;\r
 \r
+/*\r
+ * Attrib bindings.\r
+ *\r
+ * There is a fixed number of vertex attrib vectors (attrib slots). The slang_attrib_slot::addr\r
+ * maps vertex attrib index to the actual memory location of the attrib in vertex shader.\r
+ * One vertex attrib can span over many attrib slots (this is the case for matrices). The\r
+ * slang_attrib_binding::first_slot_index holds the first slot index that the attrib is bound to.\r
+ */\r
+\r
 typedef struct\r
 {\r
        slang_export_data_quant *quant;\r
        char *name;\r
-} slang_active_uniform;\r
+       GLuint first_slot_index;\r
+} slang_attrib_binding;\r
 \r
 typedef struct\r
 {\r
-       slang_active_uniform *table;\r
-       GLuint count;\r
-} slang_active_uniforms;\r
+       GLuint addr;\r
+} slang_attrib_slot;\r
+\r
+typedef struct\r
+{\r
+       slang_attrib_binding bindings[MAX_VERTEX_ATTRIBS];\r
+       GLuint binding_count;\r
+       slang_attrib_slot slots[MAX_VERTEX_ATTRIBS];\r
+} slang_attrib_bindings;\r
+\r
+/*\r
+ * Varying bindings.\r
+ *\r
+ * There is a fixed number of varying floats (varying slots). The slang_varying_slot::vert_addr\r
+ * maps varying float index to the actual memory location of the output variable in vertex shader.\r
+ * The slang_varying_slot::frag_addr maps varying float index to the actual memory location of\r
+ * the input variable in fragment shader.\r
+ */\r
 \r
 typedef struct\r
 {\r
@@ -73,17 +153,30 @@ typedef struct
 {\r
        slang_export_data_quant *quant;\r
        char *name;\r
-       GLuint slot;\r
+       GLuint first_slot_index;\r
 } slang_varying_binding;\r
 \r
 typedef struct\r
 {\r
-       slang_varying_binding table[MAX_VARYING_FLOATS];\r
-       GLuint count;\r
+       slang_varying_binding bindings[MAX_VARYING_FLOATS];\r
+       GLuint binding_count;\r
        slang_varying_slot slots[MAX_VARYING_FLOATS];\r
-       GLuint total;\r
+       GLuint slot_count;\r
 } slang_varying_bindings;\r
 \r
+/*\r
+ * Texture usage.\r
+ *\r
+ * A slang_texture_usage struct holds indirect information about texture image unit usage. The\r
+ * slang_texture_usages::table is derived from active uniform table by extracting only uniforms\r
+ * that are samplers.\r
+ *\r
+ * To collect current texture usage one must iterate the slang_texture_usages::table and read\r
+ * uniform at address slang_texture_usage::frag_address to get texture unit index. This\r
+ * index, coupled with texture access type (target) taken from slang_texture_usage::quant\r
+ * forms texture usage for that texture unit.\r
+ */\r
+\r
 typedef struct\r
 {\r
        slang_export_data_quant *quant;\r
@@ -192,8 +285,11 @@ enum
 \r
 typedef struct\r
 {\r
+       slang_active_variables active_uniforms;\r
+       slang_active_variables active_attribs;\r
+       slang_attrib_overrides attrib_overrides;\r
        slang_uniform_bindings uniforms;\r
-       slang_active_uniforms active_uniforms;\r
+       slang_attrib_bindings attribs;\r
        slang_varying_bindings varyings;\r
        slang_texture_usages texture_usage;\r
        GLuint common_fixed_entries[SLANG_SHADER_MAX][SLANG_COMMON_FIXED_MAX];\r