Merge commit 'origin/gallium-0.1'
[mesa.git] / src / mesa / drivers / dri / r300 / radeon_program_pair.c
index 4eaac50412e7d410a28c2df6a962a8dae45b38e5..365e7c17222f54ff2c7107caa3498a435efc70e8 100644 (file)
@@ -265,11 +265,21 @@ static void final_rewrite(struct pair_state *s, struct prog_instruction *inst)
                inst->SrcReg[0] = tmp;
                break;
        case OPCODE_MOV:
-               inst->SrcReg[1] = inst->SrcReg[0];
+               /* AMD say we should use CMP.
+                * However, when we transform
+                *  KIL -r0;
+                * into
+                *  CMP tmp, -r0, -r0, 0;
+                *  KIL tmp;
+                * we get incorrect behaviour on R500 when r0 == 0.0.
+                * It appears that the R500 KIL hardware treats -0.0 as less
+                * than zero.
+                */
+               inst->SrcReg[1].File = PROGRAM_BUILTIN;
+               inst->SrcReg[1].Swizzle = SWIZZLE_1111;
                inst->SrcReg[2].File = PROGRAM_BUILTIN;
                inst->SrcReg[2].Swizzle = SWIZZLE_0000;
-               inst->Opcode = OPCODE_CMP;
-               // TODO: disable output modifiers on R500
+               inst->Opcode = OPCODE_MAD;
                break;
        case OPCODE_MUL:
                inst->SrcReg[2].File = PROGRAM_BUILTIN;
@@ -295,6 +305,8 @@ static void classify_instruction(struct pair_state *s,
        switch(inst->Opcode) {
        case OPCODE_ADD:
        case OPCODE_CMP:
+       case OPCODE_DDX:
+       case OPCODE_DDY:
        case OPCODE_FRC:
        case OPCODE_MAD:
        case OPCODE_MAX:
@@ -461,6 +473,11 @@ static void allocate_input_registers(struct pair_state *s)
                alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_COL1, hwindex++);
        InputsRead &= ~FRAG_BIT_COL1;
 
+       /* Fog coordinate */
+       if (InputsRead & FRAG_BIT_FOGC)
+               alloc_hw_reg(s, PROGRAM_INPUT, FRAG_ATTRIB_FOGC, hwindex++);
+       InputsRead &= ~FRAG_BIT_FOGC;
+
        /* Anything else */
        if (InputsRead)
                error("Don't know how to handle inputs 0x%x\n", InputsRead);
@@ -578,6 +595,9 @@ static void emit_all_tex(struct pair_state *s)
        if (s->Debug)
                _mesa_printf(" BEGIN_TEX\n");
 
+       if (s->Handler->BeginTexBlock)
+               s->Error = s->Error || !s->Handler->BeginTexBlock(s->UserData);
+
        for(pairinst = readytex; pairinst; pairinst = pairinst->NextReady) {
                int ip = pairinst - s->Instructions;
                struct prog_instruction *inst = s->Program->Instructions + ip;
@@ -594,9 +614,6 @@ static void emit_all_tex(struct pair_state *s)
                s->Error = s->Error || !s->Handler->EmitTex(s->UserData, inst);
        }
 
-       if (s->Handler->EndTexBlock)
-               s->Handler->EndTexBlock(s->UserData);
-
        if (s->Debug)
                _mesa_printf(" END_TEX\n");
 }
@@ -663,8 +680,6 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
        return candidate;
 }
 
-
-
 /**
  * Fill the given ALU instruction's opcodes and source operands into the given pair,
  * if possible.
@@ -682,13 +697,26 @@ static GLboolean fill_instruction_into_pair(struct pair_state *s, struct radeon_
                        pair->RGB.Opcode = OPCODE_REPL_ALPHA;
                else
                        pair->RGB.Opcode = inst->Opcode;
+               if (inst->SaturateMode == SATURATE_ZERO_ONE)
+                       pair->RGB.Saturate = 1;
        }
-       if (pairinst->NeedAlpha)
+       if (pairinst->NeedAlpha) {
                pair->Alpha.Opcode = inst->Opcode;
+               if (inst->SaturateMode == SATURATE_ZERO_ONE)
+                       pair->Alpha.Saturate = 1;
+       }
 
        int nargs = _mesa_num_inst_src_regs(inst->Opcode);
        int i;
 
+       /* Special case for DDX/DDY (MDH/MDV). */
+       if (inst->Opcode == OPCODE_DDX || inst->Opcode == OPCODE_DDY) {
+               if (pair->RGB.Src[0].Used || pair->Alpha.Src[0].Used)
+                       return GL_FALSE;
+               else
+                       nargs++;
+       }
+
        for(i = 0; i < nargs; ++i) {
                int source;
                if (pairinst->NeedRGB && !pairinst->IsTranscendent) {
@@ -750,10 +778,10 @@ static void fill_dest_into_pair(struct pair_state *s, struct radeon_pair_instruc
        struct prog_instruction *inst = s->Program->Instructions + ip;
 
        if (inst->DstReg.File == PROGRAM_OUTPUT) {
-               if (inst->DstReg.Index == FRAG_RESULT_COLR) {
+               if (inst->DstReg.Index == FRAG_RESULT_COLOR) {
                        pair->RGB.OutputWriteMask |= inst->DstReg.WriteMask & WRITEMASK_XYZ;
                        pair->Alpha.OutputWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
-               } else if (inst->DstReg.Index == FRAG_RESULT_DEPR) {
+               } else if (inst->DstReg.Index == FRAG_RESULT_DEPTH) {
                        pair->Alpha.DepthWriteMask |= GET_BIT(inst->DstReg.WriteMask, 3);
                }
        } else {