Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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