From: Michal Krol Date: Tue, 18 Apr 2006 10:30:29 +0000 (+0000) Subject: Add support for ARB_vertex_shader attrib binding and query. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d55de658b559437272a88a5e8743304996044fff;p=mesa.git Add support for ARB_vertex_shader attrib binding and query. Clean-up ARB_shaderobjects code a bit. --- diff --git a/src/mesa/shader/shaderobjects.c b/src/mesa/shader/shaderobjects.c index a98c310bac4..fee259a9f38 100644 --- a/src/mesa/shader/shaderobjects.c +++ b/src/mesa/shader/shaderobjects.c @@ -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;\ } @@ -111,7 +111,7 @@ 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)\ @@ -125,9 +125,11 @@ 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; } diff --git a/src/mesa/shader/shaderobjects.h b/src/mesa/shader/shaderobjects.h index 19c4e8d3f8a..86a069ad6a9 100644 --- a/src/mesa/shader/shaderobjects.h +++ b/src/mesa/shader/shaderobjects.h @@ -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); }; diff --git a/src/mesa/shader/shaderobjects_3dlabs.c b/src/mesa/shader/shaderobjects_3dlabs.c index fa38a1c9af3..73c9e7d4367 100755 --- a/src/mesa/shader/shaderobjects_3dlabs.c +++ b/src/mesa/shader/shaderobjects_3dlabs.c @@ -1,1704 +1,1777 @@ -/* - * 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 -_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.total) - 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_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); -} - -GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name) -{ - struct gl2_program_impl *impl; - slang_uniform_bindings *bind; - GLuint i; - - impl = (struct gl2_program_impl *) pro; - bind = &impl->_obj.prog.uniforms; - for (i = 0; i < bind->count; i++) - if (_mesa_strcmp (bind->table[i].name, name) == 0) - return i; - return -1; -} - -GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count, - const GLvoid *data, GLenum type) -{ - struct gl2_program_impl *impl; - slang_uniform_bindings *bind; - slang_uniform_binding *b; - 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; - - impl = (struct gl2_program_impl *) pro; - bind = &impl->_obj.prog.uniforms; - if (loc >= bind->count) - return GL_FALSE; - - b = &bind->table[loc]; - /* TODO: check sizes */ - if (slang_export_data_quant_struct (b->quant)) - return GL_FALSE; - - switch (slang_export_data_quant_type (b->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 (b->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 (b->address[i] != ~0) - { - const GLfloat *src = (GLfloat *) (data); - GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]); - GLuint j; - GLuint total = count * slang_export_data_quant_components (b->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 (b->address[i] != ~0) - { - const GLuint *src = (GLuint *) (data); - GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]); - GLuint j; - GLuint total = count * slang_export_data_quant_components (b->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 (b->address[i] != ~0) - { - const GLuint *src = (GLuint *) (data); - GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]); - GLuint j; - GLuint total = count * slang_export_data_quant_components (b->quant); - - for (j = 0; j < total; j++) - dst[j] = (GLfloat) src[j]; - } - } - else - { - for (i = 0; i < SLANG_SHADER_MAX; i++) - if (b->address[i] != ~0) - { - _mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data, - count * slang_export_data_quant_size (b->quant)); - } - } - return GL_TRUE; -} - -GLuint _slang_get_active_uniform_count (struct gl2_program_intf **pro) -{ - struct gl2_program_impl *impl; - - impl = (struct gl2_program_impl *) pro; - return impl->_obj.prog.active_uniforms.count; -} - -GLuint _slang_get_active_uniform_max_length (struct gl2_program_intf **pro) -{ - struct gl2_program_impl *impl; - GLuint i, len = 0; - - impl = (struct gl2_program_impl *) pro; - for (i = 0; i < impl->_obj.prog.active_uniforms.count; i++) - { - GLuint n = _mesa_strlen (impl->_obj.prog.active_uniforms.table[i].name); - if (n > len) - len = n; - } - return len; -} - -GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, GLsizei maxLength, - GLsizei *length, GLint *size, GLenum *type, char *name) -{ - struct gl2_program_impl *impl; - slang_active_uniform *u; - GLsizei len; - - impl = (struct gl2_program_impl *) pro; - u = &impl->_obj.prog.active_uniforms.table[index]; - - len = _mesa_strlen (u->name); - if (len >= maxLength) - len = maxLength - 1; - _mesa_memcpy (name, u->name, len); - name[len] = '\0'; - if (length != NULL) - *length = len; - *type = slang_export_data_quant_type (u->quant); - *size = slang_export_data_quant_elements (u->quant); -} - -void -_mesa_init_shaderobjects_3dlabs (GLcontext *ctx) -{ -#if USE_3DLABS_FRONTEND - _glslang_3dlabs_InitProcess (); - _glslang_3dlabs_ShInitialize (); -#endif -} - +/* + * 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 +} + diff --git a/src/mesa/shader/shaderobjects_3dlabs.h b/src/mesa/shader/shaderobjects_3dlabs.h index d82079d8f31..8bf273ae9d7 100755 --- a/src/mesa/shader/shaderobjects_3dlabs.h +++ b/src/mesa/shader/shaderobjects_3dlabs.h @@ -1,56 +1,44 @@ -/* - * 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 GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name); - -extern GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count, - const GLvoid *data, GLenum type); - -extern GLuint _slang_get_active_uniform_count (struct gl2_program_intf **pro); - -extern GLuint _slang_get_active_uniform_max_length (struct gl2_program_intf **pro); - -extern GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, GLsizei maxLength, - GLsizei *length, GLint *size, GLenum *type, char *name); - -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 - +/* + * 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 + diff --git a/src/mesa/shader/slang/slang_export.c b/src/mesa/shader/slang/slang_export.c index 515c03fb641..dcf64244b74 100644 --- a/src/mesa/shader/slang/slang_export.c +++ b/src/mesa/shader/slang/slang_export.c @@ -79,6 +79,11 @@ GLboolean slang_export_data_quant_struct (slang_export_data_quant *self) return self->structure != NULL; } +GLboolean slang_export_data_quant_simple (slang_export_data_quant *self) +{ + return self->array_len == 0 && self->structure == NULL; +} + GLenum slang_export_data_quant_type (slang_export_data_quant *self) { assert (self->structure == NULL); diff --git a/src/mesa/shader/slang/slang_export.h b/src/mesa/shader/slang/slang_export.h index c158eb44431..aaf00773c1e 100644 --- a/src/mesa/shader/slang/slang_export.h +++ b/src/mesa/shader/slang/slang_export.h @@ -68,6 +68,11 @@ GLboolean slang_export_data_quant_array (slang_export_data_quant *); */ GLboolean slang_export_data_quant_struct (slang_export_data_quant *); +/* + * Returns GL_TRUE if the quant is neither an array nor a structure. + */ +GLboolean slang_export_data_quant_simple (slang_export_data_quant *); + /* * Returns basic type of the quant. It must not be a structure. */ @@ -81,7 +86,7 @@ GLuint slang_export_data_quant_fields (slang_export_data_quant *); /* * Return number of elements in the quant. * For arrays, return the size of the array. - * For scalars, return 1. + * Otherwise, return 1. */ GLuint slang_export_data_quant_elements (slang_export_data_quant *); diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index a72ec2eaa0b..9d61a29e912 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -32,6 +32,151 @@ #include "slang_link.h" #include "slang_analyse.h" +static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms) +{ + const char *str = slang_atom_pool_id (atoms, name); + return str[0] == 'g' && str[1] == 'l' && str[2] == '_'; +} + +/* + * slang_active_variables + */ + +static GLvoid slang_active_variables_ctr (slang_active_variables *self) +{ + self->table = NULL; + self->count = 0; +} + +static GLvoid slang_active_variables_dtr (slang_active_variables *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + slang_alloc_free (self->table[i].name); + slang_alloc_free (self->table); +} + +static GLboolean add_simple_variable (slang_active_variables *self, slang_export_data_quant *q, + const char *name) +{ + const GLuint n = self->count; + + self->table = (slang_active_variable *) slang_alloc_realloc (self->table, + n * sizeof (slang_active_variable), (n + 1) * sizeof (slang_active_variable)); + if (self->table == NULL) + return GL_FALSE; + + self->table[n].quant = q; + self->table[n].name = slang_string_duplicate (name); + if (self->table[n].name == NULL) + return GL_FALSE; + self->count++; + + return GL_TRUE; +} + +static GLboolean add_complex_variable (slang_active_variables *self, slang_export_data_quant *q, + char *name, slang_atom_pool *atoms) +{ + slang_string_concat (name, slang_atom_pool_id (atoms, q->name)); + if (slang_export_data_quant_array (q)) + slang_string_concat (name, "[0]"); + + if (slang_export_data_quant_struct (q)) + { + GLuint dot_pos, i; + const GLuint fields = slang_export_data_quant_fields (q); + + slang_string_concat (name, "."); + dot_pos = slang_string_length (name); + + for (i = 0; i < fields; i++) + { + if (!add_complex_variable (self, &q->structure[i], name, atoms)) + return GL_FALSE; + + name[dot_pos] = '\0'; + } + + return GL_TRUE; + } + + return add_simple_variable (self, q, name); +} + +static GLboolean gather_active_variables (slang_active_variables *self, + slang_export_data_table *tbl, slang_export_data_access access) +{ + GLuint i; + + for (i = 0; i < tbl->count; i++) + if (tbl->entries[i].access == access) + { + char name[1024] = ""; + + if (!add_complex_variable (self, &tbl->entries[i].quant, name, tbl->atoms)) + return GL_FALSE; + } + + return GL_TRUE; +} + +/* + * slang_attrib_overrides + */ + +static GLvoid slang_attrib_overrides_ctr (slang_attrib_overrides *self) +{ + self->table = NULL; + self->count = 0; +} + +static GLvoid slang_attrib_overrides_dtr (slang_attrib_overrides *self) +{ + GLuint i; + + for (i = 0; i < self->count; i++) + slang_alloc_free (self->table[i].name); + slang_alloc_free (self->table); +} + +GLboolean slang_attrib_overrides_add (slang_attrib_overrides *self, GLuint index, const GLchar *name) +{ + const GLuint n = self->count; + GLuint i; + + for (i = 0; i < n; i++) + if (slang_string_compare (name, self->table[i].name) == 0) + { + self->table[i].index = index; + return GL_TRUE; + } + + self->table = (slang_attrib_override *) slang_alloc_realloc (self->table, + n * sizeof (slang_attrib_override), (n + 1) * sizeof (slang_attrib_override)); + if (self->table == NULL) + return GL_FALSE; + + self->table[n].index = index; + self->table[n].name = slang_string_duplicate (name); + if (self->table[n].name == NULL) + return GL_FALSE; + self->count++; + + return GL_TRUE; +} + +static GLuint lookup_attrib_override (slang_attrib_overrides *self, const GLchar *name) +{ + GLuint i; + + for (i = 0; self->count; i++) + if (slang_string_compare (name, self->table[i].name) == 0) + return self->table[i].index; + return MAX_VERTEX_ATTRIBS; +} + /* * slang_uniform_bindings */ @@ -51,8 +196,8 @@ static GLvoid slang_uniform_bindings_dtr (slang_uniform_bindings *self) slang_alloc_free (self->table); } -static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang_export_data_quant *q, - const char *name, GLuint index, GLuint address) +static GLboolean add_simple_uniform_binding (slang_uniform_bindings *self, + slang_export_data_quant *q, const char *name, GLuint index, GLuint addr) { const GLuint n = self->count; GLuint i; @@ -60,7 +205,7 @@ static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang for (i = 0; i < n; i++) if (slang_string_compare (self->table[i].name, name) == 0) { - self->table[i].address[index] = address; + self->table[i].address[index] = addr; return GL_TRUE; } @@ -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)); if (self->table == NULL) return GL_FALSE; + self->table[n].quant = q; self->table[n].name = slang_string_duplicate (name); - for (i = 0; i < SLANG_SHADER_MAX; i++) - self->table[n].address[i] = ~0; - self->table[n].address[index] = address; if (self->table[n].name == NULL) return GL_FALSE; + for (i = 0; i < SLANG_SHADER_MAX; i++) + self->table[n].address[i] = ~0; + self->table[n].address[index] = addr; self->count++; + return GL_TRUE; } -static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_export_data_quant *q, - char *name, slang_atom_pool *atoms, GLuint index, GLuint addr) +static GLboolean add_complex_uniform_binding (slang_uniform_bindings *self, + slang_export_data_quant *q, char *name, slang_atom_pool *atoms, GLuint index, GLuint addr) { GLuint count, i; @@ -88,41 +235,44 @@ static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_exp count = slang_export_data_quant_elements (q); for (i = 0; i < count; i++) { - GLuint save; + GLuint bracket_pos; - save = slang_string_length (name); + bracket_pos = slang_string_length (name); if (slang_export_data_quant_array (q)) _mesa_sprintf (name + slang_string_length (name), "[%d]", i); if (slang_export_data_quant_struct (q)) { - GLuint save, i; + GLuint dot_pos, i; const GLuint fields = slang_export_data_quant_fields (q); slang_string_concat (name, "."); - save = slang_string_length (name); + dot_pos = slang_string_length (name); for (i = 0; i < fields; i++) { - if (!insert_uniform_binding (bind, &q->structure[i], name, atoms, index, addr)) + if (!add_complex_uniform_binding (self, &q->structure[i], name, atoms, index, addr)) return GL_FALSE; - name[save] = '\0'; + + name[dot_pos] = '\0'; addr += slang_export_data_quant_size (&q->structure[i]); } } else { - if (!slang_uniform_bindings_add (bind, q, name, index, addr)) + if (!add_simple_uniform_binding (self, q, name, index, addr)) return GL_FALSE; + addr += slang_export_data_quant_size (q); } - name[save] = '\0'; + + name[bracket_pos] = '\0'; } return GL_TRUE; } -static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, +static GLboolean gather_uniform_bindings (slang_uniform_bindings *self, slang_export_data_table *tbl, GLuint index) { GLuint i; @@ -132,8 +282,8 @@ static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, { char name[1024] = ""; - if (!insert_uniform_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index, - tbl->entries[i].address)) + if (!add_complex_uniform_binding (self, &tbl->entries[i].quant, name, tbl->atoms, index, + tbl->entries[i].address)) return GL_FALSE; } @@ -141,80 +291,145 @@ static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, } /* - * slang_active_uniforms + * slang_attrib_bindings */ -static GLvoid slang_active_uniforms_ctr (slang_active_uniforms *self) +static GLvoid slang_attrib_bindings_ctr (slang_attrib_bindings *self) { - self->table = NULL; - self->count = 0; + GLuint i; + + self->binding_count = 0; + for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) + self->slots[i].addr = ~0; } -static GLvoid slang_active_uniforms_dtr (slang_active_uniforms *self) +static GLvoid slang_attrib_bindings_dtr (slang_attrib_bindings *self) { GLuint i; - for (i = 0; i < self->count; i++) - slang_alloc_free (self->table[i].name); - slang_alloc_free (self->table); + for (i = 0; i < self->binding_count; i++) + slang_alloc_free (self->bindings[i].name); } -static GLboolean slang_active_uniforms_add (slang_active_uniforms *self, slang_export_data_quant *q, - const char *name) +static GLuint can_allocate_attrib_slots (slang_attrib_bindings *self, GLuint index, GLuint count) { - const GLuint n = self->count; + GLuint i; - self->table = (slang_active_uniform *) slang_alloc_realloc (self->table, - n * sizeof (slang_active_uniform), (n + 1) * sizeof (slang_active_uniform)); - if (self->table == NULL) - return GL_FALSE; - self->table[n].quant = q; - self->table[n].name = slang_string_duplicate (name); - if (self->table[n].name == NULL) - return GL_FALSE; - self->count++; - return GL_TRUE; + for (i = 0; i < count; i++) + if (self->slots[index + i].addr != ~0) + break; + return i; } -static GLboolean insert_uniform (slang_active_uniforms *u, slang_export_data_quant *q, char *name, - slang_atom_pool *atoms) +static GLuint allocate_attrib_slots (slang_attrib_bindings *self, GLuint count) { - slang_string_concat (name, slang_atom_pool_id (atoms, q->name)); - if (slang_export_data_quant_array (q)) - slang_string_concat (name, "[0]"); + GLuint i; - if (slang_export_data_quant_struct (q)) + for (i = 0; i <= MAX_VERTEX_ATTRIBS - count; i++) { - GLuint save, i; - const GLuint fields = slang_export_data_quant_fields (q); + GLuint size; + + size = can_allocate_attrib_slots (self, i, count); + if (size == count) + return i; + + /* speed-up the search a bit */ + i += count; + } + return MAX_VERTEX_ATTRIBS; +} - slang_string_concat (name, "."); - save = slang_string_length (name); +static GLboolean add_attrib_binding (slang_attrib_bindings *self, slang_export_data_quant *q, + const char *name, GLuint addr, GLuint index_override) +{ + const GLuint n = self->binding_count; + GLuint slot_span, slot_index; + GLuint i; - for (i = 0; i < fields; i++) - { - if (!insert_uniform (u, &q->structure[i], name, atoms)) - return GL_FALSE; - name[save] = '\0'; - } + assert (slang_export_data_quant_simple (q)); - return GL_TRUE; + switch (slang_export_data_quant_type (q)) + { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + slot_span = 1; + break; + case GL_FLOAT_MAT2: + slot_span = 2; + break; + case GL_FLOAT_MAT3: + slot_span = 3; + break; + case GL_FLOAT_MAT4: + slot_span = 4; + break; + default: + assert (0); } - return slang_active_uniforms_add (u, q, name); + if (index_override == MAX_VERTEX_ATTRIBS) + slot_index = allocate_attrib_slots (self, slot_span); + else if (can_allocate_attrib_slots (self, index_override, slot_span) == slot_span) + slot_index = index_override; + else + slot_index = MAX_VERTEX_ATTRIBS; + + if (slot_index == MAX_VERTEX_ATTRIBS) + { + /* TODO: info log: error: MAX_VERTEX_ATTRIBS exceeded */ + return GL_FALSE; + } + + self->bindings[n].quant = q; + self->bindings[n].name = slang_string_duplicate (name); + if (self->bindings[n].name == NULL) + return GL_FALSE; + self->bindings[n].first_slot_index = slot_index; + self->binding_count++; + + for (i = 0; i < slot_span; i++) + self->slots[self->bindings[n].first_slot_index + i].addr = addr + i * 4; + + return GL_TRUE; } -static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_data_table *tbl) +static GLboolean gather_attrib_bindings (slang_attrib_bindings *self, slang_export_data_table *tbl, + slang_attrib_overrides *ovr) { GLuint i; + /* First pass. Gather attribs that have overriden index slots. */ for (i = 0; i < tbl->count; i++) - if (tbl->entries[i].access == slang_exp_uniform) + if (tbl->entries[i].access == slang_exp_attribute && + !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) { - char name[1024] = ""; + slang_export_data_quant *quant = &tbl->entries[i].quant; + const GLchar *id = slang_atom_pool_id (tbl->atoms, quant->name); + GLuint index = lookup_attrib_override (ovr, id); - if (!insert_uniform (u, &tbl->entries[i].quant, name, tbl->atoms)) - return GL_FALSE; + if (index != MAX_VERTEX_ATTRIBS) + { + if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, index)) + return GL_FALSE; + } + } + + /* Second pass. Gather attribs that have *NOT* overriden index slots. */ + for (i = 0; i < tbl->count; i++) + if (tbl->entries[i].access == slang_exp_attribute && + !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) + { + slang_export_data_quant *quant = &tbl->entries[i].quant; + const GLchar *id = slang_atom_pool_id (tbl->atoms, quant->name); + GLuint index = lookup_attrib_override (ovr, id); + + if (index == MAX_VERTEX_ATTRIBS) + { + if (!add_attrib_binding (self, quant, id, tbl->entries[i].address, index)) + return GL_FALSE; + } } return GL_TRUE; @@ -226,75 +441,68 @@ static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_ static GLvoid slang_varying_bindings_ctr (slang_varying_bindings *self) { - self->count = 0; - self->total = 0; + self->binding_count = 0; + self->slot_count = 0; } static GLvoid slang_varying_bindings_dtr (slang_varying_bindings *self) { GLuint i; - for (i = 0; i < self->count; i++) - slang_alloc_free (self->table[i].name); + for (i = 0; i < self->binding_count; i++) + slang_alloc_free (self->bindings[i].name); } -static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean vert, - GLuint address, GLuint do_offset) +static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean is_vert, + GLuint addr, GLuint do_offset) { GLuint i; for (i = 0; i < count; i++) - if (vert) - slots[i].vert_addr = address + i * 4 * do_offset; - else - slots[i].frag_addr = address + i * 4 * do_offset; + *(is_vert ? &slots[i].vert_addr : &slots[i].frag_addr) = addr + i * 4 * do_offset; } -static GLboolean slang_varying_bindings_add (slang_varying_bindings *self, - slang_export_data_quant *q, const char *name, GLboolean vert, GLuint address) +static GLboolean add_varying_binding (slang_varying_bindings *self, + slang_export_data_quant *q, const char *name, GLboolean is_vert, GLuint addr) { - const GLuint n = self->count; - const GLuint total_components = + const GLuint n = self->binding_count; + const GLuint slot_span = slang_export_data_quant_components (q) * slang_export_data_quant_elements (q); GLuint i; for (i = 0; i < n; i++) - if (slang_string_compare (self->table[i].name, name) == 0) + if (slang_string_compare (self->bindings[i].name, name) == 0) { /* TODO: data quantities must match, or else link fails */ - update_varying_slots (&self->slots[self->table[i].slot], total_components, vert, - address, 1); + update_varying_slots (&self->slots[self->bindings[i].first_slot_index], slot_span, + is_vert, addr, 1); return GL_TRUE; } - if (self->total + total_components > MAX_VARYING_FLOATS) + if (self->slot_count + slot_span > MAX_VARYING_FLOATS) { /* TODO: info log: error: MAX_VARYING_FLOATS exceeded */ return GL_FALSE; } - self->table[n].quant = q; - self->table[n].slot = self->total; - self->table[n].name = slang_string_duplicate (name); - if (self->table[n].name == NULL) + self->bindings[n].quant = q; + self->bindings[n].name = slang_string_duplicate (name); + if (self->bindings[n].name == NULL) return GL_FALSE; - self->count++; + self->bindings[n].first_slot_index = self->slot_count; + self->binding_count++; - update_varying_slots (&self->slots[self->table[n].slot], total_components, vert, address, 1); - update_varying_slots (&self->slots[self->table[n].slot], total_components, !vert, ~0, 0); - self->total += total_components; + update_varying_slots (&self->slots[self->bindings[n].first_slot_index], slot_span, is_vert, + addr, 1); + update_varying_slots (&self->slots[self->bindings[n].first_slot_index], slot_span, !is_vert, + ~0, 0); + self->slot_count += slot_span; return GL_TRUE; } -static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms) -{ - const char *str = slang_atom_pool_id (atoms, name); - return str[0] == 'g' && str[1] == 'l' && str[2] == '_'; -} - -static GLboolean gather_varying_bindings (slang_varying_bindings *bind, - slang_export_data_table *tbl, GLboolean vert) +static GLboolean gather_varying_bindings (slang_varying_bindings *self, + slang_export_data_table *tbl, GLboolean is_vert) { GLuint i; @@ -302,9 +510,8 @@ static GLboolean gather_varying_bindings (slang_varying_bindings *bind, if (tbl->entries[i].access == slang_exp_varying && !entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms)) { - if (!slang_varying_bindings_add (bind, &tbl->entries[i].quant, - slang_atom_pool_id (tbl->atoms, tbl->entries[i].quant.name), vert, - tbl->entries[i].address)) + if (!add_varying_binding (self, &tbl->entries[i].quant, slang_atom_pool_id (tbl->atoms, + tbl->entries[i].quant.name), is_vert, tbl->entries[i].address)) return GL_FALSE; } @@ -334,8 +541,11 @@ GLvoid slang_program_ctr (slang_program *self) { GLuint i; + slang_active_variables_ctr (&self->active_uniforms); + slang_active_variables_ctr (&self->active_attribs); + slang_attrib_overrides_ctr (&self->attrib_overrides); slang_uniform_bindings_ctr (&self->uniforms); - slang_active_uniforms_ctr (&self->active_uniforms); + slang_attrib_bindings_ctr (&self->attribs); slang_varying_bindings_ctr (&self->varyings); slang_texture_usages_ctr (&self->texture_usage); for (i = 0; i < SLANG_SHADER_MAX; i++) @@ -357,12 +567,47 @@ GLvoid slang_program_ctr (slang_program *self) GLvoid slang_program_dtr (slang_program *self) { + slang_active_variables_dtr (&self->active_uniforms); + slang_active_variables_dtr (&self->active_attribs); + slang_attrib_overrides_dtr (&self->attrib_overrides); slang_uniform_bindings_dtr (&self->uniforms); - slang_active_uniforms_dtr (&self->active_uniforms); + slang_attrib_bindings_dtr (&self->attribs); slang_varying_bindings_dtr (&self->varyings); slang_texture_usages_dtr (&self->texture_usage); } +static GLvoid slang_program_rst (slang_program *self) +{ + GLuint i; + + slang_active_variables_dtr (&self->active_uniforms); + slang_active_variables_dtr (&self->active_attribs); + slang_uniform_bindings_dtr (&self->uniforms); + slang_attrib_bindings_dtr (&self->attribs); + slang_varying_bindings_dtr (&self->varyings); + slang_texture_usages_dtr (&self->texture_usage); + + slang_active_variables_ctr (&self->active_uniforms); + slang_active_variables_ctr (&self->active_attribs); + slang_uniform_bindings_ctr (&self->uniforms); + slang_attrib_bindings_ctr (&self->attribs); + slang_varying_bindings_ctr (&self->varyings); + slang_texture_usages_ctr (&self->texture_usage); + for (i = 0; i < SLANG_SHADER_MAX; i++) + { + GLuint j; + + for (j = 0; j < SLANG_COMMON_FIXED_MAX; j++) + self->common_fixed_entries[i][j] = ~0; + for (j = 0; j < SLANG_COMMON_CODE_MAX; j++) + self->code[i][j] = ~0; + } + for (i = 0; i < SLANG_VERTEX_FIXED_MAX; i++) + self->vertex_fixed_entries[i] = ~0; + for (i = 0; i < SLANG_FRAGMENT_FIXED_MAX; i++) + self->fragment_fixed_entries[i] = ~0; +} + /* * _slang_link() */ @@ -494,6 +739,8 @@ GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLui { GLuint i; + slang_program_rst (prog); + for (i = 0; i < count; i++) { GLuint index; @@ -507,11 +754,18 @@ GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLui { index = SLANG_SHADER_VERTEX; resolve_vertex_fixed (prog->vertex_fixed_entries, &units[i]->exp_data); + if (!gather_attrib_bindings (&prog->attribs, &units[i]->exp_data, + &prog->attrib_overrides)) + return GL_FALSE; } - if (!gather_uniform_bindings (&prog->uniforms, &units[i]->exp_data, index)) + if (!gather_active_variables (&prog->active_uniforms, &units[i]->exp_data, + slang_exp_uniform)) + return GL_FALSE; + if (!gather_active_variables (&prog->active_attribs, &units[i]->exp_data, + slang_exp_attribute)) return GL_FALSE; - if (!gather_active_uniforms (&prog->active_uniforms, &units[i]->exp_data)) + if (!gather_uniform_bindings (&prog->uniforms, &units[i]->exp_data, index)) return GL_FALSE; if (!gather_varying_bindings (&prog->varyings, &units[i]->exp_data, index == SLANG_SHADER_VERTEX)) diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h index e74c2565621..6f63a9d31dd 100644 --- a/src/mesa/shader/slang/slang_link.h +++ b/src/mesa/shader/slang/slang_link.h @@ -38,6 +38,61 @@ enum SLANG_SHADER_MAX }; +/* Active variables. + * + * Active uniforms or attribs can be queried by the application to get a list of uniforms + * or attribs actually used by shaders (uniforms) or vertex shader (attribs). + */ + +typedef struct +{ + slang_export_data_quant *quant; + char *name; +} slang_active_variable; + +typedef struct +{ + slang_active_variable *table; + GLuint count; +} slang_active_variables; + +/* + * Attrib binding override. + * + * The application can override GL attrib binding by specifying its preferred index assignment + * for a given attrib name. Those overrides are taken into account while linking the program. + */ + +typedef struct +{ + GLuint index; + GLchar *name; +} slang_attrib_override; + +typedef struct +{ + slang_attrib_override *table; + GLuint count; +} slang_attrib_overrides; + +GLboolean slang_attrib_overrides_add (slang_attrib_overrides *, GLuint, const GLchar *); + +/* + * Uniform bindings. + * + * Each slang_uniform_binding holds an array of addresses to actual memory locations in those + * shader types that use that uniform. Uniform bindings are held in an array and accessed + * by array index which is seen to the application as a uniform location. + * + * When the application writes to a particular uniform, it specifies its location. + * This location is treated as an array index to slang_uniform_bindings::table and tested + * against slang_uniform_bindings::count limit. The result is a pointer to slang_uniform_binding. + * The type of data being written to uniform is tested against slang_uniform_binding::quant. + * If the types are compatible, the array slang_uniform_binding::address is iterated for + * each shader type and if the address is valid (i.e. the uniform is used by this shader type), + * the new uniform value is written at that address. + */ + typedef struct { slang_export_data_quant *quant; @@ -51,17 +106,42 @@ typedef struct GLuint count; } slang_uniform_bindings; +/* + * Attrib bindings. + * + * There is a fixed number of vertex attrib vectors (attrib slots). The slang_attrib_slot::addr + * maps vertex attrib index to the actual memory location of the attrib in vertex shader. + * One vertex attrib can span over many attrib slots (this is the case for matrices). The + * slang_attrib_binding::first_slot_index holds the first slot index that the attrib is bound to. + */ + typedef struct { slang_export_data_quant *quant; char *name; -} slang_active_uniform; + GLuint first_slot_index; +} slang_attrib_binding; typedef struct { - slang_active_uniform *table; - GLuint count; -} slang_active_uniforms; + GLuint addr; +} slang_attrib_slot; + +typedef struct +{ + slang_attrib_binding bindings[MAX_VERTEX_ATTRIBS]; + GLuint binding_count; + slang_attrib_slot slots[MAX_VERTEX_ATTRIBS]; +} slang_attrib_bindings; + +/* + * Varying bindings. + * + * There is a fixed number of varying floats (varying slots). The slang_varying_slot::vert_addr + * maps varying float index to the actual memory location of the output variable in vertex shader. + * The slang_varying_slot::frag_addr maps varying float index to the actual memory location of + * the input variable in fragment shader. + */ typedef struct { @@ -73,17 +153,30 @@ typedef struct { slang_export_data_quant *quant; char *name; - GLuint slot; + GLuint first_slot_index; } slang_varying_binding; typedef struct { - slang_varying_binding table[MAX_VARYING_FLOATS]; - GLuint count; + slang_varying_binding bindings[MAX_VARYING_FLOATS]; + GLuint binding_count; slang_varying_slot slots[MAX_VARYING_FLOATS]; - GLuint total; + GLuint slot_count; } slang_varying_bindings; +/* + * Texture usage. + * + * A slang_texture_usage struct holds indirect information about texture image unit usage. The + * slang_texture_usages::table is derived from active uniform table by extracting only uniforms + * that are samplers. + * + * To collect current texture usage one must iterate the slang_texture_usages::table and read + * uniform at address slang_texture_usage::frag_address to get texture unit index. This + * index, coupled with texture access type (target) taken from slang_texture_usage::quant + * forms texture usage for that texture unit. + */ + typedef struct { slang_export_data_quant *quant; @@ -192,8 +285,11 @@ enum typedef struct { + slang_active_variables active_uniforms; + slang_active_variables active_attribs; + slang_attrib_overrides attrib_overrides; slang_uniform_bindings uniforms; - slang_active_uniforms active_uniforms; + slang_attrib_bindings attribs; slang_varying_bindings varyings; slang_texture_usages texture_usage; GLuint common_fixed_entries[SLANG_SHADER_MAX][SLANG_COMMON_FIXED_MAX];