Home | History | Annotate | Download | only in program
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5.3
      4  *
      5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file program.c
     27  * Vertex and fragment program support functions.
     28  * \author Brian Paul
     29  */
     30 
     31 
     32 #include "main/glheader.h"
     33 #include "main/context.h"
     34 #include "main/hash.h"
     35 #include "main/mfeatures.h"
     36 #include "program.h"
     37 #include "prog_cache.h"
     38 #include "prog_parameter.h"
     39 #include "prog_instruction.h"
     40 
     41 
     42 /**
     43  * A pointer to this dummy program is put into the hash table when
     44  * glGenPrograms is called.
     45  */
     46 struct gl_program _mesa_DummyProgram;
     47 
     48 
     49 /**
     50  * Init context's vertex/fragment program state
     51  */
     52 void
     53 _mesa_init_program(struct gl_context *ctx)
     54 {
     55    GLuint i;
     56 
     57    /*
     58     * If this assertion fails, we need to increase the field
     59     * size for register indexes (see INST_INDEX_BITS).
     60     */
     61    ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4
     62           <= (1 << INST_INDEX_BITS));
     63    ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4
     64           <= (1 << INST_INDEX_BITS));
     65 
     66    ASSERT(ctx->Const.VertexProgram.MaxTemps <= (1 << INST_INDEX_BITS));
     67    ASSERT(ctx->Const.VertexProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
     68    ASSERT(ctx->Const.FragmentProgram.MaxTemps <= (1 << INST_INDEX_BITS));
     69    ASSERT(ctx->Const.FragmentProgram.MaxLocalParams <= (1 << INST_INDEX_BITS));
     70 
     71    ASSERT(ctx->Const.VertexProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
     72    ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents <= 4 * MAX_UNIFORMS);
     73 
     74    ASSERT(ctx->Const.VertexProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
     75    ASSERT(ctx->Const.FragmentProgram.MaxAddressOffset <= (1 << INST_INDEX_BITS));
     76 
     77    /* If this fails, increase prog_instruction::TexSrcUnit size */
     78    ASSERT(MAX_TEXTURE_UNITS <= (1 << 5));
     79 
     80    /* If this fails, increase prog_instruction::TexSrcTarget size */
     81    ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4));
     82 
     83    ctx->Program.ErrorPos = -1;
     84    ctx->Program.ErrorString = _mesa_strdup("");
     85 
     86 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
     87    ctx->VertexProgram.Enabled = GL_FALSE;
     88 #if FEATURE_es2_glsl
     89    ctx->VertexProgram.PointSizeEnabled =
     90       (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
     91 #else
     92    ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
     93 #endif
     94    ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
     95    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
     96                             ctx->Shared->DefaultVertexProgram);
     97    assert(ctx->VertexProgram.Current);
     98    for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
     99       ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
    100       ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
    101    }
    102    ctx->VertexProgram.Cache = _mesa_new_program_cache();
    103 #endif
    104 
    105 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
    106    ctx->FragmentProgram.Enabled = GL_FALSE;
    107    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
    108                             ctx->Shared->DefaultFragmentProgram);
    109    assert(ctx->FragmentProgram.Current);
    110    ctx->FragmentProgram.Cache = _mesa_new_program_cache();
    111 #endif
    112 
    113 #if FEATURE_ARB_geometry_shader4
    114    ctx->GeometryProgram.Enabled = GL_FALSE;
    115    /* right now by default we don't have a geometry program */
    116    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
    117                             NULL);
    118    ctx->GeometryProgram.Cache = _mesa_new_program_cache();
    119 #endif
    120 
    121    /* XXX probably move this stuff */
    122 #if FEATURE_ATI_fragment_shader
    123    ctx->ATIFragmentShader.Enabled = GL_FALSE;
    124    ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
    125    assert(ctx->ATIFragmentShader.Current);
    126    ctx->ATIFragmentShader.Current->RefCount++;
    127 #endif
    128 }
    129 
    130 
    131 /**
    132  * Free a context's vertex/fragment program state
    133  */
    134 void
    135 _mesa_free_program_data(struct gl_context *ctx)
    136 {
    137 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
    138    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
    139    _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
    140 #endif
    141 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
    142    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
    143    _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
    144 #endif
    145 #if FEATURE_ARB_geometry_shader4
    146    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current, NULL);
    147    _mesa_delete_program_cache(ctx, ctx->GeometryProgram.Cache);
    148 #endif
    149    /* XXX probably move this stuff */
    150 #if FEATURE_ATI_fragment_shader
    151    if (ctx->ATIFragmentShader.Current) {
    152       ctx->ATIFragmentShader.Current->RefCount--;
    153       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
    154          free(ctx->ATIFragmentShader.Current);
    155       }
    156    }
    157 #endif
    158    free((void *) ctx->Program.ErrorString);
    159 }
    160 
    161 
    162 /**
    163  * Update the default program objects in the given context to reference those
    164  * specified in the shared state and release those referencing the old
    165  * shared state.
    166  */
    167 void
    168 _mesa_update_default_objects_program(struct gl_context *ctx)
    169 {
    170 #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
    171    _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
    172                             ctx->Shared->DefaultVertexProgram);
    173    assert(ctx->VertexProgram.Current);
    174 #endif
    175 
    176 #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
    177    _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
    178                             ctx->Shared->DefaultFragmentProgram);
    179    assert(ctx->FragmentProgram.Current);
    180 #endif
    181 
    182 #if FEATURE_ARB_geometry_shader4
    183    _mesa_reference_geomprog(ctx, &ctx->GeometryProgram.Current,
    184                       ctx->Shared->DefaultGeometryProgram);
    185 #endif
    186 
    187    /* XXX probably move this stuff */
    188 #if FEATURE_ATI_fragment_shader
    189    if (ctx->ATIFragmentShader.Current) {
    190       ctx->ATIFragmentShader.Current->RefCount--;
    191       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
    192          free(ctx->ATIFragmentShader.Current);
    193       }
    194    }
    195    ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
    196    assert(ctx->ATIFragmentShader.Current);
    197    ctx->ATIFragmentShader.Current->RefCount++;
    198 #endif
    199 }
    200 
    201 
    202 /**
    203  * Set the vertex/fragment program error state (position and error string).
    204  * This is generally called from within the parsers.
    205  */
    206 void
    207 _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
    208 {
    209    ctx->Program.ErrorPos = pos;
    210    free((void *) ctx->Program.ErrorString);
    211    if (!string)
    212       string = "";
    213    ctx->Program.ErrorString = _mesa_strdup(string);
    214 }
    215 
    216 
    217 /**
    218  * Find the line number and column for 'pos' within 'string'.
    219  * Return a copy of the line which contains 'pos'.  Free the line with
    220  * free().
    221  * \param string  the program string
    222  * \param pos     the position within the string
    223  * \param line    returns the line number corresponding to 'pos'.
    224  * \param col     returns the column number corresponding to 'pos'.
    225  * \return copy of the line containing 'pos'.
    226  */
    227 const GLubyte *
    228 _mesa_find_line_column(const GLubyte *string, const GLubyte *pos,
    229                        GLint *line, GLint *col)
    230 {
    231    const GLubyte *lineStart = string;
    232    const GLubyte *p = string;
    233    GLubyte *s;
    234    int len;
    235 
    236    *line = 1;
    237 
    238    while (p != pos) {
    239       if (*p == (GLubyte) '\n') {
    240          (*line)++;
    241          lineStart = p + 1;
    242       }
    243       p++;
    244    }
    245 
    246    *col = (pos - lineStart) + 1;
    247 
    248    /* return copy of this line */
    249    while (*p != 0 && *p != '\n')
    250       p++;
    251    len = p - lineStart;
    252    s = (GLubyte *) malloc(len + 1);
    253    memcpy(s, lineStart, len);
    254    s[len] = 0;
    255 
    256    return s;
    257 }
    258 
    259 
    260 /**
    261  * Initialize a new vertex/fragment program object.
    262  */
    263 static struct gl_program *
    264 _mesa_init_program_struct( struct gl_context *ctx, struct gl_program *prog,
    265                            GLenum target, GLuint id)
    266 {
    267    (void) ctx;
    268    if (prog) {
    269       GLuint i;
    270       memset(prog, 0, sizeof(*prog));
    271       prog->Id = id;
    272       prog->Target = target;
    273       prog->Resident = GL_TRUE;
    274       prog->RefCount = 1;
    275       prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
    276 
    277       /* default mapping from samplers to texture units */
    278       for (i = 0; i < MAX_SAMPLERS; i++)
    279          prog->SamplerUnits[i] = i;
    280    }
    281 
    282    return prog;
    283 }
    284 
    285 
    286 /**
    287  * Initialize a new fragment program object.
    288  */
    289 struct gl_program *
    290 _mesa_init_fragment_program( struct gl_context *ctx, struct gl_fragment_program *prog,
    291                              GLenum target, GLuint id)
    292 {
    293    if (prog)
    294       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
    295    else
    296       return NULL;
    297 }
    298 
    299 
    300 /**
    301  * Initialize a new vertex program object.
    302  */
    303 struct gl_program *
    304 _mesa_init_vertex_program( struct gl_context *ctx, struct gl_vertex_program *prog,
    305                            GLenum target, GLuint id)
    306 {
    307    if (prog)
    308       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
    309    else
    310       return NULL;
    311 }
    312 
    313 
    314 /**
    315  * Initialize a new geometry program object.
    316  */
    317 struct gl_program *
    318 _mesa_init_geometry_program( struct gl_context *ctx, struct gl_geometry_program *prog,
    319                              GLenum target, GLuint id)
    320 {
    321    if (prog)
    322       return _mesa_init_program_struct( ctx, &prog->Base, target, id );
    323    else
    324       return NULL;
    325 }
    326 
    327 
    328 /**
    329  * Allocate and initialize a new fragment/vertex program object but
    330  * don't put it into the program hash table.  Called via
    331  * ctx->Driver.NewProgram.  May be overridden (ie. replaced) by a
    332  * device driver function to implement OO deriviation with additional
    333  * types not understood by this function.
    334  *
    335  * \param ctx  context
    336  * \param id   program id/number
    337  * \param target  program target/type
    338  * \return  pointer to new program object
    339  */
    340 struct gl_program *
    341 _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
    342 {
    343    struct gl_program *prog;
    344    switch (target) {
    345    case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
    346    case GL_VERTEX_STATE_PROGRAM_NV:
    347       prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program),
    348                                        target, id );
    349       break;
    350    case GL_FRAGMENT_PROGRAM_NV:
    351    case GL_FRAGMENT_PROGRAM_ARB:
    352       prog =_mesa_init_fragment_program(ctx,
    353                                          CALLOC_STRUCT(gl_fragment_program),
    354                                          target, id );
    355       break;
    356    case MESA_GEOMETRY_PROGRAM:
    357       prog = _mesa_init_geometry_program(ctx,
    358                                          CALLOC_STRUCT(gl_geometry_program),
    359                                          target, id);
    360       break;
    361    default:
    362       _mesa_problem(ctx, "bad target in _mesa_new_program");
    363       prog = NULL;
    364    }
    365    return prog;
    366 }
    367 
    368 
    369 /**
    370  * Delete a program and remove it from the hash table, ignoring the
    371  * reference count.
    372  * Called via ctx->Driver.DeleteProgram.  May be wrapped (OO deriviation)
    373  * by a device driver function.
    374  */
    375 void
    376 _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
    377 {
    378    (void) ctx;
    379    ASSERT(prog);
    380    ASSERT(prog->RefCount==0);
    381 
    382    if (prog == &_mesa_DummyProgram)
    383       return;
    384 
    385    if (prog->String)
    386       free(prog->String);
    387 
    388    if (prog->Instructions) {
    389       _mesa_free_instructions(prog->Instructions, prog->NumInstructions);
    390    }
    391    if (prog->Parameters) {
    392       _mesa_free_parameter_list(prog->Parameters);
    393    }
    394 
    395    free(prog);
    396 }
    397 
    398 
    399 /**
    400  * Return the gl_program object for a given ID.
    401  * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
    402  * casts elsewhere.
    403  */
    404 struct gl_program *
    405 _mesa_lookup_program(struct gl_context *ctx, GLuint id)
    406 {
    407    if (id)
    408       return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
    409    else
    410       return NULL;
    411 }
    412 
    413 
    414 /**
    415  * Reference counting for vertex/fragment programs
    416  * This is normally only called from the _mesa_reference_program() macro
    417  * when there's a real pointer change.
    418  */
    419 void
    420 _mesa_reference_program_(struct gl_context *ctx,
    421                          struct gl_program **ptr,
    422                          struct gl_program *prog)
    423 {
    424 #ifndef NDEBUG
    425    assert(ptr);
    426    if (*ptr && prog) {
    427       /* sanity check */
    428       if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
    429          ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB);
    430       else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
    431          ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
    432                 prog->Target == GL_FRAGMENT_PROGRAM_NV);
    433       else if ((*ptr)->Target == MESA_GEOMETRY_PROGRAM)
    434          ASSERT(prog->Target == MESA_GEOMETRY_PROGRAM);
    435    }
    436 #endif
    437 
    438    if (*ptr) {
    439       GLboolean deleteFlag;
    440 
    441       /*_glthread_LOCK_MUTEX((*ptr)->Mutex);*/
    442 #if 0
    443       printf("Program %p ID=%u Target=%s  Refcount-- to %d\n",
    444              *ptr, (*ptr)->Id,
    445              ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
    446               ((*ptr)->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
    447              (*ptr)->RefCount - 1);
    448 #endif
    449       ASSERT((*ptr)->RefCount > 0);
    450       (*ptr)->RefCount--;
    451 
    452       deleteFlag = ((*ptr)->RefCount == 0);
    453       /*_glthread_UNLOCK_MUTEX((*ptr)->Mutex);*/
    454 
    455       if (deleteFlag) {
    456          ASSERT(ctx);
    457          ctx->Driver.DeleteProgram(ctx, *ptr);
    458       }
    459 
    460       *ptr = NULL;
    461    }
    462 
    463    assert(!*ptr);
    464    if (prog) {
    465       /*_glthread_LOCK_MUTEX(prog->Mutex);*/
    466       prog->RefCount++;
    467 #if 0
    468       printf("Program %p ID=%u Target=%s  Refcount++ to %d\n",
    469              prog, prog->Id,
    470              (prog->Target == GL_VERTEX_PROGRAM_ARB ? "VP" :
    471               (prog->Target == MESA_GEOMETRY_PROGRAM ? "GP" : "FP")),
    472              prog->RefCount);
    473 #endif
    474       /*_glthread_UNLOCK_MUTEX(prog->Mutex);*/
    475    }
    476 
    477    *ptr = prog;
    478 }
    479 
    480 
    481 /**
    482  * Return a copy of a program.
    483  * XXX Problem here if the program object is actually OO-derivation
    484  * made by a device driver.
    485  */
    486 struct gl_program *
    487 _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
    488 {
    489    struct gl_program *clone;
    490 
    491    clone = ctx->Driver.NewProgram(ctx, prog->Target, prog->Id);
    492    if (!clone)
    493       return NULL;
    494 
    495    assert(clone->Target == prog->Target);
    496    assert(clone->RefCount == 1);
    497 
    498    clone->String = (GLubyte *) _mesa_strdup((char *) prog->String);
    499    clone->Format = prog->Format;
    500    clone->Instructions = _mesa_alloc_instructions(prog->NumInstructions);
    501    if (!clone->Instructions) {
    502       _mesa_reference_program(ctx, &clone, NULL);
    503       return NULL;
    504    }
    505    _mesa_copy_instructions(clone->Instructions, prog->Instructions,
    506                            prog->NumInstructions);
    507    clone->InputsRead = prog->InputsRead;
    508    clone->OutputsWritten = prog->OutputsWritten;
    509    clone->SamplersUsed = prog->SamplersUsed;
    510    clone->ShadowSamplers = prog->ShadowSamplers;
    511    memcpy(clone->TexturesUsed, prog->TexturesUsed, sizeof(prog->TexturesUsed));
    512 
    513    if (prog->Parameters)
    514       clone->Parameters = _mesa_clone_parameter_list(prog->Parameters);
    515    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
    516    memcpy(clone->LocalParams, prog->LocalParams, sizeof(clone->LocalParams));
    517    clone->IndirectRegisterFiles = prog->IndirectRegisterFiles;
    518    clone->NumInstructions = prog->NumInstructions;
    519    clone->NumTemporaries = prog->NumTemporaries;
    520    clone->NumParameters = prog->NumParameters;
    521    clone->NumAttributes = prog->NumAttributes;
    522    clone->NumAddressRegs = prog->NumAddressRegs;
    523    clone->NumNativeInstructions = prog->NumNativeInstructions;
    524    clone->NumNativeTemporaries = prog->NumNativeTemporaries;
    525    clone->NumNativeParameters = prog->NumNativeParameters;
    526    clone->NumNativeAttributes = prog->NumNativeAttributes;
    527    clone->NumNativeAddressRegs = prog->NumNativeAddressRegs;
    528    clone->NumAluInstructions = prog->NumAluInstructions;
    529    clone->NumTexInstructions = prog->NumTexInstructions;
    530    clone->NumTexIndirections = prog->NumTexIndirections;
    531    clone->NumNativeAluInstructions = prog->NumNativeAluInstructions;
    532    clone->NumNativeTexInstructions = prog->NumNativeTexInstructions;
    533    clone->NumNativeTexIndirections = prog->NumNativeTexIndirections;
    534 
    535    switch (prog->Target) {
    536    case GL_VERTEX_PROGRAM_ARB:
    537       {
    538          const struct gl_vertex_program *vp = gl_vertex_program_const(prog);
    539          struct gl_vertex_program *vpc = gl_vertex_program(clone);
    540          vpc->IsPositionInvariant = vp->IsPositionInvariant;
    541          vpc->IsNVProgram = vp->IsNVProgram;
    542       }
    543       break;
    544    case GL_FRAGMENT_PROGRAM_ARB:
    545       {
    546          const struct gl_fragment_program *fp = gl_fragment_program_const(prog);
    547          struct gl_fragment_program *fpc = gl_fragment_program(clone);
    548          fpc->UsesKill = fp->UsesKill;
    549          fpc->UsesDFdy = fp->UsesDFdy;
    550          fpc->OriginUpperLeft = fp->OriginUpperLeft;
    551          fpc->PixelCenterInteger = fp->PixelCenterInteger;
    552       }
    553       break;
    554    case MESA_GEOMETRY_PROGRAM:
    555       {
    556          const struct gl_geometry_program *gp = gl_geometry_program_const(prog);
    557          struct gl_geometry_program *gpc = gl_geometry_program(clone);
    558          gpc->VerticesOut = gp->VerticesOut;
    559          gpc->InputType = gp->InputType;
    560          gpc->OutputType = gp->OutputType;
    561       }
    562       break;
    563    default:
    564       _mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
    565    }
    566 
    567    return clone;
    568 }
    569 
    570 
    571 /**
    572  * Insert 'count' NOP instructions at 'start' in the given program.
    573  * Adjust branch targets accordingly.
    574  */
    575 GLboolean
    576 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
    577 {
    578    const GLuint origLen = prog->NumInstructions;
    579    const GLuint newLen = origLen + count;
    580    struct prog_instruction *newInst;
    581    GLuint i;
    582 
    583    /* adjust branches */
    584    for (i = 0; i < prog->NumInstructions; i++) {
    585       struct prog_instruction *inst = prog->Instructions + i;
    586       if (inst->BranchTarget > 0) {
    587          if ((GLuint)inst->BranchTarget >= start) {
    588             inst->BranchTarget += count;
    589          }
    590       }
    591    }
    592 
    593    /* Alloc storage for new instructions */
    594    newInst = _mesa_alloc_instructions(newLen);
    595    if (!newInst) {
    596       return GL_FALSE;
    597    }
    598 
    599    /* Copy 'start' instructions into new instruction buffer */
    600    _mesa_copy_instructions(newInst, prog->Instructions, start);
    601 
    602    /* init the new instructions */
    603    _mesa_init_instructions(newInst + start, count);
    604 
    605    /* Copy the remaining/tail instructions to new inst buffer */
    606    _mesa_copy_instructions(newInst + start + count,
    607                            prog->Instructions + start,
    608                            origLen - start);
    609 
    610    /* free old instructions */
    611    _mesa_free_instructions(prog->Instructions, origLen);
    612 
    613    /* install new instructions */
    614    prog->Instructions = newInst;
    615    prog->NumInstructions = newLen;
    616 
    617    return GL_TRUE;
    618 }
    619 
    620 /**
    621  * Delete 'count' instructions at 'start' in the given program.
    622  * Adjust branch targets accordingly.
    623  */
    624 GLboolean
    625 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count)
    626 {
    627    const GLuint origLen = prog->NumInstructions;
    628    const GLuint newLen = origLen - count;
    629    struct prog_instruction *newInst;
    630    GLuint i;
    631 
    632    /* adjust branches */
    633    for (i = 0; i < prog->NumInstructions; i++) {
    634       struct prog_instruction *inst = prog->Instructions + i;
    635       if (inst->BranchTarget > 0) {
    636          if (inst->BranchTarget > (GLint) start) {
    637             inst->BranchTarget -= count;
    638          }
    639       }
    640    }
    641 
    642    /* Alloc storage for new instructions */
    643    newInst = _mesa_alloc_instructions(newLen);
    644    if (!newInst) {
    645       return GL_FALSE;
    646    }
    647 
    648    /* Copy 'start' instructions into new instruction buffer */
    649    _mesa_copy_instructions(newInst, prog->Instructions, start);
    650 
    651    /* Copy the remaining/tail instructions to new inst buffer */
    652    _mesa_copy_instructions(newInst + start,
    653                            prog->Instructions + start + count,
    654                            newLen - start);
    655 
    656    /* free old instructions */
    657    _mesa_free_instructions(prog->Instructions, origLen);
    658 
    659    /* install new instructions */
    660    prog->Instructions = newInst;
    661    prog->NumInstructions = newLen;
    662 
    663    return GL_TRUE;
    664 }
    665 
    666 
    667 /**
    668  * Search instructions for registers that match (oldFile, oldIndex),
    669  * replacing them with (newFile, newIndex).
    670  */
    671 static void
    672 replace_registers(struct prog_instruction *inst, GLuint numInst,
    673                   GLuint oldFile, GLuint oldIndex,
    674                   GLuint newFile, GLuint newIndex)
    675 {
    676    GLuint i, j;
    677    for (i = 0; i < numInst; i++) {
    678       /* src regs */
    679       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
    680          if (inst[i].SrcReg[j].File == oldFile &&
    681              inst[i].SrcReg[j].Index == oldIndex) {
    682             inst[i].SrcReg[j].File = newFile;
    683             inst[i].SrcReg[j].Index = newIndex;
    684          }
    685       }
    686       /* dst reg */
    687       if (inst[i].DstReg.File == oldFile && inst[i].DstReg.Index == oldIndex) {
    688          inst[i].DstReg.File = newFile;
    689          inst[i].DstReg.Index = newIndex;
    690       }
    691    }
    692 }
    693 
    694 
    695 /**
    696  * Search instructions for references to program parameters.  When found,
    697  * increment the parameter index by 'offset'.
    698  * Used when combining programs.
    699  */
    700 static void
    701 adjust_param_indexes(struct prog_instruction *inst, GLuint numInst,
    702                      GLuint offset)
    703 {
    704    GLuint i, j;
    705    for (i = 0; i < numInst; i++) {
    706       for (j = 0; j < _mesa_num_inst_src_regs(inst[i].Opcode); j++) {
    707          GLuint f = inst[i].SrcReg[j].File;
    708          if (f == PROGRAM_CONSTANT ||
    709              f == PROGRAM_UNIFORM ||
    710              f == PROGRAM_STATE_VAR) {
    711             inst[i].SrcReg[j].Index += offset;
    712          }
    713       }
    714    }
    715 }
    716 
    717 
    718 /**
    719  * Combine two programs into one.  Fix instructions so the outputs of
    720  * the first program go to the inputs of the second program.
    721  */
    722 struct gl_program *
    723 _mesa_combine_programs(struct gl_context *ctx,
    724                        const struct gl_program *progA,
    725                        const struct gl_program *progB)
    726 {
    727    struct prog_instruction *newInst;
    728    struct gl_program *newProg;
    729    const GLuint lenA = progA->NumInstructions - 1; /* omit END instr */
    730    const GLuint lenB = progB->NumInstructions;
    731    const GLuint numParamsA = _mesa_num_parameters(progA->Parameters);
    732    const GLuint newLength = lenA + lenB;
    733    GLboolean usedTemps[MAX_PROGRAM_TEMPS];
    734    GLuint firstTemp = 0;
    735    GLbitfield64 inputsB;
    736    GLuint i;
    737 
    738    ASSERT(progA->Target == progB->Target);
    739 
    740    newInst = _mesa_alloc_instructions(newLength);
    741    if (!newInst)
    742       return GL_FALSE;
    743 
    744    _mesa_copy_instructions(newInst, progA->Instructions, lenA);
    745    _mesa_copy_instructions(newInst + lenA, progB->Instructions, lenB);
    746 
    747    /* adjust branch / instruction addresses for B's instructions */
    748    for (i = 0; i < lenB; i++) {
    749       newInst[lenA + i].BranchTarget += lenA;
    750    }
    751 
    752    newProg = ctx->Driver.NewProgram(ctx, progA->Target, 0);
    753    newProg->Instructions = newInst;
    754    newProg->NumInstructions = newLength;
    755 
    756    /* find used temp regs (we may need new temps below) */
    757    _mesa_find_used_registers(newProg, PROGRAM_TEMPORARY,
    758                              usedTemps, MAX_PROGRAM_TEMPS);
    759 
    760    if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) {
    761       const struct gl_fragment_program *fprogA, *fprogB;
    762       struct gl_fragment_program *newFprog;
    763       GLbitfield64 progB_inputsRead = progB->InputsRead;
    764       GLint progB_colorFile, progB_colorIndex;
    765 
    766       fprogA = gl_fragment_program_const(progA);
    767       fprogB = gl_fragment_program_const(progB);
    768       newFprog = gl_fragment_program(newProg);
    769 
    770       newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill;
    771       newFprog->UsesDFdy = fprogA->UsesDFdy || fprogB->UsesDFdy;
    772 
    773       /* We'll do a search and replace for instances
    774        * of progB_colorFile/progB_colorIndex below...
    775        */
    776       progB_colorFile = PROGRAM_INPUT;
    777       progB_colorIndex = FRAG_ATTRIB_COL0;
    778 
    779       /*
    780        * The fragment program may get color from a state var rather than
    781        * a fragment input (vertex output) if it's constant.
    782        * See the texenvprogram.c code.
    783        * So, search the program's parameter list now to see if the program
    784        * gets color from a state var instead of a conventional fragment
    785        * input register.
    786        */
    787       for (i = 0; i < progB->Parameters->NumParameters; i++) {
    788          struct gl_program_parameter *p = &progB->Parameters->Parameters[i];
    789          if (p->Type == PROGRAM_STATE_VAR &&
    790              p->StateIndexes[0] == STATE_INTERNAL &&
    791              p->StateIndexes[1] == STATE_CURRENT_ATTRIB &&
    792              (int) p->StateIndexes[2] == (int) VERT_ATTRIB_COLOR0) {
    793             progB_inputsRead |= FRAG_BIT_COL0;
    794             progB_colorFile = PROGRAM_STATE_VAR;
    795             progB_colorIndex = i;
    796             break;
    797          }
    798       }
    799 
    800       /* Connect color outputs of fprogA to color inputs of fprogB, via a
    801        * new temporary register.
    802        */
    803       if ((progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) &&
    804           (progB_inputsRead & FRAG_BIT_COL0)) {
    805          GLint tempReg = _mesa_find_free_register(usedTemps, MAX_PROGRAM_TEMPS,
    806                                                   firstTemp);
    807          if (tempReg < 0) {
    808             _mesa_problem(ctx, "No free temp regs found in "
    809                           "_mesa_combine_programs(), using 31");
    810             tempReg = 31;
    811          }
    812          firstTemp = tempReg + 1;
    813 
    814          /* replace writes to result.color[0] with tempReg */
    815          replace_registers(newInst, lenA,
    816                            PROGRAM_OUTPUT, FRAG_RESULT_COLOR,
    817                            PROGRAM_TEMPORARY, tempReg);
    818          /* replace reads from the input color with tempReg */
    819          replace_registers(newInst + lenA, lenB,
    820                            progB_colorFile, progB_colorIndex, /* search for */
    821                            PROGRAM_TEMPORARY, tempReg  /* replace with */ );
    822       }
    823 
    824       /* compute combined program's InputsRead */
    825       inputsB = progB_inputsRead;
    826       if (progA->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) {
    827          inputsB &= ~(1 << FRAG_ATTRIB_COL0);
    828       }
    829       newProg->InputsRead = progA->InputsRead | inputsB;
    830       newProg->OutputsWritten = progB->OutputsWritten;
    831       newProg->SamplersUsed = progA->SamplersUsed | progB->SamplersUsed;
    832    }
    833    else {
    834       /* vertex program */
    835       assert(0);      /* XXX todo */
    836    }
    837 
    838    /*
    839     * Merge parameters (uniforms, constants, etc)
    840     */
    841    newProg->Parameters = _mesa_combine_parameter_lists(progA->Parameters,
    842                                                        progB->Parameters);
    843 
    844    adjust_param_indexes(newInst + lenA, lenB, numParamsA);
    845 
    846 
    847    return newProg;
    848 }
    849 
    850 
    851 /**
    852  * Populate the 'used' array with flags indicating which registers (TEMPs,
    853  * INPUTs, OUTPUTs, etc, are used by the given program.
    854  * \param file  type of register to scan for
    855  * \param used  returns true/false flags for in use / free
    856  * \param usedSize  size of the 'used' array
    857  */
    858 void
    859 _mesa_find_used_registers(const struct gl_program *prog,
    860                           gl_register_file file,
    861                           GLboolean used[], GLuint usedSize)
    862 {
    863    GLuint i, j;
    864 
    865    memset(used, 0, usedSize);
    866 
    867    for (i = 0; i < prog->NumInstructions; i++) {
    868       const struct prog_instruction *inst = prog->Instructions + i;
    869       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
    870 
    871       if (inst->DstReg.File == file) {
    872          ASSERT(inst->DstReg.Index < usedSize);
    873          if(inst->DstReg.Index < usedSize)
    874             used[inst->DstReg.Index] = GL_TRUE;
    875       }
    876 
    877       for (j = 0; j < n; j++) {
    878          if (inst->SrcReg[j].File == file) {
    879             ASSERT(inst->SrcReg[j].Index < usedSize);
    880             if(inst->SrcReg[j].Index < usedSize)
    881                used[inst->SrcReg[j].Index] = GL_TRUE;
    882          }
    883       }
    884    }
    885 }
    886 
    887 
    888 /**
    889  * Scan the given 'used' register flag array for the first entry
    890  * that's >= firstReg.
    891  * \param used  vector of flags indicating registers in use (as returned
    892  *              by _mesa_find_used_registers())
    893  * \param usedSize  size of the 'used' array
    894  * \param firstReg  first register to start searching at
    895  * \return index of unused register, or -1 if none.
    896  */
    897 GLint
    898 _mesa_find_free_register(const GLboolean used[],
    899                          GLuint usedSize, GLuint firstReg)
    900 {
    901    GLuint i;
    902 
    903    assert(firstReg < usedSize);
    904 
    905    for (i = firstReg; i < usedSize; i++)
    906       if (!used[i])
    907          return i;
    908 
    909    return -1;
    910 }
    911 
    912 
    913 
    914 /**
    915  * Check if the given register index is valid (doesn't exceed implementation-
    916  * dependent limits).
    917  * \return GL_TRUE if OK, GL_FALSE if bad index
    918  */
    919 GLboolean
    920 _mesa_valid_register_index(const struct gl_context *ctx,
    921                            gl_shader_type shaderType,
    922                            gl_register_file file, GLint index)
    923 {
    924    const struct gl_program_constants *c;
    925 
    926    switch (shaderType) {
    927    case MESA_SHADER_VERTEX:
    928       c = &ctx->Const.VertexProgram;
    929       break;
    930    case MESA_SHADER_FRAGMENT:
    931       c = &ctx->Const.FragmentProgram;
    932       break;
    933    case MESA_SHADER_GEOMETRY:
    934       c = &ctx->Const.GeometryProgram;
    935       break;
    936    default:
    937       _mesa_problem(ctx,
    938                     "unexpected shader type in _mesa_valid_register_index()");
    939       return GL_FALSE;
    940    }
    941 
    942    switch (file) {
    943    case PROGRAM_UNDEFINED:
    944       return GL_TRUE;  /* XXX or maybe false? */
    945 
    946    case PROGRAM_TEMPORARY:
    947       return index >= 0 && index < c->MaxTemps;
    948 
    949    case PROGRAM_ENV_PARAM:
    950       return index >= 0 && index < c->MaxEnvParams;
    951 
    952    case PROGRAM_LOCAL_PARAM:
    953       return index >= 0 && index < c->MaxLocalParams;
    954 
    955    case PROGRAM_NAMED_PARAM:
    956       return index >= 0 && index < c->MaxParameters;
    957 
    958    case PROGRAM_UNIFORM:
    959    case PROGRAM_STATE_VAR:
    960       /* aka constant buffer */
    961       return index >= 0 && index < c->MaxUniformComponents / 4;
    962 
    963    case PROGRAM_CONSTANT:
    964       /* constant buffer w/ possible relative negative addressing */
    965       return (index > (int) c->MaxUniformComponents / -4 &&
    966               index < c->MaxUniformComponents / 4);
    967 
    968    case PROGRAM_INPUT:
    969       if (index < 0)
    970          return GL_FALSE;
    971 
    972       switch (shaderType) {
    973       case MESA_SHADER_VERTEX:
    974          return index < VERT_ATTRIB_GENERIC0 + c->MaxAttribs;
    975       case MESA_SHADER_FRAGMENT:
    976          return index < FRAG_ATTRIB_VAR0 + ctx->Const.MaxVarying;
    977       case MESA_SHADER_GEOMETRY:
    978          return index < GEOM_ATTRIB_VAR0 + ctx->Const.MaxVarying;
    979       default:
    980          return GL_FALSE;
    981       }
    982 
    983    case PROGRAM_OUTPUT:
    984       if (index < 0)
    985          return GL_FALSE;
    986 
    987       switch (shaderType) {
    988       case MESA_SHADER_VERTEX:
    989          return index < VERT_RESULT_VAR0 + ctx->Const.MaxVarying;
    990       case MESA_SHADER_FRAGMENT:
    991          return index < FRAG_RESULT_DATA0 + ctx->Const.MaxDrawBuffers;
    992       case MESA_SHADER_GEOMETRY:
    993          return index < GEOM_RESULT_VAR0 + ctx->Const.MaxVarying;
    994       default:
    995          return GL_FALSE;
    996       }
    997 
    998    case PROGRAM_ADDRESS:
    999       return index >= 0 && index < c->MaxAddressRegs;
   1000 
   1001    default:
   1002       _mesa_problem(ctx,
   1003                     "unexpected register file in _mesa_valid_register_index()");
   1004       return GL_FALSE;
   1005    }
   1006 }
   1007 
   1008 
   1009 
   1010 /**
   1011  * "Post-process" a GPU program.  This is intended to be used for debugging.
   1012  * Example actions include no-op'ing instructions or changing instruction
   1013  * behaviour.
   1014  */
   1015 void
   1016 _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
   1017 {
   1018    static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 };
   1019    GLuint i;
   1020    GLuint whiteSwizzle;
   1021    GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters,
   1022                                                  (gl_constant_value *) white,
   1023                                                  4, &whiteSwizzle);
   1024 
   1025    (void) whiteIndex;
   1026 
   1027    for (i = 0; i < prog->NumInstructions; i++) {
   1028       struct prog_instruction *inst = prog->Instructions + i;
   1029       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
   1030 
   1031       (void) n;
   1032 
   1033       if (_mesa_is_tex_instruction(inst->Opcode)) {
   1034 #if 0
   1035          /* replace TEX/TXP/TXB with MOV */
   1036          inst->Opcode = OPCODE_MOV;
   1037          inst->DstReg.WriteMask = WRITEMASK_XYZW;
   1038          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
   1039          inst->SrcReg[0].Negate = NEGATE_NONE;
   1040 #endif
   1041 
   1042 #if 0
   1043          /* disable shadow texture mode */
   1044          inst->TexShadow = 0;
   1045 #endif
   1046       }
   1047 
   1048       if (inst->Opcode == OPCODE_TXP) {
   1049 #if 0
   1050          inst->Opcode = OPCODE_MOV;
   1051          inst->DstReg.WriteMask = WRITEMASK_XYZW;
   1052          inst->SrcReg[0].File = PROGRAM_CONSTANT;
   1053          inst->SrcReg[0].Index = whiteIndex;
   1054          inst->SrcReg[0].Swizzle = SWIZZLE_XYZW;
   1055          inst->SrcReg[0].Negate = NEGATE_NONE;
   1056 #endif
   1057 #if 0
   1058          inst->TexShadow = 0;
   1059 #endif
   1060 #if 0
   1061          inst->Opcode = OPCODE_TEX;
   1062          inst->TexShadow = 0;
   1063 #endif
   1064       }
   1065 
   1066    }
   1067 }
   1068