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