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:  7.3
  4.  *
  5.  * Copyright (C) 1999-2008  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 prog_parameter.c
  27.  * Program parameter lists and functions.
  28.  * \author Brian Paul
  29.  */
  30.  
  31.  
  32. #include "main/glheader.h"
  33. #include "main/imports.h"
  34. #include "main/macros.h"
  35. #include "prog_instruction.h"
  36. #include "prog_parameter.h"
  37. #include "prog_statevars.h"
  38.  
  39.  
  40. struct gl_program_parameter_list *
  41. _mesa_new_parameter_list(void)
  42. {
  43.    return CALLOC_STRUCT(gl_program_parameter_list);
  44. }
  45.  
  46.  
  47. struct gl_program_parameter_list *
  48. _mesa_new_parameter_list_sized(unsigned size)
  49. {
  50.    struct gl_program_parameter_list *p = _mesa_new_parameter_list();
  51.  
  52.    if ((p != NULL) && (size != 0)) {
  53.       p->Size = size;
  54.  
  55.       /* alloc arrays */
  56.       p->Parameters = (struct gl_program_parameter *)
  57.          calloc(1, size * sizeof(struct gl_program_parameter));
  58.  
  59.       p->ParameterValues = (GLfloat (*)[4])
  60.          _mesa_align_malloc(size * 4 *sizeof(GLfloat), 16);
  61.  
  62.  
  63.       if ((p->Parameters == NULL) || (p->ParameterValues == NULL)) {
  64.          free(p->Parameters);
  65.          _mesa_align_free(p->ParameterValues);
  66.          free(p);
  67.          p = NULL;
  68.       }
  69.    }
  70.  
  71.    return p;
  72. }
  73.  
  74.  
  75. /**
  76.  * Free a parameter list and all its parameters
  77.  */
  78. void
  79. _mesa_free_parameter_list(struct gl_program_parameter_list *paramList)
  80. {
  81.    GLuint i;
  82.    for (i = 0; i < paramList->NumParameters; i++) {
  83.       if (paramList->Parameters[i].Name)
  84.          free((void *) paramList->Parameters[i].Name);
  85.    }
  86.    free(paramList->Parameters);
  87.    if (paramList->ParameterValues)
  88.       _mesa_align_free(paramList->ParameterValues);
  89.    free(paramList);
  90. }
  91.  
  92.  
  93. /**
  94.  * Add a new parameter to a parameter list.
  95.  * Note that parameter values are usually 4-element GLfloat vectors.
  96.  * When size > 4 we'll allocate a sequential block of parameters to
  97.  * store all the values (in blocks of 4).
  98.  *
  99.  * \param paramList  the list to add the parameter to
  100.  * \param type  type of parameter, such as
  101.  * \param name  the parameter name, will be duplicated/copied!
  102.  * \param size  number of elements in 'values' vector (1..4, or more)
  103.  * \param datatype  GL_FLOAT, GL_FLOAT_VECx, GL_INT, GL_INT_VECx or GL_NONE.
  104.  * \param values  initial parameter value, up to 4 GLfloats, or NULL
  105.  * \param state  state indexes, or NULL
  106.  * \return  index of new parameter in the list, or -1 if error (out of mem)
  107.  */
  108. GLint
  109. _mesa_add_parameter(struct gl_program_parameter_list *paramList,
  110.                     gl_register_file type, const char *name,
  111.                     GLuint size, GLenum datatype, const GLfloat *values,
  112.                     const gl_state_index state[STATE_LENGTH],
  113.                     GLbitfield flags)
  114. {
  115.    const GLuint oldNum = paramList->NumParameters;
  116.    const GLuint sz4 = (size + 3) / 4; /* no. of new param slots needed */
  117.  
  118.    assert(size > 0);
  119.  
  120.    if (oldNum + sz4 > paramList->Size) {
  121.       /* Need to grow the parameter list array (alloc some extra) */
  122.       paramList->Size = paramList->Size + 4 * sz4;
  123.  
  124.       /* realloc arrays */
  125.       paramList->Parameters = (struct gl_program_parameter *)
  126.          _mesa_realloc(paramList->Parameters,
  127.                        oldNum * sizeof(struct gl_program_parameter),
  128.                        paramList->Size * sizeof(struct gl_program_parameter));
  129.  
  130.       paramList->ParameterValues = (GLfloat (*)[4])
  131.          _mesa_align_realloc(paramList->ParameterValues,         /* old buf */
  132.                              oldNum * 4 * sizeof(GLfloat),      /* old size */
  133.                              paramList->Size * 4 *sizeof(GLfloat), /* new sz */
  134.                              16);
  135.    }
  136.  
  137.    if (!paramList->Parameters ||
  138.        !paramList->ParameterValues) {
  139.       /* out of memory */
  140.       paramList->NumParameters = 0;
  141.       paramList->Size = 0;
  142.       return -1;
  143.    }
  144.    else {
  145.       GLuint i;
  146.  
  147.       paramList->NumParameters = oldNum + sz4;
  148.  
  149.       memset(&paramList->Parameters[oldNum], 0,
  150.              sz4 * sizeof(struct gl_program_parameter));
  151.  
  152.       for (i = 0; i < sz4; i++) {
  153.          struct gl_program_parameter *p = paramList->Parameters + oldNum + i;
  154.          p->Name = name ? _mesa_strdup(name) : NULL;
  155.          p->Type = type;
  156.          p->Size = size;
  157.          p->DataType = datatype;
  158.          p->Flags = flags;
  159.          if (values) {
  160.             COPY_4V(paramList->ParameterValues[oldNum + i], values);
  161.             values += 4;
  162.             p->Initialized = GL_TRUE;
  163.          }
  164.          else {
  165.             /* silence valgrind */
  166.             ASSIGN_4V(paramList->ParameterValues[oldNum + i], 0, 0, 0, 0);
  167.          }
  168.          size -= 4;
  169.       }
  170.  
  171.       if (state) {
  172.          for (i = 0; i < STATE_LENGTH; i++)
  173.             paramList->Parameters[oldNum].StateIndexes[i] = state[i];
  174.       }
  175.  
  176.       return (GLint) oldNum;
  177.    }
  178. }
  179.  
  180.  
  181. /**
  182.  * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement)
  183.  * \return index of the new entry in the parameter list
  184.  */
  185. GLint
  186. _mesa_add_named_parameter(struct gl_program_parameter_list *paramList,
  187.                           const char *name, const GLfloat values[4])
  188. {
  189.    return _mesa_add_parameter(paramList, PROGRAM_NAMED_PARAM, name,
  190.                               4, GL_NONE, values, NULL, 0x0);
  191.                              
  192. }
  193.  
  194.  
  195. /**
  196.  * Add a new named constant to the parameter list.
  197.  * This will be used when the program contains something like this:
  198.  *    PARAM myVals = { 0, 1, 2, 3 };
  199.  *
  200.  * \param paramList  the parameter list
  201.  * \param name  the name for the constant
  202.  * \param values  four float values
  203.  * \return index/position of the new parameter in the parameter list
  204.  */
  205. GLint
  206. _mesa_add_named_constant(struct gl_program_parameter_list *paramList,
  207.                          const char *name, const GLfloat values[4],
  208.                          GLuint size)
  209. {
  210.    /* first check if this is a duplicate constant */
  211.    GLint pos;
  212.    for (pos = 0; pos < (GLint)paramList->NumParameters; pos++) {
  213.       const GLfloat *pvals = paramList->ParameterValues[pos];
  214.       if (pvals[0] == values[0] &&
  215.           pvals[1] == values[1] &&
  216.           pvals[2] == values[2] &&
  217.           pvals[3] == values[3] &&
  218.           strcmp(paramList->Parameters[pos].Name, name) == 0) {
  219.          /* Same name and value is already in the param list - reuse it */
  220.          return pos;
  221.       }
  222.    }
  223.    /* not found, add new parameter */
  224.    return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name,
  225.                               size, GL_NONE, values, NULL, 0x0);
  226. }
  227.  
  228.  
  229. /**
  230.  * Add a new unnamed constant to the parameter list.  This will be used
  231.  * when a fragment/vertex program contains something like this:
  232.  *    MOV r, { 0, 1, 2, 3 };
  233.  * If swizzleOut is non-null we'll search the parameter list for an
  234.  * existing instance of the constant which matches with a swizzle.
  235.  *
  236.  * \param paramList  the parameter list
  237.  * \param values  four float values
  238.  * \param swizzleOut  returns swizzle mask for accessing the constant
  239.  * \return index/position of the new parameter in the parameter list.
  240.  */
  241. GLint
  242. _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList,
  243.                            const GLfloat values[4], GLuint size,
  244.                            GLuint *swizzleOut)
  245. {
  246.    GLint pos;
  247.    ASSERT(size >= 1);
  248.    ASSERT(size <= 4);
  249.  
  250.    if (swizzleOut &&
  251.        _mesa_lookup_parameter_constant(paramList, values,
  252.                                        size, &pos, swizzleOut)) {
  253.       return pos;
  254.    }
  255.  
  256.    /* Look for empty space in an already unnamed constant parameter
  257.     * to add this constant.  This will only work for single-element
  258.     * constants because we rely on smearing (i.e. .yyyy or .zzzz).
  259.     */
  260.    if (size == 1 && swizzleOut) {
  261.       for (pos = 0; pos < (GLint) paramList->NumParameters; pos++) {
  262.          struct gl_program_parameter *p = paramList->Parameters + pos;
  263.          if (p->Type == PROGRAM_CONSTANT && p->Size + size <= 4) {
  264.             /* ok, found room */
  265.             GLfloat *pVal = paramList->ParameterValues[pos];
  266.             GLuint swz = p->Size; /* 1, 2 or 3 for Y, Z, W */
  267.             pVal[p->Size] = values[0];
  268.             p->Size++;
  269.             *swizzleOut = MAKE_SWIZZLE4(swz, swz, swz, swz);
  270.             return pos;
  271.          }
  272.       }
  273.    }
  274.  
  275.    /* add a new parameter to store this constant */
  276.    pos = _mesa_add_parameter(paramList, PROGRAM_CONSTANT, NULL,
  277.                              size, GL_NONE, values, NULL, 0x0);
  278.    if (pos >= 0 && swizzleOut) {
  279.       if (size == 1)
  280.          *swizzleOut = SWIZZLE_XXXX;
  281.       else
  282.          *swizzleOut = SWIZZLE_NOOP;
  283.    }
  284.    return pos;
  285. }
  286.  
  287. /**
  288.  * Add parameter representing a varying variable.
  289.  */
  290. GLint
  291. _mesa_add_varying(struct gl_program_parameter_list *paramList,
  292.                   const char *name, GLuint size, GLenum datatype,
  293.                   GLbitfield flags)
  294. {
  295.    GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
  296.    if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) {
  297.       /* already in list */
  298.       return i;
  299.    }
  300.    else {
  301.       /*assert(size == 4);*/
  302.       i = _mesa_add_parameter(paramList, PROGRAM_VARYING, name,
  303.                               size, datatype, NULL, NULL, flags);
  304.       return i;
  305.    }
  306. }
  307.  
  308.  
  309. /**
  310.  * Add parameter representing a vertex program attribute.
  311.  * \param size  size of attribute (in floats), may be -1 if unknown
  312.  * \param attrib  the attribute index, or -1 if unknown
  313.  */
  314. GLint
  315. _mesa_add_attribute(struct gl_program_parameter_list *paramList,
  316.                     const char *name, GLint size, GLenum datatype, GLint attrib)
  317. {
  318.    GLint i = _mesa_lookup_parameter_index(paramList, -1, name);
  319.    if (i >= 0) {
  320.       /* replace */
  321.       if (attrib < 0)
  322.          attrib = i;
  323.       paramList->Parameters[i].StateIndexes[0] = attrib;
  324.    }
  325.    else {
  326.       /* add */
  327.       gl_state_index state[STATE_LENGTH];
  328.       state[0] = (gl_state_index) attrib;
  329.       if (size < 0)
  330.          size = 4;
  331.       i = _mesa_add_parameter(paramList, PROGRAM_INPUT, name,
  332.                               size, datatype, NULL, state, 0x0);
  333.    }
  334.    return i;
  335. }
  336.  
  337.  
  338.  
  339. #if 0 /* not used yet */
  340. /**
  341.  * Returns the number of 4-component registers needed to store a piece
  342.  * of GL state.  For matrices this may be as many as 4 registers,
  343.  * everything else needs
  344.  * just 1 register.
  345.  */
  346. static GLuint
  347. sizeof_state_reference(const GLint *stateTokens)
  348. {
  349.    if (stateTokens[0] == STATE_MATRIX) {
  350.       GLuint rows = stateTokens[4] - stateTokens[3] + 1;
  351.       assert(rows >= 1);
  352.       assert(rows <= 4);
  353.       return rows;
  354.    }
  355.    else {
  356.       return 1;
  357.    }
  358. }
  359. #endif
  360.  
  361.  
  362. /**
  363.  * Add a new state reference to the parameter list.
  364.  * This will be used when the program contains something like this:
  365.  *    PARAM ambient = state.material.front.ambient;
  366.  *
  367.  * \param paramList  the parameter list
  368.  * \param stateTokens  an array of 5 (STATE_LENGTH) state tokens
  369.  * \return index of the new parameter.
  370.  */
  371. GLint
  372. _mesa_add_state_reference(struct gl_program_parameter_list *paramList,
  373.                           const gl_state_index stateTokens[STATE_LENGTH])
  374. {
  375.    const GLuint size = 4; /* XXX fix */
  376.    char *name;
  377.    GLint index;
  378.  
  379.    /* Check if the state reference is already in the list */
  380.    for (index = 0; index < (GLint) paramList->NumParameters; index++) {
  381.       if (!memcmp(paramList->Parameters[index].StateIndexes,
  382.                   stateTokens, STATE_LENGTH * sizeof(gl_state_index))) {
  383.          return index;
  384.       }
  385.    }
  386.  
  387.    name = _mesa_program_state_string(stateTokens);
  388.    index = _mesa_add_parameter(paramList, PROGRAM_STATE_VAR, name,
  389.                                size, GL_NONE,
  390.                                NULL, (gl_state_index *) stateTokens, 0x0);
  391.    paramList->StateFlags |= _mesa_program_state_flags(stateTokens);
  392.  
  393.    /* free name string here since we duplicated it in add_parameter() */
  394.    free(name);
  395.  
  396.    return index;
  397. }
  398.  
  399.  
  400. /**
  401.  * Lookup a parameter value by name in the given parameter list.
  402.  * \return pointer to the float[4] values.
  403.  */
  404. GLfloat *
  405. _mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList,
  406.                              GLsizei nameLen, const char *name)
  407. {
  408.    GLint i = _mesa_lookup_parameter_index(paramList, nameLen, name);
  409.    if (i < 0)
  410.       return NULL;
  411.    else
  412.       return paramList->ParameterValues[i];
  413. }
  414.  
  415.  
  416. /**
  417.  * Given a program parameter name, find its position in the list of parameters.
  418.  * \param paramList  the parameter list to search
  419.  * \param nameLen  length of name (in chars).
  420.  *                 If length is negative, assume that name is null-terminated.
  421.  * \param name  the name to search for
  422.  * \return index of parameter in the list.
  423.  */
  424. GLint
  425. _mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList,
  426.                              GLsizei nameLen, const char *name)
  427. {
  428.    GLint i;
  429.  
  430.    if (!paramList)
  431.       return -1;
  432.  
  433.    if (nameLen == -1) {
  434.       /* name is null-terminated */
  435.       for (i = 0; i < (GLint) paramList->NumParameters; i++) {
  436.          if (paramList->Parameters[i].Name &&
  437.              strcmp(paramList->Parameters[i].Name, name) == 0)
  438.             return i;
  439.       }
  440.    }
  441.    else {
  442.       /* name is not null-terminated, use nameLen */
  443.       for (i = 0; i < (GLint) paramList->NumParameters; i++) {
  444.          if (paramList->Parameters[i].Name &&
  445.              strncmp(paramList->Parameters[i].Name, name, nameLen) == 0
  446.              && strlen(paramList->Parameters[i].Name) == (size_t)nameLen)
  447.             return i;
  448.       }
  449.    }
  450.    return -1;
  451. }
  452.  
  453.  
  454. /**
  455.  * Look for a float vector in the given parameter list.  The float vector
  456.  * may be of length 1, 2, 3 or 4.  If swizzleOut is non-null, we'll try
  457.  * swizzling to find a match.
  458.  * \param list  the parameter list to search
  459.  * \param v  the float vector to search for
  460.  * \param vSize  number of element in v
  461.  * \param posOut  returns the position of the constant, if found
  462.  * \param swizzleOut  returns a swizzle mask describing location of the
  463.  *                    vector elements if found.
  464.  * \return GL_TRUE if found, GL_FALSE if not found
  465.  */
  466. GLboolean
  467. _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *list,
  468.                                 const GLfloat v[], GLuint vSize,
  469.                                 GLint *posOut, GLuint *swizzleOut)
  470. {
  471.    GLuint i;
  472.  
  473.    assert(vSize >= 1);
  474.    assert(vSize <= 4);
  475.  
  476.    if (!list) {
  477.       *posOut = -1;
  478.       return GL_FALSE;
  479.    }
  480.  
  481.    for (i = 0; i < list->NumParameters; i++) {
  482.       if (list->Parameters[i].Type == PROGRAM_CONSTANT) {
  483.          if (!swizzleOut) {
  484.             /* swizzle not allowed */
  485.             GLuint j, match = 0;
  486.             for (j = 0; j < vSize; j++) {
  487.                if (v[j] == list->ParameterValues[i][j])
  488.                   match++;
  489.             }
  490.             if (match == vSize) {
  491.                *posOut = i;
  492.                return GL_TRUE;
  493.             }
  494.          }
  495.          else {
  496.             /* try matching w/ swizzle */
  497.              if (vSize == 1) {
  498.                 /* look for v[0] anywhere within float[4] value */
  499.                 GLuint j;
  500.                 for (j = 0; j < list->Parameters[i].Size; j++) {
  501.                    if (list->ParameterValues[i][j] == v[0]) {
  502.                       /* found it */
  503.                       *posOut = i;
  504.                       *swizzleOut = MAKE_SWIZZLE4(j, j, j, j);
  505.                       return GL_TRUE;
  506.                    }
  507.                 }
  508.              }
  509.              else if (vSize <= list->Parameters[i].Size) {
  510.                 /* see if we can match this constant (with a swizzle) */
  511.                 GLuint swz[4];
  512.                 GLuint match = 0, j, k;
  513.                 for (j = 0; j < vSize; j++) {
  514.                    if (v[j] == list->ParameterValues[i][j]) {
  515.                       swz[j] = j;
  516.                       match++;
  517.                    }
  518.                    else {
  519.                       for (k = 0; k < list->Parameters[i].Size; k++) {
  520.                          if (v[j] == list->ParameterValues[i][k]) {
  521.                             swz[j] = k;
  522.                             match++;
  523.                             break;
  524.                          }
  525.                       }
  526.                    }
  527.                 }
  528.                 /* smear last value to remaining positions */
  529.                 for (; j < 4; j++)
  530.                    swz[j] = swz[j-1];
  531.  
  532.                 if (match == vSize) {
  533.                    *posOut = i;
  534.                    *swizzleOut = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
  535.                    return GL_TRUE;
  536.                 }
  537.              }
  538.          }
  539.       }
  540.    }
  541.  
  542.    *posOut = -1;
  543.    return GL_FALSE;
  544. }
  545.  
  546.  
  547. struct gl_program_parameter_list *
  548. _mesa_clone_parameter_list(const struct gl_program_parameter_list *list)
  549. {
  550.    struct gl_program_parameter_list *clone;
  551.    GLuint i;
  552.  
  553.    clone = _mesa_new_parameter_list();
  554.    if (!clone)
  555.       return NULL;
  556.  
  557.    /** Not too efficient, but correct */
  558.    for (i = 0; i < list->NumParameters; i++) {
  559.       struct gl_program_parameter *p = list->Parameters + i;
  560.       struct gl_program_parameter *pCopy;
  561.       GLuint size = MIN2(p->Size, 4);
  562.       GLint j = _mesa_add_parameter(clone, p->Type, p->Name, size, p->DataType,
  563.                                     list->ParameterValues[i], NULL, 0x0);
  564.       ASSERT(j >= 0);
  565.       pCopy = clone->Parameters + j;
  566.       pCopy->Flags = p->Flags;
  567.       /* copy state indexes */
  568.       if (p->Type == PROGRAM_STATE_VAR) {
  569.          GLint k;
  570.          for (k = 0; k < STATE_LENGTH; k++) {
  571.             pCopy->StateIndexes[k] = p->StateIndexes[k];
  572.          }
  573.       }
  574.       else {
  575.          clone->Parameters[j].Size = p->Size;
  576.       }
  577.      
  578.    }
  579.  
  580.    clone->StateFlags = list->StateFlags;
  581.  
  582.    return clone;
  583. }
  584.  
  585.  
  586. /**
  587.  * Return a new parameter list which is listA + listB.
  588.  */
  589. struct gl_program_parameter_list *
  590. _mesa_combine_parameter_lists(const struct gl_program_parameter_list *listA,
  591.                               const struct gl_program_parameter_list *listB)
  592. {
  593.    struct gl_program_parameter_list *list;
  594.  
  595.    if (listA) {
  596.       list = _mesa_clone_parameter_list(listA);
  597.       if (list && listB) {
  598.          GLuint i;
  599.          for (i = 0; i < listB->NumParameters; i++) {
  600.             struct gl_program_parameter *param = listB->Parameters + i;
  601.             _mesa_add_parameter(list, param->Type, param->Name, param->Size,
  602.                                 param->DataType,
  603.                                 listB->ParameterValues[i],
  604.                                 param->StateIndexes,
  605.                                 param->Flags);
  606.          }
  607.       }
  608.    }
  609.    else if (listB) {
  610.       list = _mesa_clone_parameter_list(listB);
  611.    }
  612.    else {
  613.       list = NULL;
  614.    }
  615.    return list;
  616. }
  617.  
  618.  
  619.  
  620. /**
  621.  * Find longest name of all uniform parameters in list.
  622.  */
  623. GLuint
  624. _mesa_longest_parameter_name(const struct gl_program_parameter_list *list,
  625.                              gl_register_file type)
  626. {
  627.    GLuint i, maxLen = 0;
  628.    if (!list)
  629.       return 0;
  630.    for (i = 0; i < list->NumParameters; i++) {
  631.       if (list->Parameters[i].Type == type) {
  632.          GLuint len = strlen(list->Parameters[i].Name);
  633.          if (len > maxLen)
  634.             maxLen = len;
  635.       }
  636.    }
  637.    return maxLen;
  638. }
  639.  
  640.  
  641. /**
  642.  * Count the number of parameters in the last that match the given type.
  643.  */
  644. GLuint
  645. _mesa_num_parameters_of_type(const struct gl_program_parameter_list *list,
  646.                              gl_register_file type)
  647. {
  648.    GLuint i, count = 0;
  649.    if (list) {
  650.       for (i = 0; i < list->NumParameters; i++) {
  651.          if (list->Parameters[i].Type == type)
  652.             count++;
  653.       }
  654.    }
  655.    return count;
  656. }
  657.