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

nvvertparse.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  6.5.2
00004  *
00005  * Copyright (C) 1999-2006  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_vertex_program, GL_NV_vertex_program1_1:
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 "nvprogram.h"
00045 #include "nvvertparse.h"
00046 #include "prog_instruction.h"
00047 #include "program.h"
00048 
00049 
00055 struct parse_state {
00056    GLcontext *ctx;
00057    const GLubyte *start;
00058    const GLubyte *pos;
00059    const GLubyte *curLine;
00060    GLboolean isStateProgram;
00061    GLboolean isPositionInvariant;
00062    GLboolean isVersion1_1;
00063    GLbitfield inputsRead;
00064    GLbitfield outputsWritten;
00065    GLboolean anyProgRegsWritten;
00066    GLuint numInst;                 /* number of instructions parsed */
00067 };
00068 
00069 
00070 /*
00071  * Called whenever we find an error during parsing.
00072  */
00073 static void
00074 record_error(struct parse_state *parseState, const char *msg, int lineNo)
00075 {
00076 #ifdef DEBUG
00077    GLint line, column;
00078    const GLubyte *lineStr;
00079    lineStr = _mesa_find_line_column(parseState->start,
00080                                     parseState->pos, &line, &column);
00081    _mesa_debug(parseState->ctx,
00082                "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
00083                lineNo, line, column, (char *) lineStr, msg);
00084    _mesa_free((void *) lineStr);
00085 #else
00086    (void) lineNo;
00087 #endif
00088 
00089    /* Check that no error was already recorded.  Only record the first one. */
00090    if (parseState->ctx->Program.ErrorString[0] == 0) {
00091       _mesa_set_program_error(parseState->ctx,
00092                               parseState->pos - parseState->start,
00093                               msg);
00094    }
00095 }
00096 
00097 
00098 #define RETURN_ERROR                            \
00099 do {                                    \
00100    record_error(parseState, "Unexpected end of input.", __LINE__);  \
00101    return GL_FALSE;                         \
00102 } while(0)
00103 
00104 #define RETURN_ERROR1(msg)                      \
00105 do {                                    \
00106    record_error(parseState, msg, __LINE__);             \
00107    return GL_FALSE;                         \
00108 } while(0)
00109 
00110 #define RETURN_ERROR2(msg1, msg2)                   \
00111 do {                                    \
00112    char err[1000];                          \
00113    _mesa_sprintf(err, "%s %s", msg1, msg2);             \
00114    record_error(parseState, err, __LINE__);             \
00115    return GL_FALSE;                         \
00116 } while(0)
00117 
00118 
00119 
00120 
00121 
00122 static GLboolean IsLetter(GLubyte b)
00123 {
00124    return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
00125 }
00126 
00127 
00128 static GLboolean IsDigit(GLubyte b)
00129 {
00130    return b >= '0' && b <= '9';
00131 }
00132 
00133 
00134 static GLboolean IsWhitespace(GLubyte b)
00135 {
00136    return b == ' ' || b == '\t' || b == '\n' || b == '\r';
00137 }
00138 
00139 
00145 static GLint
00146 GetToken(struct parse_state *parseState, GLubyte *token)
00147 {
00148    const GLubyte *str = parseState->pos;
00149    GLint i = 0, j = 0;
00150 
00151    token[0] = 0;
00152 
00153    /* skip whitespace and comments */
00154    while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
00155       if (str[i] == '#') {
00156          /* skip comment */
00157          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
00158             i++;
00159          }
00160          if (str[i] == '\n' || str[i] == '\r')
00161             parseState->curLine = str + i + 1;
00162       }
00163       else {
00164          /* skip whitespace */
00165          if (str[i] == '\n' || str[i] == '\r')
00166             parseState->curLine = str + i + 1;
00167          i++;
00168       }
00169    }
00170 
00171    if (str[i] == 0)
00172       return -i;
00173 
00174    /* try matching an integer */
00175    while (str[i] && IsDigit(str[i])) {
00176       token[j++] = str[i++];
00177    }
00178    if (j > 0 || !str[i]) {
00179       token[j] = 0;
00180       return i;
00181    }
00182 
00183    /* try matching an identifier */
00184    if (IsLetter(str[i])) {
00185       while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
00186          token[j++] = str[i++];
00187       }
00188       token[j] = 0;
00189       return i;
00190    }
00191 
00192    /* punctuation character */
00193    if (str[i]) {
00194       token[0] = str[i++];
00195       token[1] = 0;
00196       return i;
00197    }
00198 
00199    /* end of input */
00200    token[0] = 0;
00201    return i;
00202 }
00203 
00204 
00208 static GLboolean
00209 Parse_Token(struct parse_state *parseState, GLubyte *token)
00210 {
00211    GLint i;
00212    i = GetToken(parseState, token);
00213    if (i <= 0) {
00214       parseState->pos += (-i);
00215       return GL_FALSE;
00216    }
00217    parseState->pos += i;
00218    return GL_TRUE;
00219 }
00220 
00221 
00225 static GLboolean
00226 Peek_Token(struct parse_state *parseState, GLubyte *token)
00227 {
00228    GLint i, len;
00229    i = GetToken(parseState, token);
00230    if (i <= 0) {
00231       parseState->pos += (-i);
00232       return GL_FALSE;
00233    }
00234    len = (GLint)_mesa_strlen((const char *) token);
00235    parseState->pos += (i - len);
00236    return GL_TRUE;
00237 }
00238 
00239 
00245 static GLboolean
00246 Parse_String(struct parse_state *parseState, const char *pattern)
00247 {
00248    const GLubyte *m;
00249    GLint i;
00250 
00251    /* skip whitespace and comments */
00252    while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
00253       if (*parseState->pos == '#') {
00254          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
00255             parseState->pos += 1;
00256          }
00257          if (*parseState->pos == '\n' || *parseState->pos == '\r')
00258             parseState->curLine = parseState->pos + 1;
00259       }
00260       else {
00261          /* skip whitespace */
00262          if (*parseState->pos == '\n' || *parseState->pos == '\r')
00263             parseState->curLine = parseState->pos + 1;
00264          parseState->pos += 1;
00265       }
00266    }
00267 
00268    /* Try to match the pattern */
00269    m = parseState->pos;
00270    for (i = 0; pattern[i]; i++) {
00271       if (*m != (GLubyte) pattern[i])
00272          return GL_FALSE;
00273       m += 1;
00274    }
00275    parseState->pos = m;
00276 
00277    return GL_TRUE; /* success */
00278 }
00279 
00280 
00281 /**********************************************************************/
00282 
00283 static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
00284    "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
00285    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
00286 };
00287 
00288 static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
00289    "HPOS", "COL0", "COL1", "FOGC", 
00290    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", 
00291    "PSIZ", "BFC0", "BFC1", NULL
00292 };
00293 
00294 
00295 
00299 static GLboolean
00300 Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
00301 {
00302    GLubyte token[100];
00303 
00304    /* Should be 'R##' */
00305    if (!Parse_Token(parseState, token))
00306       RETURN_ERROR;
00307    if (token[0] != 'R')
00308       RETURN_ERROR1("Expected R##");
00309 
00310    if (IsDigit(token[1])) {
00311       GLint reg = _mesa_atoi((char *) (token + 1));
00312       if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS)
00313          RETURN_ERROR1("Bad temporary register name");
00314       *tempRegNum = reg;
00315    }
00316    else {
00317       RETURN_ERROR1("Bad temporary register name");
00318    }
00319 
00320    return GL_TRUE;
00321 }
00322 
00323 
00327 static GLboolean
00328 Parse_AddrReg(struct parse_state *parseState)
00329 {
00330    /* match 'A0' */
00331    if (!Parse_String(parseState, "A0"))
00332       RETURN_ERROR;
00333 
00334    /* match '.' */
00335    if (!Parse_String(parseState, "."))
00336       RETURN_ERROR;
00337 
00338    /* match 'x' */
00339    if (!Parse_String(parseState, "x"))
00340       RETURN_ERROR;
00341 
00342    return GL_TRUE;
00343 }
00344 
00345 
00349 static GLboolean
00350 Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
00351 {
00352    GLubyte token[100];
00353 
00354    if (!Parse_String(parseState, "c"))
00355       RETURN_ERROR;
00356 
00357    if (!Parse_String(parseState, "["))
00358       RETURN_ERROR;
00359 
00360    if (!Parse_Token(parseState, token))
00361       RETURN_ERROR;
00362 
00363    if (IsDigit(token[0])) {
00364       /* a numbered program parameter register */
00365       GLint reg = _mesa_atoi((char *) token);
00366       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
00367          RETURN_ERROR1("Bad program parameter number");
00368       *regNum = reg;
00369    }
00370    else {
00371       RETURN_ERROR;
00372    }
00373 
00374    if (!Parse_String(parseState, "]"))
00375       RETURN_ERROR;
00376 
00377    return GL_TRUE;
00378 }
00379 
00380 
00381 static GLboolean
00382 Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg)
00383 {
00384    GLubyte token[100];
00385 
00386    if (!Parse_String(parseState, "c"))
00387       RETURN_ERROR;
00388 
00389    if (!Parse_String(parseState, "["))
00390       RETURN_ERROR;
00391 
00392    if (!Peek_Token(parseState, token))
00393       RETURN_ERROR;
00394 
00395    if (IsDigit(token[0])) {
00396       /* a numbered program parameter register */
00397       GLint reg;
00398       (void) Parse_Token(parseState, token);
00399       reg = _mesa_atoi((char *) token);
00400       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
00401          RETURN_ERROR1("Bad program parameter number");
00402       srcReg->File = PROGRAM_ENV_PARAM;
00403       srcReg->Index = reg;
00404    }
00405    else if (_mesa_strcmp((const char *) token, "A0") == 0) {
00406       /* address register "A0.x" */
00407       if (!Parse_AddrReg(parseState))
00408          RETURN_ERROR;
00409 
00410       srcReg->RelAddr = GL_TRUE;
00411       srcReg->File = PROGRAM_ENV_PARAM;
00412       /* Look for +/-N offset */
00413       if (!Peek_Token(parseState, token))
00414          RETURN_ERROR;
00415 
00416       if (token[0] == '-' || token[0] == '+') {
00417          const GLubyte sign = token[0];
00418          (void) Parse_Token(parseState, token); /* consume +/- */
00419 
00420          /* an integer should be next */
00421          if (!Parse_Token(parseState, token))
00422             RETURN_ERROR;
00423 
00424          if (IsDigit(token[0])) {
00425             const GLint k = _mesa_atoi((char *) token);
00426             if (sign == '-') {
00427                if (k > 64)
00428                   RETURN_ERROR1("Bad address offset");
00429                srcReg->Index = -k;
00430             }
00431             else {
00432                if (k > 63)
00433                   RETURN_ERROR1("Bad address offset");
00434                srcReg->Index = k;
00435             }
00436          }
00437          else {
00438             RETURN_ERROR;
00439          }
00440       }
00441       else {
00442          /* probably got a ']', catch it below */
00443       }
00444    }
00445    else {
00446       RETURN_ERROR;
00447    }
00448 
00449    /* Match closing ']' */
00450    if (!Parse_String(parseState, "]"))
00451       RETURN_ERROR;
00452 
00453    return GL_TRUE;
00454 }
00455 
00456 
00460 static GLboolean
00461 Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum)
00462 {
00463    GLubyte token[100];
00464    GLint j;
00465 
00466    /* Match 'v' */
00467    if (!Parse_String(parseState, "v"))
00468       RETURN_ERROR;
00469 
00470    /* Match '[' */
00471    if (!Parse_String(parseState, "["))
00472       RETURN_ERROR;
00473 
00474    /* match number or named register */
00475    if (!Parse_Token(parseState, token))
00476       RETURN_ERROR;
00477 
00478    if (parseState->isStateProgram && token[0] != '0')
00479       RETURN_ERROR1("Only v[0] accessible in vertex state programs");
00480 
00481    if (IsDigit(token[0])) {
00482       GLint reg = _mesa_atoi((char *) token);
00483       if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS)
00484          RETURN_ERROR1("Bad vertex attribute register name");
00485       *tempRegNum = reg;
00486    }
00487    else {
00488       for (j = 0; InputRegisters[j]; j++) {
00489          if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
00490             *tempRegNum = j;
00491             break;
00492          }
00493       }
00494       if (!InputRegisters[j]) {
00495          /* unknown input register label */
00496          RETURN_ERROR2("Bad register name", token);
00497       }
00498    }
00499 
00500    /* Match '[' */
00501    if (!Parse_String(parseState, "]"))
00502       RETURN_ERROR;
00503 
00504    return GL_TRUE;
00505 }
00506 
00507 
00508 static GLboolean
00509 Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
00510 {
00511    GLubyte token[100];
00512    GLint start, j;
00513 
00514    /* Match 'o' */
00515    if (!Parse_String(parseState, "o"))
00516       RETURN_ERROR;
00517 
00518    /* Match '[' */
00519    if (!Parse_String(parseState, "["))
00520       RETURN_ERROR;
00521 
00522    /* Get output reg name */
00523    if (!Parse_Token(parseState, token))
00524       RETURN_ERROR;
00525 
00526    if (parseState->isPositionInvariant)
00527       start = 1; /* skip HPOS register name */
00528    else
00529       start = 0;
00530 
00531    /* try to match an output register name */
00532    for (j = start; OutputRegisters[j]; j++) {
00533       if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
00534          *outputRegNum = j;
00535          break;
00536       }
00537    }
00538    if (!OutputRegisters[j])
00539       RETURN_ERROR1("Unrecognized output register name");
00540 
00541    /* Match ']' */
00542    if (!Parse_String(parseState, "]"))
00543       RETURN_ERROR1("Expected ]");
00544 
00545    return GL_TRUE;
00546 }
00547 
00548 
00549 static GLboolean
00550 Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg)
00551 {
00552    GLubyte token[100];
00553    GLint idx;
00554 
00555    /* Dst reg can be R<n> or o[n] */
00556    if (!Peek_Token(parseState, token))
00557       RETURN_ERROR;
00558 
00559    if (token[0] == 'R') {
00560       /* a temporary register */
00561       dstReg->File = PROGRAM_TEMPORARY;
00562       if (!Parse_TempReg(parseState, &idx))
00563          RETURN_ERROR;
00564       dstReg->Index = idx;
00565    }
00566    else if (!parseState->isStateProgram && token[0] == 'o') {
00567       /* an output register */
00568       dstReg->File = PROGRAM_OUTPUT;
00569       if (!Parse_OutputReg(parseState, &idx))
00570          RETURN_ERROR;
00571       dstReg->Index = idx;
00572    }
00573    else if (parseState->isStateProgram && token[0] == 'c' &&
00574             parseState->isStateProgram) {
00575       /* absolute program parameter register */
00576       /* Only valid for vertex state programs */
00577       dstReg->File = PROGRAM_ENV_PARAM;
00578       if (!Parse_AbsParamReg(parseState, &idx))
00579          RETURN_ERROR;
00580       dstReg->Index = idx;
00581    }
00582    else {
00583       RETURN_ERROR1("Bad destination register name");
00584    }
00585 
00586    /* Parse optional write mask */
00587    if (!Peek_Token(parseState, token))
00588       RETURN_ERROR;
00589 
00590    if (token[0] == '.') {
00591       /* got a mask */
00592       GLint k = 0;
00593 
00594       if (!Parse_String(parseState, "."))
00595          RETURN_ERROR;
00596 
00597       if (!Parse_Token(parseState, token))
00598          RETURN_ERROR;
00599 
00600       dstReg->WriteMask = 0;
00601 
00602       if (token[k] == 'x') {
00603          dstReg->WriteMask |= WRITEMASK_X;
00604          k++;
00605       }
00606       if (token[k] == 'y') {
00607          dstReg->WriteMask |= WRITEMASK_Y;
00608          k++;
00609       }
00610       if (token[k] == 'z') {
00611          dstReg->WriteMask |= WRITEMASK_Z;
00612          k++;
00613       }
00614       if (token[k] == 'w') {
00615          dstReg->WriteMask |= WRITEMASK_W;
00616          k++;
00617       }
00618       if (k == 0) {
00619          RETURN_ERROR1("Bad writemask character");
00620       }
00621       return GL_TRUE;
00622    }
00623    else {
00624       dstReg->WriteMask = WRITEMASK_XYZW;
00625       return GL_TRUE;
00626    }
00627 }
00628 
00629 
00630 static GLboolean
00631 Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
00632 {
00633    GLubyte token[100];
00634    GLint idx;
00635 
00636    srcReg->RelAddr = GL_FALSE;
00637 
00638    /* check for '-' */
00639    if (!Peek_Token(parseState, token))
00640       RETURN_ERROR;
00641    if (token[0] == '-') {
00642       (void) Parse_String(parseState, "-");
00643       srcReg->NegateBase = NEGATE_XYZW;
00644       if (!Peek_Token(parseState, token))
00645          RETURN_ERROR;
00646    }
00647    else {
00648       srcReg->NegateBase = NEGATE_NONE;
00649    }
00650 
00651    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
00652    if (token[0] == 'R') {
00653       srcReg->File = PROGRAM_TEMPORARY;
00654       if (!Parse_TempReg(parseState, &idx))
00655          RETURN_ERROR;
00656       srcReg->Index = idx;
00657    }
00658    else if (token[0] == 'c') {
00659       if (!Parse_ParamReg(parseState, srcReg))
00660          RETURN_ERROR;
00661    }
00662    else if (token[0] == 'v') {
00663       srcReg->File = PROGRAM_INPUT;
00664       if (!Parse_AttribReg(parseState, &idx))
00665          RETURN_ERROR;
00666       srcReg->Index = idx;
00667    }
00668    else {
00669       RETURN_ERROR2("Bad source register name", token);
00670    }
00671 
00672    /* init swizzle fields */
00673    srcReg->Swizzle = SWIZZLE_NOOP;
00674 
00675    /* Look for optional swizzle suffix */
00676    if (!Peek_Token(parseState, token))
00677       RETURN_ERROR;
00678    if (token[0] == '.') {
00679       (void) Parse_String(parseState, ".");  /* consume . */
00680 
00681       if (!Parse_Token(parseState, token))
00682          RETURN_ERROR;
00683 
00684       if (token[1] == 0) {
00685          /* single letter swizzle */
00686          if (token[0] == 'x')
00687             srcReg->Swizzle = SWIZZLE_XXXX;
00688          else if (token[0] == 'y')
00689             srcReg->Swizzle = SWIZZLE_YYYY;
00690          else if (token[0] == 'z')
00691             srcReg->Swizzle = SWIZZLE_ZZZZ;
00692          else if (token[0] == 'w')
00693             srcReg->Swizzle = SWIZZLE_WWWW;
00694          else
00695             RETURN_ERROR1("Expected x, y, z, or w");
00696       }
00697       else {
00698          /* 2, 3 or 4-component swizzle */
00699          GLint k;
00700 
00701          srcReg->Swizzle = 0;
00702 
00703          for (k = 0; token[k] && k < 5; k++) {
00704             if (token[k] == 'x')
00705                srcReg->Swizzle |= 0 << (k*3);
00706             else if (token[k] == 'y')
00707                srcReg->Swizzle |= 1 << (k*3);
00708             else if (token[k] == 'z')
00709                srcReg->Swizzle |= 2 << (k*3);
00710             else if (token[k] == 'w')
00711                srcReg->Swizzle |= 3 << (k*3);
00712             else
00713                RETURN_ERROR;
00714          }
00715          if (k >= 5)
00716             RETURN_ERROR;
00717       }
00718    }
00719 
00720    return GL_TRUE;
00721 }
00722 
00723 
00724 static GLboolean
00725 Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
00726 {
00727    GLubyte token[100];
00728    GLint idx;
00729 
00730    srcReg->RelAddr = GL_FALSE;
00731 
00732    /* check for '-' */
00733    if (!Peek_Token(parseState, token))
00734       RETURN_ERROR;
00735    if (token[0] == '-') {
00736       srcReg->NegateBase = NEGATE_XYZW;
00737       (void) Parse_String(parseState, "-"); /* consume '-' */
00738       if (!Peek_Token(parseState, token))
00739          RETURN_ERROR;
00740    }
00741    else {
00742       srcReg->NegateBase = NEGATE_NONE;
00743    }
00744 
00745    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
00746    if (token[0] == 'R') {
00747       srcReg->File = PROGRAM_TEMPORARY;
00748       if (!Parse_TempReg(parseState, &idx))
00749          RETURN_ERROR;
00750       srcReg->Index = idx;
00751    }
00752    else if (token[0] == 'c') {
00753       if (!Parse_ParamReg(parseState, srcReg))
00754          RETURN_ERROR;
00755    }
00756    else if (token[0] == 'v') {
00757       srcReg->File = PROGRAM_INPUT;
00758       if (!Parse_AttribReg(parseState, &idx))
00759          RETURN_ERROR;
00760       srcReg->Index = idx;
00761    }
00762    else {
00763       RETURN_ERROR2("Bad source register name", token);
00764    }
00765 
00766    /* Look for .[xyzw] suffix */
00767    if (!Parse_String(parseState, "."))
00768       RETURN_ERROR;
00769 
00770    if (!Parse_Token(parseState, token))
00771       RETURN_ERROR;
00772 
00773    if (token[0] == 'x' && token[1] == 0) {
00774       srcReg->Swizzle = 0;
00775    }
00776    else if (token[0] == 'y' && token[1] == 0) {
00777       srcReg->Swizzle = 1;
00778    }
00779    else if (token[0] == 'z' && token[1] == 0) {
00780       srcReg->Swizzle = 2;
00781    }
00782    else if (token[0] == 'w' && token[1] == 0) {
00783       srcReg->Swizzle = 3;
00784    }
00785    else {
00786       RETURN_ERROR1("Bad scalar source suffix");
00787    }
00788 
00789    return GL_TRUE;
00790 }
00791 
00792 
00793 static GLint
00794 Parse_UnaryOpInstruction(struct parse_state *parseState,
00795                          struct prog_instruction *inst,
00796                          enum prog_opcode opcode)
00797 {
00798    if (opcode == OPCODE_ABS && !parseState->isVersion1_1)
00799       RETURN_ERROR1("ABS illegal for vertex program 1.0");
00800 
00801    inst->Opcode = opcode;
00802    inst->StringPos = parseState->curLine - parseState->start;
00803 
00804    /* dest reg */
00805    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
00806       RETURN_ERROR;
00807 
00808    /* comma */
00809    if (!Parse_String(parseState, ","))
00810       RETURN_ERROR;
00811 
00812    /* src arg */
00813    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
00814       RETURN_ERROR;
00815 
00816    /* semicolon */
00817    if (!Parse_String(parseState, ";"))
00818       RETURN_ERROR;
00819 
00820    return GL_TRUE;
00821 }
00822 
00823 
00824 static GLboolean
00825 Parse_BiOpInstruction(struct parse_state *parseState,
00826                       struct prog_instruction *inst,
00827                       enum prog_opcode opcode)
00828 {
00829    if (opcode == OPCODE_DPH && !parseState->isVersion1_1)
00830       RETURN_ERROR1("DPH illegal for vertex program 1.0");
00831    if (opcode == OPCODE_SUB && !parseState->isVersion1_1)
00832       RETURN_ERROR1("SUB illegal for vertex program 1.0");
00833 
00834    inst->Opcode = opcode;
00835    inst->StringPos = parseState->curLine - parseState->start;
00836 
00837    /* dest reg */
00838    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
00839       RETURN_ERROR;
00840 
00841    /* comma */
00842    if (!Parse_String(parseState, ","))
00843       RETURN_ERROR;
00844 
00845    /* first src arg */
00846    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
00847       RETURN_ERROR;
00848 
00849    /* comma */
00850    if (!Parse_String(parseState, ","))
00851       RETURN_ERROR;
00852 
00853    /* second src arg */
00854    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
00855       RETURN_ERROR;
00856 
00857    /* semicolon */
00858    if (!Parse_String(parseState, ";"))
00859       RETURN_ERROR;
00860 
00861    /* make sure we don't reference more than one program parameter register */
00862    if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
00863        inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
00864        inst->SrcReg[0].Index != inst->SrcReg[1].Index)
00865       RETURN_ERROR1("Can't reference two program parameter registers");
00866 
00867    /* make sure we don't reference more than one vertex attribute register */
00868    if (inst->SrcReg[0].File == PROGRAM_INPUT &&
00869        inst->SrcReg[1].File == PROGRAM_INPUT &&
00870        inst->SrcReg[0].Index != inst->SrcReg[1].Index)
00871       RETURN_ERROR1("Can't reference two vertex attribute registers");
00872 
00873    return GL_TRUE;
00874 }
00875 
00876 
00877 static GLboolean
00878 Parse_TriOpInstruction(struct parse_state *parseState,
00879                        struct prog_instruction *inst,
00880                        enum prog_opcode opcode)
00881 {
00882    inst->Opcode = opcode;
00883    inst->StringPos = parseState->curLine - parseState->start;
00884 
00885    /* dest reg */
00886    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
00887       RETURN_ERROR;
00888 
00889    /* comma */
00890    if (!Parse_String(parseState, ","))
00891       RETURN_ERROR;
00892 
00893    /* first src arg */
00894    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
00895       RETURN_ERROR;
00896 
00897    /* comma */
00898    if (!Parse_String(parseState, ","))
00899       RETURN_ERROR;
00900 
00901    /* second src arg */
00902    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
00903       RETURN_ERROR;
00904 
00905    /* comma */
00906    if (!Parse_String(parseState, ","))
00907       RETURN_ERROR;
00908 
00909    /* third src arg */
00910    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2]))
00911       RETURN_ERROR;
00912 
00913    /* semicolon */
00914    if (!Parse_String(parseState, ";"))
00915       RETURN_ERROR;
00916 
00917    /* make sure we don't reference more than one program parameter register */
00918    if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
00919         inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
00920         inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
00921        (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
00922         inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
00923         inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
00924        (inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
00925         inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
00926         inst->SrcReg[1].Index != inst->SrcReg[2].Index))
00927       RETURN_ERROR1("Can only reference one program register");
00928 
00929    /* make sure we don't reference more than one vertex attribute register */
00930    if ((inst->SrcReg[0].File == PROGRAM_INPUT &&
00931         inst->SrcReg[1].File == PROGRAM_INPUT &&
00932         inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
00933        (inst->SrcReg[0].File == PROGRAM_INPUT &&
00934         inst->SrcReg[2].File == PROGRAM_INPUT &&
00935         inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
00936        (inst->SrcReg[1].File == PROGRAM_INPUT &&
00937         inst->SrcReg[2].File == PROGRAM_INPUT &&
00938         inst->SrcReg[1].Index != inst->SrcReg[2].Index))
00939       RETURN_ERROR1("Can only reference one input register");
00940 
00941    return GL_TRUE;
00942 }
00943 
00944 
00945 static GLboolean
00946 Parse_ScalarInstruction(struct parse_state *parseState,
00947                         struct prog_instruction *inst,
00948                         enum prog_opcode opcode)
00949 {
00950    if (opcode == OPCODE_RCC && !parseState->isVersion1_1)
00951       RETURN_ERROR1("RCC illegal for vertex program 1.0");
00952 
00953    inst->Opcode = opcode;
00954    inst->StringPos = parseState->curLine - parseState->start;
00955 
00956    /* dest reg */
00957    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
00958       RETURN_ERROR;
00959 
00960    /* comma */
00961    if (!Parse_String(parseState, ","))
00962       RETURN_ERROR;
00963 
00964    /* first src arg */
00965    if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
00966       RETURN_ERROR;
00967 
00968    /* semicolon */
00969    if (!Parse_String(parseState, ";"))
00970       RETURN_ERROR;
00971 
00972    return GL_TRUE;
00973 }
00974 
00975 
00976 static GLboolean
00977 Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst)
00978 {
00979    inst->Opcode = OPCODE_ARL;
00980    inst->StringPos = parseState->curLine - parseState->start;
00981 
00982    /* Make ARB_vp backends happy */
00983    inst->DstReg.File = PROGRAM_ADDRESS;
00984    inst->DstReg.WriteMask = WRITEMASK_X;
00985    inst->DstReg.Index = 0;
00986 
00987    /* dest A0 reg */
00988    if (!Parse_AddrReg(parseState))
00989       RETURN_ERROR;
00990 
00991    /* comma */
00992    if (!Parse_String(parseState, ","))
00993       RETURN_ERROR;
00994 
00995    /* parse src reg */
00996    if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
00997       RETURN_ERROR;
00998 
00999    /* semicolon */
01000    if (!Parse_String(parseState, ";"))
01001       RETURN_ERROR;
01002 
01003    return GL_TRUE;
01004 }
01005 
01006 
01007 static GLboolean
01008 Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst)
01009 {
01010    GLubyte token[100];
01011 
01012    inst->Opcode = OPCODE_END;
01013    inst->StringPos = parseState->curLine - parseState->start;
01014 
01015    /* this should fail! */
01016    if (Parse_Token(parseState, token))
01017       RETURN_ERROR2("Unexpected token after END:", token);
01018    else
01019       return GL_TRUE;
01020 }
01021 
01022 
01036 static GLboolean
01037 Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst)
01038 {
01039    const GLubyte *str;
01040    GLubyte *msg;
01041    GLuint len;
01042    GLubyte token[100];
01043    struct prog_src_register *srcReg = &inst->SrcReg[0];
01044    GLint idx;
01045 
01046    inst->Opcode = OPCODE_PRINT;
01047    inst->StringPos = parseState->curLine - parseState->start;
01048 
01049    /* The first argument is a literal string 'just like this' */
01050    if (!Parse_String(parseState, "'"))
01051       RETURN_ERROR;
01052 
01053    str = parseState->pos;
01054    for (len = 0; str[len] != '\''; len++) /* find closing quote */
01055       ;
01056    parseState->pos += len + 1;
01057    msg = (GLubyte*) _mesa_malloc(len + 1);
01058 
01059    _mesa_memcpy(msg, str, len);
01060    msg[len] = 0;
01061    inst->Data = msg;
01062 
01063    /* comma */
01064    if (Parse_String(parseState, ",")) {
01065 
01066       /* The second argument is a register name */
01067       if (!Peek_Token(parseState, token))
01068          RETURN_ERROR;
01069 
01070       srcReg->RelAddr = GL_FALSE;
01071       srcReg->NegateBase = NEGATE_NONE;
01072       srcReg->Swizzle = SWIZZLE_NOOP;
01073 
01074       /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
01075        * or an o[n] output register.
01076        */
01077       if (token[0] == 'R') {
01078          srcReg->File = PROGRAM_TEMPORARY;
01079          if (!Parse_TempReg(parseState, &idx))
01080             RETURN_ERROR;
01081      srcReg->Index = idx;
01082       }
01083       else if (token[0] == 'c') {
01084          srcReg->File = PROGRAM_ENV_PARAM;
01085          if (!Parse_ParamReg(parseState, srcReg))
01086             RETURN_ERROR;
01087       }
01088       else if (token[0] == 'v') {
01089          srcReg->File = PROGRAM_INPUT;
01090          if (!Parse_AttribReg(parseState, &idx))
01091             RETURN_ERROR;
01092      srcReg->Index = idx;
01093       }
01094       else if (token[0] == 'o') {
01095          srcReg->File = PROGRAM_OUTPUT;
01096          if (!Parse_OutputReg(parseState, &idx))
01097             RETURN_ERROR;
01098      srcReg->Index = idx;
01099       }
01100       else {
01101          RETURN_ERROR2("Bad source register name", token);
01102       }
01103    }
01104    else {
01105       srcReg->File = 0;
01106    }
01107 
01108    /* semicolon */
01109    if (!Parse_String(parseState, ";"))
01110       RETURN_ERROR;
01111 
01112    return GL_TRUE;
01113 }
01114 
01115 
01116 static GLboolean
01117 Parse_OptionSequence(struct parse_state *parseState,
01118                      struct prog_instruction program[])
01119 {
01120    (void) program;
01121    while (1) {
01122       if (!Parse_String(parseState, "OPTION"))
01123          return GL_TRUE;  /* ok, not an OPTION statement */
01124       if (Parse_String(parseState, "NV_position_invariant")) {
01125          parseState->isPositionInvariant = GL_TRUE;
01126       }
01127       else {
01128          RETURN_ERROR1("unexpected OPTION statement");
01129       }
01130       if (!Parse_String(parseState, ";"))
01131          return GL_FALSE;
01132    }
01133 }
01134 
01135 
01136 static GLboolean
01137 Parse_InstructionSequence(struct parse_state *parseState,
01138                           struct prog_instruction program[])
01139 {
01140    while (1) {
01141       struct prog_instruction *inst = program + parseState->numInst;
01142 
01143       /* Initialize the instruction */
01144       _mesa_init_instructions(inst, 1);
01145 
01146       if (Parse_String(parseState, "MOV")) {
01147          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV))
01148             RETURN_ERROR;
01149       }
01150       else if (Parse_String(parseState, "LIT")) {
01151          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT))
01152             RETURN_ERROR;
01153       }
01154       else if (Parse_String(parseState, "ABS")) {
01155          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS))
01156             RETURN_ERROR;
01157       }
01158       else if (Parse_String(parseState, "MUL")) {
01159          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL))
01160             RETURN_ERROR;
01161       }
01162       else if (Parse_String(parseState, "ADD")) {
01163          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD))
01164             RETURN_ERROR;
01165       }
01166       else if (Parse_String(parseState, "DP3")) {
01167          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3))
01168             RETURN_ERROR;
01169       }
01170       else if (Parse_String(parseState, "DP4")) {
01171          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4))
01172             RETURN_ERROR;
01173       }
01174       else if (Parse_String(parseState, "DST")) {
01175          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST))
01176             RETURN_ERROR;
01177       }
01178       else if (Parse_String(parseState, "MIN")) {
01179          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN))
01180             RETURN_ERROR;
01181       }
01182       else if (Parse_String(parseState, "MAX")) {
01183          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX))
01184             RETURN_ERROR;
01185       }
01186       else if (Parse_String(parseState, "SLT")) {
01187          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT))
01188             RETURN_ERROR;
01189       }
01190       else if (Parse_String(parseState, "SGE")) {
01191          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE))
01192             RETURN_ERROR;
01193       }
01194       else if (Parse_String(parseState, "DPH")) {
01195          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH))
01196             RETURN_ERROR;
01197       }
01198       else if (Parse_String(parseState, "SUB")) {
01199          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB))
01200             RETURN_ERROR;
01201       }
01202       else if (Parse_String(parseState, "MAD")) {
01203          if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD))
01204             RETURN_ERROR;
01205       }
01206       else if (Parse_String(parseState, "RCP")) {
01207          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP))
01208             RETURN_ERROR;
01209       }
01210       else if (Parse_String(parseState, "RSQ")) {
01211          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ))
01212             RETURN_ERROR;
01213       }
01214       else if (Parse_String(parseState, "EXP")) {
01215          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP))
01216             RETURN_ERROR;
01217       }
01218       else if (Parse_String(parseState, "LOG")) {
01219          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG))
01220             RETURN_ERROR;
01221       }
01222       else if (Parse_String(parseState, "RCC")) {
01223          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC))
01224             RETURN_ERROR;
01225       }
01226       else if (Parse_String(parseState, "ARL")) {
01227          if (!Parse_AddressInstruction(parseState, inst))
01228             RETURN_ERROR;
01229       }
01230       else if (Parse_String(parseState, "PRINT")) {
01231          if (!Parse_PrintInstruction(parseState, inst))
01232             RETURN_ERROR;
01233       }
01234       else if (Parse_String(parseState, "END")) {
01235          if (!Parse_EndInstruction(parseState, inst))
01236             RETURN_ERROR;
01237          else {
01238             parseState->numInst++;
01239             return GL_TRUE;  /* all done */
01240          }
01241       }
01242       else {
01243          /* bad instruction name */
01244          RETURN_ERROR1("Unexpected token");
01245       }
01246 
01247       /* examine input/output registers */
01248       if (inst->DstReg.File == PROGRAM_OUTPUT)
01249          parseState->outputsWritten |= (1 << inst->DstReg.Index);
01250       else if (inst->DstReg.File == PROGRAM_ENV_PARAM)
01251          parseState->anyProgRegsWritten = GL_TRUE;
01252 
01253       if (inst->SrcReg[0].File == PROGRAM_INPUT)
01254          parseState->inputsRead |= (1 << inst->SrcReg[0].Index);
01255       if (inst->SrcReg[1].File == PROGRAM_INPUT)
01256          parseState->inputsRead |= (1 << inst->SrcReg[1].Index);
01257       if (inst->SrcReg[2].File == PROGRAM_INPUT)
01258          parseState->inputsRead |= (1 << inst->SrcReg[2].Index);
01259 
01260       parseState->numInst++;
01261 
01262       if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
01263          RETURN_ERROR1("Program too long");
01264    }
01265 
01266    RETURN_ERROR;
01267 }
01268 
01269 
01270 static GLboolean
01271 Parse_Program(struct parse_state *parseState,
01272               struct prog_instruction instBuffer[])
01273 {
01274    if (parseState->isVersion1_1) {
01275       if (!Parse_OptionSequence(parseState, instBuffer)) {
01276          return GL_FALSE;
01277       }
01278    }
01279    return Parse_InstructionSequence(parseState, instBuffer);
01280 }
01281 
01282 
01288 void
01289 _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
01290                               const GLubyte *str, GLsizei len,
01291                               struct gl_vertex_program *program)
01292 {
01293    struct parse_state parseState;
01294    struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
01295    struct prog_instruction *newInst;
01296    GLenum target;
01297    GLubyte *programString;
01298 
01299    /* Make a null-terminated copy of the program string */
01300    programString = (GLubyte *) MALLOC(len + 1);
01301    if (!programString) {
01302       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
01303       return;
01304    }
01305    MEMCPY(programString, str, len);
01306    programString[len] = 0;
01307 
01308    /* Get ready to parse */
01309    parseState.ctx = ctx;
01310    parseState.start = programString;
01311    parseState.isPositionInvariant = GL_FALSE;
01312    parseState.isVersion1_1 = GL_FALSE;
01313    parseState.numInst = 0;
01314    parseState.inputsRead = 0;
01315    parseState.outputsWritten = 0;
01316    parseState.anyProgRegsWritten = GL_FALSE;
01317 
01318    /* Reset error state */
01319    _mesa_set_program_error(ctx, -1, NULL);
01320 
01321    /* check the program header */
01322    if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
01323       target = GL_VERTEX_PROGRAM_NV;
01324       parseState.pos = programString + 7;
01325       parseState.isStateProgram = GL_FALSE;
01326    }
01327    else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
01328       target = GL_VERTEX_PROGRAM_NV;
01329       parseState.pos = programString + 7;
01330       parseState.isStateProgram = GL_FALSE;
01331       parseState.isVersion1_1 = GL_TRUE;
01332    }
01333    else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
01334       target = GL_VERTEX_STATE_PROGRAM_NV;
01335       parseState.pos = programString + 8;
01336       parseState.isStateProgram = GL_TRUE;
01337    }
01338    else {
01339       /* invalid header */
01340       ctx->Program.ErrorPos = 0;
01341       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
01342       return;
01343    }
01344 
01345    /* make sure target and header match */
01346    if (target != dstTarget) {
01347       _mesa_error(ctx, GL_INVALID_OPERATION,
01348                   "glLoadProgramNV(target mismatch)");
01349       return;
01350    }
01351 
01352 
01353    if (Parse_Program(&parseState, instBuffer)) {
01354       /* successful parse! */
01355 
01356       if (parseState.isStateProgram) {
01357          if (!parseState.anyProgRegsWritten) {
01358             _mesa_error(ctx, GL_INVALID_OPERATION,
01359                         "glLoadProgramNV(c[#] not written)");
01360             return;
01361          }
01362       }
01363       else {
01364          if (!parseState.isPositionInvariant &&
01365              !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) {
01366             /* bit 1 = HPOS register */
01367             _mesa_error(ctx, GL_INVALID_OPERATION,
01368                         "glLoadProgramNV(HPOS not written)");
01369             return;
01370          }
01371       }
01372 
01373       /* copy the compiled instructions */
01374       assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
01375       newInst = _mesa_alloc_instructions(parseState.numInst);
01376       if (!newInst) {
01377          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
01378          _mesa_free(programString);
01379          return;  /* out of memory */
01380       }
01381       _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
01382 
01383       /* install the program */
01384       program->Base.Target = target;
01385       if (program->Base.String) {
01386          _mesa_free(program->Base.String);
01387       }
01388       program->Base.String = programString;
01389       program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
01390       if (program->Base.Instructions) {
01391          _mesa_free(program->Base.Instructions);
01392       }
01393       program->Base.Instructions = newInst;
01394       program->Base.InputsRead = parseState.inputsRead;
01395       if (parseState.isPositionInvariant)
01396          program->Base.InputsRead |= VERT_BIT_POS;
01397       program->Base.NumInstructions = parseState.numInst;
01398       program->Base.OutputsWritten = parseState.outputsWritten;
01399       program->IsPositionInvariant = parseState.isPositionInvariant;
01400       program->IsNVProgram = GL_TRUE;
01401 
01402 #ifdef DEBUG_foo
01403       _mesa_printf("--- glLoadProgramNV result ---\n");
01404       _mesa_print_nv_vertex_program(program);
01405       _mesa_printf("------------------------------\n");
01406 #endif
01407    }
01408    else {
01409       /* Error! */
01410       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
01411       /* NOTE: _mesa_set_program_error would have been called already */
01412       /* GL_NV_vertex_program isn't supposed to set the error string
01413        * so we reset it here.
01414        */
01415       _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
01416    }
01417 }
01418 
01419 
01420 static void
01421 PrintSrcReg(const struct prog_src_register *src)
01422 {
01423    static const char comps[5] = "xyzw";
01424    if (src->NegateBase)
01425       _mesa_printf("-");
01426    if (src->RelAddr) {
01427       if (src->Index > 0)
01428          _mesa_printf("c[A0.x + %d]", src->Index);
01429       else if (src->Index < 0)
01430          _mesa_printf("c[A0.x - %d]", -src->Index);
01431       else
01432          _mesa_printf("c[A0.x]");
01433    }
01434    else if (src->File == PROGRAM_OUTPUT) {
01435       _mesa_printf("o[%s]", OutputRegisters[src->Index]);
01436    }
01437    else if (src->File == PROGRAM_INPUT) {
01438       _mesa_printf("v[%s]", InputRegisters[src->Index]);
01439    }
01440    else if (src->File == PROGRAM_ENV_PARAM) {
01441       _mesa_printf("c[%d]", src->Index);
01442    }
01443    else {
01444       ASSERT(src->File == PROGRAM_TEMPORARY);
01445       _mesa_printf("R%d", src->Index);
01446    }
01447 
01448    if (GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 1) &&
01449        GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 2) &&
01450        GET_SWZ(src->Swizzle, 0) == GET_SWZ(src->Swizzle, 3)) {
01451       _mesa_printf(".%c", comps[GET_SWZ(src->Swizzle, 0)]);
01452    }
01453    else if (src->Swizzle != SWIZZLE_NOOP) {
01454       _mesa_printf(".%c%c%c%c",
01455              comps[GET_SWZ(src->Swizzle, 0)],
01456              comps[GET_SWZ(src->Swizzle, 1)],
01457              comps[GET_SWZ(src->Swizzle, 2)],
01458              comps[GET_SWZ(src->Swizzle, 3)]);
01459    }
01460 }
01461 
01462 
01463 static void
01464 PrintDstReg(const struct prog_dst_register *dst)
01465 {
01466    if (dst->File == PROGRAM_OUTPUT) {
01467       _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
01468    }
01469    else if (dst->File == PROGRAM_INPUT) {
01470       _mesa_printf("v[%s]", InputRegisters[dst->Index]);
01471    }
01472    else if (dst->File == PROGRAM_ENV_PARAM) {
01473       _mesa_printf("c[%d]", dst->Index);
01474    }
01475    else {
01476       ASSERT(dst->File == PROGRAM_TEMPORARY);
01477       _mesa_printf("R%d", dst->Index);
01478    }
01479 
01480    if (dst->WriteMask != 0 && dst->WriteMask != WRITEMASK_XYZW) {
01481       _mesa_printf(".");
01482       if (dst->WriteMask & WRITEMASK_X)
01483          _mesa_printf("x");
01484       if (dst->WriteMask & WRITEMASK_Y)
01485          _mesa_printf("y");
01486       if (dst->WriteMask & WRITEMASK_Z)
01487          _mesa_printf("z");
01488       if (dst->WriteMask & WRITEMASK_W)
01489          _mesa_printf("w");
01490    }
01491 }
01492 
01493 
01497 void
01498 _mesa_print_nv_vertex_instruction(const struct prog_instruction *inst)
01499 {
01500    GLuint i, n;
01501 
01502    switch (inst->Opcode) {
01503       case OPCODE_MOV:
01504       case OPCODE_LIT:
01505       case OPCODE_RCP:
01506       case OPCODE_RSQ:
01507       case OPCODE_EXP:
01508       case OPCODE_LOG:
01509       case OPCODE_RCC:
01510       case OPCODE_ABS:
01511       case OPCODE_MUL:
01512       case OPCODE_ADD:
01513       case OPCODE_DP3:
01514       case OPCODE_DP4:
01515       case OPCODE_DST:
01516       case OPCODE_MIN:
01517       case OPCODE_MAX:
01518       case OPCODE_SLT:
01519       case OPCODE_SGE:
01520       case OPCODE_DPH:
01521       case OPCODE_SUB:
01522       case OPCODE_MAD:
01523          _mesa_printf("%s ", _mesa_opcode_string(inst->Opcode));
01524          PrintDstReg(&inst->DstReg);
01525          _mesa_printf(", ");
01526          n = _mesa_num_inst_src_regs(inst->Opcode);
01527          for (i = 0; i < n; i++) {
01528             PrintSrcReg(&inst->SrcReg[i]);
01529             if (i + 1 < n)
01530                _mesa_printf(", ");
01531          }
01532          _mesa_printf(";\n");
01533          break;
01534       case OPCODE_ARL:
01535          _mesa_printf("ARL A0.x, ");
01536          PrintSrcReg(&inst->SrcReg[0]);
01537          _mesa_printf(";\n");
01538          break;
01539       case OPCODE_PRINT:
01540          _mesa_printf("PRINT '%s'", inst->Data);
01541          if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
01542             _mesa_printf(", ");
01543             PrintSrcReg(&inst->SrcReg[0]);
01544             _mesa_printf(";\n");
01545          }
01546          else {
01547             _mesa_printf("\n");
01548          }
01549          break;
01550       case OPCODE_END:
01551          _mesa_printf("END\n");
01552          break;
01553       default:
01554          _mesa_printf("BAD INSTRUCTION\n");
01555    }
01556 }
01557 
01558 
01562 void
01563 _mesa_print_nv_vertex_program(const struct gl_vertex_program *program)
01564 {
01565    const struct prog_instruction *inst;
01566 
01567    for (inst = program->Base.Instructions; ; inst++) {
01568       _mesa_print_nv_vertex_instruction(inst);
01569       if (inst->Opcode == OPCODE_END)
01570          return;
01571    }
01572 }
01573 
01574 
01575 const char *
01576 _mesa_nv_vertex_input_register_name(GLuint i)
01577 {
01578    ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
01579    return InputRegisters[i];
01580 }
01581 
01582 
01583 const char *
01584 _mesa_nv_vertex_output_register_name(GLuint i)
01585 {
01586    ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
01587    return OutputRegisters[i];
01588 }
01589 

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.