diff options
Diffstat (limited to 'src/mesa/shader/shaderobjects_3dlabs.c')
-rwxr-xr-x | src/mesa/shader/shaderobjects_3dlabs.c | 2144 |
1 files changed, 2144 insertions, 0 deletions
diff --git a/src/mesa/shader/shaderobjects_3dlabs.c b/src/mesa/shader/shaderobjects_3dlabs.c new file mode 100755 index 0000000000..3ead1a1784 --- /dev/null +++ b/src/mesa/shader/shaderobjects_3dlabs.c @@ -0,0 +1,2144 @@ +/* + * 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 +} |