summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/r300/r300_fragprog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/r300/r300_fragprog.c')
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c
index 94cb11afec..4c6289298e 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog.c
@@ -50,6 +50,130 @@
#include "r300_state.h"
+static void reset_srcreg(struct prog_src_register* reg)
+{
+ _mesa_bzero(reg, sizeof(*reg));
+ reg->Swizzle = SWIZZLE_NOOP;
+}
+
+/**
+ * Transform TEX, TXP, TXB, and KIL instructions in the following way:
+ * - premultiply texture coordinates for RECT
+ * - extract operand swizzles
+ * - introduce a temporary register when write masks are needed
+ *
+ * \todo If/when r5xx uses the radeon_program architecture, this can probably
+ * be reused.
+ */
+static GLboolean transform_TEX(
+ struct radeon_program_transform_context* context,
+ struct prog_instruction* orig_inst, void* data)
+{
+ struct r300_fragment_program_compiler *compiler =
+ (struct r300_fragment_program_compiler*)data;
+ struct prog_instruction inst = *orig_inst;
+ struct prog_instruction* tgt;
+ GLboolean destredirect = GL_FALSE;
+
+ if (inst.Opcode != OPCODE_TEX &&
+ inst.Opcode != OPCODE_TXB &&
+ inst.Opcode != OPCODE_TXP &&
+ inst.Opcode != OPCODE_KIL)
+ return GL_FALSE;
+
+ /* Hardware uses [0..1]x[0..1] range for rectangle textures
+ * instead of [0..Width]x[0..Height].
+ * Add a scaling instruction.
+ */
+ if (inst.Opcode != OPCODE_KIL && inst.TexSrcTarget == TEXTURE_RECT_INDEX) {
+ gl_state_index tokens[STATE_LENGTH] = {
+ STATE_INTERNAL, STATE_R300_TEXRECT_FACTOR, 0, 0,
+ 0
+ };
+
+ int tempreg = radeonCompilerAllocateTemporary(context->compiler);
+ int factor_index;
+
+ tokens[2] = inst.TexSrcUnit;
+ factor_index =
+ _mesa_add_state_reference(
+ compiler->fp->mesa_program.Base.Parameters, tokens);
+
+ tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
+ context->dest->NumInstructions, 1);
+
+ tgt->Opcode = OPCODE_MAD;
+ tgt->DstReg.File = PROGRAM_TEMPORARY;
+ tgt->DstReg.Index = tempreg;
+ tgt->SrcReg[0] = inst.SrcReg[0];
+ tgt->SrcReg[1].File = PROGRAM_STATE_VAR;
+ tgt->SrcReg[1].Index = factor_index;
+ tgt->SrcReg[2].File = PROGRAM_BUILTIN;
+ tgt->SrcReg[2].Swizzle = SWIZZLE_0000;
+
+ reset_srcreg(&inst.SrcReg[0]);
+ inst.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst.SrcReg[0].Index = tempreg;
+ }
+
+ /* Texture operations do not support swizzles etc. in hardware,
+ * so emit an additional arithmetic operation if necessary.
+ */
+ if (inst.SrcReg[0].Swizzle != SWIZZLE_NOOP ||
+ inst.SrcReg[0].Abs || inst.SrcReg[0].NegateBase || inst.SrcReg[0].NegateAbs) {
+ int tempreg = radeonCompilerAllocateTemporary(context->compiler);
+
+ tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
+ context->dest->NumInstructions, 1);
+
+ tgt->Opcode = OPCODE_MAD;
+ tgt->DstReg.File = PROGRAM_TEMPORARY;
+ tgt->DstReg.Index = tempreg;
+ tgt->SrcReg[0] = inst.SrcReg[0];
+ tgt->SrcReg[1].File = PROGRAM_BUILTIN;
+ tgt->SrcReg[1].Swizzle = SWIZZLE_1111;
+ tgt->SrcReg[2].File = PROGRAM_BUILTIN;
+ tgt->SrcReg[2].Swizzle = SWIZZLE_0000;
+
+ reset_srcreg(&inst.SrcReg[0]);
+ inst.SrcReg[0].File = PROGRAM_TEMPORARY;
+ inst.SrcReg[0].Index = tempreg;
+ }
+
+ if (inst.Opcode != OPCODE_KIL) {
+ if (inst.DstReg.File != PROGRAM_TEMPORARY ||
+ inst.DstReg.WriteMask != WRITEMASK_XYZW) {
+ int tempreg = radeonCompilerAllocateTemporary(context->compiler);
+
+ inst.DstReg.File = PROGRAM_TEMPORARY;
+ inst.DstReg.Index = tempreg;
+ inst.DstReg.WriteMask = WRITEMASK_XYZW;
+ destredirect = GL_TRUE;
+ }
+ }
+
+ tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
+ context->dest->NumInstructions, 1);
+ _mesa_copy_instructions(tgt, &inst, 1);
+
+ if (destredirect) {
+ tgt = radeonClauseInsertInstructions(context->compiler, context->dest,
+ context->dest->NumInstructions, 1);
+
+ tgt->Opcode = OPCODE_MAD;
+ tgt->DstReg = orig_inst->DstReg;
+ tgt->SrcReg[0].File = PROGRAM_TEMPORARY;
+ tgt->SrcReg[0].Index = inst.DstReg.Index;
+ tgt->SrcReg[1].File = PROGRAM_BUILTIN;
+ tgt->SrcReg[1].Swizzle = SWIZZLE_1111;
+ tgt->SrcReg[2].File = PROGRAM_BUILTIN;
+ tgt->SrcReg[2].Swizzle = SWIZZLE_0000;
+ }
+
+ return GL_TRUE;
+}
+
+
static void update_params(r300ContextPtr r300, struct r300_fragment_program *fp)
{
struct gl_fragment_program *mp = &fp->mesa_program;
@@ -170,6 +294,13 @@ void r300TranslateFragmentShader(r300ContextPtr r300,
insert_WPOS_trailer(&compiler);
+ struct radeon_program_transformation transformations[1] = {
+ { &transform_TEX, &compiler }
+ };
+ radeonClauseLocalTransform(&compiler.compiler,
+ &compiler.compiler.Clauses[0],
+ 1, transformations);
+
if (!r300FragmentProgramEmit(&compiler))
fp->error = GL_TRUE;