Subversion Repositories Kolibri OS

Rev

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

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