📄 nvfragparse.c
字号:
*/
static GLboolean
Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
{
char *end = NULL;
*number = (GLfloat) _mesa_strtod((const char *) parseState->pos, &end);
if (end && end > (char *) parseState->pos) {
/* got a number */
parseState->pos = (GLubyte *) end;
number[1] = *number;
number[2] = *number;
number[3] = *number;
return GL_TRUE;
}
else {
/* should be an identifier */
GLubyte ident[100];
const GLfloat *constant;
if (!Parse_Identifier(parseState, ident))
RETURN_ERROR1("Expected an identifier");
constant = _mesa_lookup_parameter_value(parseState->parameters,
-1, (const char *) ident);
/* XXX Check that it's a constant and not a parameter */
if (!constant) {
RETURN_ERROR1("Undefined symbol");
}
else {
COPY_4V(number, constant);
return GL_TRUE;
}
}
}
/**
* Parse a vector constant, one of:
* { float }
* { float, float }
* { float, float, float }
* { float, float, float, float }
*/
static GLboolean
Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
{
/* "{" was already consumed */
ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
if (!Parse_ScalarConstant(parseState, vec+0)) /* X */
return GL_FALSE;
if (Parse_String(parseState, "}")) {
return GL_TRUE;
}
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected comma in vector constant");
if (!Parse_ScalarConstant(parseState, vec+1)) /* Y */
return GL_FALSE;
if (Parse_String(parseState, "}")) {
return GL_TRUE;
}
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected comma in vector constant");
if (!Parse_ScalarConstant(parseState, vec+2)) /* Z */
return GL_FALSE;
if (Parse_String(parseState, "}")) {
return GL_TRUE;
}
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected comma in vector constant");
if (!Parse_ScalarConstant(parseState, vec+3)) /* W */
return GL_FALSE;
if (!Parse_String(parseState, "}"))
RETURN_ERROR1("Expected closing brace in vector constant");
return GL_TRUE;
}
/**
* Parse <number>, <varname> or {a, b, c, d}.
* Return number of values in the vector or scalar, or zero if parse error.
*/
static GLuint
Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
{
if (Parse_String(parseState, "{")) {
return Parse_VectorConstant(parseState, vec);
}
else {
GLboolean b = Parse_ScalarConstant(parseState, vec);
if (b) {
vec[1] = vec[2] = vec[3] = vec[0];
}
return b;
}
}
/**
* Parse a texture image source:
* [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT]
*/
static GLboolean
Parse_TextureImageId(struct parse_state *parseState,
GLubyte *texUnit, GLubyte *texTargetBit)
{
GLubyte imageSrc[100];
GLint unit;
if (!Parse_Token(parseState, imageSrc))
RETURN_ERROR;
if (imageSrc[0] != 'T' ||
imageSrc[1] != 'E' ||
imageSrc[2] != 'X') {
RETURN_ERROR1("Expected TEX# source");
}
unit = _mesa_atoi((const char *) imageSrc + 3);
if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) ||
(unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) {
RETURN_ERROR1("Invalied TEX# source index");
}
*texUnit = unit;
if (!Parse_String(parseState, ","))
RETURN_ERROR1("Expected ,");
if (Parse_String(parseState, "1D")) {
*texTargetBit = TEXTURE_1D_BIT;
}
else if (Parse_String(parseState, "2D")) {
*texTargetBit = TEXTURE_2D_BIT;
}
else if (Parse_String(parseState, "3D")) {
*texTargetBit = TEXTURE_3D_BIT;
}
else if (Parse_String(parseState, "CUBE")) {
*texTargetBit = TEXTURE_CUBE_BIT;
}
else if (Parse_String(parseState, "RECT")) {
*texTargetBit = TEXTURE_RECT_BIT;
}
else {
RETURN_ERROR1("Invalid texture target token");
}
/* update record of referenced texture units */
parseState->texturesUsed[*texUnit] |= *texTargetBit;
if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
RETURN_ERROR1("Only one texture target can be used per texture unit.");
}
return GL_TRUE;
}
/**
* Parse a scalar suffix like .x, .y, .z or .w or parse a swizzle suffix
* like .wxyz, .xxyy, etc and return the swizzle indexes.
*/
static GLboolean
Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4])
{
if (token[1] == 0) {
/* single letter swizzle (scalar) */
if (token[0] == 'x')
ASSIGN_4V(swizzle, 0, 0, 0, 0);
else if (token[0] == 'y')
ASSIGN_4V(swizzle, 1, 1, 1, 1);
else if (token[0] == 'z')
ASSIGN_4V(swizzle, 2, 2, 2, 2);
else if (token[0] == 'w')
ASSIGN_4V(swizzle, 3, 3, 3, 3);
else
return GL_FALSE;
}
else {
/* 4-component swizzle (vector) */
GLint k;
for (k = 0; token[k] && k < 4; k++) {
if (token[k] == 'x')
swizzle[k] = 0;
else if (token[k] == 'y')
swizzle[k] = 1;
else if (token[k] == 'z')
swizzle[k] = 2;
else if (token[k] == 'w')
swizzle[k] = 3;
else
return GL_FALSE;
}
if (k != 4)
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean
Parse_CondCodeMask(struct parse_state *parseState,
struct fp_dst_register *dstReg)
{
if (Parse_String(parseState, "EQ"))
dstReg->CondMask = COND_EQ;
else if (Parse_String(parseState, "GE"))
dstReg->CondMask = COND_GE;
else if (Parse_String(parseState, "GT"))
dstReg->CondMask = COND_GT;
else if (Parse_String(parseState, "LE"))
dstReg->CondMask = COND_LE;
else if (Parse_String(parseState, "LT"))
dstReg->CondMask = COND_LT;
else if (Parse_String(parseState, "NE"))
dstReg->CondMask = COND_NE;
else if (Parse_String(parseState, "TR"))
dstReg->CondMask = COND_TR;
else if (Parse_String(parseState, "FL"))
dstReg->CondMask = COND_FL;
else
RETURN_ERROR1("Invalid condition code mask");
/* look for optional .xyzw swizzle */
if (Parse_String(parseState, ".")) {
GLubyte token[100];
GLuint swz[4];
if (!Parse_Token(parseState, token)) /* get xyzw suffix */
RETURN_ERROR;
if (!Parse_SwizzleSuffix(token, swz))
RETURN_ERROR1("Invalid swizzle suffix");
dstReg->CondSwizzle = MAKE_SWIZZLE(swz);
}
return GL_TRUE;
}
/**
* Parse a temporary register: Rnn or Hnn
*/
static GLboolean
Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
{
GLubyte token[100];
/* Should be 'R##' or 'H##' */
if (!Parse_Token(parseState, token))
RETURN_ERROR;
if (token[0] != 'R' && token[0] != 'H')
RETURN_ERROR1("Expected R## or H##");
if (IsDigit(token[1])) {
GLint reg = _mesa_atoi((const char *) (token + 1));
if (token[0] == 'H')
reg += 32;
if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
RETURN_ERROR1("Invalid temporary register name");
*tempRegNum = reg;
}
else {
RETURN_ERROR1("Invalid temporary register name");
}
return GL_TRUE;
}
/**
* Parse a write-only dummy register: RC or HC.
*/
static GLboolean
Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
{
if (Parse_String(parseState, "RC")) {
*regNum = 0;
}
else if (Parse_String(parseState, "HC")) {
*regNum = 1;
}
else {
RETURN_ERROR1("Invalid write-only register name");
}
return GL_TRUE;
}
/**
* Parse a program local parameter register "p[##]"
*/
static GLboolean
Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
{
GLubyte token[100];
if (!Parse_String(parseState, "p["))
RETURN_ERROR1("Expected p[");
if (!Parse_Token(parseState, token))
RETURN_ERROR;
if (IsDigit(token[0])) {
/* a numbered program parameter register */
GLint reg = _mesa_atoi((const char *) token);
if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
RETURN_ERROR1("Invalid constant program number");
*regNum = reg;
}
else {
RETURN_ERROR;
}
if (!Parse_String(parseState, "]"))
RETURN_ERROR1("Expected ]");
return GL_TRUE;
}
/**
* Parse f[name] - fragment input register
*/
static GLboolean
Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
{
GLubyte token[100];
GLint j;
/* Match 'f[' */
if (!Parse_String(parseState, "f["))
RETURN_ERROR1("Expected f[");
/* get <name> and look for match */
if (!Parse_Token(parseState, token)) {
RETURN_ERROR;
}
for (j = 0; InputRegisters[j]; j++) {
if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
*tempRegNum = j;
parseState->inputsRead |= (1 << j);
break;
}
}
if (!InputRegisters[j]) {
/* unknown input register label */
RETURN_ERROR2("Invalid register name", token);
}
/* Match '[' */
if (!Parse_String(parseState, "]"))
RETURN_ERROR1("Expected ]");
return GL_TRUE;
}
static GLboolean
Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
{
GLubyte token[100];
GLint j;
/* Match "o[" */
if (!Parse_String(parseState, "o["))
RETURN_ERROR1("Expected o[");
/* Get output reg name */
if (!Parse_Token(parseState, token))
RETURN_ERROR;
/* try to match an output register name */
for (j = 0; OutputRegisters[j]; j++) {
if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
static GLuint bothColors = (1 << FRAG_OUTPUT_COLR) | (1 << FRAG_OUTPUT_COLH);
*outputRegNum = j;
parseState->outputsWritten |= (1 << j);
if ((parseState->outputsWritten & bothColors) == bothColors) {
RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
}
break;
}
}
if (!OutputRegisters[j])
RETURN_ERROR1("Invalid output register name");
/* Match ']' */
if (!Parse_String(parseState, "]"))
RETURN_ERROR1("Expected ]");
return GL_TRUE;
}
static GLboolean
Parse_MaskedDstReg(struct parse_state *parseState,
struct fp_dst_register *dstReg)
{
GLubyte token[100];
GLint idx;
/* Dst reg can be R<n>, H<n>, o[n], RC or HC */
if (!Peek_Token(parseState, token))
RETURN_ERROR;
if (_mesa_strcmp((const char *) token, "RC") == 0 ||
_mesa_strcmp((const char *) token, "HC") == 0) {
/* a write-only register */
dstReg->File = PROGRAM_WRITE_ONLY;
if (!Parse_DummyReg(parseState, &idx))
RETURN_ERROR;
dstReg->Index = idx;
}
else if (token[0] == 'R' || token[0] == 'H') {
/* a temporary register */
dstReg->File = PROGRAM_TEMPORARY;
if (!Parse_TempReg(parseState, &idx))
RETURN_ERROR;
dstReg->Index = idx;
}
else if (token[0] == 'o') {
/* an output register */
dstReg->File = PROGRAM_OUTPUT;
if (!Parse_OutputReg(parseState, &idx))
RETURN_ERROR;
dstReg->Index = idx;
}
else {
RETURN_ERROR1("Invalid destination register name");
}
/* Parse optional write mask */
if (Parse_String(parseState, ".")) {
/* got a mask */
GLint k = 0;
if (!Parse_Token(parseState, token)) /* get xyzw writemask */
RETURN_ERROR;
dstReg->WriteMask = 0;
if (token[k] == 'x') {
dstReg->WriteMask |= WRITEMASK_X;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -