fragment.position support

World position is calculated in the vertex shader and passed to the
fragment shader via an unused texcoord.
This commit is contained in:
Rune Petersen 2006-11-17 19:12:42 +00:00
parent 0f614df797
commit 6c9cc81601
4 changed files with 236 additions and 2 deletions

View File

@ -549,6 +549,7 @@ struct r300_stencilbuffer_state {
/* Can be tested with colormat currently. */
#define VSF_MAX_FRAGMENT_TEMPS (14)
#define STATE_R300_WINDOW_DIMENSION (STATE_INTERNAL_DRIVER+0)
struct r300_vertex_shader_fragment {
int length;
@ -623,6 +624,7 @@ struct r300_vertex_program {
int pos_end;
int num_temporaries; /* Number of temp vars used by program */
int wpos_idx;
int inputs[VERT_ATTRIB_MAX];
int outputs[VERT_RESULT_MAX];
int native;

View File

@ -1555,6 +1555,13 @@ static void init_program(struct r300_fragment_program *rp)
}
InputsRead &= ~FRAG_BITS_TEX_ANY;
/* fragment position treated as a texcoord */
if (InputsRead & FRAG_BIT_WPOS) {
cs->inputs[FRAG_ATTRIB_WPOS].refcount = 0;
cs->inputs[FRAG_ATTRIB_WPOS].reg = get_hw_temp(rp);
}
InputsRead &= ~FRAG_BIT_WPOS;
/* Then primary colour */
if (InputsRead & FRAG_BIT_COL0) {
cs->inputs[FRAG_ATTRIB_COL0].refcount = 0;

View File

@ -1044,6 +1044,59 @@ r300UpdateDrawBuffer(GLcontext *ctx)
#endif
}
static void r300FetchStateParameter(GLcontext *ctx, const enum state_index state[],
GLfloat *value)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
switch(state[0])
{
case STATE_INTERNAL:
switch(state[1])
{
case STATE_R300_WINDOW_DIMENSION:
value[0] = r300->radeon.dri.drawable->w; /* width */
value[1] = r300->radeon.dri.drawable->h; /* height */
value[2] = 0.5F; /* for moving range [-1 1] -> [0 1] */
value[3] = 1.0F; /* not used */
break;
default:;
}
default:;
}
}
/**
* Update R300's own internal state parameters.
* For now just STATE_R300_WINDOW_DIMENSION
*/
static void r300UpdateStateParameters(GLcontext * ctx, GLuint new_state)
{
struct r300_vertex_program_cont *vpc;
struct gl_program_parameter_list *paramList;
GLuint i;
if(!(new_state & (_NEW_BUFFERS|_NEW_PROGRAM)))
return;
vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
if (!vpc)
return;
paramList = vpc->mesa_program.Base.Parameters;
if (!paramList)
return;
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR){
r300FetchStateParameter(ctx,
paramList->Parameters[i].StateIndexes,
paramList->ParameterValues[i]);
}
}
}
/* =============================================================
* Polygon state
*/
@ -1304,6 +1357,20 @@ void r300_setup_rs_unit(GLcontext *ctx)
r300->hw.rr.cmd[R300_RR_ROUTE_1] = 0;
if (InputsRead & FRAG_BIT_WPOS){
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
break;
if(i == ctx->Const.MaxTextureUnits){
fprintf(stderr, "\tno free texcoord found...\n");
exit(0);
}
InputsRead |= (FRAG_BIT_TEX0 << i);
InputsRead &= ~FRAG_BIT_WPOS;
}
for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
r300->hw.ri.cmd[R300_RI_INTERP_0+i] = 0
| R300_RS_INTERP_USED
@ -1680,6 +1747,7 @@ void r300UpdateShaders(r300ContextPtr rmesa)
return ;
}
r300UpdateStateParameters(ctx, _NEW_PROGRAM);
}
}
@ -1813,6 +1881,9 @@ static void r300InvalidateState(GLcontext * ctx, GLuint new_state)
if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
r300UpdateDrawBuffer(ctx);
}
r300UpdateStateParameters(ctx, new_state);
#ifndef CB_DPATH
/* Go inefficiency! */
r300ResetHwState(r300);

View File

@ -958,17 +958,155 @@ static void position_invariant(struct gl_program *prog)
assert(vpi->Opcode == OPCODE_END);
}
static void insert_wpos(struct r300_vertex_program *vp,
struct gl_program *prog,
GLint pos)
{
GLint tokens[6] = { STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0, 0 };
struct prog_instruction *vpi;
struct prog_instruction *vpi_insert;
GLuint temp_index;
GLuint window_index;
int i = 0;
vpi = malloc((prog->NumInstructions + 5) * sizeof(struct prog_instruction));
memcpy(vpi, prog->Instructions, (pos+1) * sizeof(struct prog_instruction));
vpi_insert = &vpi[pos];
/* make a copy before outputting VERT_RESULT_HPOS */
vpi_insert->DstReg.File = vpi_insert->SrcReg[2].File;
vpi_insert->DstReg.Index = temp_index = vpi_insert->SrcReg[2].Index;
vpi_insert++;
memset(vpi_insert, 0, 5 * sizeof(struct prog_instruction));
vpi_insert[i].Opcode = OPCODE_MOV;
vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
vpi_insert[i].DstReg.Index = VERT_RESULT_HPOS;
vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
vpi_insert[i].DstReg.CondMask = COND_TR;
vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[0].Index = temp_index;
vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
i++;
/* perspective divide */
vpi_insert[i].Opcode = OPCODE_RCP;
vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY;
vpi_insert[i].DstReg.Index = temp_index;
vpi_insert[i].DstReg.WriteMask = WRITEMASK_W;
vpi_insert[i].DstReg.CondMask = COND_TR;
vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[0].Index = temp_index;
vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO);
i++;
vpi_insert[i].Opcode = OPCODE_MUL;
vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY;
vpi_insert[i].DstReg.Index = temp_index;
vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZ;
vpi_insert[i].DstReg.CondMask = COND_TR;
vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[0].Index = temp_index;
vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
vpi_insert[i].SrcReg[1].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[1].Index = temp_index;
vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_ZERO);
i++;
/* viewport transformation */
window_index = _mesa_add_state_reference(prog->Parameters, tokens);
vpi_insert[i].Opcode = OPCODE_MAD;
vpi_insert[i].DstReg.File = PROGRAM_TEMPORARY;
vpi_insert[i].DstReg.Index = temp_index;
vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZ;
vpi_insert[i].DstReg.CondMask = COND_TR;
vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[0].Index = temp_index;
vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
vpi_insert[i].SrcReg[1].File = PROGRAM_STATE_VAR;
vpi_insert[i].SrcReg[1].Index = window_index;
vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_ZERO);
vpi_insert[i].SrcReg[2].File = PROGRAM_STATE_VAR;
vpi_insert[i].SrcReg[2].Index = window_index;
vpi_insert[i].SrcReg[2].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_ZERO);
i++;
vpi_insert[i].Opcode = OPCODE_MUL;
vpi_insert[i].DstReg.File = PROGRAM_OUTPUT;
vpi_insert[i].DstReg.Index = VERT_RESULT_TEX0+vp->wpos_idx;
vpi_insert[i].DstReg.WriteMask = WRITEMASK_XYZW;
vpi_insert[i].DstReg.CondMask = COND_TR;
vpi_insert[i].SrcReg[0].File = PROGRAM_TEMPORARY;
vpi_insert[i].SrcReg[0].Index = temp_index;
vpi_insert[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W);
vpi_insert[i].SrcReg[1].File = PROGRAM_STATE_VAR;
vpi_insert[i].SrcReg[1].Index = window_index;
vpi_insert[i].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ONE, SWIZZLE_ONE);
i++;
memcpy(&vpi_insert[i], &prog->Instructions[pos+1], (prog->NumInstructions-(pos+1)) * sizeof(struct prog_instruction));
free(prog->Instructions);
prog->Instructions = vpi;
prog->NumInstructions += i;
vpi = &prog->Instructions[prog->NumInstructions-1];
assert(vpi->Opcode == OPCODE_END);
}
static void pos_as_texcoord(struct r300_vertex_program *vp,
struct gl_program *prog)
{
struct prog_instruction *vpi;
int pos = 0;
for(vpi = prog->Instructions; vpi->Opcode != OPCODE_END; vpi++, pos++){
if( vpi->DstReg.File == PROGRAM_OUTPUT &&
vpi->DstReg.Index == VERT_RESULT_HPOS ){
insert_wpos(vp, prog, pos);
break;
}
}
}
static struct r300_vertex_program *build_program(struct r300_vertex_program_key *wanted_key,
struct gl_vertex_program *mesa_vp)
struct gl_vertex_program *mesa_vp,
GLint wpos_idx)
{
struct r300_vertex_program *vp;
vp = _mesa_calloc(sizeof(*vp));
_mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
vp->wpos_idx = wpos_idx;
if(mesa_vp->IsPositionInvariant)
position_invariant(&mesa_vp->Base);
if(wpos_idx > -1)
pos_as_texcoord(vp, &mesa_vp->Base);
assert(mesa_vp->Base.NumInstructions);
vp->num_temporaries=mesa_vp->Base.NumTemporaries;
@ -986,12 +1124,28 @@ void r300_select_vertex_shader(r300ContextPtr r300)
GLint i;
struct r300_vertex_program_cont *vpc;
struct r300_vertex_program *vp;
GLint wpos_idx;
vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
wanted_key.OutputsWritten |= 1 << VERT_RESULT_HPOS;
wpos_idx = -1;
if (InputsRead & FRAG_BIT_WPOS){
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
if (!(InputsRead & (FRAG_BIT_TEX0 << i)))
break;
if(i == ctx->Const.MaxTextureUnits){
fprintf(stderr, "\tno free texcoord found\n");
exit(0);
}
InputsRead |= (FRAG_BIT_TEX0 << i);
wpos_idx = i;
}
if (InputsRead & FRAG_BIT_COL0)
wanted_key.OutputsWritten |= 1 << VERT_RESULT_COL0;
@ -1013,7 +1167,7 @@ void r300_select_vertex_shader(r300ContextPtr r300)
//_mesa_print_program(&vpc->mesa_program.Base);
vp = build_program(&wanted_key, &vpc->mesa_program);
vp = build_program(&wanted_key, &vpc->mesa_program, wpos_idx);
vp->next = vpc->progs;
vpc->progs = vp;