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

program.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  6.5.3
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00032 #include "main/glheader.h"
00033 #include "main/context.h"
00034 #include "main/hash.h"
00035 #include "program.h"
00036 #include "prog_cache.h"
00037 #include "prog_parameter.h"
00038 #include "prog_instruction.h"
00039 
00040 
00045 struct gl_program _mesa_DummyProgram;
00046 
00047 
00051 void
00052 _mesa_init_program(GLcontext *ctx)
00053 {
00054    GLuint i;
00055 
00056    /*
00057     * If this assertion fails, we need to increase the field
00058     * size for register indexes.
00059     */
00060    ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
00061           <= (1 << INST_INDEX_BITS));
00062    ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
00063           <= (1 << INST_INDEX_BITS));
00064 
00065    ctx->Program.ErrorPos = -1;
00066    ctx->Program.ErrorString = _mesa_strdup("");
00067 
00068 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
00069    ctx->VertexProgram.Enabled = GL_FALSE;
00070 #if FEATURE_es2_glsl
00071    ctx->VertexProgram.PointSizeEnabled = GL_TRUE;
00072 #else
00073    ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
00074 #endif
00075    ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
00076    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
00077                             ctx->Shared->DefaultVertexProgram);
00078    assert(ctx->VertexProgram.Current);
00079    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
00080       ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
00081       ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
00082    }
00083    ctx->VertexProgram.Cache = _mesa_new_program_cache();
00084 #endif
00085 
00086 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
00087    ctx->FragmentProgram.Enabled = GL_FALSE;
00088    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
00089                             ctx->Shared->DefaultFragmentProgram);
00090    assert(ctx->FragmentProgram.Current);
00091    ctx->FragmentProgram.Cache = _mesa_new_program_cache();
00092 #endif
00093 
00094 
00095    /* XXX probably move this stuff */
00096 #if FEATURE_ATI_fragment_shader
00097    ctx->ATIFragmentShader.Enabled = GL_FALSE;
00098    ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
00099    assert(ctx->ATIFragmentShader.Current);
00100    ctx->ATIFragmentShader.Current->RefCount++;
00101 #endif
00102 }
00103 
00104 
00108 void
00109 _mesa_free_program_data(GLcontext *ctx)
00110 {
00111 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
00112    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
00113    _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
00114 #endif
00115 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
00116    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
00117    _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache);
00118 #endif
00119    /* XXX probably move this stuff */
00120 #if FEATURE_ATI_fragment_shader
00121    if (ctx->ATIFragmentShader.Current) {
00122       ctx->ATIFragmentShader.Current->RefCount--;
00123       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
00124          _mesa_free(ctx->ATIFragmentShader.Current);
00125       }
00126    }
00127 #endif
00128    _mesa_free((void *) ctx->Program.ErrorString);
00129 }
00130 
00131 
00137 void
00138 _mesa_update_default_objects_program(GLcontext *ctx)
00139 {
00140 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
00141    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
00142                             (struct gl_vertex_program *)
00143                             ctx->Shared->DefaultVertexProgram);
00144    assert(ctx->VertexProgram.Current);
00145 #endif
00146 
00147 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
00148    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
00149                             (struct gl_fragment_program *)
00150                             ctx->Shared->DefaultFragmentProgram);
00151    assert(ctx->FragmentProgram.Current);
00152 #endif
00153 
00154    /* XXX probably move this stuff */
00155 #if FEATURE_ATI_fragment_shader
00156    if (ctx->ATIFragmentShader.Current) {
00157       ctx->ATIFragmentShader.Current->RefCount--;
00158       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
00159          _mesa_free(ctx->ATIFragmentShader.Current);
00160       }
00161    }
00162    ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
00163    assert(ctx->ATIFragmentShader.Current);
00164    ctx->ATIFragmentShader.Current->RefCount++;
00165 #endif
00166 }
00167 
00168 
00173 void
00174 _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string)
00175 {
00176    ctx->Program.ErrorPos = pos;
00177    _mesa_free((void *) ctx->Program.ErrorString);
00178    if (!string)
00179       string = "";
00180    ctx->Program.ErrorString = _mesa_strdup(string);
00181 }
00182 
00183 
00194 const GLubyte *
00195 _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
00196                        GLint *line, GLint *col)
00197 {
00198    const GLubyte *lineStart = string;
00199    const GLubyte *p = string;
00200    GLubyte *s;
00201    int len;
00202 
00203    *line = 1;
00204 
00205    while (p != pos) {
00206       if (*p == (GLubyte) '\n') {
00207          (*line)++;
00208          lineStart = p + 1;
00209       }
00210       p++;
00211    }
00212 
00213    *col = (pos - lineStart) + 1;
00214 
00215    /* return copy of this line */
00216    while (*p != 0 && *p != '\n')
00217       p++;
00218    len = p - lineStart;
00219    s = (GLubyte *) _mesa_malloc(len + 1);
00220    _mesa_memcpy(s, lineStart, len);
00221    s[len] = 0;
00222 
00223    return s;
00224 }
00225 
00226 
00230 static struct gl_program *
00231 _mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog,
00232                            GLenum target, GLuint id)
00233 {
00234    (void) ctx;
00235    if (prog) {
00236       GLuint i;
00237       _mesa_bzero(prog, sizeof(*prog));
00238       prog->Id = id;
00239       prog->Target = target;
00240       prog->Resident = GL_TRUE;
00241       prog->RefCount = 1;
00242       prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
00243 
00244       /* default mapping from samplers to texture units */
00245       for (i = 0; i < MAX_SAMPLERS; i++)
00246          prog->SamplerUnits[i] = i;
00247    }
00248 
00249    return prog;
00250 }
00251 
00252 
00256 struct gl_program *
00257 _mesa_init_fragment_program( GLcontext *ctx, struct gl_fragment_program *prog,
00258                              GLenum target, GLuint id)
00259 {
00260    if (prog)
00261       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
00262    else
00263       return NULL;
00264 }
00265 
00266 
00270 struct gl_program *
00271 _mesa_init_vertex_program( GLcontext *ctx, struct gl_vertex_program *prog,
00272                            GLenum target, GLuint id)
00273 {
00274    if (prog)
00275       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
00276    else
00277       return NULL;
00278 }
00279 
00280 
00293 struct gl_program *
00294 _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id)
00295 {
00296    struct gl_program *prog;
00297    switch (target) {
00298    case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
00299       prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
00300                                        target, id );
00301       break;
00302    case GL_FRAGMENT_PROGRAM_NV:
00303    case GL_FRAGMENT_PROGRAM_ARB:
00304       prog =_mesa_init_fragment_program(ctx,
00305                                          CALLOC_STRUCT(gl_fragment_program),
00306                                          target, id );
00307       break;
00308    default:
00309       _mesa_problem(ctx, "bad target in _mesa_new_program");
00310       prog = NULL;
00311    }
00312    return prog;
00313 }
00314 
00315 
00322 void
00323 _mesa_delete_program(GLcontext *ctx, struct gl_program *prog)
00324 {
00325    (void) ctx;
00326    ASSERT(prog);
00327    ASSERT(prog->RefCount==0);
00328 
00329    if (prog == &_mesa_DummyProgram)
00330       return;
00331 
00332    if (prog->String)
00333       _mesa_free(prog->String);
00334 
00335    _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
00336 
00337    if (prog->Parameters) {
00338       _mesa_free_parameter_list(prog->Parameters);
00339    }
00340    if (prog->Varying) {
00341       _mesa_free_parameter_list(prog->Varying);
00342    }
00343    if (prog->Attributes) {
00344       _mesa_free_parameter_list(prog->Attributes);
00345    }
00346 
00347    /* XXX this is a little ugly */
00348    if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
00349       struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
00350       if (vprog->TnlData)
00351          _mesa_free(vprog->TnlData);
00352    }
00353 
00354    _mesa_free(prog);
00355 }
00356 
00357 
00363 struct gl_program *
00364 _mesa_lookup_program(GLcontext *ctx, GLuint id)
00365 {
00366    if (id)
00367       return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
00368    else
00369       return NULL;
00370 }
00371 
00372 
00376 void
00377 _mesa_reference_program(GLcontext *ctx,
00378                         struct gl_program **ptr,
00379                         struct gl_program *prog)
00380 {
00381    assert(ptr);
00382    if (*ptr && prog) {
00383       /* sanity check */
00384       if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
00385          ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
00386       else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
00387          ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
00388                 prog->Target == GL_FRAGMENT_PROGRAM_NV);
00389    }
00390    if (*ptr == prog) {
00391       return;  /* no change */
00392    }
00393    if (*ptr) {
00394       GLboolean deleteFlag;
00395 
00396       /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
00397 #if 0
00398       printf("Program %p ID=%u Target=%s  Refcount-- to %d\n",
00399              *ptr, (*ptr)->Id,
00400              ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"),
00401              (*ptr)->RefCount - 1);
00402 #endif
00403       ASSERT((*ptr)->RefCount > 0);
00404       (*ptr)->RefCount--;
00405 
00406       deleteFlag = ((*ptr)->RefCount == 0);
00407       /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
00408 
00409       if (deleteFlag) {
00410          ASSERT(ctx);
00411          ctx->Driver.DeleteProgram(ctx, *ptr);
00412       }
00413 
00414       *ptr = NULL;
00415    }
00416 
00417    assert(!*ptr);
00418    if (prog) {
00419       /*_glthread_LOCK_MUTEX(prog->Mutex);*/
00420       prog->RefCount++;
00421 #if 0
00422       printf("Program %p ID=%u Target=%s  Refcount++ to %d\n",
00423              prog, prog->Id,
00424              (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" : "FP"),
00425              prog->RefCount);
00426 #endif
00427       /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
00428    }
00429 
00430    *ptr = prog;
00431 }
00432 
00433 
00439 struct gl_program *
00440 _mesa_clone_program(GLcontext *ctx, const struct gl_program *prog)
00441 {
00442    struct gl_program *clone;
00443 
00444    clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
00445    if (!clone)
00446       return NULL;
00447 
00448    assert(clone->Target == prog->Target);
00449    assert(clone->RefCount == 1);
00450 
00451    clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
00452    clone->Format = prog->Format;
00453    clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
00454    if (!clone->Instructions) {
00455       _mesa_reference_program(ctx, &clone, NULL);
00456       return NULL;
00457    }
00458    _mesa_copy_instructions(clone->Instructions, prog->Instructions,
00459                            prog->NumInstructions);
00460    clone->InputsRead = prog->InputsRead;
00461    clone->OutputsWritten = prog->OutputsWritten;
00462    clone->SamplersUsed = prog->SamplersUsed;
00463    clone->ShadowSamplers = prog->ShadowSamplers;
00464    memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
00465 
00466    if (prog->Parameters)
00467       clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
00468    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
00469    if (prog->Varying)
00470       clone->Varying = _mesa_clone_parameter_list(prog->Varying);
00471    if (prog->Attributes)
00472       clone->Attributes = _mesa_clone_parameter_list(prog->Attributes);
00473    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
00474    clone->NumInstructions = prog->NumInstructions;
00475    clone->NumTemporaries = prog->NumTemporaries;
00476    clone->NumParameters = prog->NumParameters;
00477    clone->NumAttributes = prog->NumAttributes;
00478    clone->NumAddressRegs = prog->NumAddressRegs;
00479    clone->NumNativeInstructions = prog->NumNativeInstructions;
00480    clone->NumNativeTemporaries = prog->NumNativeTemporaries;
00481    clone->NumNativeParameters = prog->NumNativeParameters;
00482    clone->NumNativeAttributes = prog->NumNativeAttributes;
00483    clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
00484    clone->NumAluInstructions = prog->NumAluInstructions;
00485    clone->NumTexInstructions = prog->NumTexInstructions;
00486    clone->NumTexIndirections = prog->NumTexIndirections;
00487    clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
00488    clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
00489    clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
00490 
00491    switch (prog->Target) {
00492    case GL_VERTEX_PROGRAM_ARB:
00493       {
00494          const struct gl_vertex_program *vp
00495             = (const struct gl_vertex_program *) prog;
00496          struct gl_vertex_program *vpc = (struct gl_vertex_program *) clone;
00497          vpc->IsPositionInvariant = vp->IsPositionInvariant;
00498       }
00499       break;
00500    case GL_FRAGMENT_PROGRAM_ARB:
00501       {
00502          const struct gl_fragment_program *fp
00503             = (const struct gl_fragment_program *) prog;
00504          struct gl_fragment_program *fpc = (struct gl_fragment_program *) clone;
00505          fpc->FogOption = fp->FogOption;
00506          fpc->UsesKill = fp->UsesKill;
00507       }
00508       break;
00509    default:
00510       _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
00511    }
00512 
00513    return clone;
00514 }
00515 
00516 
00521 GLboolean
00522 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
00523 {
00524    const GLuint origLen = prog->NumInstructions;
00525    const GLuint newLen = origLen + count;
00526    struct prog_instruction *newInst;
00527    GLuint i;
00528 
00529    /* adjust branches */
00530    for (i = 0; i < prog->NumInstructions; i++) {
00531       struct prog_instruction *inst = prog->Instructions + i;
00532       if (inst->BranchTarget > 0) {
00533          if ((GLuint)inst->BranchTarget >= start) {
00534             inst->BranchTarget += count;
00535          }
00536       }
00537    }
00538 
00539    /* Alloc storage for new instructions */
00540    newInst = _mesa_alloc_instructions(newLen);
00541    if (!newInst) {
00542       return GL_FALSE;
00543    }
00544 
00545    /* Copy 'start' instructions into new instruction buffer */
00546    _mesa_copy_instructions(newInst, prog->Instructions, start);
00547 
00548    /* init the new instructions */
00549    _mesa_init_instructions(newInst + start, count);
00550 
00551    /* Copy the remaining/tail instructions to new inst buffer */
00552    _mesa_copy_instructions(newInst + start + count,
00553                            prog->Instructions + start,
00554                            origLen - start);
00555 
00556    /* free old instructions */
00557    _mesa_free_instructions(prog->Instructions, origLen);
00558 
00559    /* install new instructions */
00560    prog->Instructions = newInst;
00561    prog->NumInstructions = newLen;
00562 
00563    return GL_TRUE;
00564 }
00565 
00566 
00571 GLboolean
00572 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
00573 {
00574    const GLuint origLen = prog->NumInstructions;
00575    const GLuint newLen = origLen - count;
00576    struct prog_instruction *newInst;
00577    GLuint i;
00578 
00579    /* adjust branches */
00580    for (i = 0; i < prog->NumInstructions; i++) {
00581       struct prog_instruction *inst = prog->Instructions + i;
00582       if (inst->BranchTarget > 0) {
00583          if (inst->BranchTarget > start) {
00584             inst->BranchTarget -= count;
00585          }
00586       }
00587    }
00588 
00589    /* Alloc storage for new instructions */
00590    newInst = _mesa_alloc_instructions(newLen);
00591    if (!newInst) {
00592       return GL_FALSE;
00593    }
00594 
00595    /* Copy 'start' instructions into new instruction buffer */
00596    _mesa_copy_instructions(newInst, prog->Instructions, start);
00597 
00598    /* Copy the remaining/tail instructions to new inst buffer */
00599    _mesa_copy_instructions(newInst + start,
00600                            prog->Instructions + start + count,
00601                            newLen - start);
00602 
00603    /* free old instructions */
00604    _mesa_free_instructions(prog->Instructions, origLen);
00605 
00606    /* install new instructions */
00607    prog->Instructions = newInst;
00608    prog->NumInstructions = newLen;
00609 
00610    return GL_TRUE;
00611 }
00612 
00613 
00618 static void
00619 replace_registers(struct prog_instruction *inst, GLuint numInst,
00620                   GLuint oldFile, GLuint oldIndex,
00621                   GLuint newFile, GLuint newIndex)
00622 {
00623    GLuint i, j;
00624    for (i = 0; i < numInst; i++) {
00625       /* src regs */
00626       for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) {
00627          if (inst[i].SrcReg[j].File == oldFile &&
00628              inst[i].SrcReg[j].Index == oldIndex) {
00629             inst[i].SrcReg[j].File = newFile;
00630             inst[i].SrcReg[j].Index = newIndex;
00631          }
00632       }
00633       /* dst reg */
00634       if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
00635          inst[i].DstReg.File = newFile;
00636          inst[i].DstReg.Index = newIndex;
00637       }
00638    }
00639 }
00640 
00641 
00647 static void
00648 adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
00649                      GLuint offset)
00650 {
00651    GLuint i, j;
00652    for (i = 0; i < numInst; i++) {
00653       for (j = 0; j < _mesa_num_inst_src_regs(inst->Opcode); j++) {
00654          GLuint f = inst[i].SrcReg[j].File;
00655          if (f == PROGRAM_CONSTANT ||
00656              f == PROGRAM_UNIFORM ||
00657              f == PROGRAM_STATE_VAR) {
00658             inst[i].SrcReg[j].Index += offset;
00659          }
00660       }
00661    }
00662 }
00663 
00664 
00669 struct gl_program *
00670 _mesa_combine_programs(GLcontext *ctx,
00671                        const struct gl_program *progA,
00672                        const struct gl_program *progB)
00673 {
00674    struct prog_instruction *newInst;
00675    struct gl_program *newProg;
00676    const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
00677    const GLuint lenB = progB->NumInstructions;
00678    const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
00679    const GLuint newLength = lenA + lenB;
00680    GLbitfield inputsB;
00681    GLuint i;
00682 
00683    ASSERT(progA->Target == progB->Target);
00684 
00685    newInst = _mesa_alloc_instructions(newLength);
00686    if (!newInst)
00687       return GL_FALSE;
00688 
00689    _mesa_copy_instructions(newInst, progA->Instructions, lenA);
00690    _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
00691 
00692    /* adjust branch / instruction addresses for B's instructions */
00693    for (i = 0; i < lenB; i++) {
00694       newInst[lenA + i].BranchTarget += lenA;
00695    }
00696 
00697    newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
00698    newProg->Instructions = newInst;
00699    newProg->NumInstructions = newLength;
00700 
00701    if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
00702       struct gl_fragment_program *fprogA, *fprogB, *newFprog;
00703       fprogA = (struct gl_fragment_program *) progA;
00704       fprogB = (struct gl_fragment_program *) progB;
00705       newFprog = (struct gl_fragment_program *) newProg;
00706 
00707       newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
00708 
00709       /* Connect color outputs of fprogA to color inputs of fprogB, via a
00710        * new temporary register.
00711        */
00712       if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) &&
00713           (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) {
00714          GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY);
00715          if (tempReg < 0) {
00716             _mesa_problem(ctx, "No free temp regs found in "
00717                           "_mesa_combine_programs(), using 31");
00718             tempReg = 31;
00719          }
00720          /* replace writes to result.color[0] with tempReg */
00721          replace_registers(newInst, lenA,
00722                            PROGRAM_OUTPUT, FRAG_RESULT_COLR,
00723                            PROGRAM_TEMPORARY, tempReg);
00724          /* replace reads from input.color[0] with tempReg */
00725          replace_registers(newInst + lenA, lenB,
00726                            PROGRAM_INPUT, FRAG_ATTRIB_COL0,
00727                            PROGRAM_TEMPORARY, tempReg);
00728       }
00729 
00730       inputsB = progB->InputsRead;
00731       if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) {
00732          inputsB &= ~(1 << FRAG_ATTRIB_COL0);
00733       }
00734       newProg->InputsRead = progA->InputsRead | inputsB;
00735       newProg->OutputsWritten = progB->OutputsWritten;
00736       newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
00737    }
00738    else {
00739       /* vertex program */
00740       assert(0);      /* XXX todo */
00741    }
00742 
00743    /*
00744     * Merge parameters (uniforms, constants, etc)
00745     */
00746    newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
00747                                                        progB->Parameters);
00748 
00749    adjust_param_indexes(newInst + lenA, lenB, numParamsA);
00750 
00751 
00752    return newProg;
00753 }
00754 
00755 
00756 
00757 
00762 GLint
00763 _mesa_find_free_register(const struct gl_program *prog, GLuint regFile)
00764 {
00765    GLboolean used[MAX_PROGRAM_TEMPS];
00766    GLuint i, k;
00767 
00768    assert(regFile == PROGRAM_INPUT ||
00769           regFile == PROGRAM_OUTPUT ||
00770           regFile == PROGRAM_TEMPORARY);
00771 
00772    _mesa_memset(used, 0, sizeof(used));
00773 
00774    for (i = 0; i < prog->NumInstructions; i++) {
00775       const struct prog_instruction *inst = prog->Instructions + i;
00776       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
00777 
00778       for (k = 0; k < n; k++) {
00779          if (inst->SrcReg[k].File == regFile) {
00780             used[inst->SrcReg[k].Index] = GL_TRUE;
00781          }
00782       }
00783    }
00784 
00785    for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
00786       if (!used[i])
00787          return i;
00788    }
00789 
00790    return -1;
00791 }

Generated on Sat May 26 2012 04:19:22 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.