ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

slang_link.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.3
00004  *
00005  * Copyright (C) 2008  Brian Paul   All Rights Reserved.
00006  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this software and associated documentation files (the "Software"),
00010  * to deal in the Software without restriction, including without limitation
00011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00012  * and/or sell copies of the Software, and to permit persons to whom the
00013  * Software is furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included
00016  * in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00021  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00022  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00023  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00024  */
00025 
00032 #include "main/imports.h"
00033 #include "main/context.h"
00034 #include "main/hash.h"
00035 #include "main/macros.h"
00036 #include "shader/program.h"
00037 #include "shader/prog_instruction.h"
00038 #include "shader/prog_parameter.h"
00039 #include "shader/prog_print.h"
00040 #include "shader/prog_statevars.h"
00041 #include "shader/prog_uniform.h"
00042 #include "shader/shader_api.h"
00043 #include "slang_link.h"
00044 
00045 
00047 static struct gl_vertex_program *
00048 vertex_program(struct gl_program *prog)
00049 {
00050    assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
00051    return (struct gl_vertex_program *) prog;
00052 }
00053 
00054 
00056 static struct gl_fragment_program *
00057 fragment_program(struct gl_program *prog)
00058 {
00059    assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
00060    return (struct gl_fragment_program *) prog;
00061 }
00062 
00063 
00067 static void
00068 link_error(struct gl_shader_program *shProg, const char *msg)
00069 {
00070    if (shProg->InfoLog) {
00071       _mesa_free(shProg->InfoLog);
00072    }
00073    shProg->InfoLog = _mesa_strdup(msg);
00074    shProg->LinkStatus = GL_FALSE;
00075 }
00076 
00077 
00078 
00082 static GLboolean
00083 bits_agree(GLbitfield flags1, GLbitfield flags2, GLbitfield bit)
00084 {
00085    return (flags1 & bit) == (flags2 & bit);
00086 }
00087 
00088 
00099 static GLboolean
00100 link_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog)
00101 {
00102    GLuint *map, i, firstVarying, newFile;
00103    GLbitfield *inOutFlags;
00104 
00105    map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint));
00106    if (!map)
00107       return GL_FALSE;
00108 
00109    /* Varying variables are treated like other vertex program outputs
00110     * (and like other fragment program inputs).  The position of the
00111     * first varying differs for vertex/fragment programs...
00112     * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT.
00113     */
00114    if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
00115       firstVarying = VERT_RESULT_VAR0;
00116       newFile = PROGRAM_OUTPUT;
00117       inOutFlags = prog->OutputFlags;
00118    }
00119    else {
00120       assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);
00121       firstVarying = FRAG_ATTRIB_VAR0;
00122       newFile = PROGRAM_INPUT;
00123       inOutFlags = prog->InputFlags;
00124    }
00125 
00126    for (i = 0; i < prog->Varying->NumParameters; i++) {
00127       /* see if this varying is in the linked varying list */
00128       const struct gl_program_parameter *var = prog->Varying->Parameters + i;
00129       GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name);
00130       if (j >= 0) {
00131          /* varying is already in list, do some error checking */
00132          const struct gl_program_parameter *v =
00133             &shProg->Varying->Parameters[j];
00134          if (var->Size != v->Size) {
00135             link_error(shProg, "mismatched varying variable types");
00136             return GL_FALSE;
00137          }
00138          if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_CENTROID)) {
00139             char msg[100];
00140             _mesa_snprintf(msg, sizeof(msg),
00141                            "centroid modifier mismatch for '%s'", var->Name);
00142             link_error(shProg, msg);
00143             return GL_FALSE;
00144          }
00145          if (!bits_agree(var->Flags, v->Flags, PROG_PARAM_BIT_INVARIANT)) {
00146             char msg[100];
00147             _mesa_snprintf(msg, sizeof(msg),
00148                            "invariant modifier mismatch for '%s'", var->Name);
00149             link_error(shProg, msg);
00150             return GL_FALSE;
00151          }
00152       }
00153       else {
00154          /* not already in linked list */
00155          j = _mesa_add_varying(shProg->Varying, var->Name, var->Size,
00156                                var->Flags);
00157       }
00158 
00159       /* Map varying[i] to varying[j].
00160        * Plus, set prog->Input/OutputFlags[] as described above.
00161        * Note: the loop here takes care of arrays or large (sz>4) vars.
00162        */
00163       {
00164          GLint sz = var->Size;
00165          while (sz > 0) {
00166             inOutFlags[firstVarying + j] = var->Flags;
00167             /*printf("Link varying from %d to %d\n", i, j);*/
00168             map[i++] = j++;
00169             sz -= 4;
00170          }
00171          i--; /* go back one */
00172       }
00173    }
00174 
00175 
00176    /* OK, now scan the program/shader instructions looking for varying vars,
00177     * replacing the old index with the new index.
00178     */
00179    for (i = 0; i < prog->NumInstructions; i++) {
00180       struct prog_instruction *inst = prog->Instructions + i;
00181       GLuint j;
00182 
00183       if (inst->DstReg.File == PROGRAM_VARYING) {
00184          inst->DstReg.File = newFile;
00185          inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying;
00186       }
00187 
00188       for (j = 0; j < 3; j++) {
00189          if (inst->SrcReg[j].File == PROGRAM_VARYING) {
00190             inst->SrcReg[j].File = newFile;
00191             inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying;
00192          }
00193       }
00194    }
00195 
00196    free(map);
00197 
00198    /* these will get recomputed before linking is completed */
00199    prog->InputsRead = 0x0;
00200    prog->OutputsWritten = 0x0;
00201 
00202    return GL_TRUE;
00203 }
00204 
00205 
00224 static GLboolean
00225 link_uniform_vars(GLcontext *ctx,
00226                   struct gl_shader_program *shProg,
00227                   struct gl_program *prog,
00228                   GLuint *numSamplers)
00229 {
00230    GLuint samplerMap[200]; /* max number of samplers declared, not used */
00231    GLuint i;
00232 
00233    for (i = 0; i < prog->Parameters->NumParameters; i++) {
00234       const struct gl_program_parameter *p = prog->Parameters->Parameters + i;
00235 
00236       /*
00237        * XXX FIX NEEDED HERE
00238        * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR.
00239        * For example, modelview matrix, light pos, etc.
00240        * Also, we need to update the state-var name-generator code to
00241        * generate GLSL-style names, like "gl_LightSource[0].position".
00242        * Furthermore, we'll need to fix the state-var's size/datatype info.
00243        */
00244 
00245       if ((p->Type == PROGRAM_UNIFORM || p->Type == PROGRAM_SAMPLER)
00246           && p->Used) {
00247          /* add this uniform, indexing into the target's Parameters list */
00248          struct gl_uniform *uniform =
00249             _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i);
00250          if (uniform)
00251             uniform->Initialized = p->Initialized;
00252       }
00253 
00254       /* The samplerMap[] table we build here is used to remap/re-index
00255        * sampler references by TEX instructions.
00256        */
00257       if (p->Type == PROGRAM_SAMPLER && p->Used) {
00258          /* Allocate a new sampler index */
00259          GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0];
00260          GLuint newSampNum = *numSamplers;
00261          if (newSampNum >= ctx->Const.MaxTextureImageUnits) {
00262             char s[100];
00263             _mesa_sprintf(s, "Too many texture samplers (%u, max is %u)",
00264                           newSampNum, ctx->Const.MaxTextureImageUnits);
00265             link_error(shProg, s);
00266             return GL_FALSE;
00267          }
00268          /* save old->new mapping in the table */
00269          if (oldSampNum < Elements(samplerMap))
00270             samplerMap[oldSampNum] = newSampNum;
00271          /* update parameter's sampler index */
00272          prog->Parameters->ParameterValues[i][0] = (GLfloat) newSampNum;
00273          (*numSamplers)++;
00274       }
00275    }
00276 
00277    /* OK, now scan the program/shader instructions looking for texture
00278     * instructions using sampler vars.  Replace old sampler indexes with
00279     * new ones.
00280     */
00281    prog->SamplersUsed = 0x0;
00282    for (i = 0; i < prog->NumInstructions; i++) {
00283       struct prog_instruction *inst = prog->Instructions + i;
00284       if (_mesa_is_tex_instruction(inst->Opcode)) {
00285          const GLint oldSampNum = inst->TexSrcUnit;
00286 
00287 #if 0
00288          printf("====== remap sampler from %d to %d\n",
00289                 inst->TexSrcUnit, samplerMap[ inst->TexSrcUnit ]);
00290 #endif
00291 
00292          /* here, texUnit is really samplerUnit */
00293          if (oldSampNum < Elements(samplerMap)) {
00294             const GLuint newSampNum = samplerMap[oldSampNum];
00295             inst->TexSrcUnit = newSampNum;
00296             prog->SamplerTargets[newSampNum] = inst->TexSrcTarget;
00297             prog->SamplersUsed |= (1 << newSampNum);
00298          }
00299       }
00300    }
00301 
00302    return GL_TRUE;
00303 }
00304 
00305 
00314 static GLboolean
00315 _slang_resolve_attributes(struct gl_shader_program *shProg,
00316                           const struct gl_program *origProg,
00317                           struct gl_program *linkedProg)
00318 {
00319    GLint attribMap[MAX_VERTEX_ATTRIBS];
00320    GLuint i, j;
00321    GLbitfield usedAttributes; /* generics only, not legacy attributes */
00322 
00323    assert(origProg != linkedProg);
00324    assert(origProg->Target == GL_VERTEX_PROGRAM_ARB);
00325    assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB);
00326 
00327    if (!shProg->Attributes)
00328       shProg->Attributes = _mesa_new_parameter_list();
00329 
00330    if (linkedProg->Attributes) {
00331       _mesa_free_parameter_list(linkedProg->Attributes);
00332    }
00333    linkedProg->Attributes = _mesa_new_parameter_list();
00334 
00335 
00336    /* Build a bitmask indicating which attribute indexes have been
00337     * explicitly bound by the user with glBindAttributeLocation().
00338     */
00339    usedAttributes = 0x0;
00340    for (i = 0; i < shProg->Attributes->NumParameters; i++) {
00341       GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0];
00342       usedAttributes |= (1 << attr);
00343    }
00344 
00345    /* If gl_Vertex is used, that actually counts against the limit
00346     * on generic vertex attributes.  This avoids the ambiguity of
00347     * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos)
00348     * or generic attribute[0].  If gl_Vertex is used, we want the former.
00349     */
00350    if (origProg->InputsRead & VERT_BIT_POS) {
00351       usedAttributes |= 0x1;
00352    }
00353 
00354    /* initialize the generic attribute map entries to -1 */
00355    for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) {
00356       attribMap[i] = -1;
00357    }
00358 
00359    /*
00360     * Scan program for generic attribute references
00361     */
00362    for (i = 0; i < linkedProg->NumInstructions; i++) {
00363       struct prog_instruction *inst = linkedProg->Instructions + i;
00364       for (j = 0; j < 3; j++) {
00365          if (inst->SrcReg[j].File == PROGRAM_INPUT &&
00366              inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) {
00367             /*
00368              * OK, we've found a generic vertex attribute reference.
00369              */
00370             const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0;
00371 
00372             GLint attr = attribMap[k];
00373 
00374             if (attr < 0) {
00375                /* Need to figure out attribute mapping now.
00376                 */
00377                const char *name = origProg->Attributes->Parameters[k].Name;
00378                const GLint size = origProg->Attributes->Parameters[k].Size;
00379                const GLenum type =origProg->Attributes->Parameters[k].DataType;
00380                GLint index;
00381 
00382                /* See if there's a user-defined attribute binding for
00383                 * this name.
00384                 */
00385                index = _mesa_lookup_parameter_index(shProg->Attributes,
00386                                                     -1, name);
00387                if (index >= 0) {
00388                   /* Found a user-defined binding */
00389                   attr = shProg->Attributes->Parameters[index].StateIndexes[0];
00390                }
00391                else {
00392                   /* No user-defined binding, choose our own attribute number.
00393                    * Start at 1 since generic attribute 0 always aliases
00394                    * glVertex/position.
00395                    */
00396                   for (attr = 0; attr < MAX_VERTEX_ATTRIBS; attr++) {
00397                      if (((1 << attr) & usedAttributes) == 0)
00398                         break;
00399                   }
00400                   if (attr == MAX_VERTEX_ATTRIBS) {
00401                      link_error(shProg, "Too many vertex attributes");
00402                      return GL_FALSE;
00403                   }
00404 
00405                   /* mark this attribute as used */
00406                   usedAttributes |= (1 << attr);
00407                }
00408 
00409                attribMap[k] = attr;
00410 
00411                /* Save the final name->attrib binding so it can be queried
00412                 * with glGetAttributeLocation().
00413                 */
00414                _mesa_add_attribute(linkedProg->Attributes, name,
00415                                    size, type, attr);
00416             }
00417 
00418             assert(attr >= 0);
00419 
00420             /* update the instruction's src reg */
00421             inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;
00422          }
00423       }
00424    }
00425 
00426    return GL_TRUE;
00427 }
00428 
00429 
00435 static void
00436 _slang_count_temporaries(struct gl_program *prog)
00437 {
00438    GLuint i, j;
00439    GLint maxIndex = -1;
00440 
00441    for (i = 0; i < prog->NumInstructions; i++) {
00442       const struct prog_instruction *inst = prog->Instructions + i;
00443       const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
00444       for (j = 0; j < numSrc; j++) {
00445          if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {
00446             if (maxIndex < inst->SrcReg[j].Index)
00447                maxIndex = inst->SrcReg[j].Index;
00448          }
00449          if (inst->DstReg.File == PROGRAM_TEMPORARY) {
00450             if (maxIndex < (GLint) inst->DstReg.Index)
00451                maxIndex = inst->DstReg.Index;
00452          }
00453       }
00454    }
00455 
00456    prog->NumTemporaries = (GLuint) (maxIndex + 1);
00457 }
00458 
00459 
00464 static void
00465 _slang_update_inputs_outputs(struct gl_program *prog)
00466 {
00467    GLuint i, j;
00468    GLuint maxAddrReg = 0;
00469 
00470    prog->InputsRead = 0x0;
00471    prog->OutputsWritten = 0x0;
00472 
00473    for (i = 0; i < prog->NumInstructions; i++) {
00474       const struct prog_instruction *inst = prog->Instructions + i;
00475       const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
00476       for (j = 0; j < numSrc; j++) {
00477          if (inst->SrcReg[j].File == PROGRAM_INPUT) {
00478             prog->InputsRead |= 1 << inst->SrcReg[j].Index;
00479             if (prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
00480                 inst->SrcReg[j].Index == FRAG_ATTRIB_FOGC) {
00481                /* The fragment shader FOGC input is used for fog,
00482                 * front-facing and sprite/point coord.
00483                 */
00484                struct gl_fragment_program *fp = fragment_program(prog);
00485                const GLint swz = GET_SWZ(inst->SrcReg[j].Swizzle, 0);
00486                if (swz == SWIZZLE_X)
00487                   fp->UsesFogFragCoord = GL_TRUE;
00488                else if (swz == SWIZZLE_Y)
00489                   fp->UsesFrontFacing = GL_TRUE;
00490                else if (swz == SWIZZLE_Z || swz == SWIZZLE_W)
00491                   fp->UsesPointCoord = GL_TRUE;
00492             }
00493          }
00494          else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) {
00495             maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1));
00496          }
00497       }
00498 
00499       if (inst->DstReg.File == PROGRAM_OUTPUT) {
00500          prog->OutputsWritten |= 1 << inst->DstReg.Index;
00501          if (inst->DstReg.RelAddr) {
00502             /* If the output attribute is indexed with relative addressing
00503              * we know that it must be a varying or texcoord such as
00504              * gl_TexCoord[i] = v;  In this case, mark all the texcoords
00505              * or varying outputs as being written.  It's not an error if
00506              * a vertex shader writes varying vars that aren't used by the
00507              * fragment shader.  But it is an error for a fragment shader
00508              * to use varyings that are not written by the vertex shader.
00509              */
00510             if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
00511                if (inst->DstReg.Index == VERT_RESULT_TEX0) {
00512                   /* mark all texcoord outputs as written */
00513                   const GLbitfield mask =
00514                      ((1 << MAX_TEXTURE_COORD_UNITS) - 1) << VERT_RESULT_TEX0;
00515                   prog->OutputsWritten |= mask;
00516                }
00517                else if (inst->DstReg.Index == VERT_RESULT_VAR0) {
00518                   /* mark all generic varying outputs as written */
00519                   const GLbitfield mask =
00520                      ((1 << MAX_VARYING) - 1) << VERT_RESULT_VAR0;
00521                   prog->OutputsWritten |= mask;
00522                }
00523             }
00524          }
00525       }
00526       else if (inst->DstReg.File == PROGRAM_ADDRESS) {
00527          maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1);
00528       }
00529    }
00530 
00531    prog->NumAddressRegs = maxAddrReg;
00532 }
00533 
00534 
00546 void
00547 _slang_link(GLcontext *ctx,
00548             GLhandleARB programObj,
00549             struct gl_shader_program *shProg)
00550 {
00551    const struct gl_vertex_program *vertProg;
00552    const struct gl_fragment_program *fragProg;
00553    GLuint numSamplers = 0;
00554    GLuint i;
00555 
00556    _mesa_clear_shader_program_data(ctx, shProg);
00557 
00558    /* check that all programs compiled successfully */
00559    for (i = 0; i < shProg->NumShaders; i++) {
00560       if (!shProg->Shaders[i]->CompileStatus) {
00561          link_error(shProg, "linking with uncompiled shader\n");
00562          return;
00563       }
00564    }
00565 
00566    shProg->Uniforms = _mesa_new_uniform_list();
00567    shProg->Varying = _mesa_new_parameter_list();
00568 
00572    vertProg = NULL;
00573    fragProg = NULL;
00574    for (i = 0; i < shProg->NumShaders; i++) {
00575       struct gl_shader *shader = shProg->Shaders[i];
00576       if (shader->Type == GL_VERTEX_SHADER) {
00577          if (shader->Main)
00578             vertProg = vertex_program(shader->Program);
00579       }
00580       else if (shader->Type == GL_FRAGMENT_SHADER) {
00581          if (shader->Main)
00582             fragProg = fragment_program(shader->Program);
00583       }
00584       else {
00585          _mesa_problem(ctx, "unexpected shader target in slang_link()");
00586       }
00587    }
00588 
00589 #if FEATURE_es2_glsl
00590    /* must have both a vertex and fragment program for ES2 */
00591    if (!vertProg) {
00592       link_error(shProg, "missing vertex shader\n");
00593       return;
00594    }
00595    if (!fragProg) {
00596       link_error(shProg, "missing fragment shader\n");
00597       return;
00598    }
00599 #endif
00600 
00601    /*
00602     * Make copies of the vertex/fragment programs now since we'll be
00603     * changing src/dst registers after merging the uniforms and varying vars.
00604     */
00605    _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
00606    if (vertProg) {
00607       struct gl_vertex_program *linked_vprog =
00608          vertex_program(_mesa_clone_program(ctx, &vertProg->Base));
00609       shProg->VertexProgram = linked_vprog; /* refcount OK */
00610       ASSERT(shProg->VertexProgram->Base.RefCount == 1);
00611    }
00612 
00613    _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
00614    if (fragProg) {
00615       struct gl_fragment_program *linked_fprog = 
00616          fragment_program(_mesa_clone_program(ctx, &fragProg->Base));
00617       shProg->FragmentProgram = linked_fprog; /* refcount OK */
00618       ASSERT(shProg->FragmentProgram->Base.RefCount == 1);
00619    }
00620 
00621    /* link varying vars */
00622    if (shProg->VertexProgram) {
00623       if (!link_varying_vars(shProg, &shProg->VertexProgram->Base))
00624          return;
00625    }
00626    if (shProg->FragmentProgram) {
00627       if (!link_varying_vars(shProg, &shProg->FragmentProgram->Base))
00628          return;
00629    }
00630 
00631    /* link uniform vars */
00632    if (shProg->VertexProgram) {
00633       if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base,
00634                              &numSamplers)) {
00635          return;
00636       }
00637    }
00638    if (shProg->FragmentProgram) {
00639       if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base,
00640                              &numSamplers)) {
00641          return;
00642       }
00643    }
00644 
00645    /*_mesa_print_uniforms(shProg->Uniforms);*/
00646 
00647    if (shProg->VertexProgram) {
00648       if (!_slang_resolve_attributes(shProg, &vertProg->Base,
00649                                      &shProg->VertexProgram->Base)) {
00650          return;
00651       }
00652    }
00653 
00654    if (shProg->VertexProgram) {
00655       _slang_update_inputs_outputs(&shProg->VertexProgram->Base);
00656       _slang_count_temporaries(&shProg->VertexProgram->Base);
00657       if (!(shProg->VertexProgram->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {
00658          /* the vertex program did not compute a vertex position */
00659          link_error(shProg,
00660                     "gl_Position was not written by vertex shader\n");
00661          return;
00662       }
00663    }
00664    if (shProg->FragmentProgram) {
00665       _slang_count_temporaries(&shProg->FragmentProgram->Base);
00666       _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);
00667    }
00668 
00669    /* Check that all the varying vars needed by the fragment shader are
00670     * actually produced by the vertex shader.
00671     */
00672    if (shProg->FragmentProgram) {
00673       const GLbitfield varyingRead
00674          = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;
00675       const GLbitfield varyingWritten = shProg->VertexProgram ?
00676          shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;
00677       if ((varyingRead & varyingWritten) != varyingRead) {
00678          link_error(shProg,
00679           "Fragment program using varying vars not written by vertex shader\n");
00680          return;
00681       }         
00682    }
00683 
00684    /* check that gl_FragColor and gl_FragData are not both written to */
00685    if (shProg->FragmentProgram) {
00686       GLbitfield outputsWritten = shProg->FragmentProgram->Base.OutputsWritten;
00687       if ((outputsWritten & ((1 << FRAG_RESULT_COLR))) &&
00688           (outputsWritten >= (1 << FRAG_RESULT_DATA0))) {
00689          link_error(shProg, "Fragment program cannot write both gl_FragColor"
00690                     " and gl_FragData[].\n");
00691          return;
00692       }         
00693    }
00694 
00695 
00696    if (fragProg && shProg->FragmentProgram) {
00697       /* Compute initial program's TexturesUsed info */
00698       _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base);
00699 
00700       /* notify driver that a new fragment program has been compiled/linked */
00701       ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
00702                                       &shProg->FragmentProgram->Base);
00703       if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
00704          printf("Mesa original fragment program:\n");
00705          _mesa_print_program(&fragProg->Base);
00706          _mesa_print_program_parameters(ctx, &fragProg->Base);
00707 
00708          printf("Mesa post-link fragment program:\n");
00709          _mesa_print_program(&shProg->FragmentProgram->Base);
00710          _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);
00711       }
00712    }
00713 
00714    if (vertProg && shProg->VertexProgram) {
00715       /* Compute initial program's TexturesUsed info */
00716       _mesa_update_shader_textures_used(&shProg->VertexProgram->Base);
00717 
00718       /* notify driver that a new vertex program has been compiled/linked */
00719       ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
00720                                       &shProg->VertexProgram->Base);
00721       if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
00722          printf("Mesa original vertex program:\n");
00723          _mesa_print_program(&vertProg->Base);
00724          _mesa_print_program_parameters(ctx, &vertProg->Base);
00725 
00726          printf("Mesa post-link vertex program:\n");
00727          _mesa_print_program(&shProg->VertexProgram->Base);
00728          _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);
00729       }
00730    }
00731 
00732    if (MESA_VERBOSE & VERBOSE_GLSL_DUMP) {
00733       printf("Varying vars:\n");
00734       _mesa_print_parameter_list(shProg->Varying);
00735    }
00736 
00737    shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);
00738 }
00739 

Generated on Sat May 26 2012 04:19:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.