#include "context.h"
#include "nvfragprog.h"
#include "macros.h"
+#include "program.h"
#include "s_nvfragprog.h"
#include "s_span.h"
}
-
/**
- * Fetch a 4-element float vector from the given source register.
- * Apply swizzling and negating as needed.
+ * Return a pointer to the 4-element float vector specified by the given
+ * source register.
*/
-static void
-fetch_vector4( GLcontext *ctx,
- const struct fp_src_register *source,
- struct fp_machine *machine,
- const struct fragment_program *program,
- GLfloat result[4] )
+static INLINE const GLfloat *
+get_register_pointer( GLcontext *ctx,
+ const struct fp_src_register *source,
+ const struct fp_machine *machine,
+ const struct fragment_program *program )
{
const GLfloat *src;
-
switch (source->File) {
case PROGRAM_TEMPORARY:
ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_TEMPS);
src = ctx->FragmentProgram.Parameters[source->Index];
break;
case PROGRAM_NAMED_PARAM:
- ASSERT(source->Index < program->NumParameters);
- src = program->Parameters[source->Index].Values;
+ ASSERT(source->Index < (GLint) program->Parameters->NumParameters);
+ src = program->Parameters->Parameters[source->Index].Values;
break;
case PROGRAM_STATE_VAR:
- abort();
+ src = NULL;
+ break;
default:
_mesa_problem(ctx, "Invalid input register file in fetch_vector4");
- return;
+ src = NULL;
}
+ return src;
+}
+
+
+/**
+ * Fetch a 4-element float vector from the given source register.
+ * Apply swizzling and negating as needed.
+ */
+static void
+fetch_vector4( GLcontext *ctx,
+ const struct fp_src_register *source,
+ const struct fp_machine *machine,
+ const struct fragment_program *program,
+ GLfloat result[4] )
+{
+ const GLfloat *src = get_register_pointer(ctx, source, machine, program);
+ ASSERT(src);
result[0] = src[source->Swizzle[0]];
result[1] = src[source->Swizzle[1]];
const struct fragment_program *program,
GLfloat result[4] )
{
- const GLfloat *src;
-
- switch (source->File) {
- case PROGRAM_TEMPORARY:
- ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_TEMPS);
- src = machine->Temporaries[source->Index];
- break;
- case PROGRAM_INPUT:
- ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
- src = machine->Inputs[source->Index];
- break;
- case PROGRAM_LOCAL_PARAM:
- ASSERT(source->Index < MAX_PROGRAM_LOCAL_PARAMS);
- src = program->Base.LocalParams[source->Index];
- break;
- case PROGRAM_ENV_PARAM:
- ASSERT(source->Index < MAX_NV_FRAGMENT_PROGRAM_PARAMS);
- src = ctx->FragmentProgram.Parameters[source->Index];
- break;
- case PROGRAM_NAMED_PARAM:
- ASSERT(source->Index < program->NumParameters);
- src = program->Parameters[source->Index].Values;
- break;
- case PROGRAM_STATE_VAR:
- abort();
- default:
- _mesa_problem(ctx, "Invalid input register file in fetch_vector1");
- return;
- }
+ const GLfloat *src = get_register_pointer(ctx, source, machine, program);
+ ASSERT(src);
result[0] = src[source->Swizzle[0]];
}
switch (inst->Opcode) {
+ case FP_OPCODE_ABS:
+ {
+ GLfloat a[4], result[4];
+ fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
+ result[0] = FABSF(a[0]);
+ result[1] = FABSF(a[1]);
+ result[2] = FABSF(a[2]);
+ result[3] = FABSF(a[3]);
+ store_vector4( inst, machine, result );
+ }
+ break;
case FP_OPCODE_ADD:
{
GLfloat a[4], b[4], result[4];
store_vector4( inst, machine, result );
}
break;
+ case FP_OPCODE_CMP:
+ {
+ GLfloat a[4], b[4], c[4], result[4];
+ fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
+ fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
+ fetch_vector4( ctx, &inst->SrcReg[2], machine, program, c );
+ result[0] = a[0] < 0.0F ? b[0] : c[0];
+ result[1] = a[1] < 0.0F ? b[1] : c[1];
+ result[2] = a[2] < 0.0F ? b[2] : c[2];
+ result[3] = a[3] < 0.0F ? b[3] : c[3];
+ store_vector4( inst, machine, result );
+ }
+ break;
case FP_OPCODE_COS:
{
GLfloat a[4], result[4];
store_vector4( inst, machine, result );
}
break;
+ case FP_OPCODE_DPH:
+ {
+ GLfloat a[4], b[4], result[4];
+ fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a );
+ fetch_vector4( ctx, &inst->SrcReg[1], machine, program, b );
+ result[0] = result[1] = result[2] = result[3] =
+ a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + b[3];
+ store_vector4( inst, machine, result );
+ }
+ break;
case FP_OPCODE_DST: /* Distance vector */
{
GLfloat a[4], b[4], result[4];
#endif
}
break;
+ case FP_OPCODE_SCS: /* sine and cos */
+ {
+ GLfloat a[4], result[4];
+ fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
+ result[0] = (GLfloat)cos(a[0]);
+ result[1] = (GLfloat)sin(a[0]);
+ result[2] = 0.0; /* undefined! */
+ result[3] = 0.0; /* undefined! */
+ store_vector4( inst, machine, result );
+ }
+ break;
case FP_OPCODE_SEQ: /* set on equal */
{
GLfloat a[4], b[4], result[4];
store_vector4( inst, machine, result );
}
break;
+ case FP_OPCODE_SWZ:
+ {
+ const struct fp_src_register *source = &inst->SrcReg[0];
+ const GLfloat *src = get_register_pointer(ctx, source,
+ machine, program);
+ GLfloat result[4];
+ GLuint i;
+
+ /* do extended swizzling here */
+ for (i = 0; i < 3; i++) {
+ if (source->Swizzle[i] == SWIZZLE_ZERO)
+ result[i] = 0.0;
+ else if (source->Swizzle[i] == SWIZZLE_ONE)
+ result[i] = -1.0;
+ else
+ result[i] = -src[source->Swizzle[i]];
+ if (source->NegateBase)
+ result[i] = -result[i];
+ }
+ store_vector4( inst, machine, result );
+ }
+ break;
case FP_OPCODE_TEX:
/* Texel lookup */
{
store_vector4( inst, machine, color );
}
break;
+ case FP_OPCODE_TXB:
+ /* Texel lookup with LOD bias */
+ {
+ GLfloat texcoord[4], color[4], bias, lambda;
+
+ fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
+ /* texcoord[3] is the bias to add to lambda */
+ bias = ctx->Texture.Unit[inst->TexSrcUnit].LodBias
+ + ctx->Texture.Unit[inst->TexSrcUnit]._Current->LodBias
+ + texcoord[3];
+ lambda = span->array->lambda[inst->TexSrcUnit][column] + bias;
+ fetch_texel( ctx, texcoord, lambda,
+ inst->TexSrcUnit, color );
+ store_vector4( inst, machine, color );
+ }
+ break;
case FP_OPCODE_TXD:
/* Texture lookup w/ partial derivatives for LOD */
{