📄 s_nvfragprog.c
字号:
result[0] = (a[0] != b[0]) ? 1.0F : 0.0F;
result[1] = (a[1] != b[1]) ? 1.0F : 0.0F;
result[2] = (a[2] != b[2]) ? 1.0F : 0.0F;
result[3] = (a[3] != b[3]) ? 1.0F : 0.0F;
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_STR: /* set true, operands ignored */
{
static const GLfloat result[4] = { 1.0F, 1.0F, 1.0F, 1.0F };
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_SUB:
{
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] = a[0] - b[0];
result[1] = a[1] - b[1];
result[2] = a[2] - b[2];
result[3] = a[3] - b[3];
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 < 4; i++) {
if (GET_SWZ(source->Swizzle, i) == SWIZZLE_ZERO)
result[i] = 0.0;
else if (GET_SWZ(source->Swizzle, i) == SWIZZLE_ONE)
result[i] = 1.0;
else
result[i] = src[GET_SWZ(source->Swizzle, i)];
if (source->NegateBase & (1 << i))
result[i] = -result[i];
}
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_TEX: /* Both ARB and NV frag prog */
/* Texel lookup */
{
GLfloat texcoord[4], color[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
/* Note: we pass 0 for LOD. The ARB extension requires it
* while the NV extension says it's implementation dependant.
*/
/* KW: Previously lambda was passed as zero, but I
* believe this is incorrect, the spec seems to
* indicate rather that lambda should not be
* changed/biased, unlike TXB where texcoord[3] is
* added to the lambda calculations. The lambda should
* still be calculated normally for TEX & TXP though,
* not set to zero. Otherwise it's very difficult to
* implement normal GL semantics through the fragment
* shader.
*/
fetch_texel( ctx, texcoord,
span->array->lambda[inst->TexSrcUnit][column],
inst->TexSrcUnit, color );
store_vector4( inst, machine, color );
}
break;
case FP_OPCODE_TXB: /* GL_ARB_fragment_program only */
/* 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: /* GL_NV_fragment_program only */
/* Texture lookup w/ partial derivatives for LOD */
{
GLfloat texcoord[4], dtdx[4], dtdy[4], color[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
fetch_vector4( ctx, &inst->SrcReg[1], machine, program, dtdx );
fetch_vector4( ctx, &inst->SrcReg[2], machine, program, dtdy );
fetch_texel_deriv( ctx, texcoord, dtdx, dtdy, inst->TexSrcUnit,
color );
store_vector4( inst, machine, color );
}
break;
case FP_OPCODE_TXP: /* GL_ARB_fragment_program only */
/* Texture lookup w/ projective divide */
{
GLfloat texcoord[4], color[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
/* Not so sure about this test - if texcoord[3] is
* zero, we'd probably be fine except for an ASSERT in
* IROUND_POS() which gets triggered by the inf values created.
*/
if (texcoord[3] != 0.0) {
texcoord[0] /= texcoord[3];
texcoord[1] /= texcoord[3];
texcoord[2] /= texcoord[3];
}
/* KW: Previously lambda was passed as zero, but I
* believe this is incorrect, the spec seems to
* indicate rather that lambda should not be
* changed/biased, unlike TXB where texcoord[3] is
* added to the lambda calculations. The lambda should
* still be calculated normally for TEX & TXP though,
* not set to zero.
*/
fetch_texel( ctx, texcoord,
span->array->lambda[inst->TexSrcUnit][column],
inst->TexSrcUnit, color );
store_vector4( inst, machine, color );
}
break;
case FP_OPCODE_TXP_NV: /* GL_NV_fragment_program only */
/* Texture lookup w/ projective divide */
{
GLfloat texcoord[4], color[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, texcoord );
if (inst->TexSrcIdx != TEXTURE_CUBE_INDEX &&
texcoord[3] != 0.0) {
texcoord[0] /= texcoord[3];
texcoord[1] /= texcoord[3];
texcoord[2] /= texcoord[3];
}
fetch_texel( ctx, texcoord,
span->array->lambda[inst->TexSrcUnit][column],
inst->TexSrcUnit, color );
store_vector4( inst, machine, color );
}
break;
case FP_OPCODE_UP2H: /* unpack two 16-bit floats */
{
GLfloat a[4], result[4];
const GLuint *rawBits = (const GLuint *) a;
GLhalfNV hx, hy;
fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
hx = rawBits[0] & 0xffff;
hy = rawBits[0] >> 16;
result[0] = result[2] = _mesa_half_to_float(hx);
result[1] = result[3] = _mesa_half_to_float(hy);
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_UP2US: /* unpack two GLushorts */
{
GLfloat a[4], result[4];
const GLuint *rawBits = (const GLuint *) a;
GLushort usx, usy;
fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
usx = rawBits[0] & 0xffff;
usy = rawBits[0] >> 16;
result[0] = result[2] = usx * (1.0f / 65535.0f);
result[1] = result[3] = usy * (1.0f / 65535.0f);
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_UP4B: /* unpack four GLbytes */
{
GLfloat a[4], result[4];
const GLuint *rawBits = (const GLuint *) a;
fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
result[0] = (((rawBits[0] >> 0) & 0xff) - 128) / 127.0F;
result[1] = (((rawBits[0] >> 8) & 0xff) - 128) / 127.0F;
result[2] = (((rawBits[0] >> 16) & 0xff) - 128) / 127.0F;
result[3] = (((rawBits[0] >> 24) & 0xff) - 128) / 127.0F;
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_UP4UB: /* unpack four GLubytes */
{
GLfloat a[4], result[4];
const GLuint *rawBits = (const GLuint *) a;
fetch_vector1( ctx, &inst->SrcReg[0], machine, program, a );
result[0] = ((rawBits[0] >> 0) & 0xff) / 255.0F;
result[1] = ((rawBits[0] >> 8) & 0xff) / 255.0F;
result[2] = ((rawBits[0] >> 16) & 0xff) / 255.0F;
result[3] = ((rawBits[0] >> 24) & 0xff) / 255.0F;
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_XPD: /* cross product */
{
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] = a[1] * b[2] - a[2] * b[1];
result[1] = a[2] * b[0] - a[0] * b[2];
result[2] = a[0] * b[1] - a[1] * b[0];
result[3] = 1.0;
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_X2D: /* 2-D matrix transform */
{
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] + b[0] * c[0] + b[1] * c[1];
result[1] = a[1] + b[0] * c[2] + b[1] * c[3];
result[2] = a[2] + b[0] * c[0] + b[1] * c[1];
result[3] = a[3] + b[0] * c[2] + b[1] * c[3];
store_vector4( inst, machine, result );
}
break;
case FP_OPCODE_PRINT:
{
if (inst->SrcReg[0].File != -1) {
GLfloat a[4];
fetch_vector4( ctx, &inst->SrcReg[0], machine, program, a);
_mesa_printf("%s%g, %g, %g, %g\n", (const char *) inst->Data,
a[0], a[1], a[2], a[3]);
}
else {
_mesa_printf("%s\n", (const char *) inst->Data);
}
}
break;
case FP_OPCODE_END:
return GL_TRUE;
default:
_mesa_problem(ctx, "Bad opcode %d in _mesa_exec_fragment_program",
inst->Opcode);
return GL_TRUE; /* return value doesn't matter */
}
}
return GL_TRUE;
}
static void
init_machine( GLcontext *ctx, struct fp_machine *machine,
const struct fragment_program *program,
const struct sw_span *span, GLuint col )
{
GLuint inputsRead = program->InputsRead;
GLuint u;
if (ctx->FragmentProgram.CallbackEnabled)
inputsRead = ~0;
if (program->Base.Target == GL_FRAGMENT_PROGRAM_NV) {
/* Clear temporary registers (undefined for ARB_f_p) */
_mesa_bzero(machine->Temporaries,
MAX_NV_FRAGMENT_PROGRAM_TEMPS * 4 * sizeof(GLfloat));
}
/* Load input registers */
if (inputsRead & (1 << FRAG_ATTRIB_WPOS)) {
GLfloat *wpos = machine->Inputs[FRAG_ATTRIB_WPOS];
ASSERT(span->arrayMask & SPAN_Z);
wpos[0] = (GLfloat) span->x + col;
wpos[1] = (GLfloat) span->y;
wpos[2] = (GLfloat) span->array->z[col] / ctx->DrawBuffer->_DepthMaxF;
wpos[3] = span->w + col * span->dwdx;
}
if (inputsRead & (1 << FRAG_ATTRIB_COL0)) {
GLfloat *col0 = machine->Inputs[FRAG_ATTRIB_COL0];
ASSERT(span->arrayMask & SPAN_RGBA);
col0[0] = CHAN_TO_FLOAT(span->array->rgba[col][RCOMP]);
col0[1] = CHAN_TO_FLOAT(span->array->rgba[col][GCOMP]);
col0[2] = CHAN_TO_FLOAT(span->array->rgba[col][BCOMP]);
col0[3] = CHAN_TO_FLOAT(span->array->rgba[col][ACOMP]);
}
if (inputsRead & (1 << FRAG_ATTRIB_COL1)) {
GLfloat *col1 = machine->Inputs[FRAG_ATTRIB_COL1];
col1[0] = CHAN_TO_FLOAT(span->array->spec[col][RCOMP]);
col1[1] = CHAN_TO_FLOAT(span->array->spec[col][GCOMP]);
col1[2] = CHAN_TO_FLOAT(span->array->spec[col][BCOMP]);
col1[3] = CHAN_TO_FLOAT(span->array->spec[col][ACOMP]);
}
if (inputsRead & (1 << FRAG_ATTRIB_FOGC)) {
GLfloat *fogc = machine->Inputs[FRAG_ATTRIB_FOGC];
ASSERT(span->arrayMask & SPAN_FOG);
fogc[0] = span->array->fog[col];
fogc[1] = 0.0F;
fogc[2] = 0.0F;
fogc[3] = 0.0F;
}
for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
if (inputsRead & (1 << (FRAG_ATTRIB_TEX0 + u))) {
GLfloat *tex = machine->Inputs[FRAG_ATTRIB_TEX0 + u];
/*ASSERT(ctx->Texture._EnabledCoordUnits & (1 << u));*/
COPY_4V(tex, span->array->texcoords[u][col]);
/*ASSERT(tex[0] != 0 || tex[1] != 0 || tex[2] != 0);*/
}
}
/* init condition codes */
machine->CondCodes[0] = COND_EQ;
machine->CondCodes[1] = COND_EQ;
machine->CondCodes[2] = COND_EQ;
machine->CondCodes[3] = COND_EQ;
}
/**
* Execute the current fragment program, operating on the given span.
*/
void
_swrast_exec_fragment_program( GLcontext *ctx, struct sw_span *span )
{
const struct fragment_program *program = ctx->FragmentProgram._Current;
GLuint i;
ctx->_CurrentProgram = GL_FRAGMENT_PROGRAM_ARB; /* or NV, doesn't matter */
if (program->Parameters) {
_mesa_load_state_parameters(ctx, program->Parameters);
}
for (i = 0; i < span->end; i++) {
if (span->array->mask[i]) {
init_machine(ctx, &ctx->FragmentProgram.Machine,
ctx->FragmentProgram._Current, span, i);
#ifdef USE_TCC
if (!_swrast_execute_codegen_program(ctx, program, ~0,
&ctx->FragmentProgram.Machine,
span, i)) {
span->array->mask[i] = GL_FALSE; /* killed fragment */
span->writeAll = GL_FALSE;
}
#else
if (!execute_program(ctx, program, ~0,
&ctx->FragmentProgram.Machine, span, i)) {
span->array->mask[i] = GL_FALSE; /* killed fragment */
span->writeAll = GL_FALSE;
}
#endif
/* Store output registers */
{
const GLfloat *colOut
= ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_COLR];
UNCLAMPED_FLOAT_TO_CHAN(span->array->rgba[i][RCOMP], colOut[0]);
UNCLAMPED_FLOAT_TO_CHAN(span->array->rgba[i][GCOMP], colOut[1]);
UNCLAMPED_FLOAT_TO_CHAN(span->array->rgba[i][BCOMP], colOut[2]);
UNCLAMPED_FLOAT_TO_CHAN(span->array->rgba[i][ACOMP], colOut[3]);
}
/* depth value */
if (program->OutputsWritten & (1 << FRAG_OUTPUT_DEPR)) {
const GLfloat depth
= ctx->FragmentProgram.Machine.Outputs[FRAG_OUTPUT_DEPR][2];
span->array->z[i] = IROUND(depth * ctx->DrawBuffer->_DepthMaxF);
}
}
}
if (program->OutputsWritten & (1 << FRAG_OUTPUT_DEPR)) {
span->interpMask &= ~SPAN_Z;
span->arrayMask |= SPAN_Z;
}
ctx->_CurrentProgram = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -