ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

nvfragparse.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  6.5
00004  *
00005  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00031 /*
00032  * Regarding GL_NV_fragment_program:
00033  *
00034  * Portions of this software may use or implement intellectual
00035  * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
00036  * any and all warranties with respect to such intellectual property,
00037  * including any use thereof or modifications thereto.
00038  */
00039 
00040 #include "main/glheader.h"
00041 #include "main/context.h"
00042 #include "main/imports.h"
00043 #include "main/macros.h"
00044 #include "program.h"
00045 #include "prog_parameter.h"
00046 #include "prog_instruction.h"
00047 #include "nvfragparse.h"
00048 
00049 
00050 #define INPUT_1V     1
00051 #define INPUT_2V     2
00052 #define INPUT_3V     3
00053 #define INPUT_1S     4
00054 #define INPUT_2S     5
00055 #define INPUT_CC     6
00056 #define INPUT_1V_T   7  /* one source vector, plus textureId */
00057 #define INPUT_3V_T   8  /* one source vector, plus textureId */
00058 #define INPUT_NONE   9
00059 #define INPUT_1V_S  10  /* a string and a vector register */
00060 #define OUTPUT_V    20
00061 #define OUTPUT_S    21
00062 #define OUTPUT_NONE 22
00063 
00064 /* IRIX defines some of these */
00065 #undef _R
00066 #undef _H
00067 #undef _X
00068 #undef _C
00069 #undef _S
00070 
00071 /* Optional suffixes */
00072 #define _R  FLOAT32  /* float */
00073 #define _H  FLOAT16  /* half-float */
00074 #define _X  FIXED12  /* fixed */
00075 #define _C  0x08     /* set cond codes */
00076 #define _S  0x10     /* saturate, clamp result to [0,1] */
00077 
00078 struct instruction_pattern {
00079    const char *name;
00080    enum prog_opcode opcode;
00081    GLuint inputs;
00082    GLuint outputs;
00083    GLuint suffixes;
00084 };
00085 
00086 static const struct instruction_pattern Instructions[] = {
00087    { "ADD", OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00088    { "COS", OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00089    { "DDX", OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
00090    { "DDY", OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
00091    { "DP3", OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
00092    { "DP4", OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
00093    { "DST", OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },
00094    { "EX2", OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00095    { "FLR", OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
00096    { "FRC", OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
00097    { "KIL", OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0                },
00098    { "LG2", OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00099    { "LIT", OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
00100    { "LRP", OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
00101    { "MAD", OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
00102    { "MAX", OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00103    { "MIN", OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00104    { "MOV", OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
00105    { "MUL", OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00106    { "PK2H",  OPCODE_PK2H,  INPUT_1V, OUTPUT_S, 0                  },
00107    { "PK2US", OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0                  },
00108    { "PK4B",  OPCODE_PK4B,  INPUT_1V, OUTPUT_S, 0                  },
00109    { "PK4UB", OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0                  },
00110    { "POW", OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H |      _C | _S },
00111    { "RCP", OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00112    { "RFL", OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },
00113    { "RSQ", OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00114    { "SEQ", OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00115    { "SFL", OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00116    { "SGE", OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00117    { "SGT", OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00118    { "SIN", OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
00119    { "SLE", OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00120    { "SLT", OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00121    { "SNE", OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00122    { "STR", OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00123    { "SUB", OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
00124    { "TEX", OPCODE_TEX, INPUT_1V_T, OUTPUT_V,              _C | _S },
00125    { "TXD", OPCODE_TXD, INPUT_3V_T, OUTPUT_V,              _C | _S },
00126    { "TXP", OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V,           _C | _S },
00127    { "UP2H",  OPCODE_UP2H,  INPUT_1S, OUTPUT_V,            _C | _S },
00128    { "UP2US", OPCODE_UP2US, INPUT_1S, OUTPUT_V,            _C | _S },
00129    { "UP4B",  OPCODE_UP4B,  INPUT_1S, OUTPUT_V,            _C | _S },
00130    { "UP4UB", OPCODE_UP4UB, INPUT_1S, OUTPUT_V,            _C | _S },
00131    { "X2D", OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H |      _C | _S },
00132    { "PRINT", OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0               },
00133    { NULL, (enum prog_opcode) -1, 0, 0, 0 }
00134 };
00135 
00136 
00137 /*
00138  * Information needed or computed during parsing.
00139  * Remember, we can't modify the target program object until we've
00140  * _successfully_ parsed the program text.
00141  */
00142 struct parse_state {
00143    GLcontext *ctx;
00144    const GLubyte *start;              /* start of program string */
00145    const GLubyte *pos;                /* current position */
00146    const GLubyte *curLine;
00147    struct gl_fragment_program *program;  /* current program */
00148 
00149    struct gl_program_parameter_list *parameters;
00150 
00151    GLuint numInst;                    /* number of instructions parsed */
00152    GLuint inputsRead;                 /* bitmask of input registers used */
00153    GLuint outputsWritten;             /* bitmask of 1 << FRAG_OUTPUT_* bits */
00154    GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
00155 };
00156 
00157 
00158 
00159 /*
00160  * Called whenever we find an error during parsing.
00161  */
00162 static void
00163 record_error(struct parse_state *parseState, const char *msg, int lineNo)
00164 {
00165 #ifdef DEBUG
00166    GLint line, column;
00167    const GLubyte *lineStr;
00168    lineStr = _mesa_find_line_column(parseState->start,
00169                                     parseState->pos, &line, &column);
00170    _mesa_debug(parseState->ctx,
00171                "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
00172                lineNo, line, column, (char *) lineStr, msg);
00173    _mesa_free((void *) lineStr);
00174 #else
00175    (void) lineNo;
00176 #endif
00177 
00178    /* Check that no error was already recorded.  Only record the first one. */
00179    if (parseState->ctx->Program.ErrorString[0] == 0) {
00180       _mesa_set_program_error(parseState->ctx,
00181                               parseState->pos - parseState->start,
00182                               msg);
00183    }
00184 }
00185 
00186 
00187 #define RETURN_ERROR                            \
00188 do {                                    \
00189    record_error(parseState, "Unexpected end of input.", __LINE__);  \
00190    return GL_FALSE;                         \
00191 } while(0)
00192 
00193 #define RETURN_ERROR1(msg)                      \
00194 do {                                    \
00195    record_error(parseState, msg, __LINE__);             \
00196    return GL_FALSE;                         \
00197 } while(0)
00198 
00199 #define RETURN_ERROR2(msg1, msg2)                   \
00200 do {                                    \
00201    char err[1000];                          \
00202    _mesa_sprintf(err, "%s %s", msg1, msg2);             \
00203    record_error(parseState, err, __LINE__);             \
00204    return GL_FALSE;                         \
00205 } while(0)
00206 
00207 
00208 
00209 
00210 /*
00211  * Search a list of instruction structures for a match.
00212  */
00213 static struct instruction_pattern
00214 MatchInstruction(const GLubyte *token)
00215 {
00216    const struct instruction_pattern *inst;
00217    struct instruction_pattern result;
00218 
00219    for (inst = Instructions; inst->name; inst++) {
00220       if (_mesa_strncmp((const char *) token, inst->name, 3) == 0) {
00221          /* matched! */
00222          int i = 3;
00223          result = *inst;
00224          result.suffixes = 0;
00225          /* look at suffix */
00226          if (token[i] == 'R') {
00227             result.suffixes |= _R;
00228             i++;
00229          }
00230          else if (token[i] == 'H') {
00231             result.suffixes |= _H;
00232             i++;
00233          }
00234          else if (token[i] == 'X') {
00235             result.suffixes |= _X;
00236             i++;
00237          }
00238          if (token[i] == 'C') {
00239             result.suffixes |= _C;
00240             i++;
00241          }
00242          if (token[i] == '_' && token[i+1] == 'S' &&
00243              token[i+2] == 'A' && token[i+3] == 'T') {
00244             result.suffixes |= _S;
00245          }
00246          return result;
00247       }
00248    }
00249    result.opcode = MAX_OPCODE; /* i.e. invalid instruction */
00250    return result;
00251 }
00252 
00253 
00254 
00255 
00256 /**********************************************************************/
00257 
00258 
00259 static GLboolean IsLetter(GLubyte b)
00260 {
00261    return (b >= 'a' && b <= 'z') ||
00262           (b >= 'A' && b <= 'Z') ||
00263           (b == '_') ||
00264           (b == '$');
00265 }
00266 
00267 
00268 static GLboolean IsDigit(GLubyte b)
00269 {
00270    return b >= '0' && b <= '9';
00271 }
00272 
00273 
00274 static GLboolean IsWhitespace(GLubyte b)
00275 {
00276    return b == ' ' || b == '\t' || b == '\n' || b == '\r';
00277 }
00278 
00279 
00285 static GLint
00286 GetToken(struct parse_state *parseState, GLubyte *token)
00287 {
00288    const GLubyte *str = parseState->pos;
00289    GLint i = 0, j = 0;
00290 
00291    token[0] = 0;
00292 
00293    /* skip whitespace and comments */
00294    while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
00295       if (str[i] == '#') {
00296          /* skip comment */
00297          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
00298             i++;
00299          }
00300          if (str[i] == '\n' || str[i] == '\r')
00301             parseState->curLine = str + i + 1;
00302       }
00303       else {
00304          /* skip whitespace */
00305          if (str[i] == '\n' || str[i] == '\r')
00306             parseState->curLine = str + i + 1;
00307          i++;
00308       }
00309    }
00310 
00311    if (str[i] == 0)
00312       return -i;
00313 
00314    /* try matching an integer */
00315    while (str[i] && IsDigit(str[i])) {
00316       token[j++] = str[i++];
00317    }
00318    if (j > 0 || !str[i]) {
00319       token[j] = 0;
00320       return i;
00321    }
00322 
00323    /* try matching an identifier */
00324    if (IsLetter(str[i])) {
00325       while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
00326          token[j++] = str[i++];
00327       }
00328       token[j] = 0;
00329       return i;
00330    }
00331 
00332    /* punctuation character */
00333    if (str[i]) {
00334       token[0] = str[i++];
00335       token[1] = 0;
00336       return i;
00337    }
00338 
00339    /* end of input */
00340    token[0] = 0;
00341    return i;
00342 }
00343 
00344 
00348 static GLboolean
00349 Parse_Token(struct parse_state *parseState, GLubyte *token)
00350 {
00351    GLint i;
00352    i = GetToken(parseState, token);
00353    if (i <= 0) {
00354       parseState->pos += (-i);
00355       return GL_FALSE;
00356    }
00357    parseState->pos += i;
00358    return GL_TRUE;
00359 }
00360 
00361 
00365 static GLboolean
00366 Peek_Token(struct parse_state *parseState, GLubyte *token)
00367 {
00368    GLint i, len;
00369    i = GetToken(parseState, token);
00370    if (i <= 0) {
00371       parseState->pos += (-i);
00372       return GL_FALSE;
00373    }
00374    len = (GLint)_mesa_strlen((const char *) token);
00375    parseState->pos += (i - len);
00376    return GL_TRUE;
00377 }
00378 
00379 
00380 /**********************************************************************/
00381 
00382 static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = {
00383    "WPOS", "COL0", "COL1", "FOGC",
00384    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
00385 };
00386 
00387 static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {
00388    "COLR", "COLH",
00389    /* These are only allows for register combiners */
00390    /*
00391    "TEX0", "TEX1", "TEX2", "TEX3",
00392    */
00393    "DEPR", NULL
00394 };
00395 
00396 
00397 
00398 
00399 /**********************************************************************/
00400 
00404 static GLboolean
00405 Parse_String(struct parse_state *parseState, const char *pattern)
00406 {
00407    const GLubyte *m;
00408    GLint i;
00409 
00410    /* skip whitespace and comments */
00411    while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
00412       if (*parseState->pos == '#') {
00413          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
00414             parseState->pos += 1;
00415          }
00416          if (*parseState->pos == '\n' || *parseState->pos == '\r')
00417             parseState->curLine = parseState->pos + 1;
00418       }
00419       else {
00420          /* skip whitespace */
00421          if (*parseState->pos == '\n' || *parseState->pos == '\r')
00422             parseState->curLine = parseState->pos + 1;
00423          parseState->pos += 1;
00424       }
00425    }
00426 
00427    /* Try to match the pattern */
00428    m = parseState->pos;
00429    for (i = 0; pattern[i]; i++) {
00430       if (*m != (GLubyte) pattern[i])
00431          return GL_FALSE;
00432       m += 1;
00433    }
00434    parseState->pos = m;
00435 
00436    return GL_TRUE; /* success */
00437 }
00438 
00439 
00440 static GLboolean
00441 Parse_Identifier(struct parse_state *parseState, GLubyte *ident)
00442 {
00443    if (!Parse_Token(parseState, ident))
00444       RETURN_ERROR;
00445    if (IsLetter(ident[0]))
00446       return GL_TRUE;
00447    else
00448       RETURN_ERROR1("Expected an identfier");
00449 }
00450 
00451 
00457 static GLboolean
00458 Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
00459 {
00460    char *end = NULL;
00461 
00462    *number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end);
00463 
00464    if (end && end > (char *) parseState->pos) {
00465       /* got a number */
00466       parseState->pos = (GLubyte *) end;
00467       number[1] = *number;
00468       number[2] = *number;
00469       number[3] = *number;
00470       return GL_TRUE;
00471    }
00472    else {
00473       /* should be an identifier */
00474       GLubyte ident[100];
00475       const GLfloat *constant;
00476       if (!Parse_Identifier(parseState, ident))
00477          RETURN_ERROR1("Expected an identifier");
00478       constant = _mesa_lookup_parameter_value(parseState->parameters,
00479                                               -1, (const char *) ident);
00480       /* XXX Check that it's a constant and not a parameter */
00481       if (!constant) {
00482          RETURN_ERROR1("Undefined symbol");
00483       }
00484       else {
00485          COPY_4V(number, constant);
00486          return GL_TRUE;
00487       }
00488    }
00489 }
00490 
00491 
00492 
00500 static GLboolean
00501 Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
00502 {
00503    /* "{" was already consumed */
00504 
00505    ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
00506 
00507    if (!Parse_ScalarConstant(parseState, vec+0))  /* X */
00508       return GL_FALSE;
00509 
00510    if (Parse_String(parseState, "}")) {
00511       return GL_TRUE;
00512    }
00513 
00514    if (!Parse_String(parseState, ","))
00515       RETURN_ERROR1("Expected comma in vector constant");
00516 
00517    if (!Parse_ScalarConstant(parseState, vec+1))  /* Y */
00518       return GL_FALSE;
00519 
00520    if (Parse_String(parseState, "}")) {
00521       return GL_TRUE;
00522    }
00523 
00524    if (!Parse_String(parseState, ","))
00525       RETURN_ERROR1("Expected comma in vector constant");
00526 
00527    if (!Parse_ScalarConstant(parseState, vec+2))  /* Z */
00528       return GL_FALSE;
00529 
00530    if (Parse_String(parseState, "}")) {
00531       return GL_TRUE;
00532    }
00533 
00534    if (!Parse_String(parseState, ","))
00535       RETURN_ERROR1("Expected comma in vector constant");
00536 
00537    if (!Parse_ScalarConstant(parseState, vec+3))  /* W */
00538       return GL_FALSE;
00539 
00540    if (!Parse_String(parseState, "}"))
00541       RETURN_ERROR1("Expected closing brace in vector constant");
00542 
00543    return GL_TRUE;
00544 }
00545 
00546 
00551 static GLuint
00552 Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
00553 {
00554    if (Parse_String(parseState, "{")) {
00555       return Parse_VectorConstant(parseState, vec);
00556    }
00557    else {
00558       GLboolean b = Parse_ScalarConstant(parseState, vec);
00559       if (b) {
00560          vec[1] = vec[2] = vec[3] = vec[0];
00561       }
00562       return b;
00563    }
00564 }
00565 
00566 
00571 static GLboolean
00572 Parse_TextureImageId(struct parse_state *parseState,
00573                      GLubyte *texUnit, GLubyte *texTargetBit)
00574 {
00575    GLubyte imageSrc[100];
00576    GLint unit;
00577 
00578    if (!Parse_Token(parseState, imageSrc))
00579       RETURN_ERROR;
00580    
00581    if (imageSrc[0] != 'T' ||
00582        imageSrc[1] != 'E' ||
00583        imageSrc[2] != 'X') {
00584       RETURN_ERROR1("Expected TEX# source");
00585    }
00586    unit = _mesa_atoi((const char *) imageSrc + 3);
00587    if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) ||
00588        (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) {
00589       RETURN_ERROR1("Invalied TEX# source index");
00590    }
00591    *texUnit = unit;
00592 
00593    if (!Parse_String(parseState, ","))
00594       RETURN_ERROR1("Expected ,");
00595 
00596    if (Parse_String(parseState, "1D")) {
00597       *texTargetBit = TEXTURE_1D_BIT;
00598    }
00599    else if (Parse_String(parseState, "2D")) {
00600       *texTargetBit = TEXTURE_2D_BIT;
00601    }
00602    else if (Parse_String(parseState, "3D")) {
00603       *texTargetBit = TEXTURE_3D_BIT;
00604    }
00605    else if (Parse_String(parseState, "CUBE")) {
00606       *texTargetBit = TEXTURE_CUBE_BIT;
00607    }
00608    else if (Parse_String(parseState, "RECT")) {
00609       *texTargetBit = TEXTURE_RECT_BIT;
00610    }
00611    else {
00612       RETURN_ERROR1("Invalid texture target token");
00613    }
00614 
00615    /* update record of referenced texture units */
00616    parseState->texturesUsed[*texUnit] |= *texTargetBit;
00617    if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
00618       RETURN_ERROR1("Only one texture target can be used per texture unit.");
00619    }
00620 
00621    return GL_TRUE;
00622 }
00623 
00624 
00629 static GLboolean
00630 Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4])
00631 {
00632    if (token[1] == 0) {
00633       /* single letter swizzle (scalar) */
00634       if (token[0] == 'x')
00635          ASSIGN_4V(swizzle, 0, 0, 0, 0);
00636       else if (token[0] == 'y')
00637          ASSIGN_4V(swizzle, 1, 1, 1, 1);
00638       else if (token[0] == 'z')
00639          ASSIGN_4V(swizzle, 2, 2, 2, 2);
00640       else if (token[0] == 'w')
00641          ASSIGN_4V(swizzle, 3, 3, 3, 3);
00642       else
00643          return GL_FALSE;
00644    }
00645    else {
00646       /* 4-component swizzle (vector) */
00647       GLint k;
00648       for (k = 0; token[k] && k < 4; k++) {
00649          if (token[k] == 'x')
00650             swizzle[k] = 0;
00651          else if (token[k] == 'y')
00652             swizzle[k] = 1;
00653          else if (token[k] == 'z')
00654             swizzle[k] = 2;
00655          else if (token[k] == 'w')
00656             swizzle[k] = 3;
00657          else
00658             return GL_FALSE;
00659       }
00660       if (k != 4)
00661          return GL_FALSE;
00662    }
00663    return GL_TRUE;
00664 }
00665 
00666 
00667 static GLboolean
00668 Parse_CondCodeMask(struct parse_state *parseState,
00669                    struct prog_dst_register *dstReg)
00670 {
00671    if (Parse_String(parseState, "EQ"))
00672       dstReg->CondMask = COND_EQ;
00673    else if (Parse_String(parseState, "GE"))
00674       dstReg->CondMask = COND_GE;
00675    else if (Parse_String(parseState, "GT"))
00676       dstReg->CondMask = COND_GT;
00677    else if (Parse_String(parseState, "LE"))
00678       dstReg->CondMask = COND_LE;
00679    else if (Parse_String(parseState, "LT"))
00680       dstReg->CondMask = COND_LT;
00681    else if (Parse_String(parseState, "NE"))
00682       dstReg->CondMask = COND_NE;
00683    else if (Parse_String(parseState, "TR"))
00684       dstReg->CondMask = COND_TR;
00685    else if (Parse_String(parseState, "FL"))
00686       dstReg->CondMask = COND_FL;
00687    else
00688       RETURN_ERROR1("Invalid condition code mask");
00689 
00690    /* look for optional .xyzw swizzle */
00691    if (Parse_String(parseState, ".")) {
00692       GLubyte token[100];
00693       GLuint swz[4];
00694 
00695       if (!Parse_Token(parseState, token))  /* get xyzw suffix */
00696          RETURN_ERROR;
00697 
00698       if (!Parse_SwizzleSuffix(token, swz))
00699          RETURN_ERROR1("Invalid swizzle suffix");
00700 
00701       dstReg->CondSwizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
00702    }
00703 
00704    return GL_TRUE;
00705 }
00706 
00707 
00711 static GLboolean
00712 Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
00713 {
00714    GLubyte token[100];
00715 
00716    /* Should be 'R##' or 'H##' */
00717    if (!Parse_Token(parseState, token))
00718       RETURN_ERROR;
00719    if (token[0] != 'R' && token[0] != 'H')
00720       RETURN_ERROR1("Expected R## or H##");
00721 
00722    if (IsDigit(token[1])) {
00723       GLint reg = _mesa_atoi((const char *) (token + 1));
00724       if (token[0] == 'H')
00725          reg += 32;
00726       if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
00727          RETURN_ERROR1("Invalid temporary register name");
00728       *tempRegNum = reg;
00729    }
00730    else {
00731       RETURN_ERROR1("Invalid temporary register name");
00732    }
00733 
00734    return GL_TRUE;
00735 }
00736 
00737 
00741 static GLboolean
00742 Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
00743 {
00744    if (Parse_String(parseState, "RC")) {
00745        *regNum = 0;
00746    }
00747    else if (Parse_String(parseState, "HC")) {
00748        *regNum = 1;
00749    }
00750    else {
00751       RETURN_ERROR1("Invalid write-only register name");
00752    }
00753 
00754    return GL_TRUE;
00755 }
00756 
00757 
00761 static GLboolean
00762 Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
00763 {
00764    GLubyte token[100];
00765 
00766    if (!Parse_String(parseState, "p["))
00767       RETURN_ERROR1("Expected p[");
00768 
00769    if (!Parse_Token(parseState, token))
00770       RETURN_ERROR;
00771 
00772    if (IsDigit(token[0])) {
00773       /* a numbered program parameter register */
00774       GLint reg = _mesa_atoi((const char *) token);
00775       if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
00776          RETURN_ERROR1("Invalid constant program number");
00777       *regNum = reg;
00778    }
00779    else {
00780       RETURN_ERROR;
00781    }
00782 
00783    if (!Parse_String(parseState, "]"))
00784       RETURN_ERROR1("Expected ]");
00785 
00786    return GL_TRUE;
00787 }
00788 
00789 
00793 static GLboolean
00794 Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
00795 {
00796    GLubyte token[100];
00797    GLint j;
00798 
00799    /* Match 'f[' */
00800    if (!Parse_String(parseState, "f["))
00801       RETURN_ERROR1("Expected f[");
00802 
00803    /* get <name> and look for match */
00804    if (!Parse_Token(parseState, token)) {
00805       RETURN_ERROR;
00806    }
00807    for (j = 0; InputRegisters[j]; j++) {
00808       if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
00809          *tempRegNum = j;
00810          parseState->inputsRead |= (1 << j);
00811          break;
00812       }
00813    }
00814    if (!InputRegisters[j]) {
00815       /* unknown input register label */
00816       RETURN_ERROR2("Invalid register name", token);
00817    }
00818 
00819    /* Match '[' */
00820    if (!Parse_String(parseState, "]"))
00821       RETURN_ERROR1("Expected ]");
00822 
00823    return GL_TRUE;
00824 }
00825 
00826 
00827 static GLboolean
00828 Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
00829 {
00830    GLubyte token[100];
00831    GLint j;
00832 
00833    /* Match "o[" */
00834    if (!Parse_String(parseState, "o["))
00835       RETURN_ERROR1("Expected o[");
00836 
00837    /* Get output reg name */
00838    if (!Parse_Token(parseState, token))
00839       RETURN_ERROR;
00840 
00841    /* try to match an output register name */
00842    for (j = 0; OutputRegisters[j]; j++) {
00843       if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
00844          static GLuint bothColors = (1 << FRAG_RESULT_COLR) | (1 << FRAG_RESULT_COLH);
00845          *outputRegNum = j;
00846          parseState->outputsWritten |= (1 << j);
00847          if ((parseState->outputsWritten & bothColors) == bothColors) {
00848             RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
00849          }
00850          break;
00851       }
00852    }
00853    if (!OutputRegisters[j])
00854       RETURN_ERROR1("Invalid output register name");
00855 
00856    /* Match ']' */
00857    if (!Parse_String(parseState, "]"))
00858       RETURN_ERROR1("Expected ]");
00859 
00860    return GL_TRUE;
00861 }
00862 
00863 
00864 static GLboolean
00865 Parse_MaskedDstReg(struct parse_state *parseState,
00866                    struct prog_dst_register *dstReg)
00867 {
00868    GLubyte token[100];
00869    GLint idx;
00870 
00871    /* Dst reg can be R<n>, H<n>, o[n], RC or HC */
00872    if (!Peek_Token(parseState, token))
00873       RETURN_ERROR;
00874 
00875    if (_mesa_strcmp((const char *) token, "RC") == 0 ||
00876        _mesa_strcmp((const char *) token, "HC") == 0) {
00877       /* a write-only register */
00878       dstReg->File = PROGRAM_WRITE_ONLY;
00879       if (!Parse_DummyReg(parseState, &idx))
00880          RETURN_ERROR;
00881       dstReg->Index = idx;
00882    }
00883    else if (token[0] == 'R' || token[0] == 'H') {
00884       /* a temporary register */
00885       dstReg->File = PROGRAM_TEMPORARY;
00886       if (!Parse_TempReg(parseState, &idx))
00887          RETURN_ERROR;
00888       dstReg->Index = idx;
00889    }
00890    else if (token[0] == 'o') {
00891       /* an output register */
00892       dstReg->File = PROGRAM_OUTPUT;
00893       if (!Parse_OutputReg(parseState, &idx))
00894          RETURN_ERROR;
00895       dstReg->Index = idx;
00896    }
00897    else {
00898       RETURN_ERROR1("Invalid destination register name");
00899    }
00900 
00901    /* Parse optional write mask */
00902    if (Parse_String(parseState, ".")) {
00903       /* got a mask */
00904       GLint k = 0;
00905 
00906       if (!Parse_Token(parseState, token))  /* get xyzw writemask */
00907          RETURN_ERROR;
00908 
00909       dstReg->WriteMask = 0;
00910 
00911       if (token[k] == 'x') {
00912          dstReg->WriteMask |= WRITEMASK_X;
00913          k++;
00914       }
00915       if (token[k] == 'y') {
00916          dstReg->WriteMask |= WRITEMASK_Y;
00917          k++;
00918       }
00919       if (token[k] == 'z') {
00920          dstReg->WriteMask |= WRITEMASK_Z;
00921          k++;
00922       }
00923       if (token[k] == 'w') {
00924          dstReg->WriteMask |= WRITEMASK_W;
00925          k++;
00926       }
00927       if (k == 0) {
00928          RETURN_ERROR1("Invalid writemask character");
00929       }
00930 
00931    }
00932    else {
00933       dstReg->WriteMask = WRITEMASK_XYZW;
00934    }
00935 
00936    /* optional condition code mask */
00937    if (Parse_String(parseState, "(")) {
00938       /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".x|y|z|w) */
00939       /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".[xyzw]) */
00940       if (!Parse_CondCodeMask(parseState, dstReg))
00941          RETURN_ERROR;
00942 
00943       if (!Parse_String(parseState, ")"))  /* consume ")" */
00944          RETURN_ERROR1("Expected )");
00945 
00946       return GL_TRUE;
00947    }
00948    else {
00949       /* no cond code mask */
00950       dstReg->CondMask = COND_TR;
00951       dstReg->CondSwizzle = SWIZZLE_NOOP;
00952       return GL_TRUE;
00953    }
00954 }
00955 
00956 
00963 static GLboolean
00964 Parse_VectorSrc(struct parse_state *parseState,
00965                 struct prog_src_register *srcReg)
00966 {
00967    GLfloat sign = 1.0F;
00968    GLubyte token[100];
00969    GLint idx;
00970 
00971    /*
00972     * First, take care of +/- and absolute value stuff.
00973     */
00974    if (Parse_String(parseState, "-"))
00975       sign = -1.0F;
00976    else if (Parse_String(parseState, "+"))
00977       sign = +1.0F;
00978 
00979    if (Parse_String(parseState, "|")) {
00980       srcReg->Abs = GL_TRUE;
00981       srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
00982 
00983       if (Parse_String(parseState, "-"))
00984          srcReg->NegateBase = NEGATE_XYZW;
00985       else if (Parse_String(parseState, "+"))
00986          srcReg->NegateBase = NEGATE_NONE;
00987       else
00988          srcReg->NegateBase = NEGATE_NONE;
00989    }
00990    else {
00991       srcReg->Abs = GL_FALSE;
00992       srcReg->NegateAbs = GL_FALSE;
00993       srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
00994    }
00995 
00996    /* This should be the real src vector/register name */
00997    if (!Peek_Token(parseState, token))
00998       RETURN_ERROR;
00999 
01000    /* Src reg can be Rn, Hn, f[n], p[n], a named parameter, a scalar
01001     * literal or vector literal.
01002     */
01003    if (token[0] == 'R' || token[0] == 'H') {
01004       srcReg->File = PROGRAM_TEMPORARY;
01005       if (!Parse_TempReg(parseState, &idx))
01006          RETURN_ERROR;
01007       srcReg->Index = idx;
01008    }
01009    else if (token[0] == 'f') {
01010       /* XXX this might be an identifier! */
01011       srcReg->File = PROGRAM_INPUT;
01012       if (!Parse_FragReg(parseState, &idx))
01013          RETURN_ERROR;
01014       srcReg->Index = idx;
01015    }
01016    else if (token[0] == 'p') {
01017       /* XXX this might be an identifier! */
01018       srcReg->File = PROGRAM_LOCAL_PARAM;
01019       if (!Parse_ProgramParamReg(parseState, &idx))
01020          RETURN_ERROR;
01021       srcReg->Index = idx;
01022    }
01023    else if (IsLetter(token[0])){
01024       GLubyte ident[100];
01025       GLint paramIndex;
01026       if (!Parse_Identifier(parseState, ident))
01027          RETURN_ERROR;
01028       paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
01029                                                 -1, (const char *) ident);
01030       if (paramIndex < 0) {
01031          RETURN_ERROR2("Undefined constant or parameter: ", ident);
01032       }
01033       srcReg->File = PROGRAM_NAMED_PARAM;
01034       srcReg->Index = paramIndex;      
01035    }
01036    else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){
01037       /* literal scalar constant */
01038       GLfloat values[4];
01039       GLuint paramIndex;
01040       if (!Parse_ScalarConstant(parseState, values))
01041          RETURN_ERROR;
01042       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
01043                                               values, 4, NULL);
01044       srcReg->File = PROGRAM_NAMED_PARAM;
01045       srcReg->Index = paramIndex;
01046    }
01047    else if (token[0] == '{'){
01048       /* literal vector constant */
01049       GLfloat values[4];
01050       GLuint paramIndex;
01051       (void) Parse_String(parseState, "{");
01052       if (!Parse_VectorConstant(parseState, values))
01053          RETURN_ERROR;
01054       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
01055                                               values, 4, NULL);
01056       srcReg->File = PROGRAM_NAMED_PARAM;
01057       srcReg->Index = paramIndex;      
01058    }
01059    else {
01060       RETURN_ERROR2("Invalid source register name", token);
01061    }
01062 
01063    /* init swizzle fields */
01064    srcReg->Swizzle = SWIZZLE_NOOP;
01065 
01066    /* Look for optional swizzle suffix */
01067    if (Parse_String(parseState, ".")) {
01068       GLuint swz[4];
01069 
01070       if (!Parse_Token(parseState, token))
01071          RETURN_ERROR;
01072 
01073       if (!Parse_SwizzleSuffix(token, swz))
01074          RETURN_ERROR1("Invalid swizzle suffix");
01075 
01076       srcReg->Swizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
01077    }
01078 
01079    /* Finish absolute value */
01080    if (srcReg->Abs && !Parse_String(parseState, "|")) {
01081       RETURN_ERROR1("Expected |");
01082    }
01083 
01084    return GL_TRUE;
01085 }
01086 
01087 
01088 static GLboolean
01089 Parse_ScalarSrcReg(struct parse_state *parseState,
01090                    struct prog_src_register *srcReg)
01091 {
01092    GLubyte token[100];
01093    GLfloat sign = 1.0F;
01094    GLboolean needSuffix = GL_TRUE;
01095    GLint idx;
01096 
01097    /*
01098     * First, take care of +/- and absolute value stuff.
01099     */
01100    if (Parse_String(parseState, "-"))
01101       sign = -1.0F;
01102    else if (Parse_String(parseState, "+"))
01103       sign = +1.0F;
01104 
01105    if (Parse_String(parseState, "|")) {
01106       srcReg->Abs = GL_TRUE;
01107       srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
01108 
01109       if (Parse_String(parseState, "-"))
01110          srcReg->NegateBase = NEGATE_XYZW;
01111       else if (Parse_String(parseState, "+"))
01112          srcReg->NegateBase = NEGATE_NONE;
01113       else
01114          srcReg->NegateBase = NEGATE_NONE;
01115    }
01116    else {
01117       srcReg->Abs = GL_FALSE;
01118       srcReg->NegateAbs = GL_FALSE;
01119       srcReg->NegateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
01120    }
01121 
01122    if (!Peek_Token(parseState, token))
01123       RETURN_ERROR;
01124 
01125    /* Src reg can be R<n>, H<n> or a named fragment attrib */
01126    if (token[0] == 'R' || token[0] == 'H') {
01127       srcReg->File = PROGRAM_TEMPORARY;
01128       if (!Parse_TempReg(parseState, &idx))
01129          RETURN_ERROR;
01130       srcReg->Index = idx;
01131    }
01132    else if (token[0] == 'f') {
01133       srcReg->File = PROGRAM_INPUT;
01134       if (!Parse_FragReg(parseState, &idx))
01135          RETURN_ERROR;
01136       srcReg->Index = idx;
01137    }
01138    else if (token[0] == '{') {
01139       /* vector literal */
01140       GLfloat values[4];
01141       GLuint paramIndex;
01142       (void) Parse_String(parseState, "{");
01143       if (!Parse_VectorConstant(parseState, values))
01144          RETURN_ERROR;
01145       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
01146                                               values, 4, NULL);
01147       srcReg->File = PROGRAM_NAMED_PARAM;
01148       srcReg->Index = paramIndex;      
01149    }
01150    else if (IsLetter(token[0])){
01151       /* named param/constant */
01152       GLubyte ident[100];
01153       GLint paramIndex;
01154       if (!Parse_Identifier(parseState, ident))
01155          RETURN_ERROR;
01156       paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
01157                                                 -1, (const char *) ident);
01158       if (paramIndex < 0) {
01159          RETURN_ERROR2("Undefined constant or parameter: ", ident);
01160       }
01161       srcReg->File = PROGRAM_NAMED_PARAM;
01162       srcReg->Index = paramIndex;      
01163    }
01164    else if (IsDigit(token[0])) {
01165       /* scalar literal */
01166       GLfloat values[4];
01167       GLuint paramIndex;
01168       if (!Parse_ScalarConstant(parseState, values))
01169          RETURN_ERROR;
01170       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
01171                                               values, 4, NULL);
01172       srcReg->Index = paramIndex;      
01173       srcReg->File = PROGRAM_NAMED_PARAM;
01174       needSuffix = GL_FALSE;
01175    }
01176    else {
01177       RETURN_ERROR2("Invalid scalar source argument", token);
01178    }
01179 
01180    srcReg->Swizzle = 0;
01181    if (needSuffix) {
01182       /* parse .[xyzw] suffix */
01183       if (!Parse_String(parseState, "."))
01184          RETURN_ERROR1("Expected .");
01185 
01186       if (!Parse_Token(parseState, token))
01187          RETURN_ERROR;
01188 
01189       if (token[0] == 'x' && token[1] == 0) {
01190          srcReg->Swizzle = 0;
01191       }
01192       else if (token[0] == 'y' && token[1] == 0) {
01193          srcReg->Swizzle = 1;
01194       }
01195       else if (token[0] == 'z' && token[1] == 0) {
01196          srcReg->Swizzle = 2;
01197       }
01198       else if (token[0] == 'w' && token[1] == 0) {
01199          srcReg->Swizzle = 3;
01200       }
01201       else {
01202          RETURN_ERROR1("Invalid scalar source suffix");
01203       }
01204    }
01205 
01206    /* Finish absolute value */
01207    if (srcReg->Abs && !Parse_String(parseState, "|")) {
01208       RETURN_ERROR1("Expected |");
01209    }
01210 
01211    return GL_TRUE;
01212 }
01213 
01214 
01215 static GLboolean
01216 Parse_PrintInstruction(struct parse_state *parseState,
01217                        struct prog_instruction *inst)
01218 {
01219    const GLubyte *str;
01220    GLubyte *msg;
01221    GLuint len;
01222    GLint idx;
01223 
01224    /* The first argument is a literal string 'just like this' */
01225    if (!Parse_String(parseState, "'"))
01226       RETURN_ERROR1("Expected '");
01227 
01228    str = parseState->pos;
01229    for (len = 0; str[len] != '\''; len++) /* find closing quote */
01230       ;
01231    parseState->pos += len + 1;
01232    msg = (GLubyte*) _mesa_malloc(len + 1);
01233 
01234    _mesa_memcpy(msg, str, len);
01235    msg[len] = 0;
01236    inst->Data = msg;
01237 
01238    if (Parse_String(parseState, ",")) {
01239       /* got an optional register to print */
01240       GLubyte token[100];
01241       GetToken(parseState, token);
01242       if (token[0] == 'o') {
01243          /* dst reg */
01244          if (!Parse_OutputReg(parseState, &idx))
01245             RETURN_ERROR;
01246      inst->SrcReg[0].Index = idx;
01247          inst->SrcReg[0].File = PROGRAM_OUTPUT;
01248       }
01249       else {
01250          /* src reg */
01251          if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01252             RETURN_ERROR;
01253       }
01254    }
01255    else {
01256       inst->SrcReg[0].File = PROGRAM_UNDEFINED;
01257    }
01258 
01259    inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
01260    inst->SrcReg[0].NegateBase = NEGATE_NONE;
01261    inst->SrcReg[0].Abs = GL_FALSE;
01262    inst->SrcReg[0].NegateAbs = GL_FALSE;
01263 
01264    return GL_TRUE;
01265 }
01266 
01267 
01268 static GLboolean
01269 Parse_InstructionSequence(struct parse_state *parseState,
01270                           struct prog_instruction program[])
01271 {
01272    while (1) {
01273       struct prog_instruction *inst = program + parseState->numInst;
01274       struct instruction_pattern instMatch;
01275       GLubyte token[100];
01276 
01277       /* Initialize the instruction */
01278       _mesa_init_instructions(inst, 1);
01279 
01280       /* special instructions */
01281       if (Parse_String(parseState, "DEFINE")) {
01282          GLubyte id[100];
01283          GLfloat value[7];  /* yes, 7 to be safe */
01284          if (!Parse_Identifier(parseState, id))
01285             RETURN_ERROR;
01286          /* XXX make sure id is not a reserved identifer, like R9 */
01287          if (!Parse_String(parseState, "="))
01288             RETURN_ERROR1("Expected =");
01289          if (!Parse_VectorOrScalarConstant(parseState, value))
01290             RETURN_ERROR;
01291          if (!Parse_String(parseState, ";"))
01292             RETURN_ERROR1("Expected ;");
01293          if (_mesa_lookup_parameter_index(parseState->parameters,
01294                                           -1, (const char *) id) >= 0) {
01295             RETURN_ERROR2(id, "already defined");
01296          }
01297          _mesa_add_named_parameter(parseState->parameters,
01298                                    (const char *) id, value);
01299       }
01300       else if (Parse_String(parseState, "DECLARE")) {
01301          GLubyte id[100];
01302          GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0};  /* yes, to be safe */
01303          if (!Parse_Identifier(parseState, id))
01304             RETURN_ERROR;
01305          /* XXX make sure id is not a reserved identifer, like R9 */
01306          if (Parse_String(parseState, "=")) {
01307             if (!Parse_VectorOrScalarConstant(parseState, value))
01308                RETURN_ERROR;
01309          }
01310          if (!Parse_String(parseState, ";"))
01311             RETURN_ERROR1("Expected ;");
01312          if (_mesa_lookup_parameter_index(parseState->parameters,
01313                                           -1, (const char *) id) >= 0) {
01314             RETURN_ERROR2(id, "already declared");
01315          }
01316          _mesa_add_named_parameter(parseState->parameters,
01317                                    (const char *) id, value);
01318       }
01319       else if (Parse_String(parseState, "END")) {
01320          inst->Opcode = OPCODE_END;
01321          inst->StringPos = parseState->curLine - parseState->start;
01322          assert(inst->StringPos >= 0);
01323          parseState->numInst++;
01324          if (Parse_Token(parseState, token)) {
01325             RETURN_ERROR1("Code after END opcode.");
01326          }
01327          break;
01328       }
01329       else {
01330          /* general/arithmetic instruction */
01331 
01332          /* get token */
01333          if (!Parse_Token(parseState, token)) {
01334             RETURN_ERROR1("Missing END instruction.");
01335          }
01336 
01337          /* try to find matching instuction */
01338          instMatch = MatchInstruction(token);
01339          if (instMatch.opcode >= MAX_OPCODE) {
01340             /* bad instruction name */
01341             RETURN_ERROR2("Unexpected token: ", token);
01342          }
01343 
01344          inst->Opcode = instMatch.opcode;
01345          inst->Precision = instMatch.suffixes & (_R | _H | _X);
01346          inst->SaturateMode = (instMatch.suffixes & (_S))
01347             ? SATURATE_ZERO_ONE : SATURATE_OFF;
01348          inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
01349          inst->StringPos = parseState->curLine - parseState->start;
01350          assert(inst->StringPos >= 0);
01351 
01352          /*
01353           * parse the input and output operands
01354           */
01355          if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
01356             if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
01357                RETURN_ERROR;
01358             if (!Parse_String(parseState, ","))
01359                RETURN_ERROR1("Expected ,");
01360          }
01361          else if (instMatch.outputs == OUTPUT_NONE) {
01362             if (instMatch.opcode == OPCODE_KIL_NV) {
01363                /* This is a little weird, the cond code info is in
01364                 * the dest register.
01365                 */
01366                if (!Parse_CondCodeMask(parseState, &inst->DstReg))
01367                   RETURN_ERROR;
01368             }
01369             else {
01370                ASSERT(instMatch.opcode == OPCODE_PRINT);
01371             }
01372          }
01373 
01374          if (instMatch.inputs == INPUT_1V) {
01375             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01376                RETURN_ERROR;
01377          }
01378          else if (instMatch.inputs == INPUT_2V) {
01379             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01380                RETURN_ERROR;
01381             if (!Parse_String(parseState, ","))
01382                RETURN_ERROR1("Expected ,");
01383             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
01384                RETURN_ERROR;
01385          }
01386          else if (instMatch.inputs == INPUT_3V) {
01387             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01388                RETURN_ERROR;
01389             if (!Parse_String(parseState, ","))
01390                RETURN_ERROR1("Expected ,");
01391             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
01392                RETURN_ERROR;
01393             if (!Parse_String(parseState, ","))
01394                RETURN_ERROR1("Expected ,");
01395             if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
01396                RETURN_ERROR;
01397          }
01398          else if (instMatch.inputs == INPUT_1S) {
01399             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
01400                RETURN_ERROR;
01401          }
01402          else if (instMatch.inputs == INPUT_2S) {
01403             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
01404                RETURN_ERROR;
01405             if (!Parse_String(parseState, ","))
01406                RETURN_ERROR1("Expected ,");
01407             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
01408                RETURN_ERROR;
01409          }
01410          else if (instMatch.inputs == INPUT_CC) {
01411             /* XXX to-do */
01412          }
01413          else if (instMatch.inputs == INPUT_1V_T) {
01414         GLubyte unit, idx;
01415             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01416                RETURN_ERROR;
01417             if (!Parse_String(parseState, ","))
01418                RETURN_ERROR1("Expected ,");
01419             if (!Parse_TextureImageId(parseState, &unit, &idx))
01420                RETURN_ERROR;
01421         inst->TexSrcUnit = unit;
01422         inst->TexSrcTarget = idx;
01423          }
01424          else if (instMatch.inputs == INPUT_3V_T) {
01425         GLubyte unit, idx;
01426             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
01427                RETURN_ERROR;
01428             if (!Parse_String(parseState, ","))
01429                RETURN_ERROR1("Expected ,");
01430             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
01431                RETURN_ERROR;
01432             if (!Parse_String(parseState, ","))
01433                RETURN_ERROR1("Expected ,");
01434             if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
01435                RETURN_ERROR;
01436             if (!Parse_String(parseState, ","))
01437                RETURN_ERROR1("Expected ,");
01438             if (!Parse_TextureImageId(parseState, &unit, &idx))
01439                RETURN_ERROR;
01440         inst->TexSrcUnit = unit;
01441         inst->TexSrcTarget = idx;
01442          }
01443          else if (instMatch.inputs == INPUT_1V_S) {
01444             if (!Parse_PrintInstruction(parseState, inst))
01445                RETURN_ERROR;
01446          }
01447 
01448          /* end of statement semicolon */
01449          if (!Parse_String(parseState, ";"))
01450             RETURN_ERROR1("Expected ;");
01451 
01452          parseState->numInst++;
01453 
01454          if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
01455             RETURN_ERROR1("Program too long");
01456       }
01457    }
01458    return GL_TRUE;
01459 }
01460 
01461 
01462 
01468 void
01469 _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
01470                                 const GLubyte *str, GLsizei len,
01471                                 struct gl_fragment_program *program)
01472 {
01473    struct parse_state parseState;
01474    struct prog_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS];
01475    struct prog_instruction *newInst;
01476    GLenum target;
01477    GLubyte *programString;
01478 
01479    /* Make a null-terminated copy of the program string */
01480    programString = (GLubyte *) MALLOC(len + 1);
01481    if (!programString) {
01482       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
01483       return;
01484    }
01485    MEMCPY(programString, str, len);
01486    programString[len] = 0;
01487 
01488    /* Get ready to parse */
01489    _mesa_bzero(&parseState, sizeof(struct parse_state));
01490    parseState.ctx = ctx;
01491    parseState.start = programString;
01492    parseState.program = program;
01493    parseState.numInst = 0;
01494    parseState.curLine = programString;
01495    parseState.parameters = _mesa_new_parameter_list();
01496 
01497    /* Reset error state */
01498    _mesa_set_program_error(ctx, -1, NULL);
01499 
01500    /* check the program header */
01501    if (_mesa_strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
01502       target = GL_FRAGMENT_PROGRAM_NV;
01503       parseState.pos = programString + 7;
01504    }
01505    else if (_mesa_strncmp((const char *) programString, "!!FCP1.0", 8) == 0) {
01506       /* fragment / register combiner program - not supported */
01507       _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
01508       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
01509       return;
01510    }
01511    else {
01512       /* invalid header */
01513       _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
01514       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
01515       return;
01516    }
01517 
01518    /* make sure target and header match */
01519    if (target != dstTarget) {
01520       _mesa_error(ctx, GL_INVALID_OPERATION,
01521                   "glLoadProgramNV(target mismatch 0x%x != 0x%x)",
01522                   target, dstTarget);
01523       return;
01524    }
01525 
01526    if (Parse_InstructionSequence(&parseState, instBuffer)) {
01527       GLuint u;
01528       /* successful parse! */
01529 
01530       if (parseState.outputsWritten == 0) {
01531          /* must write at least one output! */
01532          _mesa_error(ctx, GL_INVALID_OPERATION,
01533                      "Invalid fragment program - no outputs written.");
01534          return;
01535       }
01536 
01537       /* copy the compiled instructions */
01538       assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS);
01539       newInst = _mesa_alloc_instructions(parseState.numInst);
01540       if (!newInst) {
01541          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
01542          return;  /* out of memory */
01543       }
01544       _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
01545 
01546       /* install the program */
01547       program->Base.Target = target;
01548       if (program->Base.String) {
01549          FREE(program->Base.String);
01550       }
01551       program->Base.String = programString;
01552       program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
01553       if (program->Base.Instructions) {
01554          _mesa_free(program->Base.Instructions);
01555       }
01556       program->Base.Instructions = newInst;
01557       program->Base.NumInstructions = parseState.numInst;
01558       program->Base.InputsRead = parseState.inputsRead;
01559       program->Base.OutputsWritten = parseState.outputsWritten;
01560       for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
01561          program->Base.TexturesUsed[u] = parseState.texturesUsed[u];
01562 
01563       /* save program parameters */
01564       program->Base.Parameters = parseState.parameters;
01565 
01566       /* allocate registers for declared program parameters */
01567 #if 00
01568       _mesa_assign_program_registers(&(program->SymbolTable));
01569 #endif
01570 
01571 #ifdef DEBUG_foo
01572       _mesa_printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
01573       _mesa_print_nv_fragment_program(program);
01574       _mesa_printf("----------------------------------\n");
01575 #endif
01576    }
01577    else {
01578       /* Error! */
01579       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
01580       /* NOTE: _mesa_set_program_error would have been called already */
01581    }
01582 }
01583 
01584 
01585 static void
01586 PrintSrcReg(const struct gl_fragment_program *program,
01587             const struct prog_src_register *src)
01588 {
01589    static const char comps[5] = "xyzw";
01590 
01591    if (src->NegateAbs) {
01592       _mesa_printf("-");
01593    }
01594    if (src->Abs) {
01595       _mesa_printf("|");
01596    }
01597    if (src->NegateBase) {
01598       _mesa_printf("-");
01599    }
01600    if (src->File == PROGRAM_NAMED_PARAM) {
01601       if (program->Base.Parameters->Parameters[src->Index].Type
01602           == PROGRAM_CONSTANT) {
01603          const GLfloat *v;
01604          v = program->Base.Parameters->ParameterValues[src->Index];
01605          _mesa_printf("{%g, %g, %g, %g}", v[0], v[1], v[2], v[3]);
01606       }
01607       else {
01608          ASSERT(program->Base.Parameters->Parameters[src->Index].Type
01609                 == PROGRAM_NAMED_PARAM);
01610          _mesa_printf("%s", program->Base.Parameters->Parameters[src->Index].Name);
01611       }
01612    }
01613    else if (src->File == PROGRAM_OUTPUT) {
01614       _mesa_printf("o[%s]", OutputRegisters[src->Index]);
01615    }
01616    else if (src->File == PROGRAM_INPUT) {
01617       _mesa_printf("f[%s]", InputRegisters[src->Index]);
01618    }
01619    else if (src->File == PROGRAM_LOCAL_PARAM) {
01620       _mesa_printf("p[%d]", src->Index);
01621    }
01622    else if (src->File == PROGRAM_TEMPORARY) {
01623       if (src->Index >= 32)
01624          _mesa_printf("H%d", src->Index);
01625       else
01626          _mesa_printf("R%d", src->Index);
01627    }
01628    else if (src->File == PROGRAM_WRITE_ONLY) {
01629       _mesa_printf("%cC", "HR"[src->Index]);
01630    }
01631    else {
01632       _mesa_problem(NULL, "Invalid fragment register %d", src->Index);
01633       return;
01634    }
01635    if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) &&
01636        GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) &&
01637        GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) {
01638       _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]);
01639    }
01640    else if (src->Swizzle != SWIZZLE_NOOP) {
01641       _mesa_printf(".%c%c%c%c",
01642                    comps[GET_SWZ(src->Swizzle, 0)],
01643                    comps[GET_SWZ(src->Swizzle, 1)],
01644                    comps[GET_SWZ(src->Swizzle, 2)],
01645                    comps[GET_SWZ(src->Swizzle, 3)]);
01646    }
01647    if (src->Abs) {
01648       _mesa_printf("|");
01649    }
01650 }
01651 
01652 static void
01653 PrintTextureSrc(const struct prog_instruction *inst)
01654 {
01655    _mesa_printf("TEX%d, ", inst->TexSrcUnit);
01656    switch (inst->TexSrcTarget) {
01657    case TEXTURE_1D_INDEX:
01658       _mesa_printf("1D");
01659       break;
01660    case TEXTURE_2D_INDEX:
01661       _mesa_printf("2D");
01662       break;
01663    case TEXTURE_3D_INDEX:
01664       _mesa_printf("3D");
01665       break;
01666    case TEXTURE_RECT_INDEX:
01667       _mesa_printf("RECT");
01668       break;
01669    case TEXTURE_CUBE_INDEX:
01670       _mesa_printf("CUBE");
01671       break;
01672    default:
01673       _mesa_problem(NULL, "Invalid textue target in PrintTextureSrc");
01674    }
01675 }
01676 
01677 static void
01678 PrintCondCode(const struct prog_dst_register *dst)
01679 {
01680    static const char *comps = "xyzw";
01681    static const char *ccString[] = {
01682       "??", "GT", "EQ", "LT", "UN", "GE", "LE", "NE", "TR", "FL", "??"
01683    };
01684 
01685    _mesa_printf("%s", ccString[dst->CondMask]);
01686    if (GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 1) &&
01687        GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 2) &&
01688        GET_SWZ(dst->CondSwizzle, 0) == GET_SWZ(dst->CondSwizzle, 3)) {
01689       _mesa_printf(".%c", comps[GET_SWZ(dst->CondSwizzle, 0)]);
01690    }
01691    else if (dst->CondSwizzle != SWIZZLE_NOOP) {
01692       _mesa_printf(".%c%c%c%c",
01693                    comps[GET_SWZ(dst->CondSwizzle, 0)],
01694                    comps[GET_SWZ(dst->CondSwizzle, 1)],
01695                    comps[GET_SWZ(dst->CondSwizzle, 2)],
01696                    comps[GET_SWZ(dst->CondSwizzle, 3)]);
01697    }
01698 }
01699 
01700 
01701 static void
01702 PrintDstReg(const struct prog_dst_register *dst)
01703 {
01704    if (dst->File == PROGRAM_OUTPUT) {
01705       _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
01706    }
01707    else if (dst->File == PROGRAM_TEMPORARY) {
01708       if (dst->Index >= 32)
01709          _mesa_printf("H%d", dst->Index);
01710       else
01711          _mesa_printf("R%d", dst->Index);
01712    }
01713    else if (dst->File == PROGRAM_LOCAL_PARAM) {
01714       _mesa_printf("p[%d]", dst->Index);
01715    }
01716    else if (dst->File == PROGRAM_WRITE_ONLY) {
01717       _mesa_printf("%cC", "HR"[dst->Index]);
01718    }
01719    else {
01720       _mesa_printf("???");
01721    }
01722 
01723    if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) {
01724       _mesa_printf(".");
01725       if (dst->WriteMask & WRITEMASK_X)
01726          _mesa_printf("x");
01727       if (dst->WriteMask & WRITEMASK_Y)
01728          _mesa_printf("y");
01729       if (dst->WriteMask & WRITEMASK_Z)
01730          _mesa_printf("z");
01731       if (dst->WriteMask & WRITEMASK_W)
01732          _mesa_printf("w");
01733    }
01734 
01735    if (dst->CondMask != COND_TR ||
01736        dst->CondSwizzle != SWIZZLE_NOOP) {
01737       _mesa_printf(" (");
01738       PrintCondCode(dst);
01739       _mesa_printf(")");
01740    }
01741 }
01742 
01743 
01747 void
01748 _mesa_print_nv_fragment_program(const struct gl_fragment_program *program)
01749 {
01750    const struct prog_instruction *inst;
01751 
01752    for (inst = program->Base.Instructions; inst->Opcode != OPCODE_END; inst++) {
01753       int i;
01754       for (i = 0; Instructions[i].name; i++) {
01755          if (inst->Opcode == Instructions[i].opcode) {
01756             /* print instruction name */
01757             _mesa_printf("%s", Instructions[i].name);
01758             if (inst->Precision == FLOAT16)
01759                _mesa_printf("H");
01760             else if (inst->Precision == FIXED12)
01761                _mesa_printf("X");
01762             if (inst->CondUpdate)
01763                _mesa_printf("C");
01764             if (inst->SaturateMode == SATURATE_ZERO_ONE)
01765                _mesa_printf("_SAT");
01766             _mesa_printf(" ");
01767 
01768             if (Instructions[i].inputs == INPUT_CC) {
01769                PrintCondCode(&inst->DstReg);
01770             }
01771             else if (Instructions[i].outputs == OUTPUT_V ||
01772                      Instructions[i].outputs == OUTPUT_S) {
01773                /* print dest register */
01774                PrintDstReg(&inst->DstReg);
01775                _mesa_printf(", ");
01776             }
01777 
01778             /* print source register(s) */
01779             if (Instructions[i].inputs == INPUT_1V ||
01780                 Instructions[i].inputs == INPUT_1S) {
01781                PrintSrcReg(program, &inst->SrcReg[0]);
01782             }
01783             else if (Instructions[i].inputs == INPUT_2V ||
01784                      Instructions[i].inputs == INPUT_2S) {
01785                PrintSrcReg(program, &inst->SrcReg[0]);
01786                _mesa_printf(", ");
01787                PrintSrcReg(program, &inst->SrcReg[1]);
01788             }
01789             else if (Instructions[i].inputs == INPUT_3V) {
01790                PrintSrcReg(program, &inst->SrcReg[0]);
01791                _mesa_printf(", ");
01792                PrintSrcReg(program, &inst->SrcReg[1]);
01793                _mesa_printf(", ");
01794                PrintSrcReg(program, &inst->SrcReg[2]);
01795             }
01796             else if (Instructions[i].inputs == INPUT_1V_T) {
01797                PrintSrcReg(program, &inst->SrcReg[0]);
01798                _mesa_printf(", ");
01799                PrintTextureSrc(inst);
01800             }
01801             else if (Instructions[i].inputs == INPUT_3V_T) {
01802                PrintSrcReg(program, &inst->SrcReg[0]);
01803                _mesa_printf(", ");
01804                PrintSrcReg(program, &inst->SrcReg[1]);
01805                _mesa_printf(", ");
01806                PrintSrcReg(program, &inst->SrcReg[2]);
01807                _mesa_printf(", ");
01808                PrintTextureSrc(inst);
01809             }
01810             _mesa_printf(";\n");
01811             break;
01812          }
01813       }
01814       if (!Instructions[i].name) {
01815          _mesa_printf("Invalid opcode %d\n", inst->Opcode);
01816       }
01817    }
01818    _mesa_printf("END\n");
01819 }
01820 
01821 
01822 const char *
01823 _mesa_nv_fragment_input_register_name(GLuint i)
01824 {
01825    ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
01826    return InputRegisters[i];
01827 }
01828 
01829 
01830 const char *
01831 _mesa_nv_fragment_output_register_name(GLuint i)
01832 {
01833    ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
01834    return OutputRegisters[i];
01835 }

Generated on Sat May 26 2012 04:19:21 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.