diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_link2.c')
-rw-r--r-- | src/mesa/shader/slang/slang_link2.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/mesa/shader/slang/slang_link2.c b/src/mesa/shader/slang/slang_link2.c new file mode 100644 index 00000000000..e62cc01b3e1 --- /dev/null +++ b/src/mesa/shader/slang/slang_link2.c @@ -0,0 +1,226 @@ +/* + * Mesa 3-D graphics library + * Version: 6.6 + * + * Copyright (C) 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 slang_link.c + * slang linker + * \author Michal Krol + */ + +#include "imports.h" +#include "context.h" +#include "hash.h" +#include "macros.h" +#include "program.h" +#include "shaderobjects.h" +#include "slang_link.h" + + + + +#define RELEASE_GENERIC(x)\ + (**x)._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_CONTAINER(x)\ + (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_PROGRAM(x)\ + (**x)._container._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + +#define RELEASE_SHADER(x)\ + (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x)) + + + +static struct gl2_unknown_intf ** +lookup_handle(GLcontext * ctx, GLhandleARB handle, enum gl2_uiid uiid, + const char *function) +{ + struct gl2_unknown_intf **unk; + + /* + * Note: _mesa_HashLookup() requires non-zero input values, so the + * passed-in handle value must be checked beforehand. + */ + if (handle == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, function); + return NULL; + } + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + unk = (struct gl2_unknown_intf **) _mesa_HashLookup(ctx->Shared->GL2Objects, + handle); + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + + if (unk == NULL) { + _mesa_error(ctx, GL_INVALID_VALUE, function); + } + else { + unk = (**unk).QueryInterface(unk, uiid); + if (unk == NULL) + _mesa_error(ctx, GL_INVALID_OPERATION, function); + } + return unk; +} + +#define GET_GENERIC(x, handle, function)\ + struct gl2_generic_intf **x = (struct gl2_generic_intf **)\ + lookup_handle (ctx, handle, UIID_GENERIC, function); + +#define GET_CONTAINER(x, handle, function)\ + struct gl2_container_intf **x = (struct gl2_container_intf **)\ + lookup_handle (ctx, handle, UIID_CONTAINER, function); + +#define GET_PROGRAM(x, handle, function)\ + struct gl2_program_intf **x = (struct gl2_program_intf **)\ + lookup_handle (ctx, handle, UIID_PROGRAM, function); + +#define GET_SHADER(x, handle, function)\ + struct gl2_shader_intf **x = (struct gl2_shader_intf **)\ + lookup_handle (ctx, handle, UIID_SHADER, function); + + +static void +prelink(GLhandleARB programObj, struct gl_linked_program *linked) +{ + GET_CURRENT_CONTEXT(ctx); + + linked->VertexProgram = NULL; + linked->FragmentProgram = NULL; + + if (programObj != 0) { + GET_PROGRAM(program, programObj, "glUseProgramObjectARB(program)"); + + if (program == NULL) + return; + + /* XXX terrible hack to find the real vertex/fragment programs */ + { + GLuint handle; + GLsizei cnt, i; + cnt = (**program)._container.GetAttachedCount((struct gl2_container_intf **) (program)); + + for (i = 0; i < cnt; i++) { + struct gl2_generic_intf **x + = (**program)._container.GetAttached((struct gl2_container_intf **) program, i); + handle = (**x).GetName(x); + { + struct gl_program *prog; + GET_SHADER(sha, handle, "foo"); + if (sha && (*sha)->Program) { + prog = (*sha)->Program; + if (prog->Target == GL_VERTEX_PROGRAM_ARB) + linked->VertexProgram = (struct gl_vertex_program *) prog; + else if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) + linked->FragmentProgram = (struct gl_fragment_program *) prog; + } + } +#if 0 + if (linked->VertexProgram) + printf("Found vert prog %p %d\n", + linked->VertexProgram, + linked->VertexProgram->Base.NumInstructions); + if (linked->FragmentProgram) + printf("Found frag prog %p %d\n", + linked->FragmentProgram, + linked->FragmentProgram->Base.NumInstructions); +#endif + RELEASE_GENERIC(x); + } + } + + } +} + + + +void +_slang_link2(GLcontext *ctx, + GLhandleARB programObj, + struct gl_linked_program *linked) +{ + struct gl_vertex_program *vertProg; + struct gl_fragment_program *fragProg; + + prelink(programObj, linked); + + vertProg = linked->VertexProgram; + fragProg = linked->FragmentProgram; + + /* free old linked data, if any */ + if (linked->NumUniforms > 0) { + GLuint i; + for (i = 0; i < linked->NumUniforms; i++) { + _mesa_free((char *) linked->Uniforms[i].Name); + linked->Uniforms[i].Name = NULL; + linked->Uniforms[i].Value = NULL; + } + linked->NumUniforms = 0; + } + + /* + * Find uniforms. + * XXX what about dups? + */ + if (vertProg) { + GLuint i; + for (i = 0; i < vertProg->Base.Parameters->NumParameters; i++) { + struct gl_program_parameter *p + = vertProg->Base.Parameters->Parameters + i; + if (p->Name) { + struct gl_uniform *u = linked->Uniforms + linked->NumUniforms; + u->Name = _mesa_strdup(p->Name); + u->Value = &vertProg->Base.Parameters->ParameterValues[i][0]; + linked->NumUniforms++; + assert(linked->NumUniforms < MAX_UNIFORMS); + } + } + } + if (fragProg) { + GLuint i; + for (i = 0; i < fragProg->Base.Parameters->NumParameters; i++) { + struct gl_program_parameter *p + = fragProg->Base.Parameters->Parameters + i; + if (p->Name) { + struct gl_uniform *u = linked->Uniforms + linked->NumUniforms; + u->Name = _mesa_strdup(p->Name); + u->Value = &fragProg->Base.Parameters->ParameterValues[i][0]; + linked->NumUniforms++; + assert(linked->NumUniforms < MAX_UNIFORMS); + } + } + } + + /* For varying: + * scan both programs for varyings, rewrite programs so they agree + * on locations of varyings. + */ + + /** + * Linking should _copy_ the vertex and fragment shader code, + * rewriting varying references as we go along... + */ + + linked->LinkStatus = (vertProg && fragProg); +} + |