r300: Implement GL_ARB_shadow and GL_EXT_shadow_funcs

This commit is contained in:
Nicolai Haehnle 2008-06-14 04:07:51 +02:00
parent 83ad2a756e
commit a1c0c56d70
3 changed files with 152 additions and 1 deletions

View file

@ -98,6 +98,7 @@ const struct dri_extension card_extensions[] = {
{"GL_ARB_fragment_program", NULL},
{"GL_ARB_multisample", GL_ARB_multisample_functions},
{"GL_ARB_multitexture", NULL},
{"GL_ARB_shadow", NULL},
{"GL_ARB_texture_border_clamp", NULL},
{"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
{"GL_ARB_texture_cube_map", NULL},
@ -116,6 +117,7 @@ const struct dri_extension card_extensions[] = {
{"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
{"GL_EXT_gpu_program_parameters", GL_EXT_gpu_program_parameters_functions},
{"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
{"GL_EXT_shadow_funcs", NULL},
{"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions},
{"GL_EXT_stencil_wrap", NULL},
{"GL_EXT_texture_edge_clamp", NULL},

View file

@ -655,6 +655,34 @@ struct r300_vertex_program_cont {
struct r300_pfs_compile_state;
/**
* Stores state that influences the compilation of a fragment program.
*/
struct r300_fragment_program_external_state {
struct {
/**
* If the sampler is used as a shadow sampler,
* this field is:
* 0 - GL_LUMINANCE
* 1 - GL_INTENSITY
* 2 - GL_ALPHA
* depending on the depth texture mode.
*/
GLuint depth_texture_mode : 2;
/**
* If the sampler is used as a shadow sampler,
* this field is (texture_compare_func - GL_NEVER).
* [e.g. if compare function is GL_LEQUAL, this field is 3]
*
* Otherwise, this field is 0.
*/
GLuint texture_compare_func : 3;
} unit[16];
};
/**
* Stores an R300 fragment program in its compiled-to-hardware form.
*/
@ -711,6 +739,7 @@ struct r300_fragment_program {
GLboolean translated;
GLboolean error;
struct r300_fragment_program_external_state state;
struct r300_fragment_program_code code;
GLboolean WritesDepth;

View file

@ -81,6 +81,33 @@ static GLboolean transform_TEX(
inst.Opcode != OPCODE_KIL)
return GL_FALSE;
if (inst.Opcode != OPCODE_KIL &&
compiler->fp->mesa_program.Base.ShadowSamplers & (1 << inst.TexSrcUnit)) {
GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
if (comparefunc == GL_NEVER || comparefunc == GL_ALWAYS) {
tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
context->dest->NumInstructions, 1);
tgt->Opcode = OPCODE_MAD;
tgt->DstReg = inst.DstReg;
tgt->SrcReg[0].File = PROGRAM_BUILTIN;
tgt->SrcReg[0].Swizzle = SWIZZLE_0000;
tgt->SrcReg[1].File = PROGRAM_BUILTIN;
tgt->SrcReg[1].Swizzle = SWIZZLE_0000;
tgt->SrcReg[2].File = PROGRAM_BUILTIN;
tgt->SrcReg[2].Swizzle = comparefunc == GL_ALWAYS ? SWIZZLE_1111 : SWIZZLE_0000;
return GL_TRUE;
}
int tempreg = radeonCompilerAllocateTemporary(context->compiler);
inst.DstReg.File = PROGRAM_TEMPORARY;
inst.DstReg.Index = tempreg;
inst.DstReg.WriteMask = WRITEMASK_XYZW;
}
/* Hardware uses [0..1]x[0..1] range for rectangle textures
* instead of [0..Width]x[0..Height].
* Add a scaling instruction.
@ -156,7 +183,51 @@ static GLboolean transform_TEX(
context->dest->NumInstructions, 1);
_mesa_copy_instructions(tgt, &inst, 1);
if (destredirect) {
if (inst.Opcode != OPCODE_KIL &&
compiler->fp->mesa_program.Base.ShadowSamplers & (1 << inst.TexSrcUnit)) {
GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
context->dest->NumInstructions, 2);
tgt[0].Opcode = OPCODE_MAD;
tgt[0].DstReg = inst.DstReg;
tgt[0].DstReg.WriteMask = orig_inst->DstReg.WriteMask;
tgt[0].SrcReg[0].File = PROGRAM_TEMPORARY;
tgt[0].SrcReg[0].Index = inst.DstReg.Index;
if (depthmode == 0) /* GL_LUMINANCE */
tgt[0].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z);
else if (depthmode == 2) /* GL_ALPHA */
tgt[0].SrcReg[0].Swizzle = SWIZZLE_WWWW;
tgt[0].SrcReg[1].File = PROGRAM_BUILTIN;
tgt[0].SrcReg[1].Swizzle = SWIZZLE_1111;
tgt[0].SrcReg[2] = inst.SrcReg[0];
tgt[0].SrcReg[2].Swizzle = SWIZZLE_ZZZZ;
/* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
* r < tex <=> -tex+r < 0
* r >= tex <=> not (-tex+r < 0 */
if (comparefunc == GL_LESS || comparefunc == GL_GEQUAL)
tgt[0].SrcReg[0].NegateBase = tgt[0].SrcReg[0].NegateBase ^ NEGATE_XYZW;
else
tgt[0].SrcReg[2].NegateBase = tgt[0].SrcReg[2].NegateBase ^ NEGATE_XYZW;
tgt[1].Opcode = OPCODE_CMP;
tgt[1].DstReg = orig_inst->DstReg;
tgt[1].SrcReg[0].File = PROGRAM_TEMPORARY;
tgt[1].SrcReg[0].Index = tgt[0].DstReg.Index;
tgt[1].SrcReg[1].File = PROGRAM_BUILTIN;
tgt[1].SrcReg[2].File = PROGRAM_BUILTIN;
if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
tgt[1].SrcReg[1].Swizzle = SWIZZLE_1111;
tgt[1].SrcReg[2].Swizzle = SWIZZLE_0000;
} else {
tgt[1].SrcReg[1].Swizzle = SWIZZLE_0000;
tgt[1].SrcReg[2].Swizzle = SWIZZLE_1111;
}
} else if (destredirect) {
tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
context->dest->NumInstructions, 1);
@ -280,9 +351,58 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
}
static GLuint build_dtm(GLuint depthmode)
{
switch(depthmode) {
default:
case GL_LUMINANCE: return 0;
case GL_INTENSITY: return 1;
case GL_ALPHA: return 2;
}
}
static GLuint build_func(GLuint comparefunc)
{
return comparefunc - GL_NEVER;
}
/**
* Collect all external state that is relevant for compiling the given
* fragment program.
*/
static void build_state(
r300ContextPtr r300,
struct r300_fragment_program *fp,
struct r300_fragment_program_external_state *state)
{
int unit;
_mesa_bzero(state, sizeof(*state));
for(unit = 0; unit < 16; ++unit) {
if (fp->mesa_program.Base.ShadowSamplers & (1 << unit)) {
struct gl_texture_object* tex = r300->radeon.glCtx->Texture.Unit[unit]._Current;
state->unit[unit].depth_texture_mode = build_dtm(tex->DepthMode);
state->unit[unit].texture_compare_func = build_func(tex->CompareFunc);
}
}
}
void r300TranslateFragmentShader(r300ContextPtr r300,
struct r300_fragment_program *fp)
{
struct r300_fragment_program_external_state state;
build_state(r300, fp, &state);
if (_mesa_memcmp(&fp->state, &state, sizeof(state))) {
/* TODO: cache compiled programs */
fp->translated = GL_FALSE;
_mesa_memcpy(&fp->state, &state, sizeof(state));
}
if (!fp->translated) {
struct r300_fragment_program_compiler compiler;