/*
* Mesa 3-D graphics library
- * Version: 5.1
+ * Version: 6.0
*
- * 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;
}
/**
* 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++) {
break;
case ARB_POSITION_INVARIANT:
- Program->HintPositionInvariant = 1;
+ if (Program->type == GL_VERTEX_PROGRAM_ARB)
+ Program->HintPositionInvariant = 1;
break;
}
break;
Program->Position = parse_position (&inst);
if (Program->type == 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,
(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 */