/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 6.1
*
- * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
/* TODO:
* Fragment Program Stuff:
* -----------------------------------------------------
- * - How does negating on SWZ work?? If any of the components have a -,
- * negate?
- * - how does thing like 'foo[N]' work in src registers?
*
* - things from Michal's email
* + overflow on atoi
*
* Vertex Program Stuff:
* -----------------------------------------------------
- * - throw an error if we mess with position and have are position invar
+ * - Optimize param array usage and count limits correctly, see spec,
+ * section 2.14.3.7
+ * + Record if an array is reference absolutly or relatively (or both)
+ * + For absolute arrays, store a bitmap of accesses
+ * + For single parameters, store an access flag
+ * + After parsing, make a parameter cleanup and merging pass, where
+ * relative arrays are layed out first, followed by abs arrays, and
+ * finally single state.
+ * + Remap offsets for param src and dst registers
+ * + Now we can properly count parameter usage
+ *
+ * - Multiple state binding errors in param arrays (see spec, just before
+ * section 2.14.3.3)
* - grep for XXX
*
* Mesa Stuff
* -----------------------------------------------------
+ * - User clipping planes vs. PositionInvariant
+ * - Is it sufficient to just multiply by the mvp to transform in the
+ * PositionInvariant case? Or do we need something more involved?
+ *
* - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
* - fetch state listed in program_parameters list
* + WTF should this go???
return 0;
}
- memcpy (*production, ba->data, ba->len * sizeof (GLubyte));
+ _mesa_memcpy(*production, ba->data, ba->len * sizeof (GLubyte));
*size = ba->len;
barray_destroy (&ba);
* the .). We can have leading 0's here, which parse_integer will ignore,
* so we'll check for those first
*/
- while (**inst == '0')
+ while ((**inst == '0') && ( *(*inst+1) != 0))
{
leading_zeros++;
(*inst)++;
denom = 1;
while (denom < tmp[2])
denom *= 10;
- denom *= _mesa_pow( 10, leading_zeros );
+ denom *= (GLint) _mesa_pow( 10, leading_zeros );
value += (GLfloat) tmp[2] / (GLfloat) denom;
#if 0
if (tmp[0])
value *= -1;
#endif
- value *= _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
+ value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
return value;
}
parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
struct arb_program *Program, GLint * state_tokens)
{
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB)
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
state_tokens[0] = STATE_FRAGMENT_PROGRAM;
else
state_tokens[0] = STATE_VERTEX_PROGRAM;
state_tokens[2] = parse_integer (inst, Program);
/* Check state_tokens[2] against the number of ENV parameters available */
- if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+ if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
||
- ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+ ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
_mesa_set_program_error (ctx, Program->Position,
"Invalid Program Env Parameter");
state_tokens[2] = parse_integer (inst, Program);
/* Check state_tokens[2] against the number of LOCAL parameters available */
- if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+ if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
||
- ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+ ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
(state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
_mesa_set_program_error (ctx, Program->Position,
"Invalid Program Local Parameter");
GLint err = 0;
*is_generic = 0;
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
switch (*(*inst)++) {
case FRAGMENT_ATTRIB_COLOR:
err = parse_color_type (ctx, inst, Program, &coord);
switch (*(*inst)++) {
case FRAGMENT_RESULT_COLOR:
/* for frag programs, this is FRAGMENT_RESULT_COLOR */
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
*binding = FRAG_OUTPUT_COLR;
*binding_idx = 0;
}
case FRAGMENT_RESULT_DEPTH:
/* for frag programs, this is FRAGMENT_RESULT_DEPTH */
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
*binding = FRAG_OUTPUT_DEPR;
*binding_idx = 2;
}
GLuint end_idx = parse_integer (inst, Program);
out_of_range = 0;
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
if (((state_tokens[1] == STATE_ENV)
&& (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
|| ((state_tokens[1] == STATE_LOCAL)
}
/* Make sure we haven't blown past our parameter limits */
- if (((Program->type == GL_VERTEX_PROGRAM_ARB) &&
+ if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
(Program->Base.NumParameters >=
ctx->Const.MaxVertexProgramLocalParams))
- || ((Program->type == GL_FRAGMENT_PROGRAM_ARB)
+ || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
&& (Program->Base.NumParameters >=
ctx->Const.MaxFragmentProgramLocalParams))) {
_mesa_set_program_error (ctx, Program->Position,
temp_var->type = vt_temp;
- if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
+ if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
(Program->Base.NumTemporaries >=
ctx->Const.MaxFragmentProgramTemps))
- || ((Program->type == GL_VERTEX_PROGRAM_ARB)
+ || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
&& (Program->Base.NumTemporaries >=
ctx->Const.MaxVertexProgramTemps))) {
_mesa_set_program_error (ctx, Program->Position,
/**
* Handle the parsing out of a masked destination register
*
+ * If we are a vertex program, make sure we don't write to
+ * result.position of we have specified that the program is
+ * position invariant
+ *
* \param File - The register file we write to
* \param Index - The register index we write to
* \param WriteMask - The mask controlling which components we write (1->write)
return 1;
}
+
+ /* Position invariance test */
+ if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
+ (*Index == 0)) {
+ _mesa_set_program_error (ctx, Program->Position,
+ "Vertex program specified position invariance and wrote vertex position");
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "Vertex program specified position invariance and wrote vertex position");
+ }
+
/* And then the mask.
* w,a -> bit 0
* z,b -> bit 1
*/
mask = *(*inst)++;
- WriteMask[0] = (mask & (1 << 3)) >> 3;
- WriteMask[1] = (mask & (1 << 2)) >> 2;
- WriteMask[2] = (mask & (1 << 1)) >> 1;
- WriteMask[3] = (mask & (1));
+ WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3;
+ WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2;
+ WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1;
+ WriteMask[3] = (GLboolean) (mask & (1));
return 0;
}
mask[a] = SWIZZLE_ONE;
break;
case COMPONENT_X:
- mask[a] = 0;
+ mask[a] = SWIZZLE_X;
break;
case COMPONENT_Y:
- mask[a] = 1;
+ mask[a] = SWIZZLE_Y;
break;
case COMPONENT_Z:
- mask[a] = 2;
+ mask[a] = SWIZZLE_Z;
break;
case COMPONENT_W:
- mask[a] = 3;
+ mask[a] = SWIZZLE_W;
break;
}
/* The actual opcode name */
code = *(*inst)++;
+ /* Record the position in the program string for debugging */
+ vp->StringPos = Program->Position;
+
vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
for (a = 0; a < 4; a++) {
case OPTION:
switch (*inst++) {
case ARB_PRECISION_HINT_FASTEST:
- Program->HintPrecisionFastest = 1;
+ Program->PrecisionOption = GL_FASTEST;
break;
case ARB_PRECISION_HINT_NICEST:
- Program->HintPrecisionNicest = 1;
+ Program->PrecisionOption = GL_NICEST;
break;
case ARB_FOG_EXP:
- Program->HintFogExp = 1;
+ Program->FogOption = GL_EXP;
break;
case ARB_FOG_EXP2:
- Program->HintFogExp2 = 1;
+ Program->FogOption = GL_EXP2;
break;
case ARB_FOG_LINEAR:
- Program->HintFogLinear = 1;
+ Program->FogOption = GL_LINEAR;
break;
case ARB_POSITION_INVARIANT:
- Program->HintPositionInvariant = 1;
+ if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
+ Program->HintPositionInvariant = 1;
break;
}
break;
case INSTRUCTION:
Program->Position = parse_position (&inst);
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
+
+ /* Check the instruction count
+ * XXX: Does END count as an instruction?
+ */
+ if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
+ _mesa_set_program_error (ctx, Program->Position,
+ "Max instruction count exceeded!");
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "Max instruction count exceeded!");
+ }
+
/* Realloc Program->FPInstructions */
Program->FPInstructions =
(struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
}
else {
+ /* Check the instruction count
+ * XXX: Does END count as an instruction?
+ */
+ if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
+ _mesa_set_program_error (ctx, Program->Position,
+ "Max instruction count exceeded!");
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "Max instruction count exceeded!");
+ }
+
/* Realloc Program->VPInstructions */
Program->VPInstructions =
(struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
}
/* Finally, tag on an OPCODE_END instruction */
- if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
+ if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
Program->FPInstructions =
(struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
Program->Base.NumInstructions*sizeof(struct fp_instruction),
(Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
+ /* YYY Wrong Position in program, whatever, at least not random -> crash
+ Program->Position = parse_position (&inst);
+ */
+ Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
}
else {
Program->VPInstructions =
(Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
+ /* YYY Wrong Position in program, whatever, at least not random -> crash
+ Program->Position = parse_position (&inst);
+ */
+ Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
}
/* increment Program->Base.NumInstructions */
program->OutputsWritten = 0;
program->Position = 0;
program->MajorVersion = program->MinorVersion = 0;
- program->HintPrecisionFastest =
- program->HintPrecisionNicest =
- program->HintFogExp2 =
- program->HintFogExp =
- program->HintFogLinear = program->HintPositionInvariant = 0;
+ program->PrecisionOption = GL_DONT_CARE;
+ program->FogOption = GL_NONE;
+ program->HintPositionInvariant = GL_FALSE;
for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
program->TexturesUsed[a] = 0;
program->NumAluInstructions =
else {
switch (*inst++) {
case FRAGMENT_PROGRAM:
- program->type = GL_FRAGMENT_PROGRAM_ARB;
+ program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
break;
case VERTEX_PROGRAM:
- program->type = GL_VERTEX_PROGRAM_ARB;
+ program->Base.Target = GL_VERTEX_PROGRAM_ARB;
break;
}