#define LONGSTRING __extension__ in imports.h and use it to silence gcc
[mesa.git] / src / mesa / shader / shaderobjects_3dlabs.c
index fa38a1c9af33a1269a257a40bccf9d77e161ed10..3ead1a178412c333c7a51b6d74305fa66ce4ebea 100755 (executable)
-/*\r
- * Mesa 3-D graphics library\r
- * Version:  6.5\r
- *\r
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-/**\r
- * \file shaderobjects_3dlabs.c\r
- * shader objects definitions for 3dlabs compiler\r
- * \author Michal Krol\r
- */\r
-\r
-/* Set this to 1 when we are ready to use 3dlabs' front-end */\r
-#define USE_3DLABS_FRONTEND 0\r
-\r
-#include "imports.h"\r
-#include "hash.h"\r
-#include "macros.h"\r
-#include "shaderobjects.h"\r
-#include "shaderobjects_3dlabs.h"\r
-\r
-#if USE_3DLABS_FRONTEND\r
-#include "slang_mesa.h"\r
-#include "Public/ShaderLang.h"\r
-#else\r
-#include "slang_link.h"\r
-#endif\r
-\r
-struct gl2_unknown_obj\r
-{\r
-       GLuint reference_count;\r
-       void (* _destructor) (struct gl2_unknown_intf **);\r
-};\r
-\r
-struct gl2_unknown_impl\r
-{\r
-       struct gl2_unknown_intf *_vftbl;\r
-       struct gl2_unknown_obj _obj;\r
-};\r
-\r
-static void\r
-_unknown_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-}\r
-\r
-static void\r
-_unknown_AddRef (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;\r
-\r
-       impl->_obj.reference_count++;\r
-}\r
-\r
-static void\r
-_unknown_Release (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unknown_impl *impl = (struct gl2_unknown_impl *) intf;\r
-\r
-       impl->_obj.reference_count--;\r
-       if (impl->_obj.reference_count == 0)\r
-       {\r
-               impl->_obj._destructor (intf);\r
-               _mesa_free ((void *) intf);\r
-       }\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_unknown_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_UNKNOWN)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return NULL;\r
-}\r
-\r
-static struct gl2_unknown_intf _unknown_vftbl = {\r
-       _unknown_AddRef,\r
-       _unknown_Release,\r
-       _unknown_QueryInterface\r
-};\r
-\r
-static void\r
-_unknown_constructor (struct gl2_unknown_impl *impl)\r
-{\r
-       impl->_vftbl = &_unknown_vftbl;\r
-       impl->_obj.reference_count = 1;\r
-       impl->_obj._destructor = _unknown_destructor;\r
-}\r
-\r
-struct gl2_unkinner_obj\r
-{\r
-       struct gl2_unknown_intf **unkouter;\r
-};\r
-\r
-struct gl2_unkinner_impl\r
-{\r
-       struct gl2_unknown_intf *_vftbl;\r
-       struct gl2_unkinner_obj _obj;\r
-};\r
-\r
-static void\r
-_unkinner_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-}\r
-\r
-static void\r
-_unkinner_AddRef (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       (**impl->_obj.unkouter).AddRef (impl->_obj.unkouter);\r
-}\r
-\r
-static void\r
-_unkinner_Release (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       (**impl->_obj.unkouter).Release (impl->_obj.unkouter);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_unkinner_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       struct gl2_unkinner_impl *impl = (struct gl2_unkinner_impl *) intf;\r
-\r
-       return (**impl->_obj.unkouter).QueryInterface (impl->_obj.unkouter, uiid);\r
-}\r
-\r
-static struct gl2_unknown_intf _unkinner_vftbl = {\r
-       _unkinner_AddRef,\r
-       _unkinner_Release,\r
-       _unkinner_QueryInterface\r
-};\r
-\r
-static void\r
-_unkinner_constructor (struct gl2_unkinner_impl *impl, struct gl2_unknown_intf **outer)\r
-{\r
-       impl->_vftbl = &_unkinner_vftbl;\r
-       impl->_obj.unkouter = outer;\r
-}\r
-\r
-struct gl2_generic_obj\r
-{\r
-       struct gl2_unknown_obj _unknown;\r
-       GLhandleARB name;\r
-       GLboolean delete_status;\r
-       GLcharARB *info_log;\r
-};\r
-\r
-struct gl2_generic_impl\r
-{\r
-       struct gl2_generic_intf *_vftbl;\r
-       struct gl2_generic_obj _obj;\r
-};\r
-\r
-static void\r
-_generic_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.info_log);\r
-\r
-       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);\r
-       _mesa_HashRemove (ctx->Shared->GL2Objects, impl->_obj.name);\r
-       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);\r
-\r
-       _unknown_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_generic_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_GENERIC)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _unknown_QueryInterface (intf, uiid);\r
-}\r
-\r
-static void\r
-_generic_Delete (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       if (impl->_obj.delete_status == GL_FALSE)\r
-       {\r
-               impl->_obj.delete_status = GL_TRUE;\r
-               (**intf)._unknown.Release ((struct gl2_unknown_intf **) intf);\r
-       }\r
-}\r
-\r
-static GLhandleARB\r
-_generic_GetName (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.name;\r
-}\r
-\r
-static GLboolean\r
-_generic_GetDeleteStatus (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.delete_status;\r
-}\r
-\r
-static const GLcharARB *\r
-_generic_GetInfoLog (struct gl2_generic_intf **intf)\r
-{\r
-       struct gl2_generic_impl *impl = (struct gl2_generic_impl *) intf;\r
-\r
-       return impl->_obj.info_log;\r
-}\r
-\r
-static struct gl2_generic_intf _generic_vftbl = {\r
-       {\r
-               _unknown_AddRef,\r
-               _unknown_Release,\r
-               _generic_QueryInterface\r
-       },\r
-       _generic_Delete,\r
-       NULL,           /* abstract GetType */\r
-       _generic_GetName,\r
-       _generic_GetDeleteStatus,\r
-       _generic_GetInfoLog\r
-};\r
-\r
-static void\r
-_generic_constructor (struct gl2_generic_impl *impl)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-\r
-       _unknown_constructor ((struct gl2_unknown_impl *) impl);\r
-       impl->_vftbl = &_generic_vftbl;\r
-       impl->_obj._unknown._destructor = _generic_destructor;\r
-       impl->_obj.delete_status = GL_FALSE;\r
-       impl->_obj.info_log = NULL;\r
-\r
-       _glthread_LOCK_MUTEX (ctx->Shared->Mutex);\r
-       impl->_obj.name = _mesa_HashFindFreeKeyBlock (ctx->Shared->GL2Objects, 1);\r
-       _mesa_HashInsert (ctx->Shared->GL2Objects, impl->_obj.name, (void *) impl);\r
-       _glthread_UNLOCK_MUTEX (ctx->Shared->Mutex);\r
-}\r
-\r
-struct gl2_container_obj\r
-{\r
-       struct gl2_generic_obj _generic;\r
-       struct gl2_generic_intf ***attached;\r
-       GLuint attached_count;\r
-};\r
-\r
-struct gl2_container_impl\r
-{\r
-       struct gl2_container_intf *_vftbl;\r
-       struct gl2_container_obj _obj;\r
-};\r
-\r
-static void\r
-_container_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-       {\r
-               struct gl2_generic_intf **x = impl->_obj.attached[i];\r
-               (**x)._unknown.Release ((struct gl2_unknown_intf **) x);\r
-       }\r
-\r
-       _generic_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_container_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_CONTAINER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _generic_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLboolean\r
-_container_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-               if (impl->_obj.attached[i] == att)\r
-               {\r
-                       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Attach");\r
-                       return GL_FALSE;\r
-               }\r
-\r
-       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,\r
-               impl->_obj.attached_count * sizeof (*impl->_obj.attached), (impl->_obj.attached_count + 1) *\r
-               sizeof (*impl->_obj.attached));\r
-       if (impl->_obj.attached == NULL)\r
-               return GL_FALSE;\r
-\r
-       impl->_obj.attached[impl->_obj.attached_count] = att;\r
-       impl->_obj.attached_count++;\r
-       (**att)._unknown.AddRef ((struct gl2_unknown_intf **) att);\r
-       return GL_TRUE;\r
-}\r
-\r
-static GLboolean\r
-_container_Detach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-       GLuint i, j;\r
-\r
-       for (i = 0; i < impl->_obj.attached_count; i++)\r
-               if (impl->_obj.attached[i] == att)\r
-               {\r
-                       for (j = i; j < impl->_obj.attached_count - 1; j++)\r
-                               impl->_obj.attached[j] = impl->_obj.attached[j + 1];\r
-                       impl->_obj.attached = (struct gl2_generic_intf ***) _mesa_realloc (impl->_obj.attached,\r
-                               impl->_obj.attached_count * sizeof (*impl->_obj.attached),\r
-                               (impl->_obj.attached_count - 1) * sizeof (*impl->_obj.attached));\r
-                       impl->_obj.attached_count--;\r
-                       (**att)._unknown.Release ((struct gl2_unknown_intf **) att);\r
-                       return GL_TRUE;\r
-               }\r
-\r
-       _mesa_error (ctx, GL_INVALID_OPERATION, "_container_Detach");\r
-       return GL_FALSE;\r
-}\r
-\r
-static GLsizei\r
-_container_GetAttachedCount (struct gl2_container_intf **intf)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-\r
-       return impl->_obj.attached_count;\r
-}\r
-\r
-static struct gl2_generic_intf **\r
-_container_GetAttached (struct gl2_container_intf **intf, GLuint index)\r
-{\r
-       struct gl2_container_impl *impl = (struct gl2_container_impl *) intf;\r
-\r
-       (**impl->_obj.attached[index])._unknown.AddRef (\r
-               (struct gl2_unknown_intf **)impl->_obj.attached[index]);\r
-       return impl->_obj.attached[index];\r
-}\r
-\r
-static struct gl2_container_intf _container_vftbl = {\r
-       {\r
-               {\r
-                       _unknown_AddRef,\r
-                       _unknown_Release,\r
-                       _container_QueryInterface\r
-               },\r
-               _generic_Delete,\r
-               NULL,           /* abstract GetType */\r
-               _generic_GetName,\r
-               _generic_GetDeleteStatus,\r
-               _generic_GetInfoLog\r
-       },\r
-       _container_Attach,\r
-       _container_Detach,\r
-       _container_GetAttachedCount,\r
-       _container_GetAttached\r
-};\r
-\r
-static void\r
-_container_constructor (struct gl2_container_impl *impl)\r
-{\r
-       _generic_constructor ((struct gl2_generic_impl *) impl);\r
-       impl->_vftbl = &_container_vftbl;\r
-       impl->_obj._generic._unknown._destructor = _container_destructor;\r
-       impl->_obj.attached = NULL;\r
-       impl->_obj.attached_count = 0;\r
-}\r
-\r
-struct gl2_3dlabs_shhandle_obj\r
-{\r
-       struct gl2_unkinner_obj _unknown;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle handle;\r
-#endif\r
-};\r
-\r
-struct gl2_3dlabs_shhandle_impl\r
-{\r
-       struct gl2_3dlabs_shhandle_intf *_vftbl;\r
-       struct gl2_3dlabs_shhandle_obj _obj;\r
-};\r
-\r
-static void\r
-_3dlabs_shhandle_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;\r
-       ShDestruct (impl->_obj.handle);\r
-#endif\r
-       _unkinner_destructor (intf);\r
-}\r
-\r
-static GLvoid *\r
-_3dlabs_shhandle_GetShHandle (struct gl2_3dlabs_shhandle_intf **intf)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_3dlabs_shhandle_impl *impl = (struct gl2_3dlabs_shhandle_impl *) intf;\r
-       return impl->_obj.handle;\r
-#else\r
-       return NULL;\r
-#endif\r
-}\r
-\r
-static struct gl2_3dlabs_shhandle_intf _3dlabs_shhandle_vftbl = {\r
-       {\r
-               _unkinner_AddRef,\r
-               _unkinner_Release,\r
-               _unkinner_QueryInterface\r
-       },\r
-       _3dlabs_shhandle_GetShHandle\r
-};\r
-\r
-static void\r
-_3dlabs_shhandle_constructor (struct gl2_3dlabs_shhandle_impl *impl, struct gl2_unknown_intf **outer)\r
-{\r
-       _unkinner_constructor ((struct gl2_unkinner_impl *) impl, outer);\r
-       impl->_vftbl = &_3dlabs_shhandle_vftbl;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj.handle = NULL;\r
-#endif\r
-}\r
-\r
-struct gl2_shader_obj\r
-{\r
-       struct gl2_generic_obj _generic;\r
-       struct gl2_3dlabs_shhandle_impl _3dlabs_shhandle;\r
-       GLboolean compile_status;\r
-       GLcharARB *source;\r
-       GLint *offsets;\r
-       GLsizei offset_count;\r
-       slang_translation_unit unit;\r
-};\r
-\r
-struct gl2_shader_impl\r
-{\r
-       struct gl2_shader_intf *_vftbl;\r
-       struct gl2_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.source);\r
-       _mesa_free ((void *) impl->_obj.offsets);\r
-       _3dlabs_shhandle_destructor ((struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl);\r
-       _generic_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-#endif\r
-\r
-       if (uiid == UIID_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-#if USE_3DLABS_FRONTEND\r
-       if (uiid == UIID_3DLABS_SHHANDLE)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return (struct gl2_unknown_intf **) &impl->_obj._3dlabs_shhandle._vftbl;\r
-       }\r
-#endif\r
-       return _generic_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_shader_GetType (struct gl2_generic_intf **intf)\r
-{\r
-       return GL_SHADER_OBJECT_ARB;\r
-}\r
-\r
-static GLboolean\r
-_shader_GetCompileStatus (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       return impl->_obj.compile_status;\r
-}\r
-\r
-static GLvoid\r
-_shader_SetSource (struct gl2_shader_intf **intf, GLcharARB *src, GLint *off, GLsizei cnt)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       _mesa_free ((void *) impl->_obj.source);\r
-       impl->_obj.source = src;\r
-       _mesa_free ((void *) impl->_obj.offsets);\r
-       impl->_obj.offsets = off;\r
-       impl->_obj.offset_count = cnt;\r
-}\r
-\r
-static const GLcharARB *\r
-_shader_GetSource (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-\r
-       return impl->_obj.source;\r
-}\r
-\r
-static GLvoid\r
-_shader_Compile (struct gl2_shader_intf **intf)\r
-{\r
-       struct gl2_shader_impl *impl = (struct gl2_shader_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       char **strings;\r
-       TBuiltInResource res;\r
-#else\r
-       slang_unit_type type;\r
-       slang_info_log info_log;\r
-#endif\r
-\r
-       impl->_obj.compile_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._generic.info_log);\r
-       impl->_obj._generic.info_log = NULL;\r
-\r
-#if USE_3DLABS_FRONTEND\r
-       /* 3dlabs compiler expects us to feed it with null-terminated string array,\r
-       we've got only one big string with offsets, so we must split it; but when\r
-       there's only one string to deal with, we pass its address directly */\r
-\r
-       if (impl->_obj.offset_count <= 1)\r
-               strings = &impl->_obj.source;\r
-       else\r
-       {\r
-               GLsizei i, offset = 0;\r
-\r
-               strings = (char **) _mesa_malloc (impl->_obj.offset_count * sizeof (char *));\r
-               if (strings == NULL)\r
-                       return;\r
-\r
-               for (i = 0; i < impl->_obj.offset_count; i++)\r
-               {\r
-                       GLsizei size = impl->_obj.offsets[i] - offset;\r
-\r
-                       strings[i] = (char *) _mesa_malloc ((size + 1) * sizeof (char));\r
-                       if (strings[i] == NULL)\r
-                       {\r
-                               GLsizei j;\r
-\r
-                               for (j = 0; j < i; j++)\r
-                                       _mesa_free (strings[j]);\r
-                               _mesa_free (strings);\r
-                               return;\r
-                       }\r
-\r
-                       _mesa_memcpy (strings[i], impl->_obj.source + offset, size * sizeof (char));\r
-                       strings[i][size] = '\0';\r
-                       offset = impl->_obj.offsets[i];\r
-               }\r
-       }\r
-\r
-       /* TODO set these fields to some REAL numbers */\r
-       res.maxLights = 8;\r
-       res.maxClipPlanes = 6;\r
-       res.maxTextureUnits = 2;\r
-       res.maxTextureCoords = 2;\r
-       res.maxVertexAttribs = 8;\r
-       res.maxVertexUniformComponents = 64;\r
-       res.maxVaryingFloats = 8;\r
-       res.maxVertexTextureImageUnits = 2;\r
-       res.maxCombinedTextureImageUnits = 2;\r
-       res.maxTextureImageUnits = 2;\r
-       res.maxFragmentUniformComponents = 64;\r
-       res.maxDrawBuffers = 1;\r
-\r
-       if (ShCompile (impl->_obj._3dlabs_shhandle._obj.handle, strings, impl->_obj.offset_count,\r
-                       EShOptFull, &res, 0))\r
-               impl->_obj.compile_status = GL_TRUE;\r
-       if (impl->_obj.offset_count > 1)\r
-       {\r
-               GLsizei i;\r
-\r
-               for (i = 0; i < impl->_obj.offset_count; i++)\r
-                       _mesa_free (strings[i]);\r
-               _mesa_free (strings);\r
-       }\r
-\r
-       impl->_obj._generic.info_log = _mesa_strdup (ShGetInfoLog (\r
-               impl->_obj._3dlabs_shhandle._obj.handle));\r
-#else\r
-       if (impl->_vftbl->GetSubType (intf) == GL_FRAGMENT_SHADER)\r
-               type = slang_unit_fragment_shader;\r
-       else\r
-               type = slang_unit_vertex_shader;\r
-       slang_info_log_construct (&info_log);\r
-       if (_slang_compile (impl->_obj.source, &impl->_obj.unit, type, &info_log))\r
-       {\r
-               impl->_obj.compile_status = GL_TRUE;\r
-       }\r
-       if (info_log.text != NULL)\r
-               impl->_obj._generic.info_log = _mesa_strdup (info_log.text);\r
-       else\r
-               impl->_obj._generic.info_log = _mesa_strdup ("");\r
-       slang_info_log_destruct (&info_log);\r
-#endif\r
-}\r
-\r
-static struct gl2_shader_intf _shader_vftbl = {\r
-       {\r
-               {\r
-                       _unknown_AddRef,\r
-                       _unknown_Release,\r
-                       _shader_QueryInterface\r
-               },\r
-               _generic_Delete,\r
-               _shader_GetType,\r
-               _generic_GetName,\r
-               _generic_GetDeleteStatus,\r
-               _generic_GetInfoLog\r
-       },\r
-       NULL,           /* abstract GetSubType */\r
-       _shader_GetCompileStatus,\r
-       _shader_SetSource,\r
-       _shader_GetSource,\r
-       _shader_Compile\r
-};\r
-\r
-static void\r
-_shader_constructor (struct gl2_shader_impl *impl)\r
-{\r
-       _generic_constructor ((struct gl2_generic_impl *) impl);\r
-       _3dlabs_shhandle_constructor (&impl->_obj._3dlabs_shhandle, (struct gl2_unknown_intf **)\r
-               &impl->_vftbl);\r
-       impl->_vftbl = &_shader_vftbl;\r
-       impl->_obj._generic._unknown._destructor = _shader_destructor;\r
-       impl->_obj.compile_status = GL_FALSE;\r
-       impl->_obj.source = NULL;\r
-       impl->_obj.offsets = NULL;\r
-       impl->_obj.offset_count = 0;\r
-}\r
-\r
-struct gl2_program_obj\r
-{\r
-       struct gl2_container_obj _container;\r
-       GLboolean link_status;\r
-       GLboolean validate_status;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle linker;\r
-       ShHandle uniforms;\r
-#endif\r
-       slang_program prog;\r
-};\r
-\r
-struct gl2_program_impl\r
-{\r
-       struct gl2_program_intf *_vftbl;\r
-       struct gl2_program_obj _obj;\r
-};\r
-\r
-static void\r
-_program_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       ShDestruct (impl->_obj.linker);\r
-       ShDestruct (impl->_obj.uniforms);\r
-#endif\r
-       _container_destructor (intf);\r
-       slang_program_dtr (&impl->_obj.prog);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_program_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_PROGRAM)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _container_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_program_GetType (struct gl2_generic_intf **intf)\r
-{\r
-       return GL_PROGRAM_OBJECT_ARB;\r
-}\r
-\r
-static GLboolean\r
-_program_Attach (struct gl2_container_intf **intf, struct gl2_generic_intf **att)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_unknown_intf **sha;\r
-\r
-       sha = (**att)._unknown.QueryInterface ((struct gl2_unknown_intf **) att, UIID_SHADER);\r
-       if (sha == NULL)\r
-       {\r
-               _mesa_error (ctx, GL_INVALID_OPERATION, "_program_Attach");\r
-               return GL_FALSE;\r
-       }\r
-\r
-       (**sha).Release (sha);\r
-       return _container_Attach (intf, att);\r
-}\r
-\r
-static GLboolean\r
-_program_GetLinkStatus (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       return impl->_obj.link_status;\r
-}\r
-\r
-static GLboolean\r
-_program_GetValidateStatus (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       return impl->_obj.validate_status;\r
-}\r
-\r
-static GLvoid\r
-_program_Link (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-#if USE_3DLABS_FRONTEND\r
-       ShHandle *handles;\r
-#endif\r
-       GLuint i, count;\r
-       slang_translation_unit *units[2];\r
-\r
-       impl->_obj.link_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._container._generic.info_log);\r
-       impl->_obj._container._generic.info_log = NULL;\r
-       slang_program_dtr (&impl->_obj.prog);\r
-       slang_program_ctr (&impl->_obj.prog);\r
-\r
-#if USE_3DLABS_FRONTEND\r
-       handles = (ShHandle *) _mesa_malloc (impl->_obj._container.attached_count * sizeof (ShHandle));\r
-       if (handles == NULL)\r
-               return;\r
-\r
-       for (i = 0; i < impl->_obj._container.attached_count; i++)\r
-       {\r
-               struct gl2_generic_intf **gen = impl->_obj._container.attached[i];\r
-               struct gl2_3dlabs_shhandle_intf **sh;\r
-\r
-               sh = (struct gl2_3dlabs_shhandle_intf **) (**gen)._unknown.QueryInterface (\r
-                       (struct gl2_unknown_intf **) gen, UIID_3DLABS_SHHANDLE);\r
-               if (sh != NULL)\r
-               {\r
-                       handles[i] = (**sh).GetShHandle (sh);\r
-                       (**sh)._unknown.Release ((struct gl2_unknown_intf **) sh);\r
-               }\r
-               else\r
-               {\r
-                       _mesa_free (handles);\r
-                       return;\r
-               }\r
-       }\r
-\r
-       if (ShLink (impl->_obj.linker, handles, impl->_obj._container.attached_count,\r
-                       impl->_obj.uniforms, NULL, NULL))\r
-               impl->_obj.link_status = GL_TRUE;\r
-\r
-       impl->_obj._container._generic.info_log = _mesa_strdup (ShGetInfoLog (impl->_obj.linker));\r
-#else\r
-       count = impl->_obj._container.attached_count;\r
-       if (count == 0 || count > 2)\r
-               return;\r
-       for (i = 0; i < count; i++)\r
-       {\r
-               struct gl2_generic_intf **obj;\r
-               struct gl2_unknown_intf **unk;\r
-               struct gl2_shader_impl *sha;\r
-\r
-               obj = impl->_obj._container.attached[i];\r
-               unk = (**obj)._unknown.QueryInterface ((struct gl2_unknown_intf **) obj, UIID_SHADER);\r
-               (**obj)._unknown.Release ((struct gl2_unknown_intf **) obj);\r
-               if (unk == NULL)\r
-                       return;\r
-               sha = (struct gl2_shader_impl *) unk;\r
-               units[i] = &sha->_obj.unit;\r
-               (**unk).Release (unk);\r
-       }\r
-\r
-       impl->_obj.link_status = _slang_link (&impl->_obj.prog, units, count);\r
-       if (impl->_obj.link_status)\r
-               impl->_obj._container._generic.info_log = _mesa_strdup ("Link OK.\n");\r
-       else\r
-               impl->_obj._container._generic.info_log = _mesa_strdup ("Link failed.\n");\r
-#endif\r
-}\r
-\r
-static GLvoid\r
-_program_Validate (struct gl2_program_intf **intf)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-\r
-       impl->_obj.validate_status = GL_FALSE;\r
-       _mesa_free ((void *) impl->_obj._container._generic.info_log);\r
-       impl->_obj._container._generic.info_log = NULL;\r
-\r
-       /* TODO validate */\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed (slang_program *pro, GLuint index, const GLvoid *src, GLuint off, GLuint size)\r
-{\r
-       GLuint i;\r
-\r
-       for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-       {\r
-               GLuint addr;\r
-\r
-               addr = pro->common_fixed_entries[i][index];\r
-               if (addr != ~0)\r
-               {\r
-                       GLubyte *dst;\r
-\r
-                       dst = (GLubyte *) pro->machines[i]->mem + addr + off * size;\r
-                       _mesa_memcpy (dst, src, size);\r
-               }\r
-       }\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_mat4 (slang_program *pro, GLmatrix *matrix, GLuint off, GLuint i, GLuint ii,\r
-                         GLuint it, GLuint iit)\r
-{\r
-       GLfloat mat[16];\r
-\r
-       /* we want inverse matrix */\r
-       if (!matrix->inv)\r
-       {\r
-               /* allocate inverse matrix and make it dirty */\r
-               _math_matrix_alloc_inv (matrix);\r
-               _math_matrix_loadf (matrix, matrix->m);\r
-       }\r
-       _math_matrix_analyse (matrix);\r
-\r
-       write_common_fixed (pro, i, matrix->m, off, 16 * sizeof (GLfloat));\r
-\r
-       /* inverse */\r
-       write_common_fixed (pro, ii, matrix->inv, off, 16 * sizeof (GLfloat));\r
-\r
-       /* transpose */\r
-       _math_transposef (mat, matrix->m);\r
-       write_common_fixed (pro, it, mat, off, 16 * sizeof (GLfloat));\r
-\r
-       /* inverse transpose */\r
-       _math_transposef (mat, matrix->inv);\r
-       write_common_fixed (pro, iit, mat, off, 16 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_material (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e, GLuint a,\r
-                             GLuint d, GLuint sp, GLuint sh)\r
-{\r
-       GLfloat v[17];\r
-\r
-       COPY_4FV(v, ctx->Light.Material.Attrib[e]);\r
-       COPY_4FV((v + 4), ctx->Light.Material.Attrib[a]);\r
-       COPY_4FV((v + 8), ctx->Light.Material.Attrib[d]);\r
-       COPY_4FV((v + 12), ctx->Light.Material.Attrib[sp]);\r
-       v[16] = ctx->Light.Material.Attrib[sh][0];\r
-       write_common_fixed (pro, i, v, 0, 17 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_light_model_product (GLcontext *ctx, slang_program *pro, GLuint i, GLuint e,\r
-                                        GLuint a)\r
-{\r
-       GLfloat v[4];\r
-\r
-       SCALE_4V(v,     ctx->Light.Material.Attrib[a], ctx->Light.Model.Ambient);\r
-       ACC_4V(v, ctx->Light.Material.Attrib[e]);\r
-       write_common_fixed (pro, i, v, 0, 4 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-write_common_fixed_light_product (GLcontext *ctx, slang_program *pro, GLuint off, GLuint i, GLuint a,\r
-                                  GLuint d, GLuint s)\r
-{\r
-       GLfloat v[12];\r
-\r
-       SCALE_4V(v, ctx->Light.Light[off].Ambient, ctx->Light.Material.Attrib[a]);\r
-       SCALE_4V((v + 4), ctx->Light.Light[off].Diffuse, ctx->Light.Material.Attrib[d]);\r
-       SCALE_4V((v + 8), ctx->Light.Light[off].Specular, ctx->Light.Material.Attrib[s]);\r
-       write_common_fixed (pro, i, v, off, 12 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedUniforms (struct gl2_program_intf **intf)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint i;\r
-       GLfloat v[29];\r
-       GLfloat *p;\r
-\r
-       /* MODELVIEW matrix */\r
-       write_common_fixed_mat4 (pro, ctx->ModelviewMatrixStack.Top, 0,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIX,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWMATRIXINVERSETRANSPOSE);\r
-\r
-       /* PROJECTION matrix */\r
-       write_common_fixed_mat4 (pro, ctx->ProjectionMatrixStack.Top, 0,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIX,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_PROJECTIONMATRIXINVERSETRANSPOSE);\r
-\r
-       /* MVP matrix */\r
-       write_common_fixed_mat4 (pro, &ctx->_ModelProjectMatrix, 0,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIX,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXTRANSPOSE,\r
-               SLANG_COMMON_FIXED_MODELVIEWPROJECTIONMATRIXINVERSETRANSPOSE);\r
-\r
-       for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)\r
-       {\r
-               /* TEXTURE matrix */\r
-               write_common_fixed_mat4 (pro, ctx->TextureMatrixStack[i].Top, i,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIX,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSE,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXTRANSPOSE,\r
-                       SLANG_COMMON_FIXED_TEXTUREMATRIXINVERSETRANSPOSE);\r
-\r
-               /* EYE_PLANE texture-coordinate generation */\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANES, ctx->Texture.Unit[i].EyePlaneS,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANET, ctx->Texture.Unit[i].EyePlaneT,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANER, ctx->Texture.Unit[i].EyePlaneR,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_EYEPLANEQ, ctx->Texture.Unit[i].EyePlaneQ,\r
-                       i, 4 * sizeof (GLfloat));\r
-\r
-               /* OBJECT_PLANE texture-coordinate generation */\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANES, ctx->Texture.Unit[i].ObjectPlaneS,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANET, ctx->Texture.Unit[i].ObjectPlaneT,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANER, ctx->Texture.Unit[i].ObjectPlaneR,\r
-                       i, 4 * sizeof (GLfloat));\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_OBJECTPLANEQ, ctx->Texture.Unit[i].ObjectPlaneQ,\r
-                       i, 4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* NORMAL matrix - upper 3x3 inverse transpose of MODELVIEW matrix */\r
-       p = ctx->ModelviewMatrixStack.Top->inv;\r
-       v[0] = p[0];\r
-       v[1] = p[4];\r
-       v[2] = p[8];\r
-       v[3] = p[1];\r
-       v[4] = p[5];\r
-       v[5] = p[9];\r
-       v[6] = p[2];\r
-       v[7] = p[6];\r
-       v[8] = p[10];\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALMATRIX, v, 0, 9 * sizeof (GLfloat));\r
-\r
-       /* normal scale */\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_NORMALSCALE, &ctx->_ModelViewInvScale, 0, sizeof (GLfloat));\r
-\r
-       /* depth range parameters */\r
-       v[0] = ctx->Viewport.Near;\r
-       v[1] = ctx->Viewport.Far;\r
-       v[2] = ctx->Viewport.Far - ctx->Viewport.Near;\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_DEPTHRANGE, v, 0, 3 * sizeof (GLfloat));\r
-\r
-       /* CLIP_PLANEi */\r
-       for (i = 0; i < ctx->Const.MaxClipPlanes; i++)\r
-       {\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_CLIPPLANE, ctx->Transform.EyeUserPlane[i], i,\r
-                       4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* point parameters */\r
-       v[0] = ctx->Point.Size;\r
-       v[1] = ctx->Point.MinSize;\r
-       v[2] = ctx->Point.MaxSize;\r
-       v[3] = ctx->Point.Threshold;\r
-       COPY_3FV((v + 4), ctx->Point.Params);\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_POINT, v, 0, 7 * sizeof (GLfloat));\r
-\r
-       /* material parameters */\r
-       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_FRONTMATERIAL,\r
-               MAT_ATTRIB_FRONT_EMISSION,\r
-               MAT_ATTRIB_FRONT_AMBIENT,\r
-               MAT_ATTRIB_FRONT_DIFFUSE,\r
-               MAT_ATTRIB_FRONT_SPECULAR,\r
-               MAT_ATTRIB_FRONT_SHININESS);\r
-       write_common_fixed_material (ctx, pro, SLANG_COMMON_FIXED_BACKMATERIAL,\r
-               MAT_ATTRIB_BACK_EMISSION,\r
-               MAT_ATTRIB_BACK_AMBIENT,\r
-               MAT_ATTRIB_BACK_DIFFUSE,\r
-               MAT_ATTRIB_BACK_SPECULAR,\r
-               MAT_ATTRIB_BACK_SHININESS);\r
-\r
-       for (i = 0; i < ctx->Const.MaxLights; i++)\r
-       {\r
-               /* light source parameters */\r
-               COPY_4FV(v, ctx->Light.Light[i].Ambient);\r
-               COPY_4FV((v + 4), ctx->Light.Light[i].Diffuse);\r
-               COPY_4FV((v + 8), ctx->Light.Light[i].Specular);\r
-               COPY_4FV((v + 12), ctx->Light.Light[i].EyePosition);\r
-               COPY_2FV((v + 16), ctx->Light.Light[i].EyePosition);\r
-               v[18] = ctx->Light.Light[i].EyePosition[2] + 1.0f;\r
-               NORMALIZE_3FV((v + 16));\r
-               v[19] = 0.0f;\r
-               COPY_3V((v + 20), ctx->Light.Light[i].EyeDirection);\r
-               v[23] = ctx->Light.Light[i].SpotExponent;\r
-               v[24] = ctx->Light.Light[i].SpotCutoff;\r
-               v[25] = ctx->Light.Light[i]._CosCutoffNeg;\r
-               v[26] = ctx->Light.Light[i].ConstantAttenuation;\r
-               v[27] = ctx->Light.Light[i].LinearAttenuation;\r
-               v[28] = ctx->Light.Light[i].QuadraticAttenuation;\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTSOURCE, v, i, 29 * sizeof (GLfloat));\r
-\r
-               /* light product */\r
-               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_FRONTLIGHTPRODUCT,\r
-                       MAT_ATTRIB_FRONT_AMBIENT,\r
-                       MAT_ATTRIB_FRONT_DIFFUSE,\r
-                       MAT_ATTRIB_FRONT_SPECULAR);\r
-               write_common_fixed_light_product (ctx, pro, i, SLANG_COMMON_FIXED_BACKLIGHTPRODUCT,\r
-                       MAT_ATTRIB_BACK_AMBIENT,\r
-                       MAT_ATTRIB_BACK_DIFFUSE,\r
-                       MAT_ATTRIB_BACK_SPECULAR);\r
-       }\r
-\r
-       /* light model parameters */\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_LIGHTMODEL, ctx->Light.Model.Ambient, 0, 4 * sizeof (GLfloat));\r
-\r
-       /* light model product */\r
-       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_FRONTLIGHTMODELPRODUCT,\r
-               MAT_ATTRIB_FRONT_EMISSION,\r
-               MAT_ATTRIB_FRONT_AMBIENT);\r
-       write_common_fixed_light_model_product (ctx, pro, SLANG_COMMON_FIXED_BACKLIGHTMODELPRODUCT,\r
-               MAT_ATTRIB_BACK_EMISSION,\r
-               MAT_ATTRIB_BACK_AMBIENT);\r
-\r
-       /* TEXTURE_ENV_COLOR */\r
-       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)\r
-       {\r
-               write_common_fixed (pro, SLANG_COMMON_FIXED_TEXTUREENVCOLOR, ctx->Texture.Unit[i].EnvColor,\r
-                       i, 4 * sizeof (GLfloat));\r
-       }\r
-\r
-       /* fog parameters */\r
-       COPY_4FV(v, ctx->Fog.Color);\r
-       v[4] = ctx->Fog.Density;\r
-       v[5] = ctx->Fog.Start;\r
-       v[6] = ctx->Fog.End;\r
-       v[7] = ctx->Fog._Scale;\r
-       write_common_fixed (pro, SLANG_COMMON_FIXED_FOG, v, 0, 8 * sizeof (GLfloat));\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedAttribute (struct gl2_program_intf **intf, GLuint index, GLvoid *data,\r
-                                                         GLuint offset, GLuint size, GLboolean write)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       addr = pro->vertex_fixed_entries[index];\r
-       if (addr != ~0)\r
-       {\r
-               GLubyte *mem;\r
-\r
-               mem = (GLubyte *) pro->machines[SLANG_SHADER_VERTEX]->mem + addr + offset * size;\r
-               if (write)\r
-                       _mesa_memcpy (mem, data, size);\r
-               else\r
-                       _mesa_memcpy (data, mem, size);\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateFixedVarying (struct gl2_program_intf **intf, GLuint index, GLvoid *data,\r
-                                                       GLuint offset, GLuint size, GLboolean write)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       addr = pro->fragment_fixed_entries[index];\r
-       if (addr != ~0)\r
-       {\r
-               GLubyte *mem;\r
-\r
-               mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + offset * size;\r
-               if (write)\r
-                       _mesa_memcpy (mem, data, size);\r
-               else\r
-                       _mesa_memcpy (data, mem, size);\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_GetTextureImageUsage (struct gl2_program_intf **intf, GLbitfield *teximageusage)\r
-{\r
-       GET_CURRENT_CONTEXT(ctx);\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint i;\r
-\r
-       for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++)\r
-               teximageusage[i] = 0;\r
-\r
-       for (i = 0; i < pro->texture_usage.count; i++)\r
-       {\r
-               GLuint n, addr, j;\r
-\r
-               n = slang_export_data_quant_elements (pro->texture_usage.table[i].quant);\r
-               addr = pro->texture_usage.table[i].frag_address;\r
-               for (j = 0; j < n; j++)\r
-               {\r
-                       GLubyte *mem;\r
-                       GLuint image;\r
-\r
-                       mem = (GLubyte *) pro->machines[SLANG_SHADER_FRAGMENT]->mem + addr + j * 4;\r
-                       image = (GLuint) *((GLfloat *) mem);\r
-                       if (image >= 0 && image < ctx->Const.MaxTextureImageUnits)\r
-                       {\r
-                               switch (slang_export_data_quant_type (pro->texture_usage.table[i].quant))\r
-                               {\r
-                               case GL_SAMPLER_1D_ARB:\r
-                               case GL_SAMPLER_1D_SHADOW_ARB:\r
-                                       teximageusage[image] |= TEXTURE_1D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_2D_ARB:\r
-                               case GL_SAMPLER_2D_SHADOW_ARB:\r
-                                       teximageusage[image] |= TEXTURE_2D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_3D_ARB:\r
-                                       teximageusage[image] |= TEXTURE_3D_BIT;\r
-                                       break;\r
-                               case GL_SAMPLER_CUBE_ARB:\r
-                                       teximageusage[image] |= TEXTURE_CUBE_BIT;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* TODO: make sure that for 0<=i<=MaxTextureImageUint bitcount(teximageuint[i])<=0 */\r
-}\r
-\r
-static GLboolean\r
-_program_IsShaderPresent (struct gl2_program_intf **intf, GLenum subtype)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-\r
-       switch (subtype)\r
-       {\r
-       case GL_VERTEX_SHADER_ARB:\r
-               return pro->machines[SLANG_SHADER_VERTEX] != NULL;\r
-       case GL_FRAGMENT_SHADER_ARB:\r
-               return pro->machines[SLANG_SHADER_FRAGMENT] != NULL;\r
-       default:\r
-               return GL_FALSE;\r
-       }\r
-}\r
-\r
-static GLvoid\r
-_program_UpdateVarying (struct gl2_program_intf **intf, GLuint index, GLfloat *value,\r
-       GLboolean vert)\r
-{\r
-       struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;\r
-       slang_program *pro = &impl->_obj.prog;\r
-       GLuint addr;\r
-\r
-       if (index >= pro->varyings.total)\r
-               return;\r
-       if (vert)\r
-               addr = pro->varyings.slots[index].vert_addr / 4;\r
-       else\r
-               addr = pro->varyings.slots[index].frag_addr / 4;\r
-       if (addr != ~0)\r
-       {\r
-               if (vert)\r
-                       *value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float;\r
-               else\r
-                       pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value;\r
-       }\r
-}\r
-\r
-static struct gl2_program_intf _program_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _program_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _program_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _program_Attach,\r
-               _container_Detach,\r
-               _container_GetAttachedCount,\r
-               _container_GetAttached\r
-       },\r
-       _program_GetLinkStatus,\r
-       _program_GetValidateStatus,\r
-       _program_Link,\r
-       _program_Validate,\r
-       _program_UpdateFixedUniforms,\r
-       _program_UpdateFixedAttribute,\r
-       _program_UpdateFixedVarying,\r
-       _program_GetTextureImageUsage,\r
-       _program_IsShaderPresent,\r
-       _program_UpdateVarying\r
-};\r
-\r
-static void\r
-_program_constructor (struct gl2_program_impl *impl)\r
-{\r
-       _container_constructor ((struct gl2_container_impl *) impl);\r
-       impl->_vftbl = &_program_vftbl;\r
-       impl->_obj._container._generic._unknown._destructor = _program_destructor;\r
-       impl->_obj.link_status = GL_FALSE;\r
-       impl->_obj.validate_status = GL_FALSE;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj.linker = ShConstructLinker (EShExVertexFragment, 0);\r
-       impl->_obj.uniforms = ShConstructUniformMap ();\r
-#endif\r
-       slang_program_ctr (&impl->_obj.prog);\r
-}\r
-\r
-struct gl2_fragment_shader_obj\r
-{\r
-       struct gl2_shader_obj _shader;\r
-};\r
-\r
-struct gl2_fragment_shader_impl\r
-{\r
-       struct gl2_fragment_shader_intf *_vftbl;\r
-       struct gl2_fragment_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_fragment_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_fragment_shader_impl *impl = (struct gl2_fragment_shader_impl *) intf;\r
-\r
-       (void) impl;\r
-       /* TODO free fragment shader data */\r
-\r
-       _shader_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_fragment_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_FRAGMENT_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _shader_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_fragment_shader_GetSubType (struct gl2_shader_intf **intf)\r
-{\r
-       return GL_FRAGMENT_SHADER_ARB;\r
-}\r
-\r
-static struct gl2_fragment_shader_intf _fragment_shader_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _fragment_shader_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _shader_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _fragment_shader_GetSubType,\r
-               _shader_GetCompileStatus,\r
-               _shader_SetSource,\r
-               _shader_GetSource,\r
-               _shader_Compile\r
-       }\r
-};\r
-\r
-static void\r
-_fragment_shader_constructor (struct gl2_fragment_shader_impl *impl)\r
-{\r
-       _shader_constructor ((struct gl2_shader_impl *) impl);\r
-       impl->_vftbl = &_fragment_shader_vftbl;\r
-       impl->_obj._shader._generic._unknown._destructor = _fragment_shader_destructor;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangFragment, 0);\r
-#endif\r
-}\r
-\r
-struct gl2_vertex_shader_obj\r
-{\r
-       struct gl2_shader_obj _shader;\r
-};\r
-\r
-struct gl2_vertex_shader_impl\r
-{\r
-       struct gl2_vertex_shader_intf *_vftbl;\r
-       struct gl2_vertex_shader_obj _obj;\r
-};\r
-\r
-static void\r
-_vertex_shader_destructor (struct gl2_unknown_intf **intf)\r
-{\r
-       struct gl2_vertex_shader_impl *impl = (struct gl2_vertex_shader_impl *) intf;\r
-\r
-       (void) impl;\r
-       /* TODO free vertex shader data */\r
-\r
-       _shader_destructor (intf);\r
-}\r
-\r
-static struct gl2_unknown_intf **\r
-_vertex_shader_QueryInterface (struct gl2_unknown_intf **intf, enum gl2_uiid uiid)\r
-{\r
-       if (uiid == UIID_VERTEX_SHADER)\r
-       {\r
-               (**intf).AddRef (intf);\r
-               return intf;\r
-       }\r
-       return _shader_QueryInterface (intf, uiid);\r
-}\r
-\r
-static GLenum\r
-_vertex_shader_GetSubType (struct gl2_shader_intf **intf)\r
-{\r
-       return GL_VERTEX_SHADER_ARB;\r
-}\r
-\r
-static struct gl2_vertex_shader_intf _vertex_shader_vftbl = {\r
-       {\r
-               {\r
-                       {\r
-                               _unknown_AddRef,\r
-                               _unknown_Release,\r
-                               _vertex_shader_QueryInterface\r
-                       },\r
-                       _generic_Delete,\r
-                       _shader_GetType,\r
-                       _generic_GetName,\r
-                       _generic_GetDeleteStatus,\r
-                       _generic_GetInfoLog\r
-               },\r
-               _vertex_shader_GetSubType,\r
-               _shader_GetCompileStatus,\r
-               _shader_SetSource,\r
-               _shader_GetSource,\r
-               _shader_Compile\r
-       }\r
-};\r
-\r
-static void\r
-_vertex_shader_constructor (struct gl2_vertex_shader_impl *impl)\r
-{\r
-       _shader_constructor ((struct gl2_shader_impl *) impl);\r
-       impl->_vftbl = &_vertex_shader_vftbl;\r
-       impl->_obj._shader._generic._unknown._destructor = _vertex_shader_destructor;\r
-#if USE_3DLABS_FRONTEND\r
-       impl->_obj._shader._3dlabs_shhandle._obj.handle = ShConstructCompiler (EShLangVertex, 0);\r
-#endif\r
-}\r
-\r
-GLhandleARB\r
-_mesa_3dlabs_create_shader_object (GLenum shaderType)\r
-{\r
-       switch (shaderType)\r
-       {\r
-       case GL_FRAGMENT_SHADER_ARB:\r
-               {\r
-                       struct gl2_fragment_shader_impl *x = (struct gl2_fragment_shader_impl *)\r
-                               _mesa_malloc (sizeof (struct gl2_fragment_shader_impl));\r
-\r
-                       if (x != NULL)\r
-                       {\r
-                               _fragment_shader_constructor (x);\r
-                               return x->_obj._shader._generic.name;\r
-                       }\r
-               }\r
-               break;\r
-       case GL_VERTEX_SHADER_ARB:\r
-               {\r
-                       struct gl2_vertex_shader_impl *x = (struct gl2_vertex_shader_impl *)\r
-                               _mesa_malloc (sizeof (struct gl2_vertex_shader_impl));\r
-\r
-                       if (x != NULL)\r
-                       {\r
-                               _vertex_shader_constructor (x);\r
-                               return x->_obj._shader._generic.name;\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-GLhandleARB\r
-_mesa_3dlabs_create_program_object (void)\r
-{\r
-       struct gl2_program_impl *x = (struct gl2_program_impl *) \r
-               _mesa_malloc (sizeof (struct gl2_program_impl));\r
-\r
-       if (x != NULL)\r
-       {\r
-               _program_constructor (x);\r
-               return x->_obj._container._generic.name;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-#include "slang_assemble.h"\r
-#include "slang_execute.h"\r
-\r
-int _slang_fetch_discard (struct gl2_program_intf **pro, GLboolean *val)\r
-{\r
-       struct gl2_program_impl *impl;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       *val = impl->_obj.prog.machines[SLANG_SHADER_FRAGMENT]->kill ? GL_TRUE : GL_FALSE;\r
-       return 1;\r
-}\r
-\r
-static GLvoid exec_shader (struct gl2_program_intf **pro, GLuint i)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_program *p;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       p = &impl->_obj.prog;\r
-\r
-       slang_machine_init (p->machines[i]);\r
-       p->machines[i]->ip = p->code[i][SLANG_COMMON_CODE_MAIN];\r
-\r
-       _slang_execute2 (p->assemblies[i], p->machines[i]);\r
-}\r
-\r
-GLvoid _slang_exec_fragment_shader (struct gl2_program_intf **pro)\r
-{\r
-       exec_shader (pro, SLANG_SHADER_FRAGMENT);\r
-}\r
-\r
-GLvoid _slang_exec_vertex_shader (struct gl2_program_intf **pro)\r
-{\r
-       exec_shader (pro, SLANG_SHADER_VERTEX);\r
-}\r
-\r
-GLint _slang_get_uniform_location (struct gl2_program_intf **pro, const char *name)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_uniform_bindings *bind;\r
-       GLuint i;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       bind = &impl->_obj.prog.uniforms;\r
-       for (i = 0; i < bind->count; i++)\r
-               if (_mesa_strcmp (bind->table[i].name, name) == 0)\r
-                       return i;\r
-       return -1;\r
-}\r
-\r
-GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsizei count,\r
-       const GLvoid *data, GLenum type)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_uniform_bindings *bind;\r
-       slang_uniform_binding *b;\r
-       GLuint i;\r
-       GLboolean convert_float_to_bool = GL_FALSE;\r
-       GLboolean convert_int_to_bool = GL_FALSE;\r
-       GLboolean convert_int_to_float = GL_FALSE;\r
-       GLboolean types_match = GL_FALSE;\r
-\r
-       if (loc == -1)\r
-               return GL_TRUE;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       bind = &impl->_obj.prog.uniforms;\r
-       if (loc >= bind->count)\r
-               return GL_FALSE;\r
-\r
-       b = &bind->table[loc];\r
-       /* TODO: check sizes */\r
-       if (slang_export_data_quant_struct (b->quant))\r
-               return GL_FALSE;\r
-\r
-       switch (slang_export_data_quant_type (b->quant))\r
-       {\r
-       case GL_BOOL_ARB:\r
-               types_match = (type == GL_FLOAT) || (type == GL_INT);\r
-               if (type == GL_FLOAT)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC2_ARB:\r
-               types_match = (type == GL_FLOAT_VEC2_ARB) || (type == GL_INT_VEC2_ARB);\r
-               if (type == GL_FLOAT_VEC2_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC3_ARB:\r
-               types_match = (type == GL_FLOAT_VEC3_ARB) || (type == GL_INT_VEC3_ARB);\r
-               if (type == GL_FLOAT_VEC3_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_BOOL_VEC4_ARB:\r
-               types_match = (type == GL_FLOAT_VEC4_ARB) || (type == GL_INT_VEC4_ARB);\r
-               if (type == GL_FLOAT_VEC4_ARB)\r
-                       convert_float_to_bool = GL_TRUE;\r
-               else\r
-                       convert_int_to_bool = GL_TRUE;\r
-               break;\r
-       case GL_SAMPLER_1D_ARB:\r
-       case GL_SAMPLER_2D_ARB:\r
-       case GL_SAMPLER_3D_ARB:\r
-       case GL_SAMPLER_CUBE_ARB:\r
-       case GL_SAMPLER_1D_SHADOW_ARB:\r
-       case GL_SAMPLER_2D_SHADOW_ARB:\r
-               types_match = (type == GL_INT);\r
-               break;\r
-       default:\r
-               types_match = (type == slang_export_data_quant_type (b->quant));\r
-               break;\r
-       }\r
-\r
-       if (!types_match)\r
-               return GL_FALSE;\r
-\r
-       switch (type)\r
-       {\r
-       case GL_INT:\r
-       case GL_INT_VEC2_ARB:\r
-       case GL_INT_VEC3_ARB:\r
-       case GL_INT_VEC4_ARB:\r
-               convert_int_to_float = GL_TRUE;\r
-               break;\r
-       }\r
-\r
-       if (convert_float_to_bool)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLfloat *src = (GLfloat *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;\r
-                       }\r
-       }\r
-       else if (convert_int_to_bool)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLuint *src = (GLuint *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = src[j] ? 1.0f : 0.0f;\r
-                       }\r
-       }\r
-       else if (convert_int_to_float)\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               const GLuint *src = (GLuint *) (data);\r
-                               GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);\r
-                               GLuint j;\r
-                               GLuint total = count * slang_export_data_quant_components (b->quant);\r
-\r
-                               for (j = 0; j < total; j++)\r
-                                       dst[j] = (GLfloat) src[j];\r
-                       }\r
-       }\r
-       else\r
-       {\r
-               for (i = 0; i < SLANG_SHADER_MAX; i++)\r
-                       if (b->address[i] != ~0)\r
-                       {\r
-                               _mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data,\r
-                                       count * slang_export_data_quant_size (b->quant));\r
-                       }\r
-       }\r
-       return GL_TRUE;\r
-}\r
-\r
-GLuint _slang_get_active_uniform_count (struct gl2_program_intf **pro)\r
-{\r
-       struct gl2_program_impl *impl;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       return impl->_obj.prog.active_uniforms.count;\r
-}\r
-\r
-GLuint _slang_get_active_uniform_max_length (struct gl2_program_intf **pro)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       GLuint i, len = 0;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       for (i = 0; i < impl->_obj.prog.active_uniforms.count; i++)\r
-       {\r
-               GLuint n = _mesa_strlen (impl->_obj.prog.active_uniforms.table[i].name);\r
-               if (n > len)\r
-                       len = n;\r
-       }\r
-       return len;\r
-}\r
-\r
-GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, GLsizei maxLength,\r
-       GLsizei *length, GLint *size, GLenum *type, char *name)\r
-{\r
-       struct gl2_program_impl *impl;\r
-       slang_active_uniform *u;\r
-       GLsizei len;\r
-\r
-       impl = (struct gl2_program_impl *) pro;\r
-       u = &impl->_obj.prog.active_uniforms.table[index];\r
-\r
-       len = _mesa_strlen (u->name);\r
-       if (len >= maxLength)\r
-               len = maxLength - 1;\r
-       _mesa_memcpy (name, u->name, len);\r
-       name[len] = '\0';\r
-       if (length != NULL)\r
-               *length = len;\r
-       *type = slang_export_data_quant_type (u->quant);\r
-       *size = slang_export_data_quant_elements (u->quant);\r
-}\r
-\r
-void\r
-_mesa_init_shaderobjects_3dlabs (GLcontext *ctx)\r
-{\r
-#if USE_3DLABS_FRONTEND\r
-       _glslang_3dlabs_InitProcess ();\r
-       _glslang_3dlabs_ShInitialize ();\r
-#endif\r
-}\r
-\r
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file shaderobjects_3dlabs.c
+ * shader objects definitions for 3dlabs compiler
+ * \author Michal Krol
+ */
+
+/* Set this to 1 when we are ready to use 3dlabs' front-end */
+#define USE_3DLABS_FRONTEND 0
+
+#include "imports.h"
+#include "hash.h"
+#include "macros.h"
+#include "shaderobjects.h"
+#include "shaderobjects_3dlabs.h"
+
+#if USE_3DLABS_FRONTEND
+#include "slang_mesa.h"
+#include "Public/ShaderLang.h"
+#else
+#include "slang_link.h"
+#endif
+
+#if FEATURE_ARB_shader_objects
+
+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 GLvoid
+_generic_GetInfoLog(struct gl2_generic_intf **intf, GLsizei maxlen,
+                    GLcharARB * infolog)
+{
+   struct gl2_generic_impl *impl = (struct gl2_generic_impl *) (intf);
+
+   if (maxlen > 0) {
+      _mesa_strncpy(infolog, impl->_obj.info_log, maxlen - 1);
+      infolog[maxlen - 1] = '\0';
+   }
+}
+
+static GLsizei
+_generic_GetInfoLogLength(struct gl2_generic_intf **intf)
+{
+   struct gl2_generic_impl *impl = (struct gl2_generic_impl *) (intf);
+
+   if (impl->_obj.info_log == NULL)
+      return 1;
+   return _mesa_strlen(impl->_obj.info_log) + 1;
+}
+
+static struct gl2_generic_intf _generic_vftbl = {
+   {
+    _unknown_AddRef,
+    _unknown_Release,
+    _generic_QueryInterface},
+   _generic_Delete,
+   NULL,                        /* abstract GetType */
+   _generic_GetName,
+   _generic_GetDeleteStatus,
+   _generic_GetInfoLog,
+   _generic_GetInfoLogLength
+};
+
+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,
+      _generic_GetInfoLogLength
+   },
+   _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_code_object code;
+};
+
+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);
+   _slang_code_object_dtr(&impl->_obj.code);
+   _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 GLvoid
+_shader_GetInfoLog(struct gl2_generic_intf **intf, GLsizei maxlen,
+                   GLcharARB * infolog)
+{
+   struct gl2_shader_impl *impl = (struct gl2_shader_impl *) (intf);
+
+   if (maxlen > 0) {
+      if (impl->_obj._generic.info_log != NULL) {
+         GLsizei len = _mesa_strlen(impl->_obj._generic.info_log);
+         if (len > maxlen - 1)
+            len = maxlen - 1;
+         _mesa_memcpy(infolog, impl->_obj._generic.info_log, len);
+         infolog += len;
+         maxlen -= len;
+      }
+      if (impl->_obj.code.machine.infolog != NULL &&
+          impl->_obj.code.machine.infolog->text != NULL) {
+         GLsizei len = _mesa_strlen(impl->_obj.code.machine.infolog->text);
+         if (len > maxlen - 1)
+            len = maxlen - 1;
+         _mesa_memcpy(infolog, impl->_obj.code.machine.infolog->text, len);
+      }
+      infolog[maxlen - 1] = '\0';
+   }
+}
+
+static GLsizei
+_shader_GetInfoLogLength(struct gl2_generic_intf **intf)
+{
+   struct gl2_shader_impl *impl = (struct gl2_shader_impl *) (intf);
+   GLsizei length = 1;
+
+   if (impl->_obj._generic.info_log != NULL)
+      length += _mesa_strlen(impl->_obj._generic.info_log);
+   if (impl->_obj.code.machine.infolog != NULL &&
+       impl->_obj.code.machine.infolog->text != NULL)
+      length += _mesa_strlen(impl->_obj.code.machine.infolog->text);
+   return length;
+}
+
+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.code, 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 if (impl->_obj.compile_status)
+      impl->_obj._generic.info_log = _mesa_strdup("Compile OK.\n");
+   else
+      impl->_obj._generic.info_log = _mesa_strdup("Compile failed.\n");
+   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,
+      _shader_GetInfoLog,
+      _shader_GetInfoLogLength
+   },
+   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;
+   _slang_code_object_ctr(&impl->_obj.code);
+}
+
+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_code_object *code[2];
+   GLboolean all_compiled = GL_TRUE;
+
+   impl->_obj.link_status = GL_FALSE;
+   _mesa_free((void *) impl->_obj._container._generic.info_log);
+   impl->_obj._container._generic.info_log = NULL;
+   _slang_program_rst(&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 > 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);
+      if (unk == NULL)
+         return;
+      sha = (struct gl2_shader_impl *) unk;
+      code[i] = &sha->_obj.code;
+      all_compiled = all_compiled && sha->_obj.compile_status;
+      (**unk).Release(unk);
+   }
+
+   impl->_obj.link_status = all_compiled;
+   if (!impl->_obj.link_status) {
+      impl->_obj._container._generic.info_log =
+         _mesa_strdup
+         ("Error: One or more shaders has not successfully compiled.\n");
+      return;
+   }
+
+   impl->_obj.link_status = _slang_link(&impl->_obj.prog, code, count);
+   if (!impl->_obj.link_status) {
+      impl->_obj._container._generic.info_log =
+         _mesa_strdup("Link failed.\n");
+      return;
+   }
+
+   impl->_obj._container._generic.info_log = _mesa_strdup("Link OK.\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_UpdateFixedAttrib(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);
+   }
+}
+
+
+/**
+ * Called during fragment shader execution to either load a varying
+ * register with values, or fetch values from a varying register.
+ * \param intf  the internal program?
+ * \param index  which varying register, one of the SLANG_FRAGMENT_FIXED_*
+ *               values for example.
+ * \param data  source values to load (or dest to write to)
+ * \param offset  indicates a texture unit or generic varying attribute
+ * \param size  number of bytes to copy
+ * \param write  if true, write to the varying register, else store values
+ *               in 'data'
+ */
+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;
+}
+
+/**
+ * Write a uniform variable into program's memory.
+ * \return GL_TRUE for success, GL_FALSE if error
+ */
+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 < 0 || 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;
+   }
+
+   for (i = 0; i < SLANG_SHADER_MAX; i++) {
+      if (uniform->address[i] != ~0) {
+         void *dest
+            = &impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4];
+         /* total number of values to copy */
+         GLuint total
+            = count * slang_export_data_quant_components(uniform->quant);
+         GLuint j;
+         if (convert_float_to_bool) {
+            const GLfloat *src = (GLfloat *) (data);
+            GLfloat *dst = (GLfloat *) dest;
+            for (j = 0; j < total; j++)
+               dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;
+            break;
+         }
+         else if (convert_int_to_bool) {
+            const GLint *src = (GLint *) (data);
+            GLfloat *dst = (GLfloat *) dest;
+            for (j = 0; j < total; j++)
+               dst[j] = src[j] ? 1.0f : 0.0f;
+            break;
+         }
+         else if (convert_int_to_float) {
+            const GLint *src = (GLint *) (data);
+            GLfloat *dst = (GLfloat *) dest;
+            for (j = 0; j < total; j++)
+               dst[j] = (GLfloat) src[j];
+            break;
+         }
+         else {
+            _mesa_memcpy(dest, data, total * sizeof(GLfloat));
+            break;
+         }
+         break;
+      }
+   }
+   return GL_TRUE;
+}
+
+/**
+ * Read a uniform variable from program's memory.
+ * \return GL_TRUE for success, GL_FALSE if error
+ */
+static GLboolean
+_program_ReadUniform(struct gl2_program_intf **intf, GLint loc,
+                     GLsizei count, GLvoid *data, GLenum type)
+{
+   struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+   const slang_uniform_bindings *uniforms = &impl->_obj.prog.uniforms;
+   const slang_uniform_binding *uniform;
+   GLuint i;
+   GLboolean convert_bool_to_float = GL_FALSE;
+   GLboolean convert_bool_to_int = GL_FALSE;
+   GLboolean convert_float_to_int = GL_FALSE;
+   GLboolean types_match = GL_FALSE;
+
+   if (loc < 0 || loc >= uniforms->count)
+      return GL_FALSE;
+
+   uniform = &uniforms->table[loc];
+
+   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_bool_to_float = GL_TRUE;
+      else
+         convert_bool_to_int = 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_bool_to_float = GL_TRUE;
+      else
+         convert_bool_to_int = 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_bool_to_float = GL_TRUE;
+      else
+         convert_bool_to_int = 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_bool_to_float = GL_TRUE;
+      else
+         convert_bool_to_int = 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:
+      /* uniform is a float type */
+      types_match = (type == GL_FLOAT);
+      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_float_to_int = GL_TRUE;
+      break;
+   }
+
+   for (i = 0; i < SLANG_SHADER_MAX; i++) {
+      if (uniform->address[i] != ~0) {
+         /* XXX if bools are really implemented as floats, some of this
+          * could probably be culled out.
+          */
+         const void *source
+            = &impl->_obj.prog.machines[i]->mem[uniform->address[i] / 4];
+         /* total number of values to copy */
+         const GLuint total
+            = count * slang_export_data_quant_components(uniform->quant);
+         GLuint j;
+         if (convert_bool_to_float) {
+            GLfloat *dst = (GLfloat *) (data);
+            const GLfloat *src = (GLfloat *) source;
+            for (j = 0; j < total; j++)
+               dst[j] = src[j] == 0.0 ? 0.0 : 1.0;
+         }
+         else if (convert_bool_to_int) {
+            GLint *dst = (GLint *) (data);
+            const GLfloat *src = (GLfloat *) source;
+            for (j = 0; j < total; j++)
+               dst[j] = src[j] == 0.0 ? 0 : 1;
+         }
+         else if (convert_float_to_int) {
+            GLint *dst = (GLint *) (data);
+            const GLfloat *src = (GLfloat *) source;
+            for (j = 0; j < total; j++)
+               dst[j] = (GLint) src[j];
+         }
+         else {
+            /* no type conversion needed */
+            _mesa_memcpy(data, source, total * sizeof(GLfloat));
+         }
+         break;
+      } /* if */
+   } /* for */
+
+   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_WriteAttrib(struct gl2_program_intf **intf, GLuint index,
+                     const GLfloat * value)
+{
+   struct gl2_program_impl *impl = (struct gl2_program_impl *) (intf);
+   slang_program *pro = &impl->_obj.prog;
+   slang_attrib_slot *slot = &pro->attribs.slots[index];
+
+   /*
+    * Generic attributes can be allocated in a shader with scalar, vec
+    * or mat type.  For scalar and vec types (specifically float, vec2
+    * and vec3) this is simple - just ignore the extra components. For
+    * mat type this is more complicated - the vertex_shader spec
+    * requires to store every column of a matrix in a separate attrib
+    * slot.  To prvent from overwriting data from neighbouring matrix
+    * columns, the "fill" information is kept to know how many
+    * components to copy.
+    */
+
+   if (slot->addr != ~0)
+      _mesa_memcpy(&pro->machines[SLANG_SHADER_VERTEX]->mem[slot->addr / 4].
+                   _float, value, slot->fill * sizeof(GLfloat));
+}
+
+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,
+         _generic_GetInfoLogLength
+      },
+      _program_Attach,
+      _container_Detach,
+      _container_GetAttachedCount,
+      _container_GetAttached
+   },
+   _program_GetLinkStatus,
+   _program_GetValidateStatus,
+   _program_Link,
+   _program_Validate,
+   _program_UpdateFixedUniforms,
+   _program_UpdateFixedAttrib,
+   _program_UpdateFixedVarying,
+   _program_GetTextureImageUsage,
+   _program_IsShaderPresent,
+   _program_GetActiveUniform,
+   _program_GetActiveUniformMaxLength,
+   _program_GetActiveUniformCount,
+   _program_GetUniformLocation,
+   _program_WriteUniform,
+   _program_ReadUniform,
+   _program_GetActiveAttrib,
+   _program_GetActiveAttribMaxLength,
+   _program_GetActiveAttribCount,
+   _program_GetAttribLocation,
+   _program_OverrideAttribBinding,
+   _program_WriteAttrib,
+   _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,
+         _shader_GetInfoLog,
+         _shader_GetInfoLogLength
+      },
+      _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,
+         _shader_GetInfoLog,
+         _shader_GetInfoLogLength
+      },
+      _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
+}
+
+struct gl2_debug_obj
+{
+   struct gl2_generic_obj _generic;
+};
+
+struct gl2_debug_impl
+{
+   struct gl2_debug_intf *_vftbl;
+   struct gl2_debug_obj _obj;
+};
+
+static GLvoid
+_debug_destructor(struct gl2_unknown_intf **intf)
+{
+   struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf);
+
+   (void) (impl);
+   /* TODO */
+
+   _generic_destructor(intf);
+}
+
+static struct gl2_unknown_intf **
+_debug_QueryInterface(struct gl2_unknown_intf **intf, enum gl2_uiid uiid)
+{
+   if (uiid == UIID_DEBUG) {
+      (**intf).AddRef(intf);
+      return intf;
+   }
+   return _generic_QueryInterface(intf, uiid);
+}
+
+static GLenum
+_debug_GetType(struct gl2_generic_intf **intf)
+{
+   return /*GL_DEBUG_OBJECT_MESA */ 0;
+}
+
+static GLvoid
+_debug_ClearDebugLog(struct gl2_debug_intf **intf, GLenum logType,
+                     GLenum shaderType)
+{
+   struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf);
+
+   (void) (impl);
+   /* TODO */
+}
+
+static GLvoid
+_debug_GetDebugLog(struct gl2_debug_intf **intf, GLenum logType,
+                   GLenum shaderType, GLsizei maxLength, GLsizei * length,
+                   GLcharARB * infoLog)
+{
+   struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf);
+
+   (void) (impl);
+   /* TODO */
+}
+
+static GLsizei
+_debug_GetDebugLogLength(struct gl2_debug_intf **intf, GLenum logType,
+                         GLenum shaderType)
+{
+   struct gl2_debug_impl *impl = (struct gl2_debug_impl *) (intf);
+
+   (void) (impl);
+   /* TODO */
+
+   return 0;
+}
+
+static struct gl2_debug_intf _debug_vftbl = {
+   {
+      {
+         _unknown_AddRef,
+         _unknown_Release,
+         _debug_QueryInterface
+      },
+      _generic_Delete,
+      _debug_GetType,
+      _generic_GetName,
+      _generic_GetDeleteStatus,
+      _generic_GetInfoLog,
+      _generic_GetInfoLogLength
+   },
+   _debug_ClearDebugLog,
+   _debug_GetDebugLog,
+   _debug_GetDebugLogLength
+};
+
+static GLvoid
+_debug_constructor(struct gl2_debug_impl *impl)
+{
+   _generic_constructor((struct gl2_generic_impl *) (impl));
+   impl->_vftbl = &_debug_vftbl;
+   impl->_obj._generic._unknown._destructor = _debug_destructor;
+}
+
+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;
+}
+
+GLhandleARB
+_mesa_3dlabs_create_debug_object(GLvoid)
+{
+   struct gl2_debug_impl *obj;
+
+   obj =
+      (struct gl2_debug_impl *) (_mesa_malloc(sizeof(struct gl2_debug_impl)));
+   if (obj != NULL) {
+      _debug_constructor(obj);
+      return obj->_obj._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);
+}
+
+#endif
+
+void
+_mesa_init_shaderobjects_3dlabs(GLcontext * ctx)
+{
+#if USE_3DLABS_FRONTEND
+   _glslang_3dlabs_InitProcess();
+   _glslang_3dlabs_ShInitialize();
+#endif
+}