Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennvvertparse.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
1.7.6.1
|