summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.c2
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.h29
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog.c122
3 files changed, 152 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 31cc00a081..063d4e575e 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -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},
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index a9b3b061f4..ca22c5dd8a 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -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;
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c
index 814ccd3eac..da2dedece8 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog.c
@@ -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;